home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / sredird / telnetcpcd-1.09.tar.gz / telnetcpcd-1.09.tar / esprintf.c < prev    next >
C/C++ Source or Header  |  2003-08-12  |  4KB  |  147 lines

  1. /*
  2.     esprintf.c
  3.  
  4.     Copyright (c) 2002,2003 Thomas J Pinkl <tom@pinkl.com>
  5.  
  6.     Like sprintf() but also interprets the character escapes within 
  7.     the format string.  Eg. "\n" becomes the lf character.
  8.  
  9.     This file uses 4 character tabstops.
  10.  
  11.     Version 1.00    05/19/1999
  12.     Version 1.01    05/17/2001        varargs --> stdarg
  13. */
  14.  
  15. #include "telnetcpcd.h"
  16.  
  17. #define hex2Bin(c)        ((c) >= 'a' && (c) <= 'f' ? ((c)-'a'+10) : \
  18.                          (c) >= 'A' && (c) <= 'F' ? ((c)-'A'+10) : \
  19.                          ((c)-'0'))
  20. #define octal2Bin(c)    ((c) - '0')
  21. #define isOctalDigit(c)    ((c) >= '0' && (c) <= '7')
  22.  
  23. /*
  24.     copy our printf-style arguments to string s and null terminate it. 
  25.     it is the caller's responsibility to insure that s points to a 
  26.     buffer that is sufficiently large to hold the result.
  27.  
  28.     returns the number of characters in string s or a negative value if 
  29.     an error was encountered.
  30. */
  31. int esprintf(char *s,char *efmt, ...)
  32. {
  33.     va_list args;
  34.     char *fmt;                            /* format str w/o char escapes */
  35.     int ret;                            /* returned result code */
  36.  
  37.     va_start(args,efmt);                /* begin processing varargs */
  38.     fmt = calloc(1,strlen(efmt)+1);        /* alloc memory for other fmt str */
  39.     if (fmt != NULL) {
  40.         escstrcpy(fmt,efmt);            /* copy str, interpret char escapes */
  41.         ret = vsprintf(s,fmt,args);
  42.         free(fmt);                        /* release alloc memory */
  43.     } else {                            /* memory alloc failed */
  44.         ret = -1;
  45.     }
  46.     va_end(args);                        /* done processing varargs */
  47.     return(ret);
  48. }
  49.  
  50. /*
  51.     copy string s2 to s1 and interpret escape characters 
  52.     along the way.  s1 will be null terminated.
  53.  
  54.     returns a ptr to s1.
  55. */
  56. char *escstrcpy(char *s1,char *s2)
  57. {
  58.     int esclen;                            /* length of octal or hex escape */
  59.  
  60.     while (*s2 != '\0') {
  61.         if (*s2 == '\\') {                /* backslash introduces escape */
  62.             s2++;                        /* next char */
  63.             if (*s2 == '\0') break;        /* if it's null, we're done */
  64.             switch (*s2) {
  65.             case '0':                    /* octal escape */
  66.                 *s1++ = octal_esc(s2,&esclen);
  67.                 s2 += esclen;
  68.                 break;
  69.             case 'x':                    /* hex escape */
  70.                 *s1++ = hex_esc(s2,&esclen);
  71.                 s2 += esclen;
  72.                 break;
  73.             default:                    /* single char escape */
  74.                 *s1++ = char_esc(*s2);    /* get value of escape char */
  75.                 s2++;
  76.                 break;
  77.             }
  78.         } else {                        /* regular char */
  79.             *s1++ = *s2++;                /* copy char and increment both ptrs */
  80.         }
  81.     }
  82.     *s1 = '\0';                            /* null terminate destination str */
  83.     return(s1);
  84. }
  85.  
  86. /*
  87.     interpret an octal escape (\0nnn) and return the value of the 
  88.     expression.  also returns the length of the escape sequence 
  89.     (max of 4, including the '0').  initially, s points to the '0' 
  90.     following the backslash.
  91. */
  92. int octal_esc(char *s,int *len)
  93. {
  94.     int value = 0;
  95.  
  96.     for (*len = 1, ++s; *len < 4 && isOctalDigit(*s); ++(*len), ++s)
  97.         value = (value * 8) + octal2Bin(*s);
  98.     return(value);
  99. }
  100.  
  101. /*
  102.     interpret a hex escape (\xnn) and return the value of the 
  103.     expression.  also returns the length of the escape sequence 
  104.     (max of 3, including the 'x').  initially, s points to the 'x' 
  105.     following the backslash.
  106. */
  107. int hex_esc(char *s,int *len)
  108. {
  109.     int value = 0;
  110.  
  111.     for (*len = 1, ++s; *len < 3 && isxdigit(*s); ++(*len), ++s)
  112.         value = (value * 16) + hex2Bin(*s);
  113.     if (*len == 1)                        /* was an invalid hex escape */
  114.         return((int) 'x');                /* treat it as "\x" */
  115.     return(value);
  116. }
  117.  
  118. int char_esc(int c)
  119. {
  120.     switch (c) {
  121.     case 'a':                            /* alert (bell) */
  122.         return(7);
  123.         /* break; */
  124.     case 'b':                            /* backspace */
  125.         return(8);
  126.         /* break; */
  127.     case 'f':                            /* form feed */
  128.         return(12);
  129.         /* break; */
  130.     case 'n':                            /* line feed */
  131.         return(10);
  132.         /* break; */
  133.     case 'r':                            /* carriage return */
  134.         return(13);
  135.         /* break; */
  136.     case 't':                            /* tab */
  137.         return(9);
  138.         /* break; */
  139.     case 'v':                            /* vertical tab */
  140.         return(11);
  141.         /* break; */
  142.     default:                            /* anything else */
  143.         break;
  144.     }
  145.     return(c);
  146. }
  147.