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