#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdarg.h>#include <ctype.h>#include <limits.h>
Go to the source code of this file.
Classes | |
| struct | xprintf_struct |
Defines | |
| #define | va_copy(dst, src) memcpy (&dst, &src, sizeof(va_list)) |
| #define | ALLOC_CHUNK 2048 |
| #define | ALLOC_SECURITY_MARGIN 1024 |
| #define | SRCTXT (s->src_string) |
| #define | DESTTXT (s->dest_string) |
| #define | INCOHERENT() do {SRCTXT=initial_ptr; if (1) return 0;} while (0) |
| #define | INCOHERENT_TEST() do {if(*SRCTXT==0) INCOHERENT();} while (0) |
Functions | |
| static int | realloc_buff (xprintf_struct *s, size_t len) |
| static int | usual_char (xprintf_struct *s) |
| static int | print_it (xprintf_struct *s, size_t approx_len, const char *format_string,...) |
| static int | type_s (xprintf_struct *s, int width, int prec, const char *format_string, const char *arg_string) |
| static int | getint (const char **string) |
| static int | dispatch (xprintf_struct *s) |
| static int | core (xprintf_struct *s) |
| int | _xn_nprintf (int maxlen, const char *format_string,...) |
| int | _xn_vnprintf (int maxlen, const char *format_string, va_list vargs) |
| int | _xn_snprintf (char *dest_string, int maxlen, const char *format_string,...) |
| int | _xn_vsnprintf (char *dest_string, int maxlen, const char *format_string, va_list vargs) |
| int | _xn_fnprintf (FILE *file, int maxlen, const char *format_string,...) |
| int | _xn_vfnprintf (FILE *file, int maxlen, const char *format_string, va_list vargs) |
| int | _xn_asprintf (char **ptr, const char *format_string,...) |
| int | _xn_vasprintf (char **ptr, const char *format_string, va_list vargs) |
| int | _xn_asnprintf (char **ptr, int maxlen, const char *format_string,...) |
| int | _xn_vasnprintf (char **ptr, int maxlen, const char *format_string, va_list vargs) |
This file contains an implementation of xnprintf. See the original copyright notice below.
Definition in file xnprintf.c.
| #define ALLOC_CHUNK 2048 |
Definition at line 182 of file xnprintf.c.
| #define ALLOC_SECURITY_MARGIN 1024 |
Definition at line 183 of file xnprintf.c.
| #define DESTTXT (s->dest_string) |
| #define INCOHERENT | ( | ) | do {SRCTXT=initial_ptr; if (1) return 0;} while (0) |
| #define INCOHERENT_TEST | ( | ) | do {if(*SRCTXT==0) INCOHERENT();} while (0) |
| #define SRCTXT (s->src_string) |
| #define va_copy | ( | dst, | |||
| src | ) | memcpy (&dst, &src, sizeof(va_list)) |
Definition at line 169 of file xnprintf.c.
| int _xn_asnprintf | ( | char ** | ptr, | |
| int | maxlen, | |||
| const char * | format_string, | |||
| ... | ||||
| ) |
Definition at line 1012 of file xnprintf.c.
{
xprintf_struct s;
va_list vargs;
int retval;
va_start( vargs, format_string );
s.src_string = format_string;
/* s.vargs = vargs; */
va_copy(s.vargs, vargs);
s.flavour = 'a';
s.maxlen = (size_t)maxlen;
retval = core( &s );
va_end( vargs );
if ( retval != EOF )
{
*ptr = NULL;
return EOF;
}
*ptr = s.buffer_base;
return retval;
}

| int _xn_asprintf | ( | char ** | ptr, | |
| const char * | format_string, | |||
| ... | ||||
| ) |
Definition at line 951 of file xnprintf.c.
{
xprintf_struct s;
va_list vargs;
int retval;
va_start( vargs, format_string );
s.src_string = format_string;
/* s.vargs = vargs; */
va_copy(s.vargs, vargs);
s.flavour = 'a';
s.maxlen = (size_t)INT_MAX;
retval = core( &s );
va_end( vargs );
if ( retval != EOF )
{
*ptr = NULL;
return EOF;
}
*ptr = s.buffer_base;
return retval;
}

| int _xn_fnprintf | ( | FILE * | file, | |
| int | maxlen, | |||
| const char * | format_string, | |||
| ... | ||||
| ) |
Definition at line 905 of file xnprintf.c.
{
xprintf_struct s;
va_list vargs;
int retval;
va_start( vargs, format_string );
s.src_string = format_string;
s.maxlen = (size_t)maxlen;
/* s.vargs = vargs; */
va_copy(s.vargs, vargs);
s.fprintf_file = file;
s.flavour = 'f';
retval = core( &s );
va_end( vargs );
return retval;
}

| int _xn_nprintf | ( | int | maxlen, | |
| const char * | format_string, | |||
| ... | ||||
| ) |
Definition at line 798 of file xnprintf.c.
{
xprintf_struct s;
va_list vargs;
int retval;
va_start( vargs, format_string );
s.src_string = format_string;
s.maxlen = (size_t)maxlen;
/* s.vargs = vargs; */
va_copy(s.vargs, vargs);
s.flavour = 'p';
retval = core( &s );
va_end( vargs );
return retval;
}

| int _xn_snprintf | ( | char * | dest_string, | |
| int | maxlen, | |||
| const char * | format_string, | |||
| ... | ||||
| ) |
Definition at line 840 of file xnprintf.c.
{
xprintf_struct s;
va_list vargs;
int retval;
if ( dest_string == NULL )
return EOF;
va_start( vargs, format_string );
/* memset to avoid purify UMR errors */
memset(&s, 0, sizeof(s));
s.src_string = format_string;
s.maxlen = (size_t)maxlen;
/* s.vargs = vargs; */
va_copy(s.vargs, vargs);
s.sprintf_string = dest_string;
s.flavour = 's';
retval = core( &s );
va_end( vargs );
if ( retval == EOF )
if ( maxlen > 0 )
dest_string[0] = 0;
return retval;
}

| int _xn_vasnprintf | ( | char ** | ptr, | |
| int | maxlen, | |||
| const char * | format_string, | |||
| va_list | vargs | |||
| ) |
Definition at line 1044 of file xnprintf.c.
{
xprintf_struct s;
int retval;
s.src_string = format_string;
/* s.vargs = vargs; */
va_copy(s.vargs, vargs);
s.flavour = 'a';
s.maxlen = (size_t)maxlen;
retval = core( &s );
if ( retval == EOF )
{
*ptr = NULL;
return EOF;
}
*ptr = s.buffer_base;
return retval;
}

| int _xn_vasprintf | ( | char ** | ptr, | |
| const char * | format_string, | |||
| va_list | vargs | |||
| ) |
Definition at line 982 of file xnprintf.c.
{
xprintf_struct s;
int retval;
/* to shut up purify */
memset(&s, 0x0, sizeof(s));
s.src_string = format_string;
/* s.vargs = vargs; */
va_copy(s.vargs, vargs);
s.flavour = 'a';
s.maxlen = (size_t)INT_MAX;
retval = core( &s );
if ( retval == EOF )
{
*ptr = NULL;
return EOF;
}
*ptr = s.buffer_base;
return retval;
}

| int _xn_vfnprintf | ( | FILE * | file, | |
| int | maxlen, | |||
| const char * | format_string, | |||
| va_list | vargs | |||
| ) |
Definition at line 931 of file xnprintf.c.
{
xprintf_struct s;
s.src_string = format_string;
s.maxlen = (size_t)maxlen;
/* s.vargs = vargs; */
va_copy(s.vargs, vargs);
s.fprintf_file = file;
s.flavour = 'f';
return core( &s );
}

| int _xn_vnprintf | ( | int | maxlen, | |
| const char * | format_string, | |||
| va_list | vargs | |||
| ) |
Definition at line 822 of file xnprintf.c.
{
xprintf_struct s;
s.src_string = format_string;
s.maxlen = (size_t)maxlen;
/* s.vargs = vargs; */
va_copy(s.vargs, vargs);
s.flavour = 'p';
return core( &s );
}

| int _xn_vsnprintf | ( | char * | dest_string, | |
| int | maxlen, | |||
| const char * | format_string, | |||
| va_list | vargs | |||
| ) |
Definition at line 876 of file xnprintf.c.
{
xprintf_struct s;
int retval;
if ( dest_string == NULL )
return EOF;
s.src_string = format_string;
s.maxlen = (size_t)maxlen;
/* s.vargs = vargs; */
va_copy(s.vargs, vargs);
s.sprintf_string = dest_string;
s.flavour = 's';
retval = core( &s );
if ( retval == EOF )
if ( maxlen > 0 )
dest_string[0] = 0;
return retval;
}

| static int core | ( | xprintf_struct * | s | ) | [static] |
Definition at line 694 of file xnprintf.c.
{
size_t len, save_len;
char * dummy_base;
/* basic checks */
if ( (int)(s->maxlen) <= 0 ) /* 'int' to check against some convertion */
return EOF; /* error for example if value is (int)-10 */
s->maxlen--; /* because initial maxlen counts final 0 */
/* note: now 'maxlen' _can_ be zero */
if ( s->src_string == NULL )
s->src_string = "(null)";
/* struct init and memory allocation */
s->buffer_base = NULL;
s->buffer_len = 0;
s->real_len = 0;
s->pseudo_len = 0;
if ( realloc_buff(s,0) == EOF )
return EOF;
s->dest_string = s->buffer_base;
/* process source string */
for (;;)
{
/* up to end of source string */
if ( *(s->src_string) == 0 )
{
*(s->dest_string) = 0; /* final 0 */
len = s->real_len + 1;
break;
}
if ( dispatch(s) == EOF )
goto free_EOF;
/* up to end of dest string */
if ( s->real_len >= s->maxlen )
{
(s->buffer_base)[s->maxlen] = 0; /* final 0 */
len = s->maxlen + 1;
break;
}
}
/* for (v)asnprintf */
dummy_base = s->buffer_base;
save_len = 0; /* just to avoid a compiler warning */
/*---*/
switch ( s->flavour )
{
/* (v)snprintf() */
case 's': memcpy( s->sprintf_string, s->buffer_base, len );
break;
/* (v)nprintf() */
case 'p': if ( puts(s->buffer_base) == EOF )
goto free_EOF;
break;
/* (v)fnprintf() */
case 'f' : if ( fwrite(s->buffer_base,1,len-1,s->fprintf_file) != len-1 ) /* -1 because we don't write the final zero */
goto free_EOF;
break;
/* (v)as(n)printf() */
default : dummy_base = (s->buffer_base) + (s->real_len);
save_len = s->real_len;
}
/*
* process the remaining of source string to compute 'pseudo_len'. We
* overwrite again and again, starting at 'dummy_base' because we don't
* need the text, only char count.
*/
while( *(s->src_string) != 0 ) /* up to end of source string */
{
s->real_len = 0;
s->dest_string = dummy_base;
if ( dispatch(s) == EOF )
goto free_EOF;
}
if ( s->flavour == 'a' ) /* (v)as(n)printf reduce buffer size */
{
s->buffer_base = (char *)realloc( (void *)(s->buffer_base), save_len+1 );
if ( s->buffer_base == NULL )
return EOF; /* should rarely happen because we shrink the buffer */
return s->pseudo_len;
}
free( s->buffer_base );
return s->pseudo_len;
free_EOF:
if ( s->buffer_base != NULL )
free( s->buffer_base );
return EOF;
}


| static int dispatch | ( | xprintf_struct * | s | ) | [static] |
Definition at line 407 of file xnprintf.c.
{
const char * initial_ptr;
char format_string[24]; /* max length may be something like "% +-#032768.32768Ld" */
char * format_ptr;
int flag_plus, flag_minus, flag_space, flag_sharp, flag_zero;
int width;
int prec;
int modifier;
char type;
int approx_width;
/* most of those variables are here to rewrite the format string */
#define SRCTXT (s->src_string)
#define DESTTXT (s->dest_string)
/* incoherent format string. Characters after the '%' will be printed with the next call */
#define INCOHERENT() do {SRCTXT=initial_ptr; if (1) return 0;} while (0) /* do/while to avoid */
#define INCOHERENT_TEST() do {if(*SRCTXT==0) INCOHERENT();} while (0) /* a null statement */
/* 'normal' text */
if ( *SRCTXT != '%' )
return usual_char( s );
/* we then have a '%' */
SRCTXT++;
/* don't check for end-of-string ; this is done later */
/* '%%' escape sequence */
if ( *SRCTXT == '%' )
{
if ( realloc_buff(s,1) == EOF ) /* because we can have "%%%%%%%%..." */
return EOF;
*DESTTXT = '%';
DESTTXT++;
SRCTXT++;
(s->real_len)++;
(s->pseudo_len)++;
return 0;
}
/* '%' managing */
initial_ptr = SRCTXT; /* save current pointer in case of incorrect */
/* 'decoding'. Points just after the '%' so the '%' */
/* won't be printed in any case, as required. */
/* flag */
flag_plus = 0; flag_minus = 0; flag_space = 0;
flag_sharp = 0; flag_zero = 0;
for ( /*none*/; /*none*/; SRCTXT++ )
{
if ( *SRCTXT == ' ' ) { flag_space = 1; continue; }
if ( *SRCTXT == '+' ) { flag_plus = 1; continue; }
if ( *SRCTXT == '-' ) { flag_minus = 1; continue; }
if ( *SRCTXT == '#' ) { flag_sharp = 1; continue; }
if ( *SRCTXT == '0' ) { flag_zero = 1; continue; }
break;
}
INCOHERENT_TEST(); /* here is the first test for end of string */
/* width */
if ( *SRCTXT == '*' ) /* width given by next argument */
{
SRCTXT++;
width = va_arg( s->vargs, int );
if ( (unsigned int)width > 0x3fffU ) /* 'unsigned' to check against negative values too */
width = 0x3fff;
}
else if ( isdigit(*SRCTXT) != 0 ) /* width given as ASCII number */
{
width = getint( &SRCTXT );
}
else
width = -1; /* no width specified */
INCOHERENT_TEST();
/* .prec */
if ( *SRCTXT == '.' )
{
SRCTXT++;
if ( *SRCTXT == '*' ) /* .prec given by next argument */
{
prec = va_arg( s->vargs, int );
if ( (unsigned int)prec >= 0x3fffU ) /* 'unsigned' to check against negative values too */
prec = 0x3fff;
}
else
{ /* .prec given as ASCII number */
if ( isdigit(*SRCTXT) == 0 )
INCOHERENT();
prec = getint( &SRCTXT );
}
INCOHERENT_TEST();
}
else
prec = -1; /* no .prec specified */
/* modifier */
if ( *SRCTXT == 'L' || *SRCTXT == 'h' || *SRCTXT == 'l'
#ifdef __DOS_16BIT__
|| *SRCTXT == 'F' || *SRCTXT == 'N'
#endif
)
{
modifier = *SRCTXT;
SRCTXT++;
if ( modifier=='l' && *SRCTXT=='l' )
{
SRCTXT++;
modifier = 'L'; /* 'll' == 'L' long long == long double */
} /* only for compatibility ; not portable */
INCOHERENT_TEST();
}
else
{
modifier = -1; /* no modifier specified */
}
/* type */
type = *SRCTXT;
if ( strchr("diouxXfegEGcspn",type) == NULL )
INCOHERENT(); /* unknown type */
SRCTXT++;
/* rewrite format-string */
format_string[0] = '%';
format_ptr = &(format_string[1]);
if ( flag_plus != 0 ) { *format_ptr = '+'; format_ptr++; }
if ( flag_minus != 0 ) { *format_ptr = '-'; format_ptr++; }
if ( flag_space != 0 ) { *format_ptr = ' '; format_ptr++; }
if ( flag_sharp != 0 ) { *format_ptr = '#'; format_ptr++; }
if ( flag_zero != 0 ) { *format_ptr = '0'; format_ptr++; } /* '0' *must* be the last one */
if ( width != -1 )
{
sprintf( format_ptr, "%i", width ); /* itoa() may be better but not ANSI nor POSIX */
format_ptr += strlen( format_ptr );
}
if ( prec != -1 )
{
*format_ptr = '.';
format_ptr++;
sprintf( format_ptr, "%i", prec );
format_ptr += strlen( format_ptr );
}
if ( modifier != -1 )
{
*format_ptr = modifier;
format_ptr++;
}
*format_ptr = type;
format_ptr++;
*format_ptr = 0;
/* vague approximation of minimal length if width or prec are specified */
approx_width = width + prec;
if ( approx_width < 0 ) /* because width == -1 and/or prec == -1 */
approx_width = 0;
switch ( type )
{
/* int */
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X': switch ( modifier )
{
case -1 : return print_it( s, approx_width, format_string, va_arg(s->vargs,int) );
case 'l': return print_it( s, approx_width, format_string, va_arg(s->vargs,long int) );
case 'h': return print_it( s, approx_width, format_string, va_arg(s->vargs, /*short*/ int) );
default : INCOHERENT(); /* 'int' instead of 'short int' because */
} /* of default promotion is 'int' */
/* char */
case 'c': if ( modifier != -1 )
if ( print_it(s,approx_width,format_string,va_arg(s->vargs,int)) != EOF )
INCOHERENT(); /* note: because of default promotion */
/* 'int' is used instead of 'char' */
/* math */
case 'e':
case 'f':
case 'g':
case 'E':
case 'G': switch ( modifier )
{
case -1 : /* because of default promotion, no modifier means 'l' */
case 'l': return print_it( s, approx_width, format_string, va_arg(s->vargs,double) );
case 'L': return print_it( s, approx_width, format_string, va_arg(s->vargs,long double) );
default: INCOHERENT();
}
#ifdef __DOS_16BIT__
/* string */
case 's': switch ( modifier )
{
case -1 : return type_s( s, width, prec, format_string, (const char far*)va_arg(s->vargs,const char*), modifier );
case 'N': return type_s( s, width, prec, format_string, (const char far*)va_arg(s->vargs,const char near*), modifier );
case 'F': return type_s( s, width, prec, format_string, (const char far*)va_arg(s->vargs,const char far*), modifier );
default : INCOHERENT();
}
/* pointer */
case 'p': switch ( modifier )
{
case -1 : return print_it( s, approx_width, format_string, va_arg(s->vargs,void*) );
case 'N': return print_it( s, approx_width, format_string, va_arg(s->vargs,void near*) );
case 'F': return print_it( s, approx_width, format_string, va_arg(s->vargs,void far*) );
default: INCOHERENT();
}
/* store */
case 'n': {
int far * p;
switch ( modifier )
{
case -1 : p = (int far*)va_arg( s->vargs, int* );
break;
case 'N': p = (int far*)va_arg( s->vargs, int near* );
break;
case 'F': p = (int far*)va_arg( s->vargs, int far* );
break;
default : INCOHERENT();
}
if ( p != NULL )
{
*p = s->pseudo_len;
return 0;
}
return EOF;
}
#else /* end of ms-dos/16-bit section */
/* string */
case 's': return type_s( s, width, prec, format_string, va_arg(s->vargs,const char*) );
/* pointer */
case 'p': if ( modifier == -1 )
return print_it( s, approx_width, format_string, va_arg(s->vargs,void *) );
INCOHERENT();
/* store */
case 'n': if ( modifier == -1 )
{
int * p;
p = va_arg( s->vargs, int * );
if ( p != NULL )
{
*p = s->pseudo_len;
return 0;
}
return EOF;
}
INCOHERENT();
#endif
} /* switch */
INCOHERENT(); /* unknown type */
#undef INCOHERENT
#undef INCOHERENT_TEST
#undef SRCTXT
#undef DESTTXT
}


| static int getint | ( | const char ** | string | ) | [static] |
Definition at line 374 of file xnprintf.c.
{
int i;
i = 0;
while ( isdigit(**string) != 0 )
{
i = (i*10) + (**string-'0');
(*string)++;
}
if ( i<0 || i>32767 )
i = 32767; /* if we have i==-10 this is not because the number is */
/* negative ; This is because the number is biiiig */
return i;
}

| static int print_it | ( | xprintf_struct * | s, | |
| size_t | approx_len, | |||
| const char * | format_string, | |||
| ... | ||||
| ) | [static] |
Definition at line 276 of file xnprintf.c.
{
va_list varg;
int vsprintf_len;
size_t len;
if ( realloc_buff(s,approx_len) == EOF )
return EOF;
va_start( varg, format_string );
vsprintf_len = vsprintf( s->dest_string, format_string, varg );
va_end( varg );
if ( (s->buffer_base)[(s->buffer_len)-1] != 1 ) /* check for overflow */
{
fprintf( stderr, "ERROR in xnprintf library: overflow" );
exit( -1 ); /* ... sorry ... what else to do ? */
}
if ( vsprintf_len == EOF ) /* must be done *after* overflow-check */
return EOF;
s->pseudo_len += vsprintf_len;
len = strlen( s->dest_string );
s->real_len += len;
s->dest_string += len;
return 0;
}


| static int realloc_buff | ( | xprintf_struct * | s, | |
| size_t | len | |||
| ) | [static] |
Definition at line 216 of file xnprintf.c.
{
char * ptr;
if ( len + ALLOC_SECURITY_MARGIN + s->real_len > s->buffer_len )
{
len += s->real_len + ALLOC_CHUNK;
ptr = (char *)realloc( (void *)(s->buffer_base), len );
if ( ptr == NULL )
{
s->buffer_base = NULL;
return EOF;
}
s->dest_string = ptr + (size_t)( s->dest_string - s->buffer_base );
s->buffer_base = ptr;
s->buffer_len = len;
(s->buffer_base)[(s->buffer_len)-1] = 1; /* overflow marquer */
}
return 0;
}

| static int type_s | ( | xprintf_struct * | s, | |
| int | width, | |||
| int | prec, | |||
| const char * | format_string, | |||
| const char * | arg_string | |||
| ) | [static] |
Definition at line 324 of file xnprintf.c.
{
size_t string_len;
if ( arg_string == NULL )
return print_it( s, 6, "(null)", 0 );
/* hand-made strlen() whitch stops when 'prec' is reached. */
/* if 'prec' is -1 then it is never reached. */
string_len = 0;
while ( arg_string[string_len]!=0 && (unsigned int)prec!=string_len )
string_len++;
if ( width != -1 )
if ( string_len < (unsigned int)width )
string_len = (unsigned int)width;
#ifdef __DOS_16BIT__
switch( modifier )
{
case 'N': return print_it( s, string_len, format_string, (const char near*)arg_string );
case 'F': return print_it( s, string_len, format_string, (const char far*)arg_string );
}
/* modifier == -1 */
return print_it( s, string_len, format_string, (const char*)arg_string );
#else
return print_it( s, string_len, format_string, arg_string );
#endif
}


| static int usual_char | ( | xprintf_struct * | s | ) | [static] |
Definition at line 249 of file xnprintf.c.
{
size_t len;
len = strcspn( s->src_string, "%" ); /* reachs the next '%' or end of input string */
/* note: 'len' is never 0 because the presence of '%' */
/* or end-of-line is checked in the calling function */
if ( realloc_buff(s,len) == EOF )
return EOF;
memcpy( s->dest_string, s->src_string, len );
s->src_string += len;
s->dest_string += len;
s->real_len += len;
s->pseudo_len += len;
return 0;
}


1.6.3-20100507