/[muddleftpd]/muddleftpd/src/util/snprintf.c
ViewVC logotype

Diff of /muddleftpd/src/util/snprintf.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by ganneff, Sat Sep 28 11:05:57 2002 UTC revision 1.1.6.1 by ganneff, Mon Oct 21 19:52:59 2002 UTC
# Line 1  Line 1 
1    
2  /* snprintf.c snprintf implementation for computers without it */  /* snprintf.c snprintf implementation for computers without it */
3    
4  /* Modified by Beau Kuiper for muddle.ftpd */  /* Modified by Beau Kuiper for muddle.ftpd */
5    
6  /* Changed December 16, 1999 to be compliant with latest C9X snprintf()  /* Changed December 16, 1999 to be compliant with latest C9X snprintf()
7     specification: (from the comp.lang.c FAQ list, Q12.22)     specification: (from the comp.lang.c FAQ list, Q12.22)
8    
# Line 91  Line 94 
94    
95  #if defined(HAVE_STDARG_H)  #if defined(HAVE_STDARG_H)
96  # include <stdarg.h>  # include <stdarg.h>
97  # define HAVE_STDARGS    /* let's hope that works everywhere (mj) */  # define HAVE_STDARGS                   /* let's hope that works everywhere (mj) */
98  # define VA_LOCAL_DECL   va_list ap  # define VA_LOCAL_DECL   va_list ap
99  # define VA_START(f)     va_start(ap, f)  # define VA_START(f)     va_start(ap, f)
100  # define VA_SHIFT(v,t)  ;   /* no-op for ANSI */  # define VA_SHIFT(v,t)  ;               /* no-op for ANSI */
101  # define VA_END          va_end(ap)  # define VA_END          va_end(ap)
102  #else  #else
103  # if defined(HAVE_VARARGS_H)  # if defined(HAVE_VARARGS_H)
104  #  include <varargs.h>  #  include <varargs.h>
105  #  undef HAVE_STDARGS  #  undef HAVE_STDARGS
106  #  define VA_LOCAL_DECL   va_list ap  #  define VA_LOCAL_DECL   va_list ap
107  #  define VA_START(f)     va_start(ap)      /* f is ignored! */  #  define VA_START(f)     va_start(ap)  /* f is ignored! */
108  #  define VA_SHIFT(v,t) v = va_arg(ap,t)  #  define VA_SHIFT(v,t) v = va_arg(ap,t)
109  #  define VA_END        va_end(ap)  #  define VA_END        va_end(ap)
110  # else  # else
111    
112  /*XX ** NO VARARGS ** XX*/  /*XX ** NO VARARGS ** XX*/
113  # endif  # endif
114  #endif  #endif
# Line 116  Line 120 
120  #endif  #endif
121    
122  /*int snprintf (char *str, size_t count, const char *fmt, ...);*/  /*int snprintf (char *str, size_t count, const char *fmt, ...);*/
123    
124  /*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/  /*int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);*/
125    
126  static int dopr (char *buffer, size_t maxlen, const char *format,  static int dopr(char *buffer,
127                    va_list args);                                  size_t maxlen,
128  static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, size_t *reallen,                                  const char *format,
129                      char *value, int flags, int min, int max);                                  va_list args);
130  static void fmtint (char *buffer, size_t *currlen, size_t maxlen, size_t *reallen,  static void fmtstr(char *buffer,
131                      long value, int base, int min, int max, int flags);                                     size_t * currlen,
132  static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, size_t *reallen,                                     size_t maxlen,
133                     LDOUBLE fvalue, int min, int max, int flags);                                     size_t * reallen,
134  static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, size_t *reallen, char c );                                     char *value,
135                                       int flags,
136                                       int min,
137                                       int max);
138    static void fmtint(char *buffer,
139                                       size_t * currlen,
140                                       size_t maxlen,
141                                       size_t * reallen,
142                                       long value,
143                                       int base,
144                                       int min,
145                                       int max,
146                                       int flags);
147    static void fmtfp(char *buffer,
148                                      size_t * currlen,
149                                      size_t maxlen,
150                                      size_t * reallen,
151                                      LDOUBLE fvalue,
152                                      int min,
153                                      int max,
154                                      int flags);
155    static void dopr_outch(char *buffer,
156                                               size_t * currlen,
157                                               size_t maxlen,
158                                               size_t * reallen,
159                                               char c);
160    
161  /*  /*
162   * dopr(): poor man's version of doprintf   * dopr(): poor man's version of doprintf
# Line 159  static void dopr_outch (char *buffer, si Line 189  static void dopr_outch (char *buffer, si
189  #define char_to_int(p) (p - '0')  #define char_to_int(p) (p - '0')
190  #define MAX(p,q) ((p >= q) ? p : q)  #define MAX(p,q) ((p >= q) ? p : q)
191    
192  static int dopr (char *buffer, size_t maxlen, const char *format, va_list args)  static int dopr(char *buffer,
193  {                                  size_t maxlen,
194    char ch;                                  const char *format,
195    long value;                                  va_list args)
196    LDOUBLE fvalue;  {
197    char *strvalue;          char ch;
198    int min;          long value;
199    int max;          LDOUBLE fvalue;
200    int state;          char *strvalue;
201    int flags;          int min;
202    int cflags;          int max;
203    size_t currlen;          int state;
204    size_t reallen;          int flags;
205              int cflags;
206    state = DP_S_DEFAULT;          size_t currlen;
207    currlen = reallen = flags = cflags = min = 0;          size_t reallen;
208    max = -1;  
209    ch = *format++;          state = DP_S_DEFAULT;
210            currlen = reallen = flags = cflags = min = 0;
211    while (state != DP_S_DONE)          max = -1;
   {  
     if (ch == '\0')  
       state = DP_S_DONE;  
   
     switch(state)  
     {  
     case DP_S_DEFAULT:  
       if (ch == '%')  
         state = DP_S_FLAGS;  
       else  
         dopr_outch (buffer, &currlen, maxlen, &reallen, ch);  
       ch = *format++;  
       break;  
     case DP_S_FLAGS:  
       switch (ch)  
       {  
       case '-':  
         flags |= DP_F_MINUS;  
         ch = *format++;  
         break;  
       case '+':  
         flags |= DP_F_PLUS;  
         ch = *format++;  
         break;  
       case ' ':  
         flags |= DP_F_SPACE;  
         ch = *format++;  
         break;  
       case '#':  
         flags |= DP_F_NUM;  
         ch = *format++;  
         break;  
       case '0':  
         flags |= DP_F_ZERO;  
         ch = *format++;  
         break;  
       default:  
         state = DP_S_MIN;  
         break;  
       }  
       break;  
     case DP_S_MIN:  
       if (isdigit((unsigned char)ch))  
       {  
         min = 10*min + char_to_int (ch);  
         ch = *format++;  
       }  
       else if (ch == '*')  
       {  
         min = va_arg (args, int);  
         ch = *format++;  
         state = DP_S_DOT;  
       }  
       else  
         state = DP_S_DOT;  
       break;  
     case DP_S_DOT:  
       if (ch == '.')  
       {  
         state = DP_S_MAX;  
         ch = *format++;  
       }  
       else  
         state = DP_S_MOD;  
       break;  
     case DP_S_MAX:  
       if (isdigit((unsigned char)ch))  
       {  
         if (max < 0)  
           max = 0;  
         max = 10*max + char_to_int (ch);  
212          ch = *format++;          ch = *format++;
213        }  
214        else if (ch == '*')          while (state != DP_S_DONE)
215        {          {
216          max = va_arg (args, int);                  if (ch == '\0')
217          ch = *format++;                          state = DP_S_DONE;
218          state = DP_S_MOD;  
219        }                  switch (state)
220        else                  {
221          state = DP_S_MOD;                  case DP_S_DEFAULT:
222        break;                          if (ch == '%')
223      case DP_S_MOD:                                  state = DP_S_FLAGS;
224        /* Currently, we don't support Long Long, bummer */                          else
225        switch (ch)                                  dopr_outch(buffer, &currlen, maxlen, &reallen, ch);
226        {                          ch = *format++;
227        case 'h':                          break;
228          cflags = DP_C_SHORT;                  case DP_S_FLAGS:
229          ch = *format++;                          switch (ch)
230          break;                          {
231        case 'l':                          case '-':
232          cflags = DP_C_LONG;                                  flags |= DP_F_MINUS;
233          ch = *format++;                                  ch = *format++;
234          break;                                  break;
235        case 'L':                          case '+':
236          cflags = DP_C_LDOUBLE;                                  flags |= DP_F_PLUS;
237          ch = *format++;                                  ch = *format++;
238          break;                                  break;
239        default:                          case ' ':
240          break;                                  flags |= DP_F_SPACE;
241        }                                  ch = *format++;
242        state = DP_S_CONV;                                  break;
243        break;                          case '#':
244      case DP_S_CONV:                                  flags |= DP_F_NUM;
245        switch (ch)                                  ch = *format++;
246        {                                  break;
247        case 'd':                          case '0':
248        case 'i':                                  flags |= DP_F_ZERO;
249          if (cflags == DP_C_SHORT)                                  ch = *format++;
250            value = va_arg (args, short int);                                  break;
251          else if (cflags == DP_C_LONG)                          default:
252            value = va_arg (args, long int);                                  state = DP_S_MIN;
253          else                                  break;
254            value = va_arg (args, int);                          }
255          fmtint (buffer, &currlen, maxlen, &reallen, value, 10, min, max, flags);                          break;
256          break;                  case DP_S_MIN:
257        case 'o':                          if (isdigit((unsigned char) ch))
258          flags |= DP_F_UNSIGNED;                          {
259          if (cflags == DP_C_SHORT)                                  min = 10 * min + char_to_int(ch);
260            value = va_arg (args, unsigned short int);                                  ch = *format++;
261          else if (cflags == DP_C_LONG)                          }
262            value = (long)va_arg (args, unsigned long int);                          else if (ch == '*')
263          else                          {
264            value = (long)va_arg (args, unsigned int);                                  min = va_arg(args, int);
265          fmtint (buffer, &currlen, maxlen, &reallen, value, 8, min, max, flags);  
266          break;                                  ch = *format++;
267        case 'u':                                  state = DP_S_DOT;
268          flags |= DP_F_UNSIGNED;                          }
269          if (cflags == DP_C_SHORT)                          else
270            value = va_arg (args, unsigned short int);                                  state = DP_S_DOT;
271          else if (cflags == DP_C_LONG)                          break;
272            value = (long)va_arg (args, unsigned long int);                  case DP_S_DOT:
273          else                          if (ch == '.')
274            value = (long)va_arg (args, unsigned int);                          {
275          fmtint (buffer, &currlen, maxlen, &reallen, value, 10, min, max, flags);                                  state = DP_S_MAX;
276          break;                                  ch = *format++;
277        case 'X':                          }
278          flags |= DP_F_UP;                          else
279        case 'x':                                  state = DP_S_MOD;
280          flags |= DP_F_UNSIGNED;                          break;
281          if (cflags == DP_C_SHORT)                  case DP_S_MAX:
282            value = va_arg (args, unsigned short int);                          if (isdigit((unsigned char) ch))
283          else if (cflags == DP_C_LONG)                          {
284            value = (long)va_arg (args, unsigned long int);                                  if (max < 0)
285          else                                          max = 0;
286            value = (long)va_arg (args, unsigned int);                                  max = 10 * max + char_to_int(ch);
287          fmtint (buffer, &currlen, maxlen, &reallen, value, 16, min, max, flags);                                  ch = *format++;
288          break;                          }
289        case 'f':                          else if (ch == '*')
290          if (cflags == DP_C_LDOUBLE)                          {
291            fvalue = va_arg (args, LDOUBLE);                                  max = va_arg(args, int);
292          else  
293            fvalue = va_arg (args, double);                                  ch = *format++;
294          /* um, floating point? */                                  state = DP_S_MOD;
295          fmtfp (buffer, &currlen, maxlen, &reallen, fvalue, min, max, flags);                          }
296          break;                          else
297        case 'E':                                  state = DP_S_MOD;
298          flags |= DP_F_UP;                          break;
299        case 'e':                  case DP_S_MOD:
300          if (cflags == DP_C_LDOUBLE)                          /*
301            fvalue = va_arg (args, LDOUBLE);                           * Currently, we don't support Long Long, bummer
302          else                           */
303            fvalue = va_arg (args, double);                          switch (ch)
304          break;                          {
305        case 'G':                          case 'h':
306          flags |= DP_F_UP;                                  cflags = DP_C_SHORT;
307        case 'g':                                  ch = *format++;
308          if (cflags == DP_C_LDOUBLE)                                  break;
309            fvalue = va_arg (args, LDOUBLE);                          case 'l':
310          else                                  cflags = DP_C_LONG;
311            fvalue = va_arg (args, double);                                  ch = *format++;
312          break;                                  break;
313        case 'c':                          case 'L':
314          dopr_outch (buffer, &currlen, maxlen, &reallen, va_arg (args, int));                                  cflags = DP_C_LDOUBLE;
315          break;                                  ch = *format++;
316        case 's':                                  break;
317          strvalue = va_arg (args, char *);                          default:
318          if (max < 0)                                  break;
319            max = INT_MAX; /* ie, no max */                          }
320          fmtstr (buffer, &currlen, maxlen, &reallen, strvalue, flags, min, max);                          state = DP_S_CONV;
321          break;                          break;
322        case 'p':                  case DP_S_CONV:
323          strvalue = va_arg (args, void *);                          switch (ch)
324          fmtint (buffer, &currlen, maxlen, &reallen, (long) strvalue, 16, min, max, flags);                          {
325          break;                          case 'd':
326        case 'n':                          case 'i':
327          if (cflags == DP_C_SHORT)                                  if (cflags == DP_C_SHORT)
328          {                                          value = va_arg(args, short int);
329            short int *num;  
330            num = va_arg (args, short int *);                                  else if (cflags == DP_C_LONG)
331            *num = currlen;                                          value = va_arg(args, long int);
332          }  
333          else if (cflags == DP_C_LONG)                                  else
334          {                                          value = va_arg(args, int);
335            long int *num;  
336            num = va_arg (args, long int *);                                  fmtint(buffer, &currlen, maxlen, &reallen, value, 10, min,
337            *num = (long int)currlen;                                             max, flags);
338          }                                  break;
339          else                          case 'o':
340          {                                  flags |= DP_F_UNSIGNED;
341            int *num;                                  if (cflags == DP_C_SHORT)
342            num = va_arg (args, int *);                                          value = va_arg(args, unsigned short int);
343            *num = currlen;  
344          }                                  else if (cflags == DP_C_LONG)
345          break;                                          value = (long) va_arg(args, unsigned long int);
346        case '%':  
347          dopr_outch (buffer, &currlen, maxlen, &reallen, ch);                                  else
348          break;                                          value = (long) va_arg(args, unsigned int);
349        case 'w':  
350          /* not supported yet, treat as next char */                                  fmtint(buffer, &currlen, maxlen, &reallen, value, 8, min, max,
351          ch = *format++;                                             flags);
352          break;                                  break;
353        default:                          case 'u':
354          /* Unknown, skip */                                  flags |= DP_F_UNSIGNED;
355          break;                                  if (cflags == DP_C_SHORT)
356        }                                          value = va_arg(args, unsigned short int);
357        ch = *format++;  
358        state = DP_S_DEFAULT;                                  else if (cflags == DP_C_LONG)
359        flags = cflags = min = 0;                                          value = (long) va_arg(args, unsigned long int);
360        max = -1;  
361        break;                                  else
362      case DP_S_DONE:                                          value = (long) va_arg(args, unsigned int);
363        break;  
364      default:                                  fmtint(buffer, &currlen, maxlen, &reallen, value, 10, min,
365        /* hmm? */                                             max, flags);
366        break; /* some picky compilers need this */                                  break;
367      }                          case 'X':
368    }                                  flags |= DP_F_UP;
369                            case 'x':
370    if (buffer != NULL && maxlen > 0) {                                  flags |= DP_F_UNSIGNED;
371        if (currlen < maxlen)                                  if (cflags == DP_C_SHORT)
372          buffer[currlen] = '\0';                                          value = va_arg(args, unsigned short int);
373        else  
374          buffer[maxlen - 1] = '\0';                                  else if (cflags == DP_C_LONG)
375    }                                          value = (long) va_arg(args, unsigned long int);
376    
377    return reallen;                                  else
378  }                                          value = (long) va_arg(args, unsigned int);
379    
380  static void fmtstr (char *buffer, size_t *currlen, size_t maxlen, size_t *reallen,                                  fmtint(buffer, &currlen, maxlen, &reallen, value, 16, min,
381                      char *value, int flags, int min, int max)                                             max, flags);
382  {                                  break;
383    int padlen, strln;     /* amount to pad */                          case 'f':
384    int cnt = 0;                                  if (cflags == DP_C_LDOUBLE)
385                                              fvalue = va_arg(args, LDOUBLE);
386    if (value == 0)                                  else
387    {                                          fvalue = va_arg(args, double);
388      value = "<NULL>";  
389    }                                  /*
390                                     * um, floating point?
391    for (strln = 0; value[strln]; ++strln); /* strlen */                                   */
392    padlen = min - strln;                                  fmtfp(buffer, &currlen, maxlen, &reallen, fvalue, min, max,
393    if (padlen < 0)                                            flags);
394      padlen = 0;                                  break;
395    if (flags & DP_F_MINUS)                          case 'E':
396      padlen = -padlen; /* Left Justify */                                  flags |= DP_F_UP;
397                            case 'e':
398    while ((padlen > 0) && (cnt < max))                                  if (cflags == DP_C_LDOUBLE)
399    {                                          fvalue = va_arg(args, LDOUBLE);
400      dopr_outch (buffer, currlen, maxlen, reallen, ' ');                                  else
401      --padlen;                                          fvalue = va_arg(args, double);
402      ++cnt;  
403    }                                  break;
404    while (*value && (cnt < max))                          case 'G':
405    {                                  flags |= DP_F_UP;
406      dopr_outch (buffer, currlen, maxlen, reallen, *value++);                          case 'g':
407      ++cnt;                                  if (cflags == DP_C_LDOUBLE)
408    }                                          fvalue = va_arg(args, LDOUBLE);
409    while ((padlen < 0) && (cnt < max))                                  else
410    {                                          fvalue = va_arg(args, double);
411      dopr_outch (buffer, currlen, maxlen, reallen, ' ');  
412      ++padlen;                                  break;
413      ++cnt;                          case 'c':
414    }                                  dopr_outch(buffer, &currlen, maxlen, &reallen,
415                                                       va_arg(args, int));
416                                    break;
417                            case 's':
418                                    strvalue = va_arg(args, char *);
419    
420                                    if (max < 0)
421                                            max = INT_MAX;  /* ie, no max */
422                                    fmtstr(buffer, &currlen, maxlen, &reallen, strvalue, flags,
423                                               min, max);
424                                    break;
425                            case 'p':
426                                    strvalue = va_arg(args, void *);
427    
428                                    fmtint(buffer, &currlen, maxlen, &reallen, (long) strvalue,
429                                               16, min, max, flags);
430                                    break;
431                            case 'n':
432                                    if (cflags == DP_C_SHORT)
433                                    {
434                                            short int *num;
435                                            num = va_arg(args, short int *);
436    
437                                            *num = currlen;
438                                    }
439                                    else if (cflags == DP_C_LONG)
440                                    {
441                                            long int *num;
442                                            num = va_arg(args, long int *);
443    
444                                            *num = (long int) currlen;
445                                    }
446                                    else
447                                    {
448                                            int *num;
449                                            num = va_arg(args, int *);
450    
451                                            *num = currlen;
452                                    }
453                                    break;
454                            case '%':
455                                    dopr_outch(buffer, &currlen, maxlen, &reallen, ch);
456                                    break;
457                            case 'w':
458                                    /*
459                                     * not supported yet, treat as next char
460                                     */
461                                    ch = *format++;
462                                    break;
463                            default:
464                                    /*
465                                     * Unknown, skip
466                                     */
467                                    break;
468                            }
469                            ch = *format++;
470                            state = DP_S_DEFAULT;
471                            flags = cflags = min = 0;
472                            max = -1;
473                            break;
474                    case DP_S_DONE:
475                            break;
476                    default:
477                            /*
478                             * hmm?
479                             */
480                            break;                          /* some picky compilers need this */
481                    }
482            }
483    
484            if (buffer != NULL && maxlen > 0)
485            {
486                    if (currlen < maxlen)
487                            buffer[currlen] = '\0';
488                    else
489                            buffer[maxlen - 1] = '\0';
490            }
491    
492            return reallen;
493    }
494    
495    static void fmtstr(char *buffer,
496                                       size_t * currlen,
497                                       size_t maxlen,
498                                       size_t * reallen,
499                                       char *value,
500                                       int flags,
501                                       int min,
502                                       int max)
503    {
504            int padlen, strln;                      /* amount to pad */
505            int cnt = 0;
506    
507            if (value == 0)
508            {
509                    value = "<NULL>";
510            }
511    
512            for (strln = 0; value[strln]; ++strln); /* strlen */
513            padlen = min - strln;
514            if (padlen < 0)
515                    padlen = 0;
516            if (flags & DP_F_MINUS)
517                    padlen = -padlen;               /* Left Justify */
518    
519            while ((padlen > 0) && (cnt < max))
520            {
521                    dopr_outch(buffer, currlen, maxlen, reallen, ' ');
522                    --padlen;
523                    ++cnt;
524            }
525            while (*value && (cnt < max))
526            {
527                    dopr_outch(buffer, currlen, maxlen, reallen, *value++);
528                    ++cnt;
529            }
530            while ((padlen < 0) && (cnt < max))
531            {
532                    dopr_outch(buffer, currlen, maxlen, reallen, ' ');
533                    ++padlen;
534                    ++cnt;
535            }
536  }  }
537    
538  /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */  /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
539    
540  static void fmtint (char *buffer, size_t *currlen, size_t maxlen, size_t *reallen,  static void fmtint(char *buffer,
541                      long value, int base, int min, int max, int flags)                                     size_t * currlen,
542  {                                     size_t maxlen,
543    int signvalue = 0;                                     size_t * reallen,
544    unsigned long uvalue;                                     long value,
545    char convert[20];                                     int base,
546    int place = 0;                                     int min,
547    int spadlen = 0; /* amount to space pad */                                     int max,
548    int zpadlen = 0; /* amount to zero pad */                                     int flags)
549    int caps = 0;  {
550              int signvalue = 0;
551    if (max < 0)          unsigned long uvalue;
552      max = 0;          char convert[20];
553            int place = 0;
554    uvalue = value;          int spadlen = 0;                        /* amount to space pad */
555            int zpadlen = 0;                        /* amount to zero pad */
556    if(!(flags & DP_F_UNSIGNED))          int caps = 0;
557    {  
558      if( value < 0 ) {          if (max < 0)
559        signvalue = '-';                  max = 0;
560        uvalue = -value;  
561      }          uvalue = value;
562      else  
563        if (flags & DP_F_PLUS)  /* Do a sign (+/i) */          if (!(flags & DP_F_UNSIGNED))
564          signvalue = '+';          {
565      else                  if (value < 0)
566        if (flags & DP_F_SPACE)                  {
567          signvalue = ' ';                          signvalue = '-';
568    }                          uvalue = -value;
569                      }
570    if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */                  else if (flags & DP_F_PLUS)     /* Do a sign (+/i) */
571                            signvalue = '+';
572    do {                  else if (flags & DP_F_SPACE)
573      convert[place++] =                          signvalue = ' ';
574        (caps? "0123456789ABCDEF":"0123456789abcdef")          }
575        [uvalue % (unsigned)base  ];  
576      uvalue = (uvalue / (unsigned)base );          if (flags & DP_F_UP)
577    } while(uvalue && (place < 20));                  caps = 1;                               /* Should characters be upper case? */
578    if (place == 20) place--;  
579    convert[place] = 0;          do
580            {
581    zpadlen = max - place;                  convert[place++] =
582    spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);                          (caps ? "0123456789ABCDEF" : "0123456789abcdef")
583    if (zpadlen < 0) zpadlen = 0;                          [uvalue % (unsigned) base];
584    if (spadlen < 0) spadlen = 0;                  uvalue = (uvalue / (unsigned) base);
585    if (flags & DP_F_ZERO)          } while (uvalue && (place < 20));
586    {          if (place == 20)
587      zpadlen = MAX(zpadlen, spadlen);                  place--;
588      spadlen = 0;          convert[place] = 0;
589    }  
590    if (flags & DP_F_MINUS)          zpadlen = max - place;
591      spadlen = -spadlen; /* Left Justifty */          spadlen = min - MAX(max, place) - (signvalue ? 1 : 0);
592            if (zpadlen < 0)
593                    zpadlen = 0;
594            if (spadlen < 0)
595                    spadlen = 0;
596            if (flags & DP_F_ZERO)
597            {
598                    zpadlen = MAX(zpadlen, spadlen);
599                    spadlen = 0;
600            }
601            if (flags & DP_F_MINUS)
602                    spadlen = -spadlen;             /* Left Justifty */
603    
604  #ifdef DEBUG_SNPRINTF  #ifdef DEBUG_SNPRINTF
605    printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",          printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
606           zpadlen, spadlen, min, max, place);                     zpadlen, spadlen, min, max, place);
607  #endif  #endif
608    
609    /* Spaces */          /*
610    while (spadlen > 0)           * Spaces
611    {           */
612      dopr_outch (buffer, currlen, maxlen, reallen, ' ');          while (spadlen > 0)
613      --spadlen;          {
614    }                  dopr_outch(buffer, currlen, maxlen, reallen, ' ');
615                    --spadlen;
616    /* Sign */          }
617    if (signvalue)  
618      dopr_outch (buffer, currlen, maxlen, reallen, signvalue);          /*
619             * Sign
620    /* Zeros */           */
621    if (zpadlen > 0)          if (signvalue)
622    {                  dopr_outch(buffer, currlen, maxlen, reallen, signvalue);
623      while (zpadlen > 0)  
624      {          /*
625        dopr_outch (buffer, currlen, maxlen, reallen, '0');           * Zeros
626        --zpadlen;           */
627      }          if (zpadlen > 0)
628    }          {
629                    while (zpadlen > 0)
630    /* Digits */                  {
631    while (place > 0)                          dopr_outch(buffer, currlen, maxlen, reallen, '0');
632      dopr_outch (buffer, currlen, maxlen, reallen, convert[--place]);                          --zpadlen;
633                      }
634    /* Left Justified spaces */          }
635    while (spadlen < 0) {  
636      dopr_outch (buffer, currlen, maxlen, reallen, ' ');          /*
637      ++spadlen;           * Digits
638    }           */
639  }          while (place > 0)
640                    dopr_outch(buffer, currlen, maxlen, reallen, convert[--place]);
641  static LDOUBLE abs_val (LDOUBLE value)  
642  {          /*
643    LDOUBLE result = value;           * Left Justified spaces
644             */
645    if (value < 0)          while (spadlen < 0)
646      result = -value;          {
647                    dopr_outch(buffer, currlen, maxlen, reallen, ' ');
648    return result;                  ++spadlen;
649  }          }
650    }
651  static LDOUBLE pow10 (int exp)  
652  {  static LDOUBLE abs_val(LDOUBLE value)
653    LDOUBLE result = 1;  {
654            LDOUBLE result = value;
655    while (exp)  
656    {          if (value < 0)
657      result *= 10;                  result = -value;
658      exp--;  
659    }          return result;
660      }
661    return result;  
662  }  static LDOUBLE pow10(int exp)
663    {
664  static long round (LDOUBLE value)          LDOUBLE result = 1;
665  {  
666    long intpart;          while (exp)
667            {
668    intpart = (long)value;                  result *= 10;
669    value = value - intpart;                  exp--;
670    if (value >= 0.5)          }
671      intpart++;  
672            return result;
673    return intpart;  }
674  }  
675    static long round(LDOUBLE value)
676  static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, size_t *reallen,  {
677                     LDOUBLE fvalue, int min, int max, int flags)          long intpart;
678  {  
679    int signvalue = 0;          intpart = (long) value;
680    LDOUBLE ufvalue;          value = value - intpart;
681    char iconvert[20];          if (value >= 0.5)
682    char fconvert[20];                  intpart++;
683    int iplace = 0;  
684    int fplace = 0;          return intpart;
685    int padlen = 0; /* amount to pad */  }
686    int zpadlen = 0;  
687    int caps = 0;  static void fmtfp(char *buffer,
688    long intpart;                                    size_t * currlen,
689    long fracpart;                                    size_t maxlen,
690                                        size_t * reallen,
691    /*                                    LDOUBLE fvalue,
692     * AIX manpage says the default is 0, but Solaris says the default                                    int min,
693     * is 6, and sprintf on AIX defaults to 6                                    int max,
694     */                                    int flags)
695    if (max < 0)  {
696      max = 6;          int signvalue = 0;
697            LDOUBLE ufvalue;
698    ufvalue = abs_val (fvalue);          char iconvert[20];
699            char fconvert[20];
700    if (fvalue < 0)          int iplace = 0;
701      signvalue = '-';          int fplace = 0;
702    else          int padlen = 0;                         /* amount to pad */
703      if (flags & DP_F_PLUS)  /* Do a sign (+/i) */          int zpadlen = 0;
704        signvalue = '+';          int caps = 0;
705      else          long intpart;
706        if (flags & DP_F_SPACE)          long fracpart;
707          signvalue = ' ';  
708            /*
709             * AIX manpage says the default is 0, but Solaris says the default
710             * is 6, and sprintf on AIX defaults to 6
711             */
712            if (max < 0)
713                    max = 6;
714    
715            ufvalue = abs_val(fvalue);
716    
717            if (fvalue < 0)
718                    signvalue = '-';
719            else if (flags & DP_F_PLUS)     /* Do a sign (+/i) */
720                    signvalue = '+';
721            else if (flags & DP_F_SPACE)
722                    signvalue = ' ';
723    
724  #if 0  #if 0
725    if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */          if (flags & DP_F_UP)
726                    caps = 1;                               /* Should characters be upper case? */
727  #endif  #endif
728    
729    intpart = (long)ufvalue;          intpart = (long) ufvalue;
730    
731    /*          /*
732     * Sorry, we only support 9 digits past the decimal because of our           * Sorry, we only support 9 digits past the decimal because of our
733     * conversion method           * conversion method
734     */           */
735    if (max > 9)          if (max > 9)
736      max = 9;                  max = 9;
737    
738    /* We "cheat" by converting the fractional part to integer by          /*
739     * multiplying by a factor of 10           * We "cheat" by converting the fractional part to integer by
740     */           * * multiplying by a factor of 10
741    fracpart = round ((pow10 (max)) * (ufvalue - intpart));           */
742            fracpart = round((pow10(max)) * (ufvalue - intpart));
743    if (fracpart >= pow10 (max))  
744    {          if (fracpart >= pow10(max))
745      intpart++;          {
746      fracpart -= pow10 (max);                  intpart++;
747    }                  fracpart -= pow10(max);
748            }
749    
750  #ifdef DEBUG_SNPRINTF  #ifdef DEBUG_SNPRINTF
751    printf("fmtfp: %g %d.%d min=%d max=%d\n",          printf("fmtfp: %g %d.%d min=%d max=%d\n",
752           (double)fvalue, intpart, fracpart, min, max);                     (double) fvalue, intpart, fracpart, min, max);
753  #endif  #endif
754    
755    /* Convert integer part */          /*
756    do {           * Convert integer part
757      iconvert[iplace++] =           */
758        (caps? "0123456789ABCDEF":"0123456789abcdef")[intpart % 10];          do
759      intpart = (intpart / 10);          {
760    } while(intpart && (iplace < 20));                  iconvert[iplace++] =
761    if (iplace == 20) iplace--;                          (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10];
762    iconvert[iplace] = 0;                  intpart = (intpart / 10);
763            } while (intpart && (iplace < 20));
764    /* Convert fractional part */          if (iplace == 20)
765    do {                  iplace--;
766      fconvert[fplace++] =          iconvert[iplace] = 0;
767        (caps? "0123456789ABCDEF":"0123456789abcdef")[fracpart % 10];  
768      fracpart = (fracpart / 10);          /*
769    } while(fracpart && (fplace < 20));           * Convert fractional part
770    if (fplace == 20) fplace--;           */
771    fconvert[fplace] = 0;          do
772            {
773    /* -1 for decimal point, another -1 if we are printing a sign */                  fconvert[fplace++] =
774    padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);                          (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 10];
775    zpadlen = max - fplace;                  fracpart = (fracpart / 10);
776    if (zpadlen < 0)          } while (fracpart && (fplace < 20));
777      zpadlen = 0;          if (fplace == 20)
778    if (padlen < 0)                  fplace--;
779      padlen = 0;          fconvert[fplace] = 0;
780    if (flags & DP_F_MINUS)  
781      padlen = -padlen; /* Left Justifty */          /*
782             * -1 for decimal point, another -1 if we are printing a sign
783    if ((flags & DP_F_ZERO) && (padlen > 0))           */
784    {          padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
785      if (signvalue)          zpadlen = max - fplace;
786      {          if (zpadlen < 0)
787        dopr_outch (buffer, currlen, maxlen, reallen, signvalue);                  zpadlen = 0;
788        --padlen;          if (padlen < 0)
789        signvalue = 0;                  padlen = 0;
790      }          if (flags & DP_F_MINUS)
791      while (padlen > 0)                  padlen = -padlen;               /* Left Justifty */
     {  
       dopr_outch (buffer, currlen, maxlen, reallen, '0');  
       --padlen;  
     }  
   }  
   while (padlen > 0)  
   {  
     dopr_outch (buffer, currlen, maxlen, reallen, ' ');  
     --padlen;  
   }  
   if (signvalue)  
     dopr_outch (buffer, currlen, maxlen, reallen, signvalue);  
