Diff for /embedaddon/rsync/lib/snprintf.c between versions 1.1 and 1.1.1.2

version 1.1, 2012/02/17 15:09:30 version 1.1.1.2, 2013/10/14 07:51:14
Line 37 Line 37
  *    which showed it, so that's been fixed.  Also, formated the code   *    which showed it, so that's been fixed.  Also, formated the code
  *    to mutt conventions, and removed dead code left over from the   *    to mutt conventions, and removed dead code left over from the
  *    original.  Also, there is now a builtin-test, just compile with:   *    original.  Also, there is now a builtin-test, just compile with:
 *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm *           gcc -I.. -DTEST_SNPRINTF -o snprintf snprintf.c -lm
  *    and run snprintf for results.   *    and run snprintf for results.
  *    * 
  *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i   *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
Line 89 Line 89
  *   *
  *    Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even   *    Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even
  *    if the C library has some snprintf functions already.   *    if the C library has some snprintf functions already.
    *
    * Darren Tucker (dtucker@zip.com.au) 2005
    *    Fix bug allowing read overruns of the source string with "%.*s"
    *    Usually harmless unless the read runs outside the process' allocation
    *    (eg if your malloc does guard pages) in which case it will segfault.
    *    From OpenSSH.  Also added test for same.
    *
    * Simo Sorce (idra@samba.org) Jan 2006
    * 
    *    Add support for position independent parameters 
    *    fix fmtstr now it conforms to sprintf wrt min.max
    *
  **************************************************************/   **************************************************************/
   
 #ifndef NO_CONFIG_H  
 #include "config.h"  #include "config.h"
 #else  
 #define NULL 0  
 #endif   
   
 #ifdef TEST_SNPRINTF /* need math library headers for testing */  #ifdef TEST_SNPRINTF /* need math library headers for testing */
   
Line 133 Line 141
  void dummy_snprintf(void) {}    void dummy_snprintf(void) {} 
 #endif /* HAVE_SNPRINTF, etc */  #endif /* HAVE_SNPRINTF, etc */
   
   #ifdef STDC_HEADERS
   #include <stddef.h>
   #endif
   
 #ifdef HAVE_LONG_DOUBLE  #ifdef HAVE_LONG_DOUBLE
 #define LDOUBLE long double  #define LDOUBLE long double
 #else  #else
 #define LDOUBLE double  #define LDOUBLE double
 #endif  #endif
   
#if SIZEOF_LONG_LONG#if !defined HAVE_LONG_LONG && SIZEOF_LONG_LONG
 #define HAVE_LONG_LONG 1
 #endif
 #ifdef HAVE_LONG_LONG
 #define LLONG long long  #define LLONG long long
 #else  #else
 #define LLONG long  #define LLONG long
Line 155 Line 170
 #define VA_COPY(dest, src) (dest) = (src)  #define VA_COPY(dest, src) (dest) = (src)
 #endif  #endif
 #endif  #endif
   #endif
   
   /* yes this really must be a ||. Don't muck with this (tridge) */
   #if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
   
 /*  /*
  * dopr(): poor man's version of doprintf   * dopr(): poor man's version of doprintf
  */   */
Line 180 Line 199
 #define DP_F_UNSIGNED   (1 << 6)  #define DP_F_UNSIGNED   (1 << 6)
   
 /* Conversion Flags */  /* Conversion Flags */
#define DP_C_SHORT   1#define DP_C_CHAR    1
#define DP_C_LONG    2#define DP_C_SHORT   2
#define DP_C_LDOUBLE 3#define DP_C_LONG    3
#define DP_C_LLONG   4#define DP_C_LDOUBLE 4
 #define DP_C_LLONG   5
 #define DP_C_SIZET   6
   
   /* Chunk types */
   #define CNK_FMT_STR 0
   #define CNK_INT     1
   #define CNK_OCTAL   2
   #define CNK_UINT    3
   #define CNK_HEX     4
   #define CNK_FLOAT   5
   #define CNK_CHAR    6
   #define CNK_STRING  7
   #define CNK_PTR     8
   #define CNK_NUM     9
   #define CNK_PRCNT   10
   
 #define char_to_int(p) ((p)- '0')  #define char_to_int(p) ((p)- '0')
 #ifndef MAX  #ifndef MAX
 #define MAX(p,q) (((p) >= (q)) ? (p) : (q))  #define MAX(p,q) (((p) >= (q)) ? (p) : (q))
 #endif  #endif
   
/* yes this really must be a ||. Don't muck with this (tridge) */struct pr_chunk {
#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)        int type; /* chunk type */
         int num; /* parameter number */
         int min; 
         int max;
         int flags;
         int cflags;
         int start;
         int len;
         LLONG value;
         LDOUBLE fvalue;
         char *strvalue;
         void *pnum;
         struct pr_chunk *min_star;
         struct pr_chunk *max_star;
         struct pr_chunk *next;
 };
   
static size_t dopr(char *buffer, size_t maxlen, const char *format, struct pr_chunk_x {
         struct pr_chunk **chunks;
         int num;
 };
 
 static int dopr(char *buffer, size_t maxlen, const char *format, 
                    va_list args_in);                     va_list args_in);
 static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,  static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
                     char *value, int flags, int min, int max);                      char *value, int flags, int min, int max);
 static void fmtint(char *buffer, size_t *currlen, size_t maxlen,  static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
                    long value, int base, int min, int max, int flags);                    LLONG value, int base, int min, int max, int flags);
 static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,  static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
                    LDOUBLE fvalue, int min, int max, int flags);                     LDOUBLE fvalue, int min, int max, int flags);
 static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);  static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
   static struct pr_chunk *new_chunk(void);
   static int add_cnk_list_entry(struct pr_chunk_x **list,
                                   int max_num, struct pr_chunk *chunk);
   
static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)static int dopr(char *buffer, size_t maxlen, const char *format, va_list args_in)
 {  {
         char ch;          char ch;
         LLONG value;  
         LDOUBLE fvalue;  
         char *strvalue;  
         int min;  
         int max;  
         int state;          int state;
        int flags;        int pflag;
        int cflags;        int pnum;
         int pfirst;
         size_t currlen;          size_t currlen;
         va_list args;          va_list args;
           const char *base;
           struct pr_chunk *chunks = NULL;
           struct pr_chunk *cnk = NULL;
           struct pr_chunk_x *clist = NULL;
           int max_pos;
           int ret = -1;
   
         VA_COPY(args, args_in);          VA_COPY(args, args_in);
        
         state = DP_S_DEFAULT;          state = DP_S_DEFAULT;
        currlen = flags = cflags = min = 0;        pfirst = 1;
        max = -1;        pflag = 0;
         pnum = 0;
 
         max_pos = 0;
         base = format;
         ch = *format++;          ch = *format++;
                   
           /* retrieve the string structure as chunks */
         while (state != DP_S_DONE) {          while (state != DP_S_DONE) {
                 if (ch == '\0')                   if (ch == '\0') 
                         state = DP_S_DONE;                          state = DP_S_DONE;
   
                 switch(state) {                  switch(state) {
                 case DP_S_DEFAULT:                  case DP_S_DEFAULT:
                        if (ch == '%')                         
                         if (cnk) {
                                 cnk->next = new_chunk();
                                 cnk = cnk->next;
                         } else {
                                 cnk = new_chunk();
                         }
                         if (!cnk) goto done;
                         if (!chunks) chunks = cnk;
                         
                         if (ch == '%') {
                                 state = DP_S_FLAGS;                                  state = DP_S_FLAGS;
                        else                                 ch = *format++;
                                dopr_outch (buffer, &currlen, maxlen, ch);                        } else {
                        ch = *format++;                                cnk->type = CNK_FMT_STR;
                                 cnk->start = format - base -1;
                                 while ((ch != '\0') && (ch != '%')) ch = *format++;
                                 cnk->len = format - base - cnk->start -1;
                         }
                         break;                          break;
                 case DP_S_FLAGS:                  case DP_S_FLAGS:
                         switch (ch) {                          switch (ch) {
                         case '-':                          case '-':
                                flags |= DP_F_MINUS;                                cnk->flags |= DP_F_MINUS;
                                 ch = *format++;                                  ch = *format++;
                                 break;                                  break;
                         case '+':                          case '+':
                                flags |= DP_F_PLUS;                                cnk->flags |= DP_F_PLUS;
                                 ch = *format++;                                  ch = *format++;
                                 break;                                  break;
                         case ' ':                          case ' ':
                                flags |= DP_F_SPACE;                                cnk->flags |= DP_F_SPACE;
                                 ch = *format++;                                  ch = *format++;
                                 break;                                  break;
                         case '#':                          case '#':
                                flags |= DP_F_NUM;                                cnk->flags |= DP_F_NUM;
                                 ch = *format++;                                  ch = *format++;
                                 break;                                  break;
                         case '0':                          case '0':
                                flags |= DP_F_ZERO;                                cnk->flags |= DP_F_ZERO;
                                 ch = *format++;                                  ch = *format++;
                                 break;                                  break;
                           case 'I':
                                   /* internationalization not supported yet */
                                   ch = *format++;
                                   break;
                         default:                          default:
                                 state = DP_S_MIN;                                  state = DP_S_MIN;
                                 break;                                  break;
Line 265  static size_t dopr(char *buffer, size_t maxlen, const  Line 347  static size_t dopr(char *buffer, size_t maxlen, const 
                         break;                          break;
                 case DP_S_MIN:                  case DP_S_MIN:
                         if (isdigit((unsigned char)ch)) {                          if (isdigit((unsigned char)ch)) {
                                min = 10*min + char_to_int (ch);                                cnk->min = 10 * cnk->min + char_to_int (ch);
                                 ch = *format++;                                  ch = *format++;
                           } else if (ch == '$') {
                                   if (!pfirst && !pflag) {
                                           /* parameters must be all positioned or none */
                                           goto done;
                                   }
                                   if (pfirst) {
                                           pfirst = 0;
                                           pflag = 1;
                                   }
                                   if (cnk->min == 0) /* what ?? */
                                           goto done;
                                   cnk->num = cnk->min;
                                   cnk->min = 0;
                                   ch = *format++;
                         } else if (ch == '*') {                          } else if (ch == '*') {
                                min = va_arg (args, int);                                if (pfirst) pfirst = 0;
                                 cnk->min_star = new_chunk();
                                 if (!cnk->min_star) /* out of memory :-( */
                                         goto done;
                                 cnk->min_star->type = CNK_INT;
                                 if (pflag) {
                                         int num;
                                         ch = *format++;
                                         if (!isdigit((unsigned char)ch)) {
                                                 /* parameters must be all positioned or none */
                                                 goto done;
                                         }
                                         for (num = 0; isdigit((unsigned char)ch); ch = *format++) {
                                                 num = 10 * num + char_to_int(ch);
                                         }
                                         cnk->min_star->num = num;
                                         if (ch != '$') /* what ?? */
                                                 goto done;
                                 } else {
                                         cnk->min_star->num = ++pnum;
                                 }
                                 max_pos = add_cnk_list_entry(&clist, max_pos, cnk->min_star);
                                 if (max_pos == 0) /* out of memory :-( */
                                         goto done;
                                 ch = *format++;                                  ch = *format++;
                                 state = DP_S_DOT;                                  state = DP_S_DOT;
                         } else {                          } else {
                                   if (pfirst) pfirst = 0;
                                 state = DP_S_DOT;                                  state = DP_S_DOT;
                         }                          }
                         break;                          break;
Line 285  static size_t dopr(char *buffer, size_t maxlen, const  Line 405  static size_t dopr(char *buffer, size_t maxlen, const 
                         break;                          break;
                 case DP_S_MAX:                  case DP_S_MAX:
                         if (isdigit((unsigned char)ch)) {                          if (isdigit((unsigned char)ch)) {
                                if (max < 0)                                if (cnk->max < 0)
                                        max = 0;                                        cnk->max = 0;
                                max = 10*max + char_to_int (ch);                                cnk->max = 10 * cnk->max + char_to_int (ch);
                                 ch = *format++;                                  ch = *format++;
                           } else if (ch == '$') {
                                   if (!pfirst && !pflag) {
                                           /* parameters must be all positioned or none */
                                           goto done;
                                   }
                                   if (cnk->max <= 0) /* what ?? */
                                           goto done;
                                   cnk->num = cnk->max;
                                   cnk->max = -1;
                                   ch = *format++;
                         } else if (ch == '*') {                          } else if (ch == '*') {
                                max = va_arg (args, int);                                cnk->max_star = new_chunk();
                                 if (!cnk->max_star) /* out of memory :-( */
                                         goto done;
                                 cnk->max_star->type = CNK_INT;
                                 if (pflag) {
                                         int num;
                                         ch = *format++;
                                         if (!isdigit((unsigned char)ch)) {
                                                 /* parameters must be all positioned or none */
                                                 goto done;
                                         }
                                         for (num = 0; isdigit((unsigned char)ch); ch = *format++) {
                                                 num = 10 * num + char_to_int(ch);
                                         }
                                         cnk->max_star->num = num;
                                         if (ch != '$') /* what ?? */
                                                 goto done;
                                 } else {
                                         cnk->max_star->num = ++pnum;
                                 }
                                 max_pos = add_cnk_list_entry(&clist, max_pos, cnk->max_star);
                                 if (max_pos == 0) /* out of memory :-( */
                                         goto done;
 
                                 ch = *format++;                                  ch = *format++;
                                 state = DP_S_MOD;                                  state = DP_S_MOD;
                         } else {                          } else {
Line 300  static size_t dopr(char *buffer, size_t maxlen, const  Line 453  static size_t dopr(char *buffer, size_t maxlen, const 
                 case DP_S_MOD:                  case DP_S_MOD:
                         switch (ch) {                          switch (ch) {
                         case 'h':                          case 'h':
                                cflags = DP_C_SHORT;                                cnk->cflags = DP_C_SHORT;
                                 ch = *format++;                                  ch = *format++;
                                   if (ch == 'h') {
                                           cnk->cflags = DP_C_CHAR;
                                           ch = *format++;
                                   }
                                 break;                                  break;
                         case 'l':                          case 'l':
                                cflags = DP_C_LONG;                                cnk->cflags = DP_C_LONG;
                                 ch = *format++;                                  ch = *format++;
                                 if (ch == 'l') {        /* It's a long long */                                  if (ch == 'l') {        /* It's a long long */
                                        cflags = DP_C_LLONG;                                        cnk->cflags = DP_C_LLONG;
                                         ch = *format++;                                          ch = *format++;
                                 }                                  }
                                 break;                                  break;
                         case 'L':                          case 'L':
                                cflags = DP_C_LDOUBLE;                                cnk->cflags = DP_C_LDOUBLE;
                                 ch = *format++;                                  ch = *format++;
                                 break;                                  break;
                           case 'z':
                                   cnk->cflags = DP_C_SIZET;
                                   ch = *format++;
                                   break;
                         default:                          default:
                                 break;                                  break;
                         }                          }
                         state = DP_S_CONV;                          state = DP_S_CONV;
                         break;                          break;
                 case DP_S_CONV:                  case DP_S_CONV:
                           if (cnk->num == 0) cnk->num = ++pnum;
                           max_pos = add_cnk_list_entry(&clist, max_pos, cnk);
                           if (max_pos == 0) /* out of memory :-( */
                                   goto done;
                           
                         switch (ch) {                          switch (ch) {
                         case 'd':                          case 'd':
                         case 'i':                          case 'i':
                                if (cflags == DP_C_SHORT)                                 cnk->type = CNK_INT;
                                        value = va_arg (args, int); 
                                else if (cflags == DP_C_LONG) 
                                        value = va_arg (args, long int); 
                                else if (cflags == DP_C_LLONG) 
                                        value = va_arg (args, LLONG); 
                                else 
                                        value = va_arg (args, int); 
                                fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); 
                                 break;                                  break;
                         case 'o':                          case 'o':
                                flags |= DP_F_UNSIGNED;                                cnk->type = CNK_OCTAL;
                                if (cflags == DP_C_SHORT)                                cnk->flags |= DP_F_UNSIGNED;
                                        value = va_arg (args, unsigned int); 
                                else if (cflags == DP_C_LONG) 
                                        value = (long)va_arg (args, unsigned long int); 
                                else if (cflags == DP_C_LLONG) 
                                        value = (long)va_arg (args, unsigned LLONG); 
                                else 
                                        value = (long)va_arg (args, unsigned int); 
                                fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); 
                                 break;                                  break;
                         case 'u':                          case 'u':
                                flags |= DP_F_UNSIGNED;                                cnk->type = CNK_UINT;
                                if (cflags == DP_C_SHORT)                                cnk->flags |= DP_F_UNSIGNED;
                                        value = va_arg (args, unsigned int); 
                                else if (cflags == DP_C_LONG) 
                                        value = (long)va_arg (args, unsigned long int); 
                                else if (cflags == DP_C_LLONG) 
                                        value = (LLONG)va_arg (args, unsigned LLONG); 
                                else 
                                        value = (long)va_arg (args, unsigned int); 
                                fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); 
                                 break;                                  break;
                         case 'X':                          case 'X':
                                flags |= DP_F_UP;                                cnk->flags |= DP_F_UP;
                         case 'x':                          case 'x':
                                flags |= DP_F_UNSIGNED;                                cnk->type = CNK_HEX;
                                if (cflags == DP_C_SHORT)                                cnk->flags |= DP_F_UNSIGNED;
                                        value = va_arg (args, unsigned int); 
                                else if (cflags == DP_C_LONG) 
                                        value = (long)va_arg (args, unsigned long int); 
                                else if (cflags == DP_C_LLONG) 
                                        value = (LLONG)va_arg (args, unsigned LLONG); 
                                else 
                                        value = (long)va_arg (args, unsigned int); 
                                fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); 
                                 break;                                  break;
                        case 'f':                        case 'A':
                                if (cflags == DP_C_LDOUBLE)                                /* hex float not supported yet */
                                        fvalue = va_arg (args, LDOUBLE); 
                                else 
                                        fvalue = va_arg (args, double); 
                                /* um, floating point? */ 
                                fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); 
                                break; 
                         case 'E':                          case 'E':
                                 flags |= DP_F_UP;  
                         case 'e':  
                                 if (cflags == DP_C_LDOUBLE)  
                                         fvalue = va_arg (args, LDOUBLE);  
                                 else  
                                         fvalue = va_arg (args, double);  
                                 fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);  
                                 break;  
                         case 'G':                          case 'G':
                                flags |= DP_F_UP;                        case 'F':
                                 cnk->flags |= DP_F_UP;
                         case 'a':
                                 /* hex float not supported yet */
                         case 'e':
                         case 'f':
                         case 'g':                          case 'g':
                                if (cflags == DP_C_LDOUBLE)                                cnk->type = CNK_FLOAT;
                                        fvalue = va_arg (args, LDOUBLE); 
                                else 
                                        fvalue = va_arg (args, double); 
                                fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); 
                                 break;                                  break;
                         case 'c':                          case 'c':
                                dopr_outch (buffer, &currlen, maxlen, va_arg (args, int));                                cnk->type = CNK_CHAR;
                                 break;                                  break;
                         case 's':                          case 's':
                                strvalue = va_arg (args, char *);                                cnk->type = CNK_STRING;
                                if (!strvalue) strvalue = "(NULL)"; 
                                if (max == -1) { 
                                        max = strlen(strvalue); 
                                } 
                                if (min > 0 && max >= 0 && min > max) max = min; 
                                fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); 
                                 break;                                  break;
                         case 'p':                          case 'p':
                                strvalue = va_arg (args, void *);                                cnk->type = CNK_PTR;
                                fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);                                cnk->flags |= DP_F_UNSIGNED;
                                 break;                                  break;
                         case 'n':                          case 'n':
                                if (cflags == DP_C_SHORT) {                                cnk->type = CNK_NUM;
                                        short int *num; 
                                        num = va_arg (args, short int *); 
                                        *num = currlen; 
                                } else if (cflags == DP_C_LONG) { 
                                        long int *num; 
                                        num = va_arg (args, long int *); 
                                        *num = (long int)currlen; 
                                } else if (cflags == DP_C_LLONG) { 
                                        LLONG *num; 
                                        num = va_arg (args, LLONG *); 
                                        *num = (LLONG)currlen; 
                                } else { 
                                        int *num; 
                                        num = va_arg (args, int *); 
                                        *num = currlen; 
                                } 
                                 break;                                  break;
                         case '%':                          case '%':
                                dopr_outch (buffer, &currlen, maxlen, ch);                                cnk->type = CNK_PRCNT;
                                 break;                                  break;
                         case 'w':  
                                 /* not supported yet, treat as next char */  
                                 ch = *format++;  
                                 break;  
                         default:                          default:
                                /* Unknown, skip */                                /* Unknown, bail out*/
                                break;                                goto done;
                         }                          }
                         ch = *format++;                          ch = *format++;
                         state = DP_S_DEFAULT;                          state = DP_S_DEFAULT;
                         flags = cflags = min = 0;  
                         max = -1;  
                         break;                          break;
                 case DP_S_DONE:                  case DP_S_DONE:
                         break;                          break;
Line 456  static size_t dopr(char *buffer, size_t maxlen, const  Line 549  static size_t dopr(char *buffer, size_t maxlen, const 
                         break; /* some picky compilers need this */                          break; /* some picky compilers need this */
                 }                  }
         }          }
   
           /* retrieve the format arguments */
           for (pnum = 0; pnum < max_pos; pnum++) {
                   int i;
   
                   if (clist[pnum].num == 0) {
                           /* ignoring a parameter should not be permitted
                            * all parameters must be matched at least once
                            * BUT seem some system ignore this rule ...
                            * at least my glibc based system does --SSS
                            */
   #ifdef DEBUG_SNPRINTF
                           printf("parameter at position %d not used\n", pnum+1);
   #endif
                           /* eat the parameter */
                           va_arg (args, int);
                           continue;
                   }
                   for (i = 1; i < clist[pnum].num; i++) {
                           if (clist[pnum].chunks[0]->type != clist[pnum].chunks[i]->type) {
                                   /* nooo noo no!
                                    * all the references to a parameter
                                    * must be of the same type
                                    */
                                   goto done;
                           }
                   }
                   cnk = clist[pnum].chunks[0];
                   switch (cnk->type) {
                   case CNK_INT:
                           if (cnk->cflags == DP_C_SHORT) 
                                   cnk->value = va_arg (args, int);
                           else if (cnk->cflags == DP_C_LONG)
                                   cnk->value = va_arg (args, long int);
                           else if (cnk->cflags == DP_C_LLONG)
                                   cnk->value = va_arg (args, LLONG);
                           else if (cnk->cflags == DP_C_SIZET)
                                   cnk->value = va_arg (args, ssize_t);
                           else
                                   cnk->value = va_arg (args, int);
   
                           for (i = 1; i < clist[pnum].num; i++) {
                                   clist[pnum].chunks[i]->value = cnk->value;
                           }
                           break;
   
                   case CNK_OCTAL:
                   case CNK_UINT:
                   case CNK_HEX:
                           if (cnk->cflags == DP_C_SHORT)
                                   cnk->value = va_arg (args, unsigned int);
                           else if (cnk->cflags == DP_C_LONG)
                                   cnk->value = (unsigned long int)va_arg (args, unsigned long int);
                           else if (cnk->cflags == DP_C_LLONG)
                                   cnk->value = (LLONG)va_arg (args, unsigned LLONG);
                           else if (cnk->cflags == DP_C_SIZET)
                                   cnk->value = (size_t)va_arg (args, size_t);
                           else
                                   cnk->value = (unsigned int)va_arg (args, unsigned int);
   
                           for (i = 1; i < clist[pnum].num; i++) {
                                   clist[pnum].chunks[i]->value = cnk->value;
                           }
                           break;
   
                   case CNK_FLOAT:
                           if (cnk->cflags == DP_C_LDOUBLE)
                                   cnk->fvalue = va_arg (args, LDOUBLE);
                           else
                                   cnk->fvalue = va_arg (args, double);
   
                           for (i = 1; i < clist[pnum].num; i++) {
                                   clist[pnum].chunks[i]->fvalue = cnk->fvalue;
                           }
                           break;
   
                   case CNK_CHAR:
                           cnk->value = va_arg (args, int);
   
                           for (i = 1; i < clist[pnum].num; i++) {
                                   clist[pnum].chunks[i]->value = cnk->value;
                           }
                           break;
   
                   case CNK_STRING:
                           cnk->strvalue = va_arg (args, char *);
                           if (!cnk->strvalue) cnk->strvalue = "(NULL)";
   
                           for (i = 1; i < clist[pnum].num; i++) {
                                   clist[pnum].chunks[i]->strvalue = cnk->strvalue;
                           }
                           break;
   
                   case CNK_PTR:
                           cnk->strvalue = va_arg (args, void *);
                           for (i = 1; i < clist[pnum].num; i++) {
                                   clist[pnum].chunks[i]->strvalue = cnk->strvalue;
                           }
                           break;
   
                   case CNK_NUM:
                           if (cnk->cflags == DP_C_CHAR)
                                   cnk->pnum = va_arg (args, char *);
                           else if (cnk->cflags == DP_C_SHORT)
                                   cnk->pnum = va_arg (args, short int *);
                           else if (cnk->cflags == DP_C_LONG)
                                   cnk->pnum = va_arg (args, long int *);
                           else if (cnk->cflags == DP_C_LLONG)
                                   cnk->pnum = va_arg (args, LLONG *);
                           else if (cnk->cflags == DP_C_SIZET)
                                   cnk->pnum = va_arg (args, ssize_t *);
                           else
                                   cnk->pnum = va_arg (args, int *);
   
                           for (i = 1; i < clist[pnum].num; i++) {
                                   clist[pnum].chunks[i]->pnum = cnk->pnum;
                           }
                           break;
   
                   case CNK_PRCNT:
                           break;
   
                   default:
                           /* what ?? */
                           goto done;
                   }
           }
           /* print out the actual string from chunks */
           currlen = 0;
           cnk = chunks;
           while (cnk) {
                   int len, min, max;
   
                   if (cnk->min_star) min = cnk->min_star->value;
                   else min = cnk->min;
                   if (cnk->max_star) max = cnk->max_star->value;
                   else max = cnk->max;
   
                   switch (cnk->type) {
   
                   case CNK_FMT_STR:
                           if (maxlen != 0 && maxlen > currlen) {
                                   if (maxlen > (currlen + cnk->len)) len = cnk->len;
                                   else len = maxlen - currlen;
   
                                   memcpy(&(buffer[currlen]), &(base[cnk->start]), len);
                           }
                           currlen += cnk->len;
                                   
                           break;
   
                   case CNK_INT:
                   case CNK_UINT:
                           fmtint (buffer, &currlen, maxlen, cnk->value, 10, min, max, cnk->flags);
                           break;
   
                   case CNK_OCTAL:
                           fmtint (buffer, &currlen, maxlen, cnk->value, 8, min, max, cnk->flags);
                           break;
   
                   case CNK_HEX:
                           fmtint (buffer, &currlen, maxlen, cnk->value, 16, min, max, cnk->flags);
                           break;
   
                   case CNK_FLOAT:
                           fmtfp (buffer, &currlen, maxlen, cnk->fvalue, min, max, cnk->flags);
                           break;
   
                   case CNK_CHAR:
                           dopr_outch (buffer, &currlen, maxlen, cnk->value);
                           break;
   
                   case CNK_STRING:
                           if (max == -1) {
                                   max = strlen(cnk->strvalue);
                           }
                           fmtstr (buffer, &currlen, maxlen, cnk->strvalue, cnk->flags, min, max);
                           break;
   
                   case CNK_PTR:
                           fmtint (buffer, &currlen, maxlen, (long)(cnk->strvalue), 16, min, max, cnk->flags);
                           break;
   
                   case CNK_NUM:
                           if (cnk->cflags == DP_C_CHAR)
                                   *((char *)(cnk->pnum)) = (char)currlen;
                           else if (cnk->cflags == DP_C_SHORT)
                                   *((short int *)(cnk->pnum)) = (short int)currlen;
                           else if (cnk->cflags == DP_C_LONG)
                                   *((long int *)(cnk->pnum)) = (long int)currlen;
                           else if (cnk->cflags == DP_C_LLONG)
                                   *((LLONG *)(cnk->pnum)) = (LLONG)currlen;
                           else if (cnk->cflags == DP_C_SIZET)
                                   *((ssize_t *)(cnk->pnum)) = (ssize_t)currlen;
                           else
                                   *((int *)(cnk->pnum)) = (int)currlen;
                           break;
   
                   case CNK_PRCNT:
                           dopr_outch (buffer, &currlen, maxlen, '%');
                           break;
   
                   default:
                           /* what ?? */
                           goto done;
                   }
                   cnk = cnk->next;
           }
         if (maxlen != 0) {          if (maxlen != 0) {
                 if (currlen < maxlen - 1)                   if (currlen < maxlen - 1) 
                         buffer[currlen] = '\0';                          buffer[currlen] = '\0';
                 else if (maxlen > 0)                   else if (maxlen > 0) 
                         buffer[maxlen - 1] = '\0';                          buffer[maxlen - 1] = '\0';
         }          }
                ret = currlen;
        return currlen;
 done:
         va_end(args);
 
         while (chunks) {
                 cnk = chunks->next;
                 free(chunks);
                 chunks = cnk;
         }
         if (clist) {
                 for (pnum = 0; pnum < max_pos; pnum++) {
                         if (clist[pnum].chunks) free(clist[pnum].chunks);
                 }
                 free(clist);
         }
         return ret;
 }  }
   
 static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,  static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
Line 479  static void fmtstr(char *buffer, size_t *currlen, size Line 795  static void fmtstr(char *buffer, size_t *currlen, size
                 value = "<NULL>";                  value = "<NULL>";
         }          }
   
        for (strln = 0; value[strln]; ++strln); /* strlen */        for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */
         padlen = min - strln;          padlen = min - strln;
         if (padlen < 0)           if (padlen < 0) 
                 padlen = 0;                  padlen = 0;
         if (flags & DP_F_MINUS)           if (flags & DP_F_MINUS) 
                 padlen = -padlen; /* Left Justify */                  padlen = -padlen; /* Left Justify */
                   
        while ((padlen > 0) && (cnt < max)) {        while (padlen > 0) {
                 dopr_outch (buffer, currlen, maxlen, ' ');                  dopr_outch (buffer, currlen, maxlen, ' ');
                 --padlen;                  --padlen;
                 ++cnt;  
         }          }
         while (*value && (cnt < max)) {          while (*value && (cnt < max)) {
                 dopr_outch (buffer, currlen, maxlen, *value++);                  dopr_outch (buffer, currlen, maxlen, *value++);
                 ++cnt;                  ++cnt;
         }          }
        while ((padlen < 0) && (cnt < max)) {        while (padlen < 0) {
                 dopr_outch (buffer, currlen, maxlen, ' ');                  dopr_outch (buffer, currlen, maxlen, ' ');
                 ++padlen;                  ++padlen;
                 ++cnt;  
         }          }
 }  }
   
 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */  /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
   
 static void fmtint(char *buffer, size_t *currlen, size_t maxlen,  static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
                    long value, int base, int min, int max, int flags)                    LLONG value, int base, int min, int max, int flags)
 {  {
         int signvalue = 0;          int signvalue = 0;
        unsigned long uvalue;        unsigned LLONG uvalue;
         char convert[20];          char convert[20];
         int place = 0;          int place = 0;
         int spadlen = 0; /* amount to space pad */          int spadlen = 0; /* amount to space pad */
Line 626  static LLONG ROUND(LDOUBLE value) Line 940  static LLONG ROUND(LDOUBLE value)
 static double my_modf(double x0, double *iptr)  static double my_modf(double x0, double *iptr)
 {  {
         int i;          int i;
        long l;        LLONG l=0;
         double x = x0;          double x = x0;
         double f = 1.0;          double f = 1.0;
   
         for (i=0;i<100;i++) {          for (i=0;i<100;i++) {
                 l = (long)x;                  l = (long)x;
                if (l <= (x+1) && l >= (x-1)) {                if (l <= (x+1) && l >= (x-1)) break;
                        if (i != 0) { 
                                double i2; 
                                double ret; 
 
                                ret = my_modf(x0-l*f, &i2); 
                                (*iptr) = l*f + i2; 
                                return ret; 
                        }  
 
                        (*iptr) = l; 
                        return x - (*iptr); 
                } 
                 x *= 0.1;                  x *= 0.1;
                 f *= 10.0;                  f *= 10.0;
         }          }
   
        /* yikes! the number is beyond what we can handle. What do we do? */        if (i == 100) {
        (*iptr) = 0;                /* yikes! the number is beyond what we can handle. What do we do? */
        return 0;                (*iptr) = 0;
                 return 0;
         }
 
         if (i != 0) {
                 double i2;
                 double ret;
 
                 ret = my_modf(x0-l*f, &i2);
                 (*iptr) = l*f + i2;
                 return ret;
         } 
 
         (*iptr) = l;
         return x - (*iptr);
 }  }
   
   
Line 701  static void fmtfp (char *buffer, size_t *currlen, size Line 1017  static void fmtfp (char *buffer, size_t *currlen, size
 #endif  #endif
   
         /*           /* 
         * Sorry, we only support 16 digits past the decimal because of our          * Sorry, we only support 9 digits past the decimal because of our 
          * conversion method           * conversion method
          */           */
        if (max > 16)        if (max > 9)
                max = 16;                max = 9;
   
         /* We "cheat" by converting the fractional part to integer by          /* We "cheat" by converting the fractional part to integer by
          * multiplying by a factor of 10           * multiplying by a factor of 10
Line 815  static void dopr_outch(char *buffer, size_t *currlen,  Line 1131  static void dopr_outch(char *buffer, size_t *currlen, 
         (*currlen)++;          (*currlen)++;
 }  }
   
   static struct pr_chunk *new_chunk(void) {
           struct pr_chunk *new_c = (struct pr_chunk *)malloc(sizeof(struct pr_chunk));
   
           if (!new_c)
                   return NULL;
   
           new_c->type = 0;
           new_c->num = 0;
           new_c->min = 0;
           new_c->min_star = NULL;
           new_c->max = -1;
           new_c->max_star = NULL;
           new_c->flags = 0;
           new_c->cflags = 0;
           new_c->start = 0;
           new_c->len = 0;
           new_c->value = 0;
           new_c->fvalue = 0;
           new_c->strvalue = NULL;
           new_c->pnum = NULL;
           new_c->next = NULL;
   
           return new_c;
   }
   
   static int add_cnk_list_entry(struct pr_chunk_x **list,
                                   int max_num, struct pr_chunk *chunk) {
           struct pr_chunk_x *l;
           struct pr_chunk **c;
           int max;
           int cnum;
           int i, pos;
   
           if (chunk->num > max_num) {
                   max = chunk->num;
           
                   if (*list == NULL) {
                           l = (struct pr_chunk_x *)malloc(sizeof(struct pr_chunk_x) * max);
                           pos = 0;
                   } else {
                           l = (struct pr_chunk_x *)realloc(*list, sizeof(struct pr_chunk_x) * max);
                           pos = max_num;
                   }
                   if (l == NULL) {
                           for (i = 0; i < max; i++) {
                                   if ((*list)[i].chunks) free((*list)[i].chunks);
                           }
                           return 0;
                   }
                   for (i = pos; i < max; i++) {
                           l[i].chunks = NULL;
                           l[i].num = 0;
                   }
           } else {
                   l = *list;
                   max = max_num;
           }
   
           i = chunk->num - 1;
           cnum = l[i].num + 1;
           if (l[i].chunks == NULL) {
                   c = (struct pr_chunk **)malloc(sizeof(struct pr_chunk *) * cnum); 
           } else {
                   c = (struct pr_chunk **)realloc(l[i].chunks, sizeof(struct pr_chunk *) * cnum);
           }
           if (c == NULL) {
                   for (i = 0; i < max; i++) {
                           if (l[i].chunks) free(l[i].chunks);
                   }
                   return 0;
           }
           c[l[i].num] = chunk;
           l[i].chunks = c;
           l[i].num = cnum;
   
           *list = l;
           return max;
   }
   
  int rsync_vsnprintf (char *str, size_t count, const char *fmt, va_list args)   int rsync_vsnprintf (char *str, size_t count, const char *fmt, va_list args)
 {  {
         return dopr(str, count, fmt, args);          return dopr(str, count, fmt, args);
Line 842  int rsync_snprintf(char *str,size_t count,const char * Line 1237  int rsync_snprintf(char *str,size_t count,const char *
 #define snprintf rsync_snprintf  #define snprintf rsync_snprintf
 #endif  #endif
   
 #endif   
   
 #ifndef HAVE_VASPRINTF  #ifndef HAVE_VASPRINTF
  int vasprintf(char **ptr, const char *format, va_list ap)   int vasprintf(char **ptr, const char *format, va_list ap)
 {  {
Line 851  int rsync_snprintf(char *str,size_t count,const char * Line 1244  int rsync_snprintf(char *str,size_t count,const char *
         va_list ap2;          va_list ap2;
   
         VA_COPY(ap2, ap);          VA_COPY(ap2, ap);
           
         ret = vsnprintf(NULL, 0, format, ap2);          ret = vsnprintf(NULL, 0, format, ap2);
        if (ret <= 0) return ret;        va_end(ap2);
         if (ret < 0) return ret;
   
         (*ptr) = (char *)malloc(ret+1);          (*ptr) = (char *)malloc(ret+1);
         if (!*ptr) return -1;          if (!*ptr) return -1;
   
         VA_COPY(ap2, ap);          VA_COPY(ap2, ap);
   
         ret = vsnprintf(*ptr, ret+1, format, ap2);          ret = vsnprintf(*ptr, ret+1, format, ap2);
           va_end(ap2);
   
         return ret;          return ret;
 }  }
Line 885  int rsync_snprintf(char *str,size_t count,const char * Line 1278  int rsync_snprintf(char *str,size_t count,const char *
 #ifdef TEST_SNPRINTF  #ifdef TEST_SNPRINTF
   
  int sprintf(char *str,const char *fmt,...);   int sprintf(char *str,const char *fmt,...);
    int printf(const char *fmt,...);
   
  int main (void)   int main (void)
 {  {
         char buf1[1024];          char buf1[1024];
         char buf2[1024];          char buf2[1024];
           char *buf3;
         char *fp_fmt[] = {          char *fp_fmt[] = {
                 "%1.1f",                  "%1.1f",
                 "%-1.5f",                  "%-1.5f",
Line 905  int rsync_snprintf(char *str,size_t count,const char * Line 1300  int rsync_snprintf(char *str,size_t count,const char *
                 "%3.2f",                  "%3.2f",
                 "%.0f",                  "%.0f",
                 "%f",                  "%f",
                "-16.16f",                "%-8.8f",
                 "%-9.9f",
                 NULL                  NULL
         };          };
         double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996,           double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996, 
Line 924  int rsync_snprintf(char *str,size_t count,const char * Line 1320  int rsync_snprintf(char *str,size_t count,const char *
                 "%d",                  "%d",
                 NULL                  NULL
         };          };
        long int_nums[] = { -1, 134, 91340, 341, 0203, 0};        long int_nums[] = { -1, 134, 91340, 341, 0203, 1234567890, 0};
         char *str_fmt[] = {          char *str_fmt[] = {
                "10.5s",                "%10.5s",
                "5.10s",                "%-10.5s",
                "10.1s",                "%5.10s",
                "0.10s",                "%-5.10s",
                "10.0s",                "%10.1s",
                "1.10s",                "%0.10s",
                 "%10.0s",
                 "%1.10s",
                 "%s",                  "%s",
                 "%.1s",                  "%.1s",
                 "%.10s",                  "%.10s",
Line 939  int rsync_snprintf(char *str,size_t count,const char * Line 1337  int rsync_snprintf(char *str,size_t count,const char *
                 NULL                  NULL
         };          };
         char *str_vals[] = {"hello", "a", "", "a longer string", NULL};          char *str_vals[] = {"hello", "a", "", "a longer string", NULL};
   #ifdef HAVE_LONG_LONG
           char *ll_fmt[] = {
                   "%llu",
                   NULL
           };
           LLONG ll_nums[] = { 134, 91340, 341, 0203, 1234567890, 128006186140000000LL, 0};
   #endif
         int x, y;          int x, y;
         int fail = 0;          int fail = 0;
         int num = 0;          int num = 0;
           int l1, l2;
           char *ss_fmt[] = {
                   "%zd",
                   "%zu",
                   NULL
           };
           size_t ss_nums[] = {134, 91340, 123456789, 0203, 1234567890, 0};
   
         printf ("Testing snprintf format codes against system sprintf...\n");          printf ("Testing snprintf format codes against system sprintf...\n");
   
         for (x = 0; fp_fmt[x] ; x++) {          for (x = 0; fp_fmt[x] ; x++) {
                 for (y = 0; fp_nums[y] != 0 ; y++) {                  for (y = 0; fp_nums[y] != 0 ; y++) {
                        int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]);                        buf1[0] = buf2[0] = '\0';
                        int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);                        l1 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
                        sprintf (buf2, fp_fmt[x], fp_nums[y]);                        l2 = sprintf (buf2, fp_fmt[x], fp_nums[y]);
                        if (strcmp (buf1, buf2)) {                        buf1[1023] = buf2[1023] = '\0';
                                printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",                         if (strcmp (buf1, buf2) || (l1 != l2)) {
                                       fp_fmt[x], buf1, buf2);                                printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", 
                                        fp_fmt[x], l1, buf1, l2, buf2);
                                 fail++;                                  fail++;
                         }                          }
                         if (l1 != l2) {  
                                 printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]);  
                                 fail++;  
                         }  
                         num++;                          num++;
                 }                  }
         }          }
   
         for (x = 0; int_fmt[x] ; x++) {          for (x = 0; int_fmt[x] ; x++) {
                 for (y = 0; int_nums[y] != 0 ; y++) {                  for (y = 0; int_nums[y] != 0 ; y++) {
                        int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]);                        buf1[0] = buf2[0] = '\0';
                        int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);                        l1 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
                        sprintf (buf2, int_fmt[x], int_nums[y]);                        l2 = sprintf (buf2, int_fmt[x], int_nums[y]);
                        if (strcmp (buf1, buf2)) {                        buf1[1023] = buf2[1023] = '\0';
                                printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",                         if (strcmp (buf1, buf2) || (l1 != l2)) {
                                       int_fmt[x], buf1, buf2);                                printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", 
                                        int_fmt[x], l1, buf1, l2, buf2);
                                 fail++;                                  fail++;
                         }                          }
                         if (l1 != l2) {  
                                 printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]);  
                                 fail++;  
                         }  
                         num++;                          num++;
                 }                  }
         }          }
   
         for (x = 0; str_fmt[x] ; x++) {          for (x = 0; str_fmt[x] ; x++) {
                 for (y = 0; str_vals[y] != 0 ; y++) {                  for (y = 0; str_vals[y] != 0 ; y++) {
                        int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]);                        buf1[0] = buf2[0] = '\0';
                        int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);                        l1 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
                        sprintf (buf2, str_fmt[x], str_vals[y]);                        l2 = sprintf (buf2, str_fmt[x], str_vals[y]);
                        if (strcmp (buf1, buf2)) {                        buf1[1023] = buf2[1023] = '\0';
                                printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",                         if (strcmp (buf1, buf2) || (l1 != l2)) {
                                       str_fmt[x], buf1, buf2);                                printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", 
                                        str_fmt[x], l1, buf1, l2, buf2);
                                 fail++;                                  fail++;
                         }                          }
                        if (l1 != l2) {                        num++;
                                printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]);                }
         }
 
 #ifdef HAVE_LONG_LONG
         for (x = 0; ll_fmt[x] ; x++) {
                 for (y = 0; ll_nums[y] != 0 ; y++) {
                         buf1[0] = buf2[0] = '\0';
                         l1 = snprintf(buf1, sizeof(buf1), ll_fmt[x], ll_nums[y]);
                         l2 = sprintf (buf2, ll_fmt[x], ll_nums[y]);
                         buf1[1023] = buf2[1023] = '\0';
                         if (strcmp (buf1, buf2) || (l1 != l2)) {
                                 printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", 
                                        ll_fmt[x], l1, buf1, l2, buf2);
                                 fail++;                                  fail++;
                         }                          }
                         num++;                          num++;
                 }                  }
         }          }
   #endif
   
   #define BUFSZ 2048
   
           buf1[0] = buf2[0] = '\0';
           if ((buf3 = malloc(BUFSZ)) == NULL) {
                   fail++;
           } else {
                   num++;
                   memset(buf3, 'a', BUFSZ);
                   snprintf(buf1, sizeof(buf1), "%.*s", 1, buf3);
                   buf1[1023] = '\0';
                   if (strcmp(buf1, "a") != 0) {
                           printf("length limit buf1 '%s' expected 'a'\n", buf1);
                           fail++;
                   }
           }
   
           buf1[0] = buf2[0] = '\0';
           l1 = snprintf(buf1, sizeof(buf1), "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9);
           l2 = sprintf(buf2, "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9);
           buf1[1023] = buf2[1023] = '\0';
           if (strcmp(buf1, buf2) || (l1 != l2)) {
                   printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
                                   "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2);
                   fail++;
           }
   
           buf1[0] = buf2[0] = '\0';
           l1 = snprintf(buf1, sizeof(buf1), "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9);
           l2 = sprintf(buf2, "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9);
           buf1[1023] = buf2[1023] = '\0';
           if (strcmp(buf1, buf2)) {
                   printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
                                   "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2);
                   fail++;
           }
   
           for (x = 0; ss_fmt[x] ; x++) {
                   for (y = 0; ss_nums[y] != 0 ; y++) {
                           buf1[0] = buf2[0] = '\0';
                           l1 = snprintf(buf1, sizeof(buf1), ss_fmt[x], ss_nums[y]);
                           l2 = sprintf (buf2, ss_fmt[x], ss_nums[y]);
                           buf1[1023] = buf2[1023] = '\0';
                           if (strcmp (buf1, buf2) || (l1 != l2)) {
                                   printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", 
                                          ss_fmt[x], l1, buf1, l2, buf2);
                                   fail++;
                           }
                           num++;
                   }
           }
   #if 0
           buf1[0] = buf2[0] = '\0';
           l1 = snprintf(buf1, sizeof(buf1), "%lld", (LLONG)1234567890);
           l2 = sprintf(buf2, "%lld", (LLONG)1234567890);
           buf1[1023] = buf2[1023] = '\0';
           if (strcmp(buf1, buf2)) {
                   printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
                                   "%lld", l1, buf1, l2, buf2);
                   fail++;
           }
   
           buf1[0] = buf2[0] = '\0';
           l1 = snprintf(buf1, sizeof(buf1), "%Lf", (LDOUBLE)890.1234567890123);
           l2 = sprintf(buf2, "%Lf", (LDOUBLE)890.1234567890123);
           buf1[1023] = buf2[1023] = '\0';
           if (strcmp(buf1, buf2)) {
                   printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n",
                                   "%Lf", l1, buf1, l2, buf2);
                   fail++;
           }
   #endif
         printf ("%d tests failed out of %d.\n", fail, num);          printf ("%d tests failed out of %d.\n", fail, num);
   
         printf("seeing how many digits we support\n");          printf("seeing how many digits we support\n");

Removed from v.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>