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 >
Wrap
C/C++ Source or Header
|
2003-08-12
|
4KB
|
147 lines
/*
esprintf.c
Copyright (c) 2002,2003 Thomas J Pinkl <tom@pinkl.com>
Like sprintf() but also interprets the character escapes within
the format string. Eg. "\n" becomes the lf character.
This file uses 4 character tabstops.
Version 1.00 05/19/1999
Version 1.01 05/17/2001 varargs --> stdarg
*/
#include "telnetcpcd.h"
#define hex2Bin(c) ((c) >= 'a' && (c) <= 'f' ? ((c)-'a'+10) : \
(c) >= 'A' && (c) <= 'F' ? ((c)-'A'+10) : \
((c)-'0'))
#define octal2Bin(c) ((c) - '0')
#define isOctalDigit(c) ((c) >= '0' && (c) <= '7')
/*
copy our printf-style arguments to string s and null terminate it.
it is the caller's responsibility to insure that s points to a
buffer that is sufficiently large to hold the result.
returns the number of characters in string s or a negative value if
an error was encountered.
*/
int esprintf(char *s,char *efmt, ...)
{
va_list args;
char *fmt; /* format str w/o char escapes */
int ret; /* returned result code */
va_start(args,efmt); /* begin processing varargs */
fmt = calloc(1,strlen(efmt)+1); /* alloc memory for other fmt str */
if (fmt != NULL) {
escstrcpy(fmt,efmt); /* copy str, interpret char escapes */
ret = vsprintf(s,fmt,args);
free(fmt); /* release alloc memory */
} else { /* memory alloc failed */
ret = -1;
}
va_end(args); /* done processing varargs */
return(ret);
}
/*
copy string s2 to s1 and interpret escape characters
along the way. s1 will be null terminated.
returns a ptr to s1.
*/
char *escstrcpy(char *s1,char *s2)
{
int esclen; /* length of octal or hex escape */
while (*s2 != '\0') {
if (*s2 == '\\') { /* backslash introduces escape */
s2++; /* next char */
if (*s2 == '\0') break; /* if it's null, we're done */
switch (*s2) {
case '0': /* octal escape */
*s1++ = octal_esc(s2,&esclen);
s2 += esclen;
break;
case 'x': /* hex escape */
*s1++ = hex_esc(s2,&esclen);
s2 += esclen;
break;
default: /* single char escape */
*s1++ = char_esc(*s2); /* get value of escape char */
s2++;
break;
}
} else { /* regular char */
*s1++ = *s2++; /* copy char and increment both ptrs */
}
}
*s1 = '\0'; /* null terminate destination str */
return(s1);
}
/*
interpret an octal escape (\0nnn) and return the value of the
expression. also returns the length of the escape sequence
(max of 4, including the '0'). initially, s points to the '0'
following the backslash.
*/
int octal_esc(char *s,int *len)
{
int value = 0;
for (*len = 1, ++s; *len < 4 && isOctalDigit(*s); ++(*len), ++s)
value = (value * 8) + octal2Bin(*s);
return(value);
}
/*
interpret a hex escape (\xnn) and return the value of the
expression. also returns the length of the escape sequence
(max of 3, including the 'x'). initially, s points to the 'x'
following the backslash.
*/
int hex_esc(char *s,int *len)
{
int value = 0;
for (*len = 1, ++s; *len < 3 && isxdigit(*s); ++(*len), ++s)
value = (value * 16) + hex2Bin(*s);
if (*len == 1) /* was an invalid hex escape */
return((int) 'x'); /* treat it as "\x" */
return(value);
}
int char_esc(int c)
{
switch (c) {
case 'a': /* alert (bell) */
return(7);
/* break; */
case 'b': /* backspace */
return(8);
/* break; */
case 'f': /* form feed */
return(12);
/* break; */
case 'n': /* line feed */
return(10);
/* break; */
case 'r': /* carriage return */
return(13);
/* break; */
case 't': /* tab */
return(9);
/* break; */
case 'v': /* vertical tab */
return(11);
/* break; */
default: /* anything else */
break;
}
return(c);
}