c406d4ad590631c89aaca0ced4f63e39468401ff
[platform/upstream/bash.git] / lib / sh / snprintf.c
1 /* snprintf - formatted output to strings, with bounds checking and allocation */
2
3 /*
4  build a test version with
5    gcc -g -DDRIVER -I../.. -I../../include -o test-snprintf snprintf.c fmtu*long.o
6 */
7  
8 /*
9    Unix snprintf implementation.
10    derived from inetutils/libinetutils/snprintf.c Version 1.1
11
12    Copyright (C) 2001,2006 Free Software Foundation, Inc.
13
14    This file is part of GNU Bash, the Bourne Again SHell.
15
16    Bash is free software: you can redistribute it and/or modify
17    it under the terms of the GNU General Public License as published by
18    the Free Software Foundation, either version 3 of the License, or
19    (at your option) any later version.
20
21    Bash is distributed in the hope that it will be useful,
22    but WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24    GNU General Public License for more details.
25
26    You should have received a copy of the GNU General Public License
27    along with Bash.  If not, see <http://www.gnu.org/licenses/>.
28    
29    Revision History:
30
31    1.1:
32       *  added changes from Miles Bader
33       *  corrected a bug with %f
34       *  added support for %#g
35       *  added more comments :-)
36    1.0:
37       *  supporting must ANSI syntaxic_sugars
38    0.0:
39       *  support %s %c %d
40
41  THANKS(for the patches and ideas):
42      Miles Bader
43      Cyrille Rustom
44      Jacek Slabocewiz
45      Mike Parker(mouse)
46
47 */
48
49 /*
50  * Currently doesn't handle (and bash/readline doesn't use):
51  *      * *M$ width, precision specifications
52  *      * %N$ numbered argument conversions
53  *      * inf, nan floating values imperfect (if isinf(), isnan() not in libc)
54  *      * support for `F' is imperfect with ldfallback(), since underlying
55  *        printf may not handle it -- should ideally have another autoconf test
56  */
57
58 #define FLOATING_POINT
59
60 #ifdef HAVE_CONFIG_H
61 #  include <config.h>
62 #endif
63
64 #if defined(DEBUG)
65 #  undef HAVE_SNPRINTF
66 #  undef HAVE_ASPRINTF
67 #endif
68
69 #if defined(DRIVER) && !defined(HAVE_CONFIG_H)
70 #define HAVE_LONG_LONG
71 #define HAVE_LONG_DOUBLE
72 #ifdef __linux__
73 #define HAVE_PRINTF_A_FORMAT
74 #endif
75 #define HAVE_ISINF_IN_LIBC
76 #define HAVE_ISNAN_IN_LIBC
77 #define PREFER_STDARG
78 #define HAVE_STRINGIZE
79 #define HAVE_LIMITS_H
80 #define HAVE_STDDEF_H
81 #define HAVE_LOCALE_H
82 #define intmax_t long
83 #endif
84
85 #if !defined (HAVE_SNPRINTF) || !defined (HAVE_ASPRINTF)
86
87 #include <bashtypes.h>
88
89 #if defined(PREFER_STDARG)
90 #  include <stdarg.h>
91 #else
92 #  include <varargs.h>
93 #endif
94
95 #ifdef HAVE_LIMITS_H
96 #  include <limits.h>
97 #endif
98 #include <bashansi.h>
99 #ifdef HAVE_STDDEF_H
100 #  include <stddef.h>
101 #endif
102 #include <chartypes.h>
103
104 #ifdef HAVE_STDINT_H
105 #  include <stdint.h>
106 #endif
107
108 #ifdef FLOATING_POINT
109 #  include <float.h>    /* for manifest constants */
110 #  include <stdio.h>    /* for sprintf */
111 #endif
112
113 #include <typemax.h>
114
115 #ifdef HAVE_LOCALE_H
116 #  include <locale.h>
117 #endif
118
119 #include "stdc.h"
120 #include <shmbutil.h>
121
122 #ifndef DRIVER
123 #  include "shell.h"
124 #else
125 #  define FL_PREFIX     0x01    /* add 0x, 0X, or 0 prefix as appropriate */
126 #  define FL_ADDBASE    0x02    /* add base# prefix to converted value */
127 #  define FL_HEXUPPER   0x04    /* use uppercase when converting to hex */
128 #  define FL_UNSIGNED   0x08    /* don't add any sign */
129 extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
130 extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
131 #endif
132
133 #ifndef FREE
134 #  define FREE(x)       if (x) free (x)
135 #endif
136
137 /* Bound on length of the string representing an integer value of type T.
138    Subtract one for the sign bit if T is signed;
139    302 / 1000 is log10 (2) rounded up;
140    add one for integer division truncation;
141    add one more for a minus sign if t is signed.  */
142 #define INT_STRLEN_BOUND(t) \
143   ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
144      + 1 + TYPE_SIGNED (t))
145
146 /* conversion flags */
147 #define PF_ALTFORM      0x00001         /* # */
148 #define PF_HEXPREFIX    0x00002         /* 0[Xx] */
149 #define PF_LADJUST      0x00004         /* - */
150 #define PF_ZEROPAD      0x00008         /* 0 */
151 #define PF_PLUS         0x00010         /* + */
152 #define PF_SPACE        0x00020         /* ' ' */
153 #define PF_THOUSANDS    0x00040         /* ' */
154
155 #define PF_DOT          0x00080         /* `.precision' */
156 #define PF_STAR_P       0x00100         /* `*' after precision */
157 #define PF_STAR_W       0x00200         /* `*' before or without precision */
158
159 /* length modifiers */
160 #define PF_SIGNEDCHAR   0x00400         /* hh */
161 #define PF_SHORTINT     0x00800         /* h */
162 #define PF_LONGINT      0x01000         /* l */
163 #define PF_LONGLONG     0x02000         /* ll */
164 #define PF_LONGDBL      0x04000         /* L */
165 #define PF_INTMAX_T     0x08000         /* j */
166 #define PF_SIZE_T       0x10000         /* z */
167 #define PF_PTRDIFF_T    0x20000         /* t */
168
169 #define PF_ALLOCBUF     0x40000         /* for asprintf, vasprintf */
170
171 #define PFM_SN          0x01            /* snprintf, vsnprintf */
172 #define PFM_AS          0x02            /* asprintf, vasprintf */
173
174 #define ASBUFSIZE       128
175
176 #define x_digs  "0123456789abcdef"
177 #define X_digs  "0123456789ABCDEF"
178
179 static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
180
181 static int decpoint;
182 static int thoussep;
183 static char *grouping;
184
185 /* 
186  * For the FLOATING POINT FORMAT :
187  *  the challenge was finding a way to
188  *  manipulate the Real numbers without having
189  *  to resort to mathematical function(it
190  *  would require to link with -lm) and not
191  *  going down to the bit pattern(not portable)
192  *
193  *  so a number, a real is:
194
195       real = integral + fraction
196
197       integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
198       fraction = b(1)*10^-1 + b(2)*10^-2 + ...
199
200       where:
201        0 <= a(i) => 9 
202        0 <= b(i) => 9 
203  
204     from then it was simple math
205  */
206
207 /*
208  * size of the buffer for the integral part
209  * and the fraction part 
210  */
211 #define MAX_INT  99 + 1 /* 1 for the null */
212 #define MAX_FRACT 307 + 1
213
214 /* 
215  * These functions use static buffers to store the results,
216  * and so are not reentrant
217  */
218 #define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0);
219 #define dtoa(n, p, f) numtoa(n, 10, p, f)
220
221 #define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
222
223 #define GETARG(type)    (va_arg(args, type))
224
225 /* Macros that do proper sign extension and handle length modifiers.  Used
226    for the integer conversion specifiers. */
227 #define GETSIGNED(p) \
228   (((p)->flags & PF_LONGINT) \
229         ? GETARG (long) \
230         : (((p)->flags & PF_SHORTINT) ? (long)(short)GETARG (int) \
231                                       : (long)GETARG (int)))
232
233 #define GETUNSIGNED(p) \
234   (((p)->flags & PF_LONGINT) \
235         ? GETARG (unsigned long) \
236         : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)GETARG (int) \
237                                       : (unsigned long)GETARG (unsigned int)))
238
239
240 #ifdef HAVE_LONG_DOUBLE
241 #define GETLDOUBLE(p) GETARG (long double)
242 #endif
243 #define GETDOUBLE(p) GETARG (double)
244
245 #define SET_SIZE_FLAGS(p, type) \
246   if (sizeof (type) > sizeof (int)) \
247     (p)->flags |= PF_LONGINT; \
248   if (sizeof (type) > sizeof (long)) \
249     (p)->flags |= PF_LONGLONG;
250
251 /* this struct holds everything we need */
252 struct DATA
253 {
254   int length;
255   char *base;           /* needed for [v]asprintf */
256   char *holder;
257   int counter;
258   const char *pf;
259
260 /* FLAGS */
261   int flags;
262   int justify;
263   int width, precision;
264   char pad;
265 };
266
267 /* the floating point stuff */
268 #ifdef FLOATING_POINT
269 static double pow_10 __P((int));
270 static int log_10 __P((double));
271 static double integral __P((double, double *));
272 static char *numtoa __P((double, int, int, char **));
273 #endif
274
275 static void init_data __P((struct DATA *, char *, size_t, const char *, int));
276 static void init_conv_flag __P((struct DATA *));
277
278 /* for the format */
279 #ifdef FLOATING_POINT
280 static void floating __P((struct DATA *, double));
281 static void exponent __P((struct DATA *, double));
282 #endif
283 static void number __P((struct DATA *, unsigned long, int));
284 #ifdef HAVE_LONG_LONG
285 static void lnumber __P((struct DATA *, unsigned long long, int));
286 #endif
287 static void pointer __P((struct DATA *, unsigned long));
288 static void strings __P((struct DATA *, char *));
289
290 #ifdef FLOATING_POINT
291 #  define FALLBACK_FMTSIZE      32
292 #  define FALLBACK_BASE         4096
293 #  define LFALLBACK_BASE        5120
294 #  ifdef HAVE_LONG_DOUBLE
295 static void ldfallback __P((struct DATA *, const char *, const char *, long double));
296 #  endif
297 static void dfallback __P((struct DATA *, const char *, const char *, double));
298 #endif
299
300 static char *groupnum __P((char *));
301
302 #ifdef DRIVER
303 static void memory_error_and_abort ();
304 static void *xmalloc __P((size_t));
305 static void *xrealloc __P((void *, size_t));
306 static void xfree __P((void *));
307 #else
308 #  include <xmalloc.h>
309 #endif
310
311 /* those are defines specific to snprintf to hopefully
312  * make the code clearer :-)
313  */
314 #define RIGHT 1
315 #define LEFT  0
316 #define NOT_FOUND -1
317 #define FOUND 1
318 #define MAX_FIELD 15
319
320 /* round off to the precision */
321 #define ROUND(d, p) \
322             (d < 0.) ? \
323              d - pow_10(-(p)->precision) * 0.5 : \
324              d + pow_10(-(p)->precision) * 0.5
325
326 /* set default precision */
327 #define DEF_PREC(p) \
328             if ((p)->precision == NOT_FOUND) \
329               (p)->precision = 6
330
331 /* put a char.  increment the number of chars written even if we've exceeded
332    the vsnprintf/snprintf buffer size (for the return value) */
333 #define PUT_CHAR(c, p) \
334         do \
335           { \
336             if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \
337               { \
338                 (p)->length += ASBUFSIZE; \
339                 (p)->base = (char *)xrealloc((p)->base, (p)->length); \
340                 (p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \
341               } \
342             if ((p)->counter < (p)->length) \
343               *(p)->holder++ = (c); \
344             (p)->counter++; \
345           } \
346         while (0)
347
348 /* Output a string.  P->WIDTH has already been adjusted for padding. */
349 #define PUT_STRING(string, len, p) \
350         do \
351           { \
352             PAD_RIGHT (p); \
353             while ((len)-- > 0) \
354               { \
355                 PUT_CHAR (*(string), (p)); \
356                 (string)++; \
357               } \
358             PAD_LEFT (p); \
359           } \
360         while (0)
361
362 #define PUT_PLUS(d, p, zero) \
363             if ((d) > zero && (p)->justify == RIGHT) \
364               PUT_CHAR('+', p)
365
366 #define PUT_SPACE(d, p, zero) \
367             if (((p)->flags & PF_SPACE) && (d) > zero) \
368               PUT_CHAR(' ', p)
369
370 /* pad right */ 
371 #define PAD_RIGHT(p) \
372             if ((p)->width > 0 && (p)->justify != LEFT) \
373               for (; (p)->width > 0; (p)->width--) \
374                  PUT_CHAR((p)->pad, p)
375
376 /* pad left */
377 #define PAD_LEFT(p) \
378             if ((p)->width > 0 && (p)->justify == LEFT) \
379               for (; (p)->width > 0; (p)->width--) \
380                  PUT_CHAR((p)->pad, p)
381
382 /* pad with zeros from decimal precision */
383 #define PAD_ZERO(p) \
384         if ((p)->precision > 0) \
385           for (; (p)->precision > 0; (p)->precision--) \
386             PUT_CHAR('0', p)
387
388 /* if width and prec. in the args */
389 #define STAR_ARGS(p) \
390         do { \
391             if ((p)->flags & PF_STAR_W) \
392               { \
393                 (p)->width = GETARG (int); \
394                 if ((p)->width < 0) \
395                   { \
396                     (p)->flags |= PF_LADJUST; \
397                     (p)->justify = LEFT; \
398                     (p)->width = -(p)->width; \
399                   } \
400               } \
401             if ((p)->flags & PF_STAR_P) \
402               { \
403                 (p)->precision = GETARG (int); \
404                 if ((p)->precision < 0) \
405                   { \
406                     (p)->flags &= ~PF_STAR_P; \
407                     (p)->precision = NOT_FOUND; \
408                   } \
409               } \
410         } while (0)
411
412 #if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV)
413 #  define GETLOCALEDATA(d, t, g) \
414       do \
415         { \
416           struct lconv *lv; \
417           if ((d) == 0) { \
418           (d) = '.'; (t) = -1; (g) = 0; /* defaults */ \
419           lv = localeconv(); \
420           if (lv) \
421             { \
422               if (lv->decimal_point && lv->decimal_point[0]) \
423                 (d) = lv->decimal_point[0]; \
424               if (lv->thousands_sep && lv->thousands_sep[0]) \
425                 (t) = lv->thousands_sep[0]; \
426               (g) = lv->grouping ? lv->grouping : ""; \
427               if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \
428             } \
429           } \
430         } \
431       while (0);
432 #else
433 #  define GETLOCALEDATA(d, t, g) \
434       ( (d) = '.', (t) = ',', g = "\003" )
435 #endif
436
437 #ifdef FLOATING_POINT
438 /*
439  * Find the nth power of 10
440  */
441 static double
442 pow_10(n)
443      int n;
444
445   double P;
446
447   /* handle common cases with fast switch statement. */
448   switch (n)
449     {
450     case -3:    return .001;
451     case -2:    return .01;
452     case -1:    return .1;
453     case 0:     return 1.;
454     case 1:     return 10.;
455     case 2:     return 100.;
456     case 3:     return 1000.;
457     }
458
459   if (n < 0)
460     {
461       P = .0001;
462       for (n += 4; n < 0; n++)
463         P /= 10.;
464     }
465   else
466     {
467       P = 10000.;
468       for (n -= 4; n > 0; n--)
469         P *= 10.;
470     }
471
472   return P;
473 }
474
475 /*
476  * Find the integral part of the log in base 10 
477  * Note: this not a real log10()
478          I just need and approximation(integerpart) of x in:
479           10^x ~= r
480  * log_10(200) = 2;
481  * log_10(250) = 2;
482  *
483  * NOTE: do not call this with r == 0 -- an infinite loop results.
484  */
485 static int
486 log_10(r)
487      double r;
488
489   int i = 0;
490   double result = 1.;
491
492   if (r < 0.)
493     r = -r;
494
495   if (r < 1.)
496     {
497       while (result >= r)
498         {
499           result /= 10.;
500           i++;
501         }
502       return (-i);
503     }
504   else
505     {
506       while (result <= r)
507         {
508           result *= 10.;
509           i++;
510         }
511       return (i - 1);
512     }
513 }
514
515 /*
516  * This function return the fraction part of a double
517  * and set in ip the integral part.
518  * In many ways it resemble the modf() found on most Un*x
519  */
520 static double
521 integral(real, ip)
522      double real;
523      double *ip;
524
525   int j;
526   double i, s, p;
527   double real_integral = 0.;
528
529   /* take care of the obvious */
530   /* equal to zero ? */
531   if (real == 0.)
532     {
533       *ip = 0.;
534       return (0.);
535     }
536
537   /* negative number ? */
538   if (real < 0.)
539     real = -real;
540
541   /* a fraction ? */
542   if ( real < 1.)
543     {
544       *ip = 0.;
545       return real;
546     }
547
548   /* the real work :-) */
549   for (j = log_10(real); j >= 0; j--)
550     {
551       p = pow_10(j);
552       s = (real - real_integral)/p;
553       i = 0.;
554       while (i + 1. <= s)
555         i++;
556       real_integral += i*p;
557     }
558   *ip = real_integral;
559   return (real - real_integral);
560 }
561
562 #define PRECISION 1.e-6
563 /* 
564  * return an ascii representation of the integral part of the number
565  * and set fract to be an ascii representation of the fraction part
566  * the container for the fraction and the integral part or staticly
567  * declare with fix size 
568  */
569 static char *
570 numtoa(number, base, precision, fract)
571      double number;
572      int base, precision;
573      char **fract;
574 {
575   register int i, j;
576   double ip, fp; /* integer and fraction part */
577   double fraction;
578   int digits = MAX_INT - 1;
579   static char integral_part[MAX_INT];
580   static char fraction_part[MAX_FRACT];
581   double sign;
582   int ch;
583
584   /* taking care of the obvious case: 0.0 */
585   if (number == 0.)
586     { 
587       integral_part[0] = '0';
588       integral_part[1] = '\0';
589       /* The fractional part has to take the precision into account */
590       for (ch = 0; ch < precision-1; ch++)
591         fraction_part[ch] = '0';
592       fraction_part[ch] = '0';
593       fraction_part[ch+1] = '\0';
594       if (fract)
595         *fract = fraction_part;
596       return integral_part;
597     }
598
599   /* for negative numbers */
600   if ((sign = number) < 0.)
601     {
602       number = -number;
603       digits--; /* sign consume one digit */
604     }
605
606   fraction = integral(number, &ip);
607   number = ip;
608
609   /* do the integral part */
610   if (ip == 0.)
611     {
612       integral_part[0] = '0';
613       i = 1;
614     }
615   else
616     {
617       for ( i = 0; i < digits && number != 0.; ++i)
618         {
619           number /= base;
620           fp = integral(number, &ip);
621           ch = (int)((fp + PRECISION)*base); /* force to round */
622           integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
623           if (! ISXDIGIT((unsigned char)integral_part[i]))
624             break;      /* bail out overflow !! */
625           number = ip;
626          }
627     }
628      
629   /* Oh No !! out of bound, ho well fill it up ! */
630   if (number != 0.)
631     for (i = 0; i < digits; ++i)
632       integral_part[i] = '9';
633
634   /* put the sign ? */
635   if (sign < 0.)
636     integral_part[i++] = '-';
637
638   integral_part[i] = '\0';
639
640   /* reverse every thing */
641   for ( i--, j = 0; j < i; j++, i--)
642     SWAP_INT(integral_part[i], integral_part[j]);  
643
644   /* the fractional part */
645   for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--)
646     {
647       fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
648       if (! DIGIT(fraction_part[i])) /* underflow ? */
649         break;
650       fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
651     }
652   fraction_part[i] = '\0';
653
654   if (fract != (char **)0)
655     *fract = fraction_part;
656
657   return integral_part;
658 }
659 #endif
660
661 /* for %d and friends, it puts in holder
662  * the representation with the right padding
663  */
664 static void
665 number(p, d, base)
666      struct DATA *p;
667      unsigned long d;
668      int base;
669 {
670   char *tmp, *t;
671   long sd;
672   int flags;
673
674   /* An explicit precision turns off the zero-padding flag. */
675   if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
676     p->flags &= ~PF_ZEROPAD;
677
678   sd = d;       /* signed for ' ' padding in base 10 */
679   flags = 0;
680   flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
681   if (*p->pf == 'X')
682     flags |= FL_HEXUPPER;
683
684   tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags);
685   t = 0;
686   if ((p->flags & PF_THOUSANDS))
687     {
688       GETLOCALEDATA(decpoint, thoussep, grouping);
689       if (grouping && (t = groupnum (tmp)))
690         tmp = t;
691     }
692
693   p->width -= strlen(tmp);
694   PAD_RIGHT(p);
695
696   if ((p->flags & PF_DOT) && p->precision > 0)
697     {
698       p->precision -= strlen(tmp);
699       PAD_ZERO(p);
700     }
701
702   switch (base)
703     {
704     case 10:
705       PUT_PLUS(sd, p, 0);
706       PUT_SPACE(sd, p, 0);
707       break;
708     case 8:
709       if (p->flags & PF_ALTFORM)
710         PUT_CHAR('0', p);
711       break;
712     case 16:
713       if (p->flags & PF_ALTFORM)
714         {
715           PUT_CHAR('0', p);
716           PUT_CHAR(*p->pf, p);
717         }
718       break;
719     }
720
721   while (*tmp)
722     {
723       PUT_CHAR(*tmp, p);
724       tmp++;
725     }
726
727   PAD_LEFT(p);
728   FREE (t);
729 }
730
731 #ifdef HAVE_LONG_LONG
732 /*
733  * identical to number() but works for `long long'
734  */
735 static void
736 lnumber(p, d, base)
737      struct DATA *p;
738      unsigned long long d;
739      int base;
740 {
741   char *tmp, *t;
742   long long sd;
743   int flags;
744
745   /* An explicit precision turns off the zero-padding flag. */
746   if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
747     p->flags &= ~PF_ZEROPAD;
748
749   sd = d;       /* signed for ' ' padding in base 10 */
750   flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
751   if (*p->pf == 'X')
752     flags |= FL_HEXUPPER;
753
754   tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags);
755   t = 0;
756   if ((p->flags & PF_THOUSANDS))
757     {
758       GETLOCALEDATA(decpoint, thoussep, grouping);
759       if (grouping && (t = groupnum (tmp)))
760         tmp = t;
761     }
762
763   p->width -= strlen(tmp);
764   PAD_RIGHT(p);
765
766   if ((p->flags & PF_DOT) && p->precision > 0)
767     {
768       p->precision -= strlen(tmp);
769       PAD_ZERO(p);
770     }
771
772   switch (base)
773     {
774     case 10:
775       PUT_PLUS(sd, p, 0);
776       PUT_SPACE(sd, p, 0);
777       break;
778     case 8:
779       if (p->flags & PF_ALTFORM)
780         PUT_CHAR('0', p);
781       break;
782     case 16:
783       if (p->flags & PF_ALTFORM)
784         {
785           PUT_CHAR('0', p);
786           PUT_CHAR(*p->pf, p);
787         }
788       break;
789     }
790
791   while (*tmp)
792     {
793       PUT_CHAR(*tmp, p);
794       tmp++;
795     }
796
797   PAD_LEFT(p);
798   FREE (t);
799 }
800 #endif
801
802 static void
803 pointer(p, d)
804      struct DATA *p;
805      unsigned long d;
806 {
807   char *tmp;
808
809   tmp = fmtulong(d, 16, intbuf, sizeof(intbuf), 0);
810   p->width -= strlen(tmp);
811   PAD_RIGHT(p);
812
813   /* prefix '0x' for pointers */
814   PUT_CHAR('0', p);
815   PUT_CHAR('x', p);
816
817   while (*tmp)
818     {
819       PUT_CHAR(*tmp, p);
820       tmp++;
821     }
822
823   PAD_LEFT(p);
824 }
825
826 /* %s strings */
827 static void
828 strings(p, tmp)
829      struct DATA *p;
830      char *tmp;
831 {
832   size_t len;
833
834   len = strlen(tmp);
835   if (p->precision != NOT_FOUND) /* the smallest number */
836     len = (len < p->precision ? len : p->precision);
837   p->width -= len;
838
839   PUT_STRING (tmp, len, p);
840 }
841
842 #if HANDLE_MULTIBYTE
843 /* %ls wide-character strings */
844 static void
845 wstrings(p, tmp)
846      struct DATA *p;
847      wchar_t *tmp;
848 {
849   size_t len;
850   mbstate_t mbs;
851   char *os;
852   const wchar_t *ws;
853
854   memset (&mbs, '\0', sizeof (mbstate_t));
855   ws = (const wchar_t *)tmp;
856
857   os = (char *)NULL;
858   if (p->precision != NOT_FOUND)
859     {
860       os = (char *)xmalloc (p->precision + 1);
861       len = wcsrtombs (os, &ws, p->precision, &mbs);
862     }
863   else
864     {
865       len = wcsrtombs (NULL, &ws, 0, &mbs);
866       if (len != (size_t)-1)
867         {
868           memset (&mbs, '\0', sizeof (mbstate_t));
869           os = (char *)xmalloc (len + 1);
870           (void)wcsrtombs (os, &ws, len + 1, &mbs);
871         }
872     }
873   if (len == (size_t)-1)
874     {
875       /* invalid multibyte sequence; bail now. */
876       FREE (os);      
877       return;
878     }
879
880   p->width -= len;
881   PUT_STRING (os, len, p);
882   free (os);
883 }
884
885 static void
886 wchars (p, wc)
887      struct DATA *p;
888      wint_t wc;
889 {
890   char *lbuf, *l;
891   mbstate_t mbs;
892   size_t len;
893
894   lbuf = (char *)malloc (MB_CUR_MAX+1);
895   if (lbuf == 0)
896     return;
897   memset (&mbs, '\0', sizeof (mbstate_t));
898   len = wcrtomb (lbuf, wc, &mbs);
899   if (len == (size_t)-1)
900     /* conversion failed; bail now. */
901     return;
902   p->width -= len;
903   l = lbuf;
904   PUT_STRING (l, len, p);
905   free (lbuf);
906 }
907 #endif /* HANDLE_MULTIBYTE */
908
909 #ifdef FLOATING_POINT
910
911 #ifndef HAVE_ISINF_IN_LIBC
912 /* Half-assed versions, since we don't want to link with libm. */
913 static int
914 isinf(d)
915      double d;
916 {
917 #ifdef DBL_MAX
918   if (d < DBL_MIN)
919     return -1;
920   else if (d > DBL_MAX)
921     return 1;
922   else
923 #endif
924     return 0;
925 }
926 #endif
927
928 #ifndef HAVE_ISNAN_IN_LIBC
929 static int
930 isnan(d)
931      double d;
932 {
933   return 0;
934 }
935 #endif
936
937 /* Check for [+-]infinity and NaN.  If MODE == 1, we check for Infinity, else
938    (mode == 2) we check for NaN.  This does the necessary printing.  Returns
939    1 if Inf or Nan, 0 if not. */
940 static int
941 chkinfnan(p, d, mode)
942      struct DATA *p;
943      double d;
944      int mode;          /* == 1 for inf, == 2 for nan */
945 {
946   int i;
947   char *tmp;
948   char *big, *small;
949
950   i = (mode == 1) ? isinf(d) : isnan(d);
951   if (i == 0)
952     return 0;
953   big = (mode == 1) ? "INF" : "NAN";
954   small = (mode == 1) ? "inf" : "nan";
955
956   tmp = (*p->pf == 'F' || *p->pf == 'G' || *p->pf == 'E') ? big : small;
957
958   if (i < 0)
959     PUT_CHAR('-', p);
960
961   while (*tmp)
962     {
963       PUT_CHAR (*tmp, p);
964       tmp++;
965     }
966
967   return 1;
968 }
969
970 /* %f %F %g %G floating point representation */
971 static void
972 floating(p, d)
973      struct DATA *p;
974      double d;
975 {
976   char *tmp, *tmp2, *t;
977   int i;
978
979   if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)))
980     return;     /* already printed nan or inf */
981
982   GETLOCALEDATA(decpoint, thoussep, grouping);
983   DEF_PREC(p);
984   d = ROUND(d, p);
985   tmp = dtoa(d, p->precision, &tmp2);
986   t = 0;
987   if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp)))
988     tmp = t;
989
990   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
991     {
992       /* smash the trailing zeros unless altform */
993       for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
994         tmp2[i] = '\0'; 
995       if (tmp2[0] == '\0')
996         p->precision = 0;
997     }
998
999   /* calculate the padding. 1 for the dot */
1000   p->width = p->width -
1001             ((d > 0. && p->justify == RIGHT) ? 1:0) -
1002             ((p->flags & PF_SPACE) ? 1:0) -
1003             strlen(tmp) - p->precision -
1004             ((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0);   /* radix char */
1005   PAD_RIGHT(p);  
1006   PUT_PLUS(d, p, 0.);
1007   PUT_SPACE(d, p, 0.);
1008
1009   while (*tmp)
1010     {
1011       PUT_CHAR(*tmp, p);        /* the integral */
1012       tmp++;
1013     }
1014   FREE (t);
1015
1016   if (p->precision != 0 || (p->flags & PF_ALTFORM))
1017     PUT_CHAR(decpoint, p);  /* put the '.' */
1018
1019   for (; *tmp2; tmp2++)
1020     PUT_CHAR(*tmp2, p); /* the fraction */
1021   
1022   PAD_LEFT(p);
1023
1024
1025 /* %e %E %g %G exponent representation */
1026 static void
1027 exponent(p, d)
1028      struct DATA *p;
1029      double d;
1030 {
1031   char *tmp, *tmp2;
1032   int j, i;
1033
1034   if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)))
1035     return;     /* already printed nan or inf */
1036
1037   GETLOCALEDATA(decpoint, thoussep, grouping);
1038   DEF_PREC(p);
1039   if (d == 0.)
1040     j = 0;
1041   else
1042     {
1043       j = log_10(d);
1044       d = d / pow_10(j);  /* get the Mantissa */
1045       d = ROUND(d, p);            
1046     }
1047   tmp = dtoa(d, p->precision, &tmp2);
1048
1049   /* 1 for unit, 1 for the '.', 1 for 'e|E',
1050    * 1 for '+|-', 2 for 'exp' */
1051   /* calculate how much padding need */
1052   p->width = p->width - 
1053              ((d > 0. && p->justify == RIGHT) ? 1:0) -
1054              ((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
1055
1056   PAD_RIGHT(p);
1057   PUT_PLUS(d, p, 0.);
1058   PUT_SPACE(d, p, 0.);
1059
1060   while (*tmp)
1061     {
1062       PUT_CHAR(*tmp, p);
1063       tmp++;
1064     }
1065
1066   if (p->precision != 0 || (p->flags & PF_ALTFORM))
1067       PUT_CHAR(decpoint, p);  /* the '.' */
1068
1069   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
1070     /* smash the trailing zeros unless altform */
1071     for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
1072       tmp2[i] = '\0'; 
1073
1074   for (; *tmp2; tmp2++)
1075     PUT_CHAR(*tmp2, p); /* the fraction */
1076
1077   /* the exponent put the 'e|E' */
1078   if (*p->pf == 'g' || *p->pf == 'e')
1079     PUT_CHAR('e', p);
1080   else
1081     PUT_CHAR('E', p);
1082
1083   /* the sign of the exp */
1084   if (j >= 0)
1085     PUT_CHAR('+', p);
1086   else
1087     {
1088       PUT_CHAR('-', p);
1089       j = -j;
1090     }
1091
1092    tmp = itoa(j);
1093    /* pad out to at least two spaces.  pad with `0' if the exponent is a
1094       single digit. */
1095    if (j <= 9)
1096      PUT_CHAR('0', p);
1097
1098    /* the exponent */
1099    while (*tmp)
1100      {
1101        PUT_CHAR(*tmp, p);
1102        tmp++;
1103      }
1104
1105    PAD_LEFT(p);
1106 }
1107 #endif
1108
1109 /* Return a new string with the digits in S grouped according to the locale's
1110    grouping info and thousands separator.  If no grouping should be performed,
1111    this returns NULL; the caller needs to check for it. */
1112 static char *
1113 groupnum (s)
1114      char *s;
1115 {
1116   char *se, *ret, *re, *g;
1117   int len, slen;
1118
1119   if (grouping == 0 || *grouping <= 0 || *grouping == CHAR_MAX)
1120     return ((char *)NULL);
1121
1122   /* find min grouping to size returned string */
1123   for (len = *grouping, g = grouping; *g; g++)
1124       if (*g > 0 && *g < len)
1125         len = *g;
1126
1127   slen = strlen (s);
1128   len = slen / len + 1;
1129   ret = (char *)xmalloc (slen + len + 1);
1130   re = ret + slen + len;
1131   *re = '\0';
1132
1133   g = grouping;
1134   se = s + slen;
1135   len = *g;
1136
1137   while (se > s)
1138     {
1139       *--re = *--se;
1140
1141       /* handle `-' inserted by numtoa() and the fmtu* family here. */
1142       if (se > s && se[-1] == '-')
1143         continue;
1144
1145       /* begin new group. */
1146       if (--len == 0 && se > s)
1147         {
1148           *--re = thoussep;
1149           len = *++g;           /* was g++, but that uses first char twice (glibc bug, too) */
1150           if (*g == '\0')
1151             len = *--g;         /* use previous grouping */
1152           else if (*g == CHAR_MAX)
1153             {
1154               do
1155                 *--re = *--se;
1156               while (se > s);
1157               break;
1158             }
1159         }
1160     }
1161
1162   if (re > ret)
1163 #ifdef HAVE_MEMMOVE
1164     memmove (ret, re, strlen (re) + 1);
1165 #else
1166     strcpy (ret, re);
1167 #endif
1168    
1169   return ret;
1170 }
1171
1172 /* initialize the conversion specifiers */
1173 static void
1174 init_conv_flag (p)
1175      struct DATA *p;
1176 {
1177   p->flags &= PF_ALLOCBUF;              /* preserve PF_ALLOCBUF flag */
1178   p->precision = p->width = NOT_FOUND;
1179   p->justify = NOT_FOUND;
1180   p->pad = ' ';
1181 }
1182
1183 static void
1184 init_data (p, string, length, format, mode)
1185      struct DATA *p;
1186      char *string;
1187      size_t length;
1188      const char *format;
1189      int mode;
1190 {
1191   p->length = length - 1; /* leave room for '\0' */
1192   p->holder = p->base = string;
1193   p->pf = format;
1194   p->counter = 0;
1195   p->flags = (mode == PFM_AS) ? PF_ALLOCBUF : 0;
1196 }
1197
1198 static int
1199 #if defined (__STDC__)
1200 vsnprintf_internal(struct DATA *data, char *string, size_t length, const char *format, va_list args)
1201 #else
1202 vsnprintf_internal(data, string, length, format, args)
1203      struct DATA *data;
1204      char *string;
1205      size_t length;
1206      const char *format;
1207      va_list args;
1208 #endif
1209 {
1210   double d; /* temporary holder */
1211 #ifdef HAVE_LONG_DOUBLE
1212   long double ld;       /* for later */
1213 #endif
1214   unsigned long ul;
1215 #ifdef HAVE_LONG_LONG
1216   unsigned long long ull;
1217 #endif
1218   int state, i, c, n;
1219   char *s;
1220 #if HANDLE_MULTIBYTE
1221   wchar_t *ws;
1222   wint_t wc;
1223 #endif
1224   const char *convstart;
1225   int negprec;
1226
1227   /* Sanity check, the string length must be >= 0.  C99 actually says that
1228      LENGTH can be zero here, in the case of snprintf/vsnprintf (it's never
1229      0 in the case of asprintf/vasprintf), and the return value is the number
1230      of characters that would have been written. */
1231   if (length < 0)
1232     return -1;
1233
1234   if (format == 0)
1235     return 0;
1236
1237   /* Reset these for each call because the locale might have changed. */
1238   decpoint = thoussep = 0;
1239   grouping = 0;
1240
1241   negprec = 0;
1242   for (; c = *(data->pf); data->pf++)
1243     {
1244       if (c != '%')
1245         {
1246           PUT_CHAR (c, data);
1247           continue;
1248         }
1249
1250       convstart = data->pf;
1251       init_conv_flag (data); /* initialise format flags */
1252
1253       state = 1;
1254       for (state = 1; state && *data->pf; )
1255         {
1256           c = *(++data->pf);
1257               /* fmtend = data->pf */
1258 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1259           if (data->flags & PF_LONGDBL)
1260             {
1261               switch (c)
1262                 {
1263                 case 'f': case 'F':
1264                 case 'e': case 'E':
1265                 case 'g': case 'G':
1266 #  ifdef HAVE_PRINTF_A_FORMAT
1267                 case 'a': case 'A':
1268 #  endif
1269                   STAR_ARGS (data);
1270                   ld = GETLDOUBLE (data);
1271                   ldfallback (data, convstart, data->pf, ld);
1272                   goto conv_break;
1273                 }
1274             }
1275 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1276
1277           switch (c)
1278             {
1279               /* Parse format flags */
1280               case '\0': /* a NULL here ? ? bail out */
1281                 *data->holder = '\0';
1282                 return data->counter;
1283                 break;
1284               case '#':
1285                 data->flags |= PF_ALTFORM;
1286                 continue;
1287               case '0':
1288                 data->flags |= PF_ZEROPAD;
1289                 data->pad = '0';
1290                 continue;
1291               case '*':
1292                 if (data->flags & PF_DOT)
1293                   data->flags |= PF_STAR_P;
1294                 else
1295                   data->flags |= PF_STAR_W;
1296                 continue;
1297               case '-':
1298                 if ((data->flags & PF_DOT) == 0)
1299                   {
1300                     data->flags |= PF_LADJUST;
1301                     data->justify = LEFT;
1302                   }
1303                 else
1304                   negprec = 1;
1305                 continue;
1306               case ' ':
1307                 if ((data->flags & PF_PLUS) == 0)
1308                   data->flags |= PF_SPACE;
1309                 continue;
1310               case '+':
1311                 if ((data->flags & PF_DOT) == 0)
1312                   {
1313                     data->flags |= PF_PLUS;
1314                     data->justify = RIGHT;
1315                   }
1316                 continue;
1317               case '\'':
1318                 data->flags |= PF_THOUSANDS;
1319                 continue;
1320
1321               case '1': case '2': case '3':
1322               case '4': case '5': case '6':
1323               case '7': case '8': case '9':
1324                 n = 0;
1325                 do
1326                   {
1327                     n = n * 10 + TODIGIT(c);
1328                     c = *(++data->pf);
1329                   }
1330                 while (DIGIT(c));
1331                 data->pf--;             /* went too far */
1332                 if (n < 0)
1333                   n = 0;
1334                 if (data->flags & PF_DOT)
1335                   data->precision = negprec ? NOT_FOUND : n;
1336                 else
1337                   data->width = n;
1338                 continue;
1339
1340               /* optional precision */
1341               case '.':
1342                 data->flags |= PF_DOT;
1343                 data->precision = 0;
1344                 continue;
1345
1346               /* length modifiers */
1347               case 'h':
1348                 data->flags |= (data->flags & PF_SHORTINT) ? PF_SIGNEDCHAR : PF_SHORTINT;
1349                 continue;
1350               case 'l':
1351                 data->flags |= (data->flags & PF_LONGINT) ? PF_LONGLONG : PF_LONGINT;
1352                 continue;
1353               case 'L':
1354                 data->flags |= PF_LONGDBL;
1355                 continue;
1356               case 'q':
1357                 data->flags |= PF_LONGLONG;
1358                 continue;
1359               case 'j':
1360                 data->flags |= PF_INTMAX_T;
1361                 SET_SIZE_FLAGS(data, intmax_t);
1362                 continue;
1363               case 'z':
1364                 data->flags |= PF_SIZE_T;
1365                 SET_SIZE_FLAGS(data, size_t);
1366                 continue;
1367               case 't':
1368                 data->flags |= PF_PTRDIFF_T;
1369                 SET_SIZE_FLAGS(data, ptrdiff_t);
1370                 continue;
1371                 
1372               /* Conversion specifiers */
1373 #ifdef FLOATING_POINT
1374               case 'f':  /* float, double */
1375               case 'F':
1376                 STAR_ARGS(data);
1377                 d = GETDOUBLE(data);
1378                 floating(data, d);
1379 conv_break:             
1380                 state = 0;
1381                 break;
1382               case 'g': 
1383               case 'G':
1384                 STAR_ARGS(data);
1385                 DEF_PREC(data);
1386                 d = GETDOUBLE(data);
1387                 i = (d != 0.) ? log_10(d) : -1;
1388                 /*
1389                  * for '%g|%G' ANSI: use f if exponent
1390                  * is in the range or [-4,p] exclusively
1391                  * else use %e|%E
1392                  */
1393                 if (-4 < i && i < data->precision)
1394                   {
1395                     /* reset precision */
1396                     data->precision -= i + 1;
1397                     floating(data, d);
1398                   }
1399                 else
1400                   {
1401                     /* reduce precision by 1 because of leading digit before
1402                        decimal point in e format. */
1403                     data->precision--;
1404                     exponent(data, d);
1405                   }
1406                 state = 0;
1407                 break;
1408               case 'e':
1409               case 'E':  /* Exponent double */
1410                 STAR_ARGS(data);
1411                 d = GETDOUBLE(data);
1412                 exponent(data, d);
1413                 state = 0;
1414                 break;
1415 #  ifdef HAVE_PRINTF_A_FORMAT
1416               case 'a':
1417               case 'A':
1418                 STAR_ARGS(data);
1419                 d = GETDOUBLE(data);
1420                 dfallback(data, convstart, data->pf, d);
1421                 state = 0;
1422                 break;
1423 #  endif /* HAVE_PRINTF_A_FORMAT */
1424 #endif /* FLOATING_POINT */
1425               case 'U':
1426                 data->flags |= PF_LONGINT;
1427                 /* FALLTHROUGH */
1428               case 'u':
1429                 STAR_ARGS(data);
1430 #ifdef HAVE_LONG_LONG
1431                 if (data->flags & PF_LONGLONG)
1432                   {
1433                     ull = GETARG (unsigned long long);
1434                     lnumber(data, ull, 10);
1435                   }
1436                 else
1437 #endif
1438                   {
1439                     ul = GETUNSIGNED(data);
1440                     number(data, ul, 10);
1441                   }
1442                 state = 0;
1443                 break;
1444               case 'D':
1445                 data->flags |= PF_LONGINT;
1446                 /* FALLTHROUGH */
1447               case 'd':  /* decimal */
1448               case 'i':
1449                 STAR_ARGS(data);
1450 #ifdef HAVE_LONG_LONG
1451                 if (data->flags & PF_LONGLONG)
1452                   {
1453                     ull = GETARG (long long);
1454                     lnumber(data, ull, 10);
1455                   }
1456                 else
1457 #endif
1458                   {
1459                     ul = GETSIGNED(data);
1460                     number(data, ul, 10);
1461                   }
1462                 state = 0;
1463                 break;
1464               case 'o':  /* octal */
1465                 STAR_ARGS(data);
1466 #ifdef HAVE_LONG_LONG
1467                 if (data->flags & PF_LONGLONG)
1468                   {
1469                     ull = GETARG (unsigned long long);
1470                     lnumber(data, ull, 8);
1471                   }
1472                 else
1473 #endif
1474                   {
1475                     ul = GETUNSIGNED(data);
1476                     number(data, ul, 8);
1477                   }
1478                 state = 0;
1479                 break;
1480               case 'x': 
1481               case 'X':  /* hexadecimal */
1482                 STAR_ARGS(data);
1483 #ifdef HAVE_LONG_LONG
1484                 if (data->flags & PF_LONGLONG)
1485                   {
1486                     ull = GETARG (unsigned long long);
1487                     lnumber(data, ull, 16);
1488                   }
1489                 else
1490 #endif
1491                   {
1492                     ul = GETUNSIGNED(data);
1493                     number(data, ul, 16);
1494                   }
1495                 state = 0;
1496                 break;
1497               case 'p':
1498                 STAR_ARGS(data);
1499                 ul = (unsigned long)GETARG (void *);
1500                 pointer(data, ul);
1501                 state = 0;
1502                 break;
1503 #if HANDLE_MULTIBYTE
1504               case 'C':
1505                 data->flags |= PF_LONGINT;
1506                 /* FALLTHROUGH */
1507 #endif
1508               case 'c': /* character */
1509                 STAR_ARGS(data);
1510 #if HANDLE_MULTIBYTE
1511                 if (data->flags & PF_LONGINT)
1512                   {
1513                     wc = GETARG (wint_t);
1514                     wchars (data, wc);
1515                   }
1516                 else
1517 #endif
1518                   {             
1519                     ul = GETARG (int);
1520                     PUT_CHAR(ul, data);
1521                   }
1522                 state = 0;
1523                 break;
1524 #if HANDLE_MULTIBYTE
1525               case 'S':
1526                 data->flags |= PF_LONGINT;
1527                 /* FALLTHROUGH */
1528 #endif
1529               case 's':  /* string */
1530                 STAR_ARGS(data);
1531 #if HANDLE_MULTIBYTE
1532                 if (data->flags & PF_LONGINT)
1533                   {
1534                     ws = GETARG (wchar_t *);
1535                     wstrings (data, ws);
1536                   }
1537                 else
1538 #endif
1539                   {
1540                     s = GETARG (char *);
1541                     strings(data, s);
1542                   }
1543                 state = 0;
1544                 break;
1545               case 'n':
1546 #ifdef HAVE_LONG_LONG
1547                 if (data->flags & PF_LONGLONG)
1548                   *(GETARG (long long *)) = data->counter;
1549                 else
1550 #endif
1551                 if (data->flags & PF_LONGINT)
1552                   *(GETARG (long *)) = data->counter;
1553                 else if (data->flags & PF_SHORTINT)
1554                   *(GETARG (short *)) = data->counter;
1555                 else
1556                   *(GETARG (int *)) = data->counter;
1557                 state = 0;
1558                 break;
1559               case '%':  /* nothing just % */
1560                 PUT_CHAR('%', data);
1561                 state = 0;
1562                 break;
1563               default:
1564                 /* is this an error ? maybe bail out */
1565                 state = 0;
1566                 break;
1567         } /* end switch */
1568       } /* end of `%' for loop */
1569     } /* end of format string for loop */
1570
1571   if (data->length >= 0)
1572     *data->holder = '\0'; /* the end ye ! */
1573
1574   return data->counter;
1575 }
1576
1577 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1578 /*
1579  * Printing floating point numbers accurately is an art.  I'm not good
1580  * at it.  Fall back to sprintf for long double formats.
1581  */
1582 static void
1583 ldfallback (data, fs, fe, ld)
1584      struct DATA *data;
1585      const char *fs, *fe;
1586      long double ld;
1587 {
1588   register char *x;
1589   char fmtbuf[FALLBACK_FMTSIZE], *obuf;
1590   int fl;
1591
1592   fl = LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2;
1593   obuf = (char *)xmalloc (fl);
1594   fl = fe - fs + 1;
1595   strncpy (fmtbuf, fs, fl);
1596   fmtbuf[fl] = '\0';
1597
1598   if ((data->flags & PF_STAR_W) && (data->flags & PF_STAR_P))
1599     sprintf (obuf, fmtbuf, data->width, data->precision, ld);
1600   else if (data->flags & PF_STAR_W)
1601     sprintf (obuf, fmtbuf, data->width, ld);
1602   else if (data->flags & PF_STAR_P)
1603     sprintf (obuf, fmtbuf, data->precision, ld);
1604   else
1605     sprintf (obuf, fmtbuf, ld);
1606
1607   for (x = obuf; *x; x++)
1608     PUT_CHAR (*x, data);    
1609   xfree (obuf);
1610 }
1611 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1612
1613 #ifdef FLOATING_POINT
1614 /* Used for %a, %A if the libc printf supports them. */
1615 static void
1616 dfallback (data, fs, fe, d)
1617      struct DATA *data;
1618      const char *fs, *fe;
1619      double d;
1620 {
1621   register char *x;
1622   char fmtbuf[FALLBACK_FMTSIZE], obuf[FALLBACK_BASE];
1623   int fl;
1624
1625   fl = fe - fs + 1;
1626   strncpy (fmtbuf, fs, fl);
1627   fmtbuf[fl] = '\0';
1628
1629   if ((data->flags & PF_STAR_W) && (data->flags & PF_STAR_P))
1630     sprintf (obuf, fmtbuf, data->width, data->precision, d);
1631   else if (data->flags & PF_STAR_W)
1632     sprintf (obuf, fmtbuf, data->width, d);
1633   else if (data->flags & PF_STAR_P)
1634     sprintf (obuf, fmtbuf, data->precision, d);
1635   else
1636     sprintf (obuf, fmtbuf, d);
1637
1638   for (x = obuf; *x; x++)
1639     PUT_CHAR (*x, data);    
1640 }
1641 #endif /* FLOATING_POINT */
1642
1643 #ifndef HAVE_SNPRINTF
1644
1645 int
1646 #if defined (__STDC__)
1647 vsnprintf(char *string, size_t length, const char *format, va_list args)
1648 #else
1649 vsnprintf(string, length, format, args)
1650      char *string;
1651      size_t length;
1652      const char *format;
1653      va_list args;
1654 #endif
1655 {
1656   struct DATA data;
1657
1658   if (string == 0 && length != 0)
1659     return 0;
1660   init_data (&data, string, length, format, PFM_SN);
1661   return (vsnprintf_internal(&data, string, length, format, args));
1662 }
1663
1664 int
1665 #if defined(PREFER_STDARG)
1666 snprintf(char *string, size_t length, const char * format, ...)
1667 #else
1668 snprintf(string, length, format, va_alist)
1669      char *string;
1670      size_t length;
1671      const char *format;
1672      va_dcl
1673 #endif
1674 {
1675   struct DATA data;
1676   int rval;
1677   va_list args;
1678
1679   SH_VA_START(args, format);
1680
1681   if (string == 0 && length != 0)
1682     return 0;
1683   init_data (&data, string, length, format, PFM_SN);
1684   rval = vsnprintf_internal (&data, string, length, format, args);
1685
1686   va_end(args);
1687
1688   return rval;
1689 }
1690
1691 #endif /* HAVE_SNPRINTF */
1692
1693 #ifndef HAVE_ASPRINTF
1694
1695 int
1696 #if defined (__STDC__)
1697 vasprintf(char **stringp, const char *format, va_list args)
1698 #else
1699 vasprintf(stringp, format, args)
1700      char **stringp;
1701      const char *format;
1702      va_list args;
1703 #endif
1704 {
1705   struct DATA data;
1706   char *string;
1707   int r;
1708
1709   string = (char *)xmalloc(ASBUFSIZE);
1710   init_data (&data, string, ASBUFSIZE, format, PFM_AS);
1711   r = vsnprintf_internal(&data, string, ASBUFSIZE, format, args);
1712   *stringp = data.base;         /* not string in case reallocated */
1713   return r;
1714 }
1715
1716 int
1717 #if defined(PREFER_STDARG)
1718 asprintf(char **stringp, const char * format, ...)
1719 #else
1720 asprintf(stringp, format, va_alist)
1721      char **stringp;
1722      const char *format;
1723      va_dcl
1724 #endif
1725 {
1726   int rval;
1727   va_list args;
1728
1729   SH_VA_START(args, format);
1730
1731   rval = vasprintf (stringp, format, args);
1732
1733   va_end(args);
1734
1735   return rval;
1736 }
1737
1738 #endif
1739
1740 #endif
1741
1742 #ifdef DRIVER
1743
1744 static void
1745 memory_error_and_abort ()
1746 {
1747   write (2, "out of virtual memory\n", 22);
1748   abort ();
1749 }
1750
1751 static void *
1752 xmalloc(bytes)
1753      size_t bytes;
1754 {
1755   void *ret;
1756
1757   ret = malloc(bytes);
1758   if (ret == 0)
1759     memory_error_and_abort ();
1760   return ret;
1761 }
1762
1763 static void *
1764 xrealloc (pointer, bytes)
1765      void *pointer;
1766      size_t bytes;
1767 {
1768   void *ret;
1769
1770   ret = pointer ? realloc(pointer, bytes) : malloc(bytes);
1771   if (ret == 0)
1772     memory_error_and_abort ();
1773   return ret;
1774 }
1775
1776 static void
1777 xfree(x)
1778      void *x;
1779 {
1780   if (x)
1781     free (x);
1782 }
1783
1784 /* set of small tests for snprintf() */
1785 main()
1786 {
1787   char holder[100];
1788   char *h;
1789   int i, si, ai;
1790
1791 #ifdef HAVE_LOCALE_H
1792   setlocale(LC_ALL, "");
1793 #endif
1794
1795 #if 1
1796   si = snprintf((char *)NULL, 0, "abcde\n");
1797   printf("snprintf returns %d with NULL first argument and size of 0\n", si);
1798   si = snprintf(holder, 0, "abcde\n");
1799   printf("snprintf returns %d with non-NULL first argument and size of 0\n", si);
1800   si = snprintf((char *)NULL, 16, "abcde\n");
1801   printf("snprintf returns %d with NULL first argument and non-zero size\n", si);
1802   
1803 /*
1804   printf("Suite of test for snprintf:\n");
1805   printf("a_format\n");
1806   printf("printf() format\n");
1807   printf("snprintf() format\n\n");
1808 */
1809 /* Checking the field widths */
1810
1811   printf("/%%ld %%ld/, 336, 336\n");
1812   snprintf(holder, sizeof holder, "/%ld %ld/\n", 336, 336);
1813   asprintf(&h, "/%ld %ld/\n", 336, 336);
1814   printf("/%ld %ld/\n", 336, 336);
1815   printf("%s", holder);
1816   printf("%s\n", h);
1817
1818   printf("/%%d/, 336\n");
1819   snprintf(holder, sizeof holder, "/%d/\n", 336);
1820   asprintf(&h, "/%d/\n", 336);
1821   printf("/%d/\n", 336);
1822   printf("%s", holder);
1823   printf("%s\n", h);
1824
1825   printf("/%%2d/, 336\n");
1826   snprintf(holder, sizeof holder, "/%2d/\n", 336);
1827   asprintf(&h, "/%2d/\n", 336);
1828   printf("/%2d/\n", 336);
1829   printf("%s", holder);
1830   printf("%s\n", h);
1831
1832   printf("/%%10d/, 336\n");
1833   snprintf(holder, sizeof holder, "/%10d/\n", 336);
1834   asprintf(&h, "/%10d/\n", 336);
1835   printf("/%10d/\n", 336);
1836   printf("%s", holder);
1837   printf("%s\n", h);
1838
1839   printf("/%%-10d/, 336\n");
1840   snprintf(holder, sizeof holder, "/%-10d/\n", 336);
1841   asprintf(&h, "/%-10d/\n", 336);
1842   printf("/%-10d/\n", 336);
1843   printf("%s", holder);
1844   printf("%s\n", h);
1845
1846
1847 /* floating points */
1848
1849   printf("/%%f/, 1234.56\n");
1850   snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
1851   asprintf(&h, "/%f/\n", 1234.56);
1852   printf("/%f/\n", 1234.56);
1853   printf("%s", holder);
1854   printf("%s\n", h);
1855
1856   printf("/%%e/, 1234.56\n");
1857   snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
1858   asprintf(&h, "/%e/\n", 1234.56);
1859   printf("/%e/\n", 1234.56);
1860   printf("%s", holder);
1861   printf("%s\n", h);
1862
1863   printf("/%%4.2f/, 1234.56\n");
1864   snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
1865   asprintf(&h, "/%4.2f/\n", 1234.56);
1866   printf("/%4.2f/\n", 1234.56);
1867   printf("%s", holder);
1868   printf("%s\n", h);
1869
1870   printf("/%%3.1f/, 1234.56\n");
1871   snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
1872   asprintf(&h, "/%3.1f/\n", 1234.56);
1873   printf("/%3.1f/\n", 1234.56);
1874   printf("%s", holder);
1875   printf("%s\n", h);
1876
1877   printf("/%%10.3f/, 1234.56\n");
1878   snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
1879   asprintf(&h, "/%10.3f/\n", 1234.56);
1880   printf("/%10.3f/\n", 1234.56);
1881   printf("%s", holder);
1882   printf("%s\n", h);
1883
1884   printf("/%%10.3e/, 1234.56\n");
1885   snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
1886   asprintf(&h, "/%10.3e/\n", 1234.56);
1887   printf("/%10.3e/\n", 1234.56);
1888   printf("%s", holder);
1889   printf("%s\n", h);
1890
1891   printf("/%%+4.2f/, 1234.56\n");
1892   snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
1893   asprintf(&h, "/%+4.2f/\n", 1234.56);
1894   printf("/%+4.2f/\n", 1234.56);
1895   printf("%s", holder);
1896   printf("%s\n", h);
1897
1898   printf("/%%010.2f/, 1234.56\n");
1899   snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
1900   asprintf(&h, "/%010.2f/\n", 1234.56);
1901   printf("/%010.2f/\n", 1234.56);
1902   printf("%s", holder);
1903   printf("%s\n", h);
1904
1905 #define BLURB "Outstanding acting !"
1906 /* strings precisions */
1907
1908   printf("/%%2s/, \"%s\"\n", BLURB);
1909   snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
1910   asprintf(&h, "/%2s/\n", BLURB);
1911   printf("/%2s/\n", BLURB);
1912   printf("%s", holder);
1913   printf("%s\n", h);
1914
1915   printf("/%%22s/ %s\n", BLURB);
1916   snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
1917   asprintf(&h, "/%22s/\n", BLURB);
1918   printf("/%22s/\n", BLURB);
1919   printf("%s", holder);
1920   printf("%s\n", h);
1921
1922   printf("/%%22.5s/ %s\n", BLURB);
1923   snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
1924   asprintf(&h, "/%22.5s/\n", BLURB);
1925   printf("/%22.5s/\n", BLURB);
1926   printf("%s", holder);
1927   printf("%s\n", h);
1928
1929   printf("/%%-22.5s/ %s\n", BLURB);
1930   snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
1931   asprintf(&h, "/%-22.5s/\n", BLURB);
1932   printf("/%-22.5s/\n", BLURB);
1933   printf("%s", holder);
1934   printf("%s\n", h);
1935
1936 /* see some flags */
1937
1938   printf("%%x %%X %%#x, 31, 31, 31\n");
1939   snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
1940   asprintf(&h, "%x %X %#x\n", 31, 31, 31);
1941   printf("%x %X %#x\n", 31, 31, 31);
1942   printf("%s", holder);
1943   printf("%s\n", h);
1944
1945   printf("**%%d**%% d**%% d**, 42, 42, -42\n");
1946   snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
1947   asprintf(&h, "**%d**% d**% d**\n", 42, 42, -42);
1948   printf("**%d**% d**% d**\n", 42, 42, -42);
1949   printf("%s", holder);
1950   printf("%s\n", h);
1951
1952 /* other flags */
1953
1954   printf("/%%g/, 31.4\n");
1955   snprintf(holder, sizeof holder, "/%g/\n", 31.4);
1956   asprintf(&h, "/%g/\n", 31.4);
1957   printf("/%g/\n", 31.4);
1958   printf("%s", holder);
1959   printf("%s\n", h);
1960
1961   printf("/%%.6g/, 31.4\n");
1962   snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
1963   asprintf(&h, "/%.6g/\n", 31.4);
1964   printf("/%.6g/\n", 31.4);
1965   printf("%s", holder);
1966   printf("%s\n", h);
1967
1968   printf("/%%.1G/, 31.4\n");
1969   snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
1970   asprintf(&h, "/%.1G/\n", 31.4);
1971   printf("/%.1G/\n", 31.4);
1972   printf("%s", holder);
1973   printf("%s\n", h);
1974
1975   printf("/%%.1G/, 3100000000.4\n");
1976   snprintf(holder, sizeof holder, "/%.1G/\n", 3100000000.4);  
1977   asprintf(&h, "/%.1G/\n", 3100000000.4);  
1978   printf("/%.1G/\n", 3100000000.4); 
1979   printf("%s", holder);
1980   printf("%s\n", h);
1981
1982   printf("abc%%n\n");
1983   printf("abc%n", &i); printf("%d\n", i);
1984   snprintf(holder, sizeof holder, "abc%n", &i);
1985   printf("%s", holder); printf("%d\n\n", i);
1986   asprintf(&h, "abc%n", &i);
1987   printf("%s", h); printf("%d\n\n", i);
1988   
1989   printf("%%*.*s --> 10.10\n");
1990   snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
1991   asprintf(&h, "%*.*s\n", 10, 10, BLURB);
1992   printf("%*.*s\n", 10, 10, BLURB);
1993   printf("%s", holder);
1994   printf("%s\n", h);
1995
1996   printf("%%%%%%%%\n");
1997   snprintf(holder, sizeof holder, "%%%%\n");
1998   asprintf(&h, "%%%%\n");
1999   printf("%%%%\n");
2000   printf("%s", holder);
2001   printf("%s\n", h);
2002
2003 #define BIG "Hello this is a too big string for the buffer"
2004 /*  printf("A buffer to small of 10, trying to put this:\n");*/
2005   printf("<%%>, %s\n", BIG); 
2006   i = snprintf(holder, 10, "%s\n", BIG);
2007   i = asprintf(&h, "%s", BIG);
2008   printf("<%s>\n", BIG);
2009   printf("<%s>\n", holder);
2010   printf("<%s>\n\n", h);
2011
2012   printf ("<%%p> vsnprintf\n");
2013   i = snprintf(holder, 100, "%p", vsnprintf);
2014   i = asprintf(&h, "%p", vsnprintf);
2015   printf("<%p>\n", vsnprintf);
2016   printf("<%s>\n", holder);  
2017   printf("<%s>\n\n", h);
2018
2019   printf ("<%%lu> LONG_MAX+1\n");
2020   i = snprintf(holder, 100, "%lu", (unsigned long)(LONG_MAX)+1);
2021   i = asprintf(&h, "%lu", (unsigned long)(LONG_MAX)+1);
2022   printf("<%lu>\n", (unsigned long)(LONG_MAX)+1);
2023   printf("<%s>\n", holder);
2024   printf("<%s>\n\n", h);
2025
2026 #ifdef HAVE_LONG_LONG
2027   printf ("<%%llu> LLONG_MAX+1\n");
2028   i = snprintf(holder, 100, "%llu", (unsigned long long)(LLONG_MAX)+1);
2029   i = asprintf(&h, "%llu", (unsigned long long)(LLONG_MAX)+1);
2030   printf("<%llu>\n", (unsigned long long)(LLONG_MAX)+1);
2031   printf("<%s>\n", holder);
2032   printf("<%s>\n\n", h);
2033 #endif
2034
2035 #ifdef HAVE_LONG_DOUBLE
2036   printf ("<%%6.2LE> 42.42\n");
2037   i = snprintf(holder, 100, "%6.2LE", (long double)42.42);
2038   i = asprintf(&h, "%6.2LE", (long double)42.42);
2039   printf ("<%6.2LE>\n", (long double)42.42);
2040   printf ("<%s>\n", holder);
2041   printf ("<%s>\n\n", h);
2042 #endif
2043
2044 #ifdef HAVE_PRINTF_A_FORMAT
2045   printf ("<%%6.2A> 42.42\n");
2046   i = snprintf(holder, 100, "%6.2A", 42.42);
2047   i = asprintf(&h, "%6.2A", 42.42);
2048   printf ("<%6.2A>\n", 42.42);
2049   printf ("<%s>\n", holder);
2050   printf ("<%s>\n\n", h);
2051
2052   printf ("<%%6.2LA> 42.42\n");
2053   i = snprintf(holder, 100, "%6.2LA", (long double)42.42);
2054   i = asprintf(&h, "%6.2LA", (long double)42.42);
2055   printf ("<%6.2LA>\n", (long double)42.42);
2056   printf ("<%s>\n", holder);
2057   printf ("<%s>\n\n", h);
2058 #endif
2059
2060   printf ("<%%.10240f> DBL_MAX\n");
2061   si = snprintf(holder, 100, "%.10240f", DBL_MAX);
2062   ai = asprintf(&h, "%.10240f", DBL_MAX);
2063   printf ("<%.10240f>\n", DBL_MAX);
2064   printf ("<%d> <%s>\n", si, holder);
2065   printf ("<%d> <%s>\n\n", ai, h);
2066
2067   printf ("<%%.10240Lf> LDBL_MAX\n");
2068   si = snprintf(holder, 100, "%.10240Lf", (long double)LDBL_MAX);
2069   ai = asprintf(&h, "%.10240Lf", (long double)LDBL_MAX);
2070   printf ("<%.10240Lf>\n", (long double)LDBL_MAX);
2071   printf ("<%d> <%s>\n", si, holder);
2072   printf ("<%d> <%s>\n\n", ai, h);
2073
2074   /* huh? */
2075   printf("/%%g/, 421.2345\n");
2076   snprintf(holder, sizeof holder, "/%g/\n", 421.2345);
2077   asprintf(&h, "/%g/\n", 421.2345);
2078   printf("/%g/\n", 421.2345);
2079   printf("%s", holder);
2080   printf("%s\n", h);
2081
2082   printf("/%%g/, 4214.2345\n");
2083   snprintf(holder, sizeof holder, "/%g/\n", 4214.2345);
2084   asprintf(&h, "/%g/\n", 4214.2345);
2085   printf("/%g/\n", 4214.2345);
2086   printf("%s", holder);
2087   printf("%s\n", h);
2088
2089   printf("/%%.5g/, 4214.2345\n");
2090   snprintf(holder, sizeof holder, "/%.5g/\n", 4214.2345);
2091   asprintf(&h, "/%.5g/\n", 4214.2345);
2092   printf("/%.5g/\n", 4214.2345);
2093   printf("%s", holder);
2094   printf("%s\n", h);
2095
2096   printf("/%%.4g/, 4214.2345\n");
2097   snprintf(holder, sizeof holder, "/%.4g/\n", 4214.2345);
2098   asprintf(&h, "/%.4g/\n", 4214.2345);
2099   printf("/%.4g/\n", 4214.2345);
2100   printf("%s", holder);
2101   printf("%s\n", h);
2102
2103   printf("/%%'ld %%'ld/, 12345, 1234567\n");
2104   snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 12345, 1234567);
2105   asprintf(&h, "/%'ld %'ld/\n", 12345, 1234567);
2106   printf("/%'ld %'ld/\n", 12345, 1234567);
2107   printf("%s", holder);
2108   printf("%s\n", h);
2109
2110   printf("/%%'ld %%'ld/, 336, 3336\n");
2111   snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 336, 3336);
2112   asprintf(&h, "/%'ld %'ld/\n", 336, 3336);
2113   printf("/%'ld %'ld/\n", 336, 3336);
2114   printf("%s", holder);
2115   printf("%s\n", h);
2116
2117   printf("/%%'ld %%'ld/, -42786, -142786\n");
2118   snprintf(holder, sizeof holder, "/%'ld %'ld/\n", -42786, -142786);
2119   asprintf(&h, "/%'ld %'ld/\n", -42786, -142786);
2120   printf("/%'ld %'ld/\n", -42786, -142786);
2121   printf("%s", holder);
2122   printf("%s\n", h);
2123
2124   printf("/%%'f %%'f/, 421.2345, 421234.56789\n");
2125   snprintf(holder, sizeof holder, "/%'f %'f/\n", 421.2345, 421234.56789);
2126   asprintf(&h, "/%'f %'f/\n", 421.2345, 421234.56789);
2127   printf("/%'f %'f/\n", 421.2345, 421234.56789);
2128   printf("%s", holder);
2129   printf("%s\n", h);
2130
2131   printf("/%%'f %%'f/, -421.2345, -421234.56789\n");
2132   snprintf(holder, sizeof holder, "/%'f %'f/\n", -421.2345, -421234.56789);
2133   asprintf(&h, "/%'f %'f/\n", -421.2345, -421234.56789);
2134   printf("/%'f %'f/\n", -421.2345, -421234.56789);
2135   printf("%s", holder);
2136   printf("%s\n", h);
2137
2138   printf("/%%'g %%'g/, 421.2345, 421234.56789\n");
2139   snprintf(holder, sizeof holder, "/%'g %'g/\n", 421.2345, 421234.56789);
2140   asprintf(&h, "/%'g %'g/\n", 421.2345, 421234.56789);
2141   printf("/%'g %'g/\n", 421.2345, 421234.56789);
2142   printf("%s", holder);
2143   printf("%s\n", h);
2144
2145   printf("/%%'g %%'g/, -421.2345, -421234.56789\n");
2146   snprintf(holder, sizeof holder, "/%'g %'g/\n", -421.2345, -421234.56789);
2147   asprintf(&h, "/%'g %'g/\n", -421.2345, -421234.56789);
2148   printf("/%'g %'g/\n", -421.2345, -421234.56789);
2149   printf("%s", holder);
2150   printf("%s\n", h);
2151 #endif
2152
2153   printf("/%%'g/, 4213455.8392\n");
2154   snprintf(holder, sizeof holder, "/%'g/\n", 4213455.8392);
2155   asprintf(&h, "/%'g/\n", 4213455.8392);
2156   printf("/%'g/\n", 4213455.8392);
2157   printf("%s", holder);
2158   printf("%s\n", h);
2159
2160   exit (0);
2161 }
2162 #endif