792    
793    while (iplace > 0)          if ((flags & DP_F_ZERO) && (padlen > 0))
794      dopr_outch (buffer, currlen, maxlen, reallen, iconvert[--iplace]);          {
795                    if (signvalue)
796                    {
797                            dopr_outch(buffer, currlen, maxlen, reallen, signvalue);
798                            --padlen;
799                            signvalue = 0;
800                    }
801                    while (padlen > 0)
802                    {
803                            dopr_outch(buffer, currlen, maxlen, reallen, '0');
804                            --padlen;
805                    }
806            }
807            while (padlen > 0)
808            {
809                    dopr_outch(buffer, currlen, maxlen, reallen, ' ');
810                    --padlen;
811            }
812            if (signvalue)
813                    dopr_outch(buffer, currlen, maxlen, reallen, signvalue);
814    
815            while (iplace > 0)
816                    dopr_outch(buffer, currlen, maxlen, reallen, iconvert[--iplace]);
817    
818  #ifdef DEBUG_SNPRINTF  #ifdef DEBUG_SNPRINTF
819    printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);          printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
820  #endif  #endif
821    
822    /*          /*
823     * Decimal point.  This should probably use locale to find the correct           * Decimal point.  This should probably use locale to find the correct
824     * char to print out.           * char to print out.
825     */           */
826    if (max > 0) {          if (max > 0)
827            dopr_outch (buffer, currlen, maxlen, reallen, '.');          {
828                    dopr_outch(buffer, currlen, maxlen, reallen, '.');
829            while (fplace > 0)  
830                    dopr_outch (buffer, currlen, maxlen, reallen, fconvert[--fplace]);                  while (fplace > 0)
831    }                          dopr_outch(buffer, currlen, maxlen, reallen, fconvert[--fplace]);
832            }
833    while (zpadlen > 0)  
834    {          while (zpadlen > 0)
835      dopr_outch (buffer, currlen, maxlen, reallen, '0');          {
836      --zpadlen;                  dopr_outch(buffer, currlen, maxlen, reallen, '0');
837    }                  --zpadlen;
838            }
839    while (padlen < 0)  
840    {          while (padlen < 0)
841      dopr_outch (buffer, currlen, maxlen, reallen, ' ');          {
842      ++padlen;                  dopr_outch(buffer, currlen, maxlen, reallen, ' ');
843    }                  ++padlen;
844            }
845  }  }
846    
847  static void dopr_outch (char *buffer, size_t *currlen, size_t maxlen, size_t *reallen, char c)  static void dopr_outch(char *buffer,
848                                               size_t * currlen,
849                                               size_t maxlen,
850                                               size_t * reallen,
851                                               char c)
852  {  {
853    if (buffer != NULL && maxlen > 0 && *currlen < maxlen)          if (buffer != NULL && maxlen > 0 && *currlen < maxlen)
854      buffer[(*currlen)++] = c;                  buffer[(*currlen)++] = c;
855    
856    (*reallen)++;          (*reallen)++;
857  }  }
858  #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */  #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
859    
860  #ifndef HAVE_VSNPRINTF  #ifndef HAVE_VSNPRINTF
861   int vsnprintf (char *str, size_t count, const char *fmt, va_list args)  int vsnprintf(char *str,
862  {                            size_t count,
863    if (str != NULL)                            const char *fmt,
864      str[0] = 0;                            va_list args)
865    return dopr(str, count, fmt, args);  {
866            if (str != NULL)
867                    str[0] = 0;
868            return dopr(str, count, fmt, args);
869  }  }
870  #endif /* !HAVE_VSNPRINTF */  #endif /* !HAVE_VSNPRINTF */
871    
872  #ifndef HAVE_SNPRINTF  #ifndef HAVE_SNPRINTF
873    
874  /* VARARGS3 */  /* VARARGS3 */
875  #ifdef HAVE_STDARGS  #ifdef HAVE_STDARGS
876   int snprintf (char *str,size_t count,const char *fmt,...)  int snprintf(char *str,
877                             size_t count,
878                             const char *fmt,
879                             ...)
880  #else  #else
881   int snprintf (va_alist) va_dcl  int snprintf(va_alist)
882    va_dcl
883  #endif  #endif
884  {  {
885  #ifndef HAVE_STDARGS  #ifndef HAVE_STDARGS
886    char *str;          char *str;
887    size_t count;          size_t count;
888    char *fmt;          char *fmt;
889  #endif  #endif
890    VA_LOCAL_DECL;          VA_LOCAL_DECL;
891    int result;          int result;
       
   VA_START (fmt);  
   VA_SHIFT (str, char *);  
   VA_SHIFT (count, size_t );  
   VA_SHIFT (fmt, char *);  
   result = vsnprintf(str, count, fmt, ap);  
   VA_END;  
892    
893    return result;          VA_START(fmt);
894  }          VA_SHIFT(str, char *);
895    
896            VA_SHIFT(count, size_t);
897            VA_SHIFT(fmt, char *);
898    
899            result = vsnprintf(str, count, fmt, ap);
900            VA_END;
901    
902            return result;
903    }
904    
905  #else  #else
906   /* keep compilers happy about empty files */   /*
907   void dummy_snprintf(void) {}    * keep compilers happy about empty files
908      */
909    void dummy_snprintf(void)
910    {
911    }
912  #endif /* !HAVE_SNPRINTF */  #endif /* !HAVE_SNPRINTF */
913    
914  #ifdef TEST_SNPRINTF  #ifdef TEST_SNPRINTF
915  #ifndef LONG_STRING  #ifndef LONG_STRING
916  #define LONG_STRING 1024  #define LONG_STRING 1024
917  #endif  #endif
918   int main (void)  int main(void)
919  {  {
920    char buf1[LONG_STRING];          char buf1[LONG_STRING];
921    char buf2[LONG_STRING];          char buf2[LONG_STRING];
922    char *fp_fmt[] = {          char *fp_fmt[] = {
923      "%-1.5f",                  "%-1.5f",
924      "%1.5f",                  "%1.5f",
925      "%123.9f",                  "%123.9f",
926      "%10.5f",                  "%10.5f",
927      "% 10.5f",                  "% 10.5f",
928      "%+22.9f",                  "%+22.9f",
929      "%+4.9f",                  "%+4.9f",
930      "%01.3f",                  "%01.3f",
931      "%4f",                  "%4f",
932      "%3.1f",                  "%3.1f",
933      "%3.2f",                  "%3.2f",
934      "%.0f",                  "%.0f",
935      "%.1f",                  "%.1f",
936      NULL                  NULL
937    };          };
938    double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,          double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
939      0.9996, 1.996, 4.136, 0};                  0.9996, 1.996, 4.136, 0
940    char *int_fmt[] = {          };
941      "%-1.5d",          char *int_fmt[] = {
942      "%1.5d",                  "%-1.5d",
943      "%123.9d",                  "%1.5d",
944      "%5.5d",                  "%123.9d",
945      "%10.5d",                  "%5.5d",
946      "% 10.5d",                  "%10.5d",
947      "%+22.33d",                  "% 10.5d",
948      "%01.3d",                  "%+22.33d",
949      "%4d",                  "%01.3d",
950      NULL                  "%4d",
951    };                  NULL
952    long int_nums[] = { -1, 134, 91340, 341, 0203, 0};          };
953    int x, y;          long int_nums[] = { -1, 134, 91340, 341, 0203, 0 };
954    int fail = 0;          int x, y;
955    int num = 0;          int fail = 0;
956            int num = 0;
957    printf ("Testing snprintf format codes against system sprintf...\n");  
958            printf("Testing snprintf format codes against system sprintf...\n");
959    for (x = 0; fp_fmt[x] != NULL ; x++)  
960      for (y = 0; fp_nums[y] != 0 ; y++)          for (x = 0; fp_fmt[x] != NULL; x++)
961      {                  for (y = 0; fp_nums[y] != 0; y++)
962        snprintf (buf1, sizeof (buf1), fp_fmt[x], fp_nums[y]);                  {
963        sprintf (buf2, fp_fmt[x], fp_nums[y]);                          snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
964        if (strcmp (buf1, buf2))                          sprintf(buf2, fp_fmt[x], fp_nums[y]);
965        {                          if (strcmp(buf1, buf2))
966          printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",                          {
967              fp_fmt[x], buf1, buf2);                                  printf
968          fail++;                                          ("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
969        }                                           fp_fmt[x], buf1, buf2);
970        num++;                                  fail++;
971      }                          }
972                            num++;
973    for (x = 0; int_fmt[x] != NULL ; x++)                  }
974      for (y = 0; int_nums[y] != 0 ; y++)  
975      {          for (x = 0; int_fmt[x] != NULL; x++)
976        snprintf (buf1, sizeof (buf1), int_fmt[x], int_nums[y]);                  for (y = 0; int_nums[y] != 0; y++)
977        sprintf (buf2, int_fmt[x], int_nums[y]);                  {
978        if (strcmp (buf1, buf2))                          snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
979        {                          sprintf(buf2, int_fmt[x], int_nums[y]);
980          printf("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",                          if (strcmp(buf1, buf2))
981              int_fmt[x], buf1, buf2);                          {
982          fail++;                                  printf
983        }                                          ("snprintf doesn't match Format: %s\n\tsnprintf = %s\n\tsprintf  = %s\n",
984        num++;                                           int_fmt[x], buf1, buf2);
985      }                                  fail++;
986    printf ("%d tests failed out of %d.\n", fail, num);                          }
987                            num++;
988                    }
989            printf("%d tests failed out of %d.\n", fail, num);
990  }  }
991  #endif /* SNPRINTF_TEST */  #endif /* SNPRINTF_TEST */

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.1.6.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26