Imported from ../bash-3.2.48.tar.gz.
[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  * NOTE: do not call this with r == 0 -- an infinite loop results.
476  */
477 static int
478 log_10(r)
479      double r;
480
481   int i = 0;
482   double result = 1.;
483
484   if (r < 0.)
485     r = -r;
486
487   if (r < 1.)
488     {
489       while (result >= r)
490         {
491           result /= 10.;
492           i++;
493         }
494       return (-i);
495     }
496   else
497     {
498       while (result <= r)
499         {
500           result *= 10.;
501           i++;
502         }
503       return (i - 1);
504     }
505 }
506
507 /*
508  * This function return the fraction part of a double
509  * and set in ip the integral part.
510  * In many ways it resemble the modf() found on most Un*x
511  */
512 static double
513 integral(real, ip)
514      double real;
515      double *ip;
516
517   int j;
518   double i, s, p;
519   double real_integral = 0.;
520
521   /* take care of the obvious */
522   /* equal to zero ? */
523   if (real == 0.)
524     {
525       *ip = 0.;
526       return (0.);
527     }
528
529   /* negative number ? */
530   if (real < 0.)
531     real = -real;
532
533   /* a fraction ? */
534   if ( real < 1.)
535     {
536       *ip = 0.;
537       return real;
538     }
539
540   /* the real work :-) */
541   for (j = log_10(real); j >= 0; j--)
542     {
543       p = pow_10(j);
544       s = (real - real_integral)/p;
545       i = 0.;
546       while (i + 1. <= s)
547         i++;
548       real_integral += i*p;
549     }
550   *ip = real_integral;
551   return (real - real_integral);
552 }
553
554 #define PRECISION 1.e-6
555 /* 
556  * return an ascii representation of the integral part of the number
557  * and set fract to be an ascii representation of the fraction part
558  * the container for the fraction and the integral part or staticly
559  * declare with fix size 
560  */
561 static char *
562 numtoa(number, base, precision, fract)
563      double number;
564      int base, precision;
565      char **fract;
566 {
567   register int i, j;
568   double ip, fp; /* integer and fraction part */
569   double fraction;
570   int digits = MAX_INT - 1;
571   static char integral_part[MAX_INT];
572   static char fraction_part[MAX_FRACT];
573   double sign;
574   int ch;
575
576   /* taking care of the obvious case: 0.0 */
577   if (number == 0.)
578     { 
579       integral_part[0] = '0';
580       integral_part[1] = '\0';
581       /* The fractional part has to take the precision into account */
582       for (ch = 0; ch < precision-1; ch++)
583         fraction_part[ch] = '0';
584       fraction_part[ch] = '0';
585       fraction_part[ch+1] = '\0';
586       if (fract)
587         *fract = fraction_part;
588       return integral_part;
589     }
590
591   /* for negative numbers */
592   if ((sign = number) < 0.)
593     {
594       number = -number;
595       digits--; /* sign consume one digit */
596     }
597
598   fraction = integral(number, &ip);
599   number = ip;
600
601   /* do the integral part */
602   if (ip == 0.)
603     {
604       integral_part[0] = '0';
605       i = 1;
606     }
607   else
608     {
609       for ( i = 0; i < digits && number != 0.; ++i)
610         {
611           number /= base;
612           fp = integral(number, &ip);
613           ch = (int)((fp + PRECISION)*base); /* force to round */
614           integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
615           if (! ISXDIGIT((unsigned char)integral_part[i]))
616             break;      /* bail out overflow !! */
617           number = ip;
618          }
619     }
620      
621   /* Oh No !! out of bound, ho well fill it up ! */
622   if (number != 0.)
623     for (i = 0; i < digits; ++i)
624       integral_part[i] = '9';
625
626   /* put the sign ? */
627   if (sign < 0.)
628     integral_part[i++] = '-';
629
630   integral_part[i] = '\0';
631
632   /* reverse every thing */
633   for ( i--, j = 0; j < i; j++, i--)
634     SWAP_INT(integral_part[i], integral_part[j]);  
635
636   /* the fractional part */
637   for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--)
638     {
639       fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
640       if (! DIGIT(fraction_part[i])) /* underflow ? */
641         break;
642       fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
643     }
644   fraction_part[i] = '\0';
645
646   if (fract != (char **)0)
647     *fract = fraction_part;
648
649   return integral_part;
650 }
651 #endif
652
653 /* for %d and friends, it puts in holder
654  * the representation with the right padding
655  */
656 static void
657 number(p, d, base)
658      struct DATA *p;
659      unsigned long d;
660      int base;
661 {
662   char *tmp, *t;
663   long sd;
664   int flags;
665
666   /* An explicit precision turns off the zero-padding flag. */
667   if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
668     p->flags &= ~PF_ZEROPAD;
669
670   sd = d;       /* signed for ' ' padding in base 10 */
671   flags = 0;
672   flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
673   if (*p->pf == 'X')
674     flags |= FL_HEXUPPER;
675
676   tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags);
677   t = 0;
678   if ((p->flags & PF_THOUSANDS))
679     {
680       GETLOCALEDATA(decpoint, thoussep, grouping);
681       if (grouping && (t = groupnum (tmp)))
682         tmp = t;
683     }
684
685   p->width -= strlen(tmp);
686   PAD_RIGHT(p);
687
688   if ((p->flags & PF_DOT) && p->precision > 0)
689     {
690       p->precision -= strlen(tmp);
691       PAD_ZERO(p);
692     }
693
694   switch (base)
695     {
696     case 10:
697       PUT_PLUS(sd, p, 0);
698       PUT_SPACE(sd, p, 0);
699       break;
700     case 8:
701       if (p->flags & PF_ALTFORM)
702         PUT_CHAR('0', p);
703       break;
704     case 16:
705       if (p->flags & PF_ALTFORM)
706         {
707           PUT_CHAR('0', p);
708           PUT_CHAR(*p->pf, p);
709         }
710       break;
711     }
712
713   while (*tmp)
714     {
715       PUT_CHAR(*tmp, p);
716       tmp++;
717     }
718
719   PAD_LEFT(p);
720   FREE (t);
721 }
722
723 #ifdef HAVE_LONG_LONG
724 /*
725  * identical to number() but works for `long long'
726  */
727 static void
728 lnumber(p, d, base)
729      struct DATA *p;
730      unsigned long long d;
731      int base;
732 {
733   char *tmp, *t;
734   long long sd;
735   int flags;
736
737   /* An explicit precision turns off the zero-padding flag. */
738   if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
739     p->flags &= ~PF_ZEROPAD;
740
741   sd = d;       /* signed for ' ' padding in base 10 */
742   flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
743   if (*p->pf == 'X')
744     flags |= FL_HEXUPPER;
745
746   tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags);
747   t = 0;
748   if ((p->flags & PF_THOUSANDS))
749     {
750       GETLOCALEDATA(decpoint, thoussep, grouping);
751       if (grouping && (t = groupnum (tmp)))
752         tmp = t;
753     }
754
755   p->width -= strlen(tmp);
756   PAD_RIGHT(p);
757
758   if ((p->flags & PF_DOT) && p->precision > 0)
759     {
760       p->precision -= strlen(tmp);
761       PAD_ZERO(p);
762     }
763
764   switch (base)
765     {
766     case 10:
767       PUT_PLUS(sd, p, 0);
768       PUT_SPACE(sd, p, 0);
769       break;
770     case 8:
771       if (p->flags & PF_ALTFORM)
772         PUT_CHAR('0', p);
773       break;
774     case 16:
775       if (p->flags & PF_ALTFORM)
776         {
777           PUT_CHAR('0', p);
778           PUT_CHAR(*p->pf, p);
779         }
780       break;
781     }
782
783   while (*tmp)
784     {
785       PUT_CHAR(*tmp, p);
786       tmp++;
787     }
788
789   PAD_LEFT(p);
790   FREE (t);
791 }
792 #endif
793
794 static void
795 pointer(p, d)
796      struct DATA *p;
797      unsigned long d;
798 {
799   char *tmp;
800
801   tmp = fmtulong(d, 16, intbuf, sizeof(intbuf), 0);
802   p->width -= strlen(tmp);
803   PAD_RIGHT(p);
804
805   /* prefix '0x' for pointers */
806   PUT_CHAR('0', p);
807   PUT_CHAR('x', p);
808
809   while (*tmp)
810     {
811       PUT_CHAR(*tmp, p);
812       tmp++;
813     }
814
815   PAD_LEFT(p);
816 }
817
818 /* %s strings */
819 static void
820 strings(p, tmp)
821      struct DATA *p;
822      char *tmp;
823 {
824   size_t len;
825
826   len = strlen(tmp);
827   if (p->precision != NOT_FOUND) /* the smallest number */
828     len = (len < p->precision ? len : p->precision);
829   p->width -= len;
830
831   PUT_STRING (tmp, len, p);
832 }
833
834 #if HANDLE_MULTIBYTE
835 /* %ls wide-character strings */
836 static void
837 wstrings(p, tmp)
838      struct DATA *p;
839      wchar_t *tmp;
840 {
841   size_t len;
842   mbstate_t mbs;
843   char *os;
844   const wchar_t *ws;
845
846   memset (&mbs, '\0', sizeof (mbstate_t));
847   ws = (const wchar_t *)tmp;
848
849   os = (char *)NULL;
850   if (p->precision != NOT_FOUND)
851     {
852       os = (char *)xmalloc (p->precision + 1);
853       len = wcsrtombs (os, &ws, p->precision, &mbs);
854     }
855   else
856     {
857       len = wcsrtombs (NULL, &ws, 0, &mbs);
858       if (len != (size_t)-1)
859         {
860           memset (&mbs, '\0', sizeof (mbstate_t));
861           os = (char *)xmalloc (len + 1);
862           (void)wcsrtombs (os, &ws, len + 1, &mbs);
863         }
864     }
865   if (len == (size_t)-1)
866     {
867       /* invalid multibyte sequence; bail now. */
868       FREE (os);      
869       return;
870     }
871
872   p->width -= len;
873   PUT_STRING (os, len, p);
874   free (os);
875 }
876
877 static void
878 wchars (p, wc)
879      struct DATA *p;
880      wint_t wc;
881 {
882   char *lbuf, *l;
883   mbstate_t mbs;
884   size_t len;
885
886   lbuf = (char *)malloc (MB_CUR_MAX+1);
887   if (lbuf == 0)
888     return;
889   memset (&mbs, '\0', sizeof (mbstate_t));
890   len = wcrtomb (lbuf, wc, &mbs);
891   if (len == (size_t)-1)
892     /* conversion failed; bail now. */
893     return;
894   p->width -= len;
895   l = lbuf;
896   PUT_STRING (l, len, p);
897   free (lbuf);
898 }
899 #endif /* HANDLE_MULTIBYTE */
900
901 #ifdef FLOATING_POINT
902
903 #ifndef HAVE_ISINF_IN_LIBC
904 /* Half-assed versions, since we don't want to link with libm. */
905 static int
906 isinf(d)
907      double d;
908 {
909 #ifdef DBL_MAX
910   if (d < DBL_MIN)
911     return -1;
912   else if (d > DBL_MAX)
913     return 1;
914   else
915 #endif
916     return 0;
917 }
918 #endif
919
920 #ifndef HAVE_ISNAN_IN_LIBC
921 static int
922 isnan(d)
923      double d;
924 {
925   return 0;
926 }
927 #endif
928
929 /* Check for [+-]infinity and NaN.  If MODE == 1, we check for Infinity, else
930    (mode == 2) we check for NaN.  This does the necessary printing.  Returns
931    1 if Inf or Nan, 0 if not. */
932 static int
933 chkinfnan(p, d, mode)
934      struct DATA *p;
935      double d;
936      int mode;          /* == 1 for inf, == 2 for nan */
937 {
938   int i;
939   char *tmp;
940   char *big, *small;
941
942   i = (mode == 1) ? isinf(d) : isnan(d);
943   if (i == 0)
944     return 0;
945   big = (mode == 1) ? "INF" : "NAN";
946   small = (mode == 1) ? "inf" : "nan";
947
948   tmp = (*p->pf == 'F' || *p->pf == 'G' || *p->pf == 'E') ? big : small;
949
950   if (i < 0)
951     PUT_CHAR('-', p);
952
953   while (*tmp)
954     {
955       PUT_CHAR (*tmp, p);
956       tmp++;
957     }
958
959   return 1;
960 }
961
962 /* %f %F %g %G floating point representation */
963 static void
964 floating(p, d)
965      struct DATA *p;
966      double d;
967 {
968   char *tmp, *tmp2, *t;
969   int i;
970
971   if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)))
972     return;     /* already printed nan or inf */
973
974   GETLOCALEDATA(decpoint, thoussep, grouping);
975   DEF_PREC(p);
976   d = ROUND(d, p);
977   tmp = dtoa(d, p->precision, &tmp2);
978   t = 0;
979   if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp)))
980     tmp = t;
981
982   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
983     {
984       /* smash the trailing zeros unless altform */
985       for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
986         tmp2[i] = '\0'; 
987       if (tmp2[0] == '\0')
988         p->precision = 0;
989     }
990
991   /* calculate the padding. 1 for the dot */
992   p->width = p->width -
993             ((d > 0. && p->justify == RIGHT) ? 1:0) -
994             ((p->flags & PF_SPACE) ? 1:0) -
995             strlen(tmp) - p->precision -
996             ((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0);   /* radix char */
997   PAD_RIGHT(p);  
998   PUT_PLUS(d, p, 0.);
999   PUT_SPACE(d, p, 0.);
1000
1001   while (*tmp)
1002     {
1003       PUT_CHAR(*tmp, p);        /* the integral */
1004       tmp++;
1005     }
1006   FREE (t);
1007
1008   if (p->precision != 0 || (p->flags & PF_ALTFORM))
1009     PUT_CHAR(decpoint, p);  /* put the '.' */
1010
1011   for (; *tmp2; tmp2++)
1012     PUT_CHAR(*tmp2, p); /* the fraction */
1013   
1014   PAD_LEFT(p);
1015
1016
1017 /* %e %E %g %G exponent representation */
1018 static void
1019 exponent(p, d)
1020      struct DATA *p;
1021      double d;
1022 {
1023   char *tmp, *tmp2;
1024   int j, i;
1025
1026   if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)))
1027     return;     /* already printed nan or inf */
1028
1029   GETLOCALEDATA(decpoint, thoussep, grouping);
1030   DEF_PREC(p);
1031   if (d == 0.)
1032     j = 0;
1033   else
1034     {
1035       j = log_10(d);
1036       d = d / pow_10(j);  /* get the Mantissa */
1037       d = ROUND(d, p);            
1038     }
1039   tmp = dtoa(d, p->precision, &tmp2);
1040
1041   /* 1 for unit, 1 for the '.', 1 for 'e|E',
1042    * 1 for '+|-', 2 for 'exp' */
1043   /* calculate how much padding need */
1044   p->width = p->width - 
1045              ((d > 0. && p->justify == RIGHT) ? 1:0) -
1046              ((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
1047
1048   PAD_RIGHT(p);
1049   PUT_PLUS(d, p, 0.);
1050   PUT_SPACE(d, p, 0.);
1051
1052   while (*tmp)
1053     {
1054       PUT_CHAR(*tmp, p);
1055       tmp++;
1056     }
1057
1058   if (p->precision != 0 || (p->flags & PF_ALTFORM))
1059       PUT_CHAR(decpoint, p);  /* the '.' */
1060
1061   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
1062     /* smash the trailing zeros unless altform */
1063     for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
1064       tmp2[i] = '\0'; 
1065
1066   for (; *tmp2; tmp2++)
1067     PUT_CHAR(*tmp2, p); /* the fraction */
1068
1069   /* the exponent put the 'e|E' */
1070   if (*p->pf == 'g' || *p->pf == 'e')
1071     PUT_CHAR('e', p);
1072   else
1073     PUT_CHAR('E', p);
1074
1075   /* the sign of the exp */
1076   if (j >= 0)
1077     PUT_CHAR('+', p);
1078   else
1079     {
1080       PUT_CHAR('-', p);
1081       j = -j;
1082     }
1083
1084    tmp = itoa(j);
1085    /* pad out to at least two spaces.  pad with `0' if the exponent is a
1086       single digit. */
1087    if (j <= 9)
1088      PUT_CHAR('0', p);
1089
1090    /* the exponent */
1091    while (*tmp)
1092      {
1093        PUT_CHAR(*tmp, p);
1094        tmp++;
1095      }
1096
1097    PAD_LEFT(p);
1098 }
1099 #endif
1100
1101 /* Return a new string with the digits in S grouped according to the locale's
1102    grouping info and thousands separator.  If no grouping should be performed,
1103    this returns NULL; the caller needs to check for it. */
1104 static char *
1105 groupnum (s)
1106      char *s;
1107 {
1108   char *se, *ret, *re, *g;
1109   int len, slen;
1110
1111   if (grouping == 0 || *grouping <= 0 || *grouping == CHAR_MAX)
1112     return ((char *)NULL);
1113
1114   /* find min grouping to size returned string */
1115   for (len = *grouping, g = grouping; *g; g++)
1116       if (*g > 0 && *g < len)
1117         len = *g;
1118
1119   slen = strlen (s);
1120   len = slen / len + 1;
1121   ret = (char *)xmalloc (slen + len + 1);
1122   re = ret + slen + len;
1123   *re = '\0';
1124
1125   g = grouping;
1126   se = s + slen;
1127   len = *g;
1128
1129   while (se > s)
1130     {
1131       *--re = *--se;
1132
1133       /* handle `-' inserted by numtoa() and the fmtu* family here. */
1134       if (se > s && se[-1] == '-')
1135         continue;
1136
1137       /* begin new group. */
1138       if (--len == 0 && se > s)
1139         {
1140           *--re = thoussep;
1141           len = *++g;           /* was g++, but that uses first char twice (glibc bug, too) */
1142           if (*g == '\0')
1143             len = *--g;         /* use previous grouping */
1144           else if (*g == CHAR_MAX)
1145             {
1146               do
1147                 *--re = *--se;
1148               while (se > s);
1149               break;
1150             }
1151         }
1152     }
1153
1154   if (re > ret)
1155 #ifdef HAVE_MEMMOVE
1156     memmove (ret, re, strlen (re) + 1);
1157 #else
1158     strcpy (ret, re);
1159 #endif
1160    
1161   return ret;
1162 }
1163
1164 /* initialize the conversion specifiers */
1165 static void
1166 init_conv_flag (p)
1167      struct DATA *p;
1168 {
1169   p->flags &= PF_ALLOCBUF;              /* preserve PF_ALLOCBUF flag */
1170   p->precision = p->width = NOT_FOUND;
1171   p->justify = NOT_FOUND;
1172   p->pad = ' ';
1173 }
1174
1175 static void
1176 init_data (p, string, length, format, mode)
1177      struct DATA *p;
1178      char *string;
1179      size_t length;
1180      const char *format;
1181      int mode;
1182 {
1183   p->length = length - 1; /* leave room for '\0' */
1184   p->holder = p->base = string;
1185   p->pf = format;
1186   p->counter = 0;
1187   p->flags = (mode == PFM_AS) ? PF_ALLOCBUF : 0;
1188 }
1189
1190 static int
1191 #if defined (__STDC__)
1192 vsnprintf_internal(struct DATA *data, char *string, size_t length, const char *format, va_list args)
1193 #else
1194 vsnprintf_internal(data, string, length, format, args)
1195      struct DATA *data;
1196      char *string;
1197      size_t length;
1198      const char *format;
1199      va_list args;
1200 #endif
1201 {
1202   double d; /* temporary holder */
1203 #ifdef HAVE_LONG_DOUBLE
1204   long double ld;       /* for later */
1205 #endif
1206   unsigned long ul;
1207 #ifdef HAVE_LONG_LONG
1208   unsigned long long ull;
1209 #endif
1210   int state, i, c, n;
1211   char *s;
1212 #if HANDLE_MULTIBYTE
1213   wchar_t *ws;
1214   wint_t wc;
1215 #endif
1216   const char *convstart;
1217   int negprec;
1218
1219   /* Sanity check, the string length must be >= 0.  C99 actually says that
1220      LENGTH can be zero here, in the case of snprintf/vsnprintf (it's never
1221      0 in the case of asprintf/vasprintf), and the return value is the number
1222      of characters that would have been written. */
1223   if (length < 0)
1224     return -1;
1225
1226   if (format == 0)
1227     return 0;
1228
1229   /* Reset these for each call because the locale might have changed. */
1230   decpoint = thoussep = 0;
1231   grouping = 0;
1232
1233   negprec = 0;
1234   for (; c = *(data->pf); data->pf++)
1235     {
1236       if (c != '%')
1237         {
1238           PUT_CHAR (c, data);
1239           continue;
1240         }
1241
1242       convstart = data->pf;
1243       init_conv_flag (data); /* initialise format flags */
1244
1245       state = 1;
1246       for (state = 1; state && *data->pf; )
1247         {
1248           c = *(++data->pf);
1249               /* fmtend = data->pf */
1250 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1251           if (data->flags & PF_LONGDBL)
1252             {
1253               switch (c)
1254                 {
1255                 case 'f': case 'F':
1256                 case 'e': case 'E':
1257                 case 'g': case 'G':
1258 #  ifdef HAVE_PRINTF_A_FORMAT
1259                 case 'a': case 'A':
1260 #  endif
1261                   STAR_ARGS (data);
1262                   ld = GETLDOUBLE (data);
1263                   ldfallback (data, convstart, data->pf, ld);
1264                   goto conv_break;
1265                 }
1266             }
1267 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1268
1269           switch (c)
1270             {
1271               /* Parse format flags */
1272               case '\0': /* a NULL here ? ? bail out */
1273                 *data->holder = '\0';
1274                 return data->counter;
1275                 break;
1276               case '#':
1277                 data->flags |= PF_ALTFORM;
1278                 continue;
1279               case '0':
1280                 data->flags |= PF_ZEROPAD;
1281                 data->pad = '0';
1282                 continue;
1283               case '*':
1284                 if (data->flags & PF_DOT)
1285                   data->flags |= PF_STAR_P;
1286                 else
1287                   data->flags |= PF_STAR_W;
1288                 continue;
1289               case '-':
1290                 if ((data->flags & PF_DOT) == 0)
1291                   {
1292                     data->flags |= PF_LADJUST;
1293                     data->justify = LEFT;
1294                   }
1295                 else
1296                   negprec = 1;
1297                 continue;
1298               case ' ':
1299                 if ((data->flags & PF_PLUS) == 0)
1300                   data->flags |= PF_SPACE;
1301                 continue;
1302               case '+':
1303                 if ((data->flags & PF_DOT) == 0)
1304                   {
1305                     data->flags |= PF_PLUS;
1306                     data->justify = RIGHT;
1307                   }
1308                 continue;
1309               case '\'':
1310                 data->flags |= PF_THOUSANDS;
1311                 continue;
1312
1313               case '1': case '2': case '3':
1314               case '4': case '5': case '6':
1315               case '7': case '8': case '9':
1316                 n = 0;
1317                 do
1318                   {
1319                     n = n * 10 + TODIGIT(c);
1320                     c = *(++data->pf);
1321                   }
1322                 while (DIGIT(c));
1323                 data->pf--;             /* went too far */
1324                 if (n < 0)
1325                   n = 0;
1326                 if (data->flags & PF_DOT)
1327                   data->precision = negprec ? NOT_FOUND : n;
1328                 else
1329                   data->width = n;
1330                 continue;
1331
1332               /* optional precision */
1333               case '.':
1334                 data->flags |= PF_DOT;
1335                 data->precision = 0;
1336                 continue;
1337
1338               /* length modifiers */
1339               case 'h':
1340                 data->flags |= (data->flags & PF_SHORTINT) ? PF_SIGNEDCHAR : PF_SHORTINT;
1341                 continue;
1342               case 'l':
1343                 data->flags |= (data->flags & PF_LONGINT) ? PF_LONGLONG : PF_LONGINT;
1344                 continue;
1345               case 'L':
1346                 data->flags |= PF_LONGDBL;
1347                 continue;
1348               case 'q':
1349                 data->flags |= PF_LONGLONG;
1350                 continue;
1351               case 'j':
1352                 data->flags |= PF_INTMAX_T;
1353                 SET_SIZE_FLAGS(data, intmax_t);
1354                 continue;
1355               case 'z':
1356                 data->flags |= PF_SIZE_T;
1357                 SET_SIZE_FLAGS(data, size_t);
1358                 continue;
1359               case 't':
1360                 data->flags |= PF_PTRDIFF_T;
1361                 SET_SIZE_FLAGS(data, ptrdiff_t);
1362                 continue;
1363                 
1364               /* Conversion specifiers */
1365 #ifdef FLOATING_POINT
1366               case 'f':  /* float, double */
1367               case 'F':
1368                 STAR_ARGS(data);
1369                 d = GETDOUBLE(data);
1370                 floating(data, d);
1371 conv_break:             
1372                 state = 0;
1373                 break;
1374               case 'g': 
1375               case 'G':
1376                 STAR_ARGS(data);
1377                 DEF_PREC(data);
1378                 d = GETDOUBLE(data);
1379                 i = (d != 0.) ? log_10(d) : -1;
1380                 /*
1381                  * for '%g|%G' ANSI: use f if exponent
1382                  * is in the range or [-4,p] exclusively
1383                  * else use %e|%E
1384                  */
1385                 if (-4 < i && i < data->precision)
1386                   {
1387                     /* reset precision */
1388                     data->precision -= i + 1;
1389                     floating(data, d);
1390                   }
1391                 else
1392                   {
1393                     /* reduce precision by 1 because of leading digit before
1394                        decimal point in e format. */
1395                     data->precision--;
1396                     exponent(data, d);
1397                   }
1398                 state = 0;
1399                 break;
1400               case 'e':
1401               case 'E':  /* Exponent double */
1402                 STAR_ARGS(data);
1403                 d = GETDOUBLE(data);
1404                 exponent(data, d);
1405                 state = 0;
1406                 break;
1407 #  ifdef HAVE_PRINTF_A_FORMAT
1408               case 'a':
1409               case 'A':
1410                 STAR_ARGS(data);
1411                 d = GETDOUBLE(data);
1412                 dfallback(data, convstart, data->pf, d);
1413                 state = 0;
1414                 break;
1415 #  endif /* HAVE_PRINTF_A_FORMAT */
1416 #endif /* FLOATING_POINT */
1417               case 'U':
1418                 data->flags |= PF_LONGINT;
1419                 /* FALLTHROUGH */
1420               case 'u':
1421                 STAR_ARGS(data);
1422 #ifdef HAVE_LONG_LONG
1423                 if (data->flags & PF_LONGLONG)
1424                   {
1425                     ull = GETARG (unsigned long long);
1426                     lnumber(data, ull, 10);
1427                   }
1428                 else
1429 #endif
1430                   {
1431                     ul = GETUNSIGNED(data);
1432                     number(data, ul, 10);
1433                   }
1434                 state = 0;
1435                 break;
1436               case 'D':
1437                 data->flags |= PF_LONGINT;
1438                 /* FALLTHROUGH */
1439               case 'd':  /* decimal */
1440               case 'i':
1441                 STAR_ARGS(data);
1442 #ifdef HAVE_LONG_LONG
1443                 if (data->flags & PF_LONGLONG)
1444                   {
1445                     ull = GETARG (long long);
1446                     lnumber(data, ull, 10);
1447                   }
1448                 else
1449 #endif
1450                   {
1451                     ul = GETSIGNED(data);
1452                     number(data, ul, 10);
1453                   }
1454                 state = 0;
1455                 break;
1456               case 'o':  /* octal */
1457                 STAR_ARGS(data);
1458 #ifdef HAVE_LONG_LONG
1459                 if (data->flags & PF_LONGLONG)
1460                   {
1461                     ull = GETARG (unsigned long long);
1462                     lnumber(data, ull, 8);
1463                   }
1464                 else
1465 #endif
1466                   {
1467                     ul = GETUNSIGNED(data);
1468                     number(data, ul, 8);
1469                   }
1470                 state = 0;
1471                 break;
1472               case 'x': 
1473               case 'X':  /* hexadecimal */
1474                 STAR_ARGS(data);
1475 #ifdef HAVE_LONG_LONG
1476                 if (data->flags & PF_LONGLONG)
1477                   {
1478                     ull = GETARG (unsigned long long);
1479                     lnumber(data, ull, 16);
1480                   }
1481                 else
1482 #endif
1483                   {
1484                     ul = GETUNSIGNED(data);
1485                     number(data, ul, 16);
1486                   }
1487                 state = 0;
1488                 break;
1489               case 'p':
1490                 STAR_ARGS(data);
1491                 ul = (unsigned long)GETARG (void *);
1492                 pointer(data, ul);
1493                 state = 0;
1494                 break;
1495 #if HANDLE_MULTIBYTE
1496               case 'C':
1497                 data->flags |= PF_LONGINT;
1498                 /* FALLTHROUGH */
1499 #endif
1500               case 'c': /* character */
1501                 STAR_ARGS(data);
1502 #if HANDLE_MULTIBYTE
1503                 if (data->flags & PF_LONGINT)
1504                   {
1505                     wc = GETARG (wint_t);
1506                     wchars (data, wc);
1507                   }
1508                 else
1509 #endif
1510                   {             
1511                     ul = GETARG (int);
1512                     PUT_CHAR(ul, data);
1513                   }
1514                 state = 0;
1515                 break;
1516 #if HANDLE_MULTIBYTE
1517               case 'S':
1518                 data->flags |= PF_LONGINT;
1519                 /* FALLTHROUGH */
1520 #endif
1521               case 's':  /* string */
1522                 STAR_ARGS(data);
1523 #if HANDLE_MULTIBYTE
1524                 if (data->flags & PF_LONGINT)
1525                   {
1526                     ws = GETARG (wchar_t *);
1527                     wstrings (data, ws);
1528                   }
1529                 else
1530 #endif
1531                   {
1532                     s = GETARG (char *);
1533                     strings(data, s);
1534                   }
1535                 state = 0;
1536                 break;
1537               case 'n':
1538 #ifdef HAVE_LONG_LONG
1539                 if (data->flags & PF_LONGLONG)
1540                   *(GETARG (long long *)) = data->counter;
1541                 else
1542 #endif
1543                 if (data->flags & PF_LONGINT)
1544                   *(GETARG (long *)) = data->counter;
1545                 else if (data->flags & PF_SHORTINT)
1546                   *(GETARG (short *)) = data->counter;
1547                 else
1548                   *(GETARG (int *)) = data->counter;
1549                 state = 0;
1550                 break;
1551               case '%':  /* nothing just % */
1552                 PUT_CHAR('%', data);
1553                 state = 0;
1554                 break;
1555               default:
1556                 /* is this an error ? maybe bail out */
1557                 state = 0;
1558                 break;
1559         } /* end switch */
1560       } /* end of `%' for loop */
1561     } /* end of format string for loop */
1562
1563   if (data->length >= 0)
1564     *data->holder = '\0'; /* the end ye ! */
1565
1566   return data->counter;
1567 }
1568
1569 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1570 /*
1571  * Printing floating point numbers accurately is an art.  I'm not good
1572  * at it.  Fall back to sprintf for long double formats.
1573  */
1574 static void
1575 ldfallback (data, fs, fe, ld)
1576      struct DATA *data;
1577      const char *fs, *fe;
1578      long double ld;
1579 {
1580   register char *x;
1581   char fmtbuf[FALLBACK_FMTSIZE], *obuf;
1582   int fl;
1583
1584   fl = LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2;
1585   obuf = (char *)xmalloc (fl);
1586   fl = fe - fs + 1;
1587   strncpy (fmtbuf, fs, fl);
1588   fmtbuf[fl] = '\0';
1589
1590   if ((data->flags & PF_STAR_W) && (data->flags & PF_STAR_P))
1591     sprintf (obuf, fmtbuf, data->width, data->precision, ld);
1592   else if (data->flags & PF_STAR_W)
1593     sprintf (obuf, fmtbuf, data->width, ld);
1594   else if (data->flags & PF_STAR_P)
1595     sprintf (obuf, fmtbuf, data->precision, ld);
1596   else
1597     sprintf (obuf, fmtbuf, ld);
1598
1599   for (x = obuf; *x; x++)
1600     PUT_CHAR (*x, data);    
1601   xfree (obuf);
1602 }
1603 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1604
1605 #ifdef FLOATING_POINT
1606 /* Used for %a, %A if the libc printf supports them. */
1607 static void
1608 dfallback (data, fs, fe, d)
1609      struct DATA *data;
1610      const char *fs, *fe;
1611      double d;
1612 {
1613   register char *x;
1614   char fmtbuf[FALLBACK_FMTSIZE], obuf[FALLBACK_BASE];
1615   int fl;
1616
1617   fl = fe - fs + 1;
1618   strncpy (fmtbuf, fs, fl);
1619   fmtbuf[fl] = '\0';
1620
1621   if ((data->flags & PF_STAR_W) && (data->flags & PF_STAR_P))
1622     sprintf (obuf, fmtbuf, data->width, data->precision, d);
1623   else if (data->flags & PF_STAR_W)
1624     sprintf (obuf, fmtbuf, data->width, d);
1625   else if (data->flags & PF_STAR_P)
1626     sprintf (obuf, fmtbuf, data->precision, d);
1627   else
1628     sprintf (obuf, fmtbuf, d);
1629
1630   for (x = obuf; *x; x++)
1631     PUT_CHAR (*x, data);    
1632 }
1633 #endif /* FLOATING_POINT */
1634
1635 #ifndef HAVE_SNPRINTF
1636
1637 int
1638 #if defined (__STDC__)
1639 vsnprintf(char *string, size_t length, const char *format, va_list args)
1640 #else
1641 vsnprintf(string, length, format, args)
1642      char *string;
1643      size_t length;
1644      const char *format;
1645      va_list args;
1646 #endif
1647 {
1648   struct DATA data;
1649
1650   if (string == 0 && length != 0)
1651     return 0;
1652   init_data (&data, string, length, format, PFM_SN);
1653   return (vsnprintf_internal(&data, string, length, format, args));
1654 }
1655
1656 int
1657 #if defined(PREFER_STDARG)
1658 snprintf(char *string, size_t length, const char * format, ...)
1659 #else
1660 snprintf(string, length, format, va_alist)
1661      char *string;
1662      size_t length;
1663      const char *format;
1664      va_dcl
1665 #endif
1666 {
1667   struct DATA data;
1668   int rval;
1669   va_list args;
1670
1671   SH_VA_START(args, format);
1672
1673   if (string == 0 && length != 0)
1674     return 0;
1675   init_data (&data, string, length, format, PFM_SN);
1676   rval = vsnprintf_internal (&data, string, length, format, args);
1677
1678   va_end(args);
1679
1680   return rval;
1681 }
1682
1683 #endif /* HAVE_SNPRINTF */
1684
1685 #ifndef HAVE_ASPRINTF
1686
1687 int
1688 #if defined (__STDC__)
1689 vasprintf(char **stringp, const char *format, va_list args)
1690 #else
1691 vasprintf(stringp, format, args)
1692      char **stringp;
1693      const char *format;
1694      va_list args;
1695 #endif
1696 {
1697   struct DATA data;
1698   char *string;
1699   int r;
1700
1701   string = (char *)xmalloc(ASBUFSIZE);
1702   init_data (&data, string, ASBUFSIZE, format, PFM_AS);
1703   r = vsnprintf_internal(&data, string, ASBUFSIZE, format, args);
1704   *stringp = data.base;         /* not string in case reallocated */
1705   return r;
1706 }
1707
1708 int
1709 #if defined(PREFER_STDARG)
1710 asprintf(char **stringp, const char * format, ...)
1711 #else
1712 asprintf(stringp, format, va_alist)
1713      char **stringp;
1714      const char *format;
1715      va_dcl
1716 #endif
1717 {
1718   int rval;
1719   va_list args;
1720
1721   SH_VA_START(args, format);
1722
1723   rval = vasprintf (stringp, format, args);
1724
1725   va_end(args);
1726
1727   return rval;
1728 }
1729
1730 #endif
1731
1732 #endif
1733
1734 #ifdef DRIVER
1735
1736 static void
1737 memory_error_and_abort ()
1738 {
1739   write (2, "out of virtual memory\n", 22);
1740   abort ();
1741 }
1742
1743 static void *
1744 xmalloc(bytes)
1745      size_t bytes;
1746 {
1747   void *ret;
1748
1749   ret = malloc(bytes);
1750   if (ret == 0)
1751     memory_error_and_abort ();
1752   return ret;
1753 }
1754
1755 static void *
1756 xrealloc (pointer, bytes)
1757      void *pointer;
1758      size_t bytes;
1759 {
1760   void *ret;
1761
1762   ret = pointer ? realloc(pointer, bytes) : malloc(bytes);
1763   if (ret == 0)
1764     memory_error_and_abort ();
1765   return ret;
1766 }
1767
1768 static void
1769 xfree(x)
1770      void *x;
1771 {
1772   if (x)
1773     free (x);
1774 }
1775
1776 /* set of small tests for snprintf() */
1777 main()
1778 {
1779   char holder[100];
1780   char *h;
1781   int i, si, ai;
1782
1783 #ifdef HAVE_LOCALE_H
1784   setlocale(LC_ALL, "");
1785 #endif
1786
1787 #if 1
1788   si = snprintf((char *)NULL, 0, "abcde\n");
1789   printf("snprintf returns %d with NULL first argument and size of 0\n", si);
1790   si = snprintf(holder, 0, "abcde\n");
1791   printf("snprintf returns %d with non-NULL first argument and size of 0\n", si);
1792   si = snprintf((char *)NULL, 16, "abcde\n");
1793   printf("snprintf returns %d with NULL first argument and non-zero size\n", si);
1794   
1795 /*
1796   printf("Suite of test for snprintf:\n");
1797   printf("a_format\n");
1798   printf("printf() format\n");
1799   printf("snprintf() format\n\n");
1800 */
1801 /* Checking the field widths */
1802
1803   printf("/%%ld %%ld/, 336, 336\n");
1804   snprintf(holder, sizeof holder, "/%ld %ld/\n", 336, 336);
1805   asprintf(&h, "/%ld %ld/\n", 336, 336);
1806   printf("/%ld %ld/\n", 336, 336);
1807   printf("%s", holder);
1808   printf("%s\n", h);
1809
1810   printf("/%%d/, 336\n");
1811   snprintf(holder, sizeof holder, "/%d/\n", 336);
1812   asprintf(&h, "/%d/\n", 336);
1813   printf("/%d/\n", 336);
1814   printf("%s", holder);
1815   printf("%s\n", h);
1816
1817   printf("/%%2d/, 336\n");
1818   snprintf(holder, sizeof holder, "/%2d/\n", 336);
1819   asprintf(&h, "/%2d/\n", 336);
1820   printf("/%2d/\n", 336);
1821   printf("%s", holder);
1822   printf("%s\n", h);
1823
1824   printf("/%%10d/, 336\n");
1825   snprintf(holder, sizeof holder, "/%10d/\n", 336);
1826   asprintf(&h, "/%10d/\n", 336);
1827   printf("/%10d/\n", 336);
1828   printf("%s", holder);
1829   printf("%s\n", h);
1830
1831   printf("/%%-10d/, 336\n");
1832   snprintf(holder, sizeof holder, "/%-10d/\n", 336);
1833   asprintf(&h, "/%-10d/\n", 336);
1834   printf("/%-10d/\n", 336);
1835   printf("%s", holder);
1836   printf("%s\n", h);
1837
1838
1839 /* floating points */
1840
1841   printf("/%%f/, 1234.56\n");
1842   snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
1843   asprintf(&h, "/%f/\n", 1234.56);
1844   printf("/%f/\n", 1234.56);
1845   printf("%s", holder);
1846   printf("%s\n", h);
1847
1848   printf("/%%e/, 1234.56\n");
1849   snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
1850   asprintf(&h, "/%e/\n", 1234.56);
1851   printf("/%e/\n", 1234.56);
1852   printf("%s", holder);
1853   printf("%s\n", h);
1854
1855   printf("/%%4.2f/, 1234.56\n");
1856   snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
1857   asprintf(&h, "/%4.2f/\n", 1234.56);
1858   printf("/%4.2f/\n", 1234.56);
1859   printf("%s", holder);
1860   printf("%s\n", h);
1861
1862   printf("/%%3.1f/, 1234.56\n");
1863   snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
1864   asprintf(&h, "/%3.1f/\n", 1234.56);
1865   printf("/%3.1f/\n", 1234.56);
1866   printf("%s", holder);
1867   printf("%s\n", h);
1868
1869   printf("/%%10.3f/, 1234.56\n");
1870   snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
1871   asprintf(&h, "/%10.3f/\n", 1234.56);
1872   printf("/%10.3f/\n", 1234.56);
1873   printf("%s", holder);
1874   printf("%s\n", h);
1875
1876   printf("/%%10.3e/, 1234.56\n");
1877   snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
1878   asprintf(&h, "/%10.3e/\n", 1234.56);
1879   printf("/%10.3e/\n", 1234.56);
1880   printf("%s", holder);
1881   printf("%s\n", h);
1882
1883   printf("/%%+4.2f/, 1234.56\n");
1884   snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
1885   asprintf(&h, "/%+4.2f/\n", 1234.56);
1886   printf("/%+4.2f/\n", 1234.56);
1887   printf("%s", holder);
1888   printf("%s\n", h);
1889
1890   printf("/%%010.2f/, 1234.56\n");
1891   snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
1892   asprintf(&h, "/%010.2f/\n", 1234.56);
1893   printf("/%010.2f/\n", 1234.56);
1894   printf("%s", holder);
1895   printf("%s\n", h);
1896
1897 #define BLURB "Outstanding acting !"
1898 /* strings precisions */
1899
1900   printf("/%%2s/, \"%s\"\n", BLURB);
1901   snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
1902   asprintf(&h, "/%2s/\n", BLURB);
1903   printf("/%2s/\n", BLURB);
1904   printf("%s", holder);
1905   printf("%s\n", h);
1906
1907   printf("/%%22s/ %s\n", BLURB);
1908   snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
1909   asprintf(&h, "/%22s/\n", BLURB);
1910   printf("/%22s/\n", BLURB);
1911   printf("%s", holder);
1912   printf("%s\n", h);
1913
1914   printf("/%%22.5s/ %s\n", BLURB);
1915   snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
1916   asprintf(&h, "/%22.5s/\n", BLURB);
1917   printf("/%22.5s/\n", BLURB);
1918   printf("%s", holder);
1919   printf("%s\n", h);
1920
1921   printf("/%%-22.5s/ %s\n", BLURB);
1922   snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
1923   asprintf(&h, "/%-22.5s/\n", BLURB);
1924   printf("/%-22.5s/\n", BLURB);
1925   printf("%s", holder);
1926   printf("%s\n", h);
1927
1928 /* see some flags */
1929
1930   printf("%%x %%X %%#x, 31, 31, 31\n");
1931   snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
1932   asprintf(&h, "%x %X %#x\n", 31, 31, 31);
1933   printf("%x %X %#x\n", 31, 31, 31);
1934   printf("%s", holder);
1935   printf("%s\n", h);
1936
1937   printf("**%%d**%% d**%% d**, 42, 42, -42\n");
1938   snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
1939   asprintf(&h, "**%d**% d**% d**\n", 42, 42, -42);
1940   printf("**%d**% d**% d**\n", 42, 42, -42);
1941   printf("%s", holder);
1942   printf("%s\n", h);
1943
1944 /* other flags */
1945
1946   printf("/%%g/, 31.4\n");
1947   snprintf(holder, sizeof holder, "/%g/\n", 31.4);
1948   asprintf(&h, "/%g/\n", 31.4);
1949   printf("/%g/\n", 31.4);
1950   printf("%s", holder);
1951   printf("%s\n", h);
1952
1953   printf("/%%.6g/, 31.4\n");
1954   snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
1955   asprintf(&h, "/%.6g/\n", 31.4);
1956   printf("/%.6g/\n", 31.4);
1957   printf("%s", holder);
1958   printf("%s\n", h);
1959
1960   printf("/%%.1G/, 31.4\n");
1961   snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
1962   asprintf(&h, "/%.1G/\n", 31.4);
1963   printf("/%.1G/\n", 31.4);
1964   printf("%s", holder);
1965   printf("%s\n", h);
1966
1967   printf("/%%.1G/, 3100000000.4\n");
1968   snprintf(holder, sizeof holder, "/%.1G/\n", 3100000000.4);  
1969   asprintf(&h, "/%.1G/\n", 3100000000.4);  
1970   printf("/%.1G/\n", 3100000000.4); 
1971   printf("%s", holder);
1972   printf("%s\n", h);
1973
1974   printf("abc%%n\n");
1975   printf("abc%n", &i); printf("%d\n", i);
1976   snprintf(holder, sizeof holder, "abc%n", &i);
1977   printf("%s", holder); printf("%d\n\n", i);
1978   asprintf(&h, "abc%n", &i);
1979   printf("%s", h); printf("%d\n\n", i);
1980   
1981   printf("%%*.*s --> 10.10\n");
1982   snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
1983   asprintf(&h, "%*.*s\n", 10, 10, BLURB);
1984   printf("%*.*s\n", 10, 10, BLURB);
1985   printf("%s", holder);
1986   printf("%s\n", h);
1987
1988   printf("%%%%%%%%\n");
1989   snprintf(holder, sizeof holder, "%%%%\n");
1990   asprintf(&h, "%%%%\n");
1991   printf("%%%%\n");
1992   printf("%s", holder);
1993   printf("%s\n", h);
1994
1995 #define BIG "Hello this is a too big string for the buffer"
1996 /*  printf("A buffer to small of 10, trying to put this:\n");*/
1997   printf("<%%>, %s\n", BIG); 
1998   i = snprintf(holder, 10, "%s\n", BIG);
1999   i = asprintf(&h, "%s", BIG);
2000   printf("<%s>\n", BIG);
2001   printf("<%s>\n", holder);
2002   printf("<%s>\n\n", h);
2003
2004   printf ("<%%p> vsnprintf\n");
2005   i = snprintf(holder, 100, "%p", vsnprintf);
2006   i = asprintf(&h, "%p", vsnprintf);
2007   printf("<%p>\n", vsnprintf);
2008   printf("<%s>\n", holder);  
2009   printf("<%s>\n\n", h);
2010
2011   printf ("<%%lu> LONG_MAX+1\n");
2012   i = snprintf(holder, 100, "%lu", (unsigned long)(LONG_MAX)+1);
2013   i = asprintf(&h, "%lu", (unsigned long)(LONG_MAX)+1);
2014   printf("<%lu>\n", (unsigned long)(LONG_MAX)+1);
2015   printf("<%s>\n", holder);
2016   printf("<%s>\n\n", h);
2017
2018 #ifdef HAVE_LONG_LONG
2019   printf ("<%%llu> LLONG_MAX+1\n");
2020   i = snprintf(holder, 100, "%llu", (unsigned long long)(LLONG_MAX)+1);
2021   i = asprintf(&h, "%llu", (unsigned long long)(LLONG_MAX)+1);
2022   printf("<%llu>\n", (unsigned long long)(LLONG_MAX)+1);
2023   printf("<%s>\n", holder);
2024   printf("<%s>\n\n", h);
2025 #endif
2026
2027 #ifdef HAVE_LONG_DOUBLE
2028   printf ("<%%6.2LE> 42.42\n");
2029   i = snprintf(holder, 100, "%6.2LE", (long double)42.42);
2030   i = asprintf(&h, "%6.2LE", (long double)42.42);
2031   printf ("<%6.2LE>\n", (long double)42.42);
2032   printf ("<%s>\n", holder);
2033   printf ("<%s>\n\n", h);
2034 #endif
2035
2036 #ifdef HAVE_PRINTF_A_FORMAT
2037   printf ("<%%6.2A> 42.42\n");
2038   i = snprintf(holder, 100, "%6.2A", 42.42);
2039   i = asprintf(&h, "%6.2A", 42.42);
2040   printf ("<%6.2A>\n", 42.42);
2041   printf ("<%s>\n", holder);
2042   printf ("<%s>\n\n", h);
2043
2044   printf ("<%%6.2LA> 42.42\n");
2045   i = snprintf(holder, 100, "%6.2LA", (long double)42.42);
2046   i = asprintf(&h, "%6.2LA", (long double)42.42);
2047   printf ("<%6.2LA>\n", (long double)42.42);
2048   printf ("<%s>\n", holder);
2049   printf ("<%s>\n\n", h);
2050 #endif
2051
2052   printf ("<%%.10240f> DBL_MAX\n");
2053   si = snprintf(holder, 100, "%.10240f", DBL_MAX);
2054   ai = asprintf(&h, "%.10240f", DBL_MAX);
2055   printf ("<%.10240f>\n", DBL_MAX);
2056   printf ("<%d> <%s>\n", si, holder);
2057   printf ("<%d> <%s>\n\n", ai, h);
2058
2059   printf ("<%%.10240Lf> LDBL_MAX\n");
2060   si = snprintf(holder, 100, "%.10240Lf", (long double)LDBL_MAX);
2061   ai = asprintf(&h, "%.10240Lf", (long double)LDBL_MAX);
2062   printf ("<%.10240Lf>\n", (long double)LDBL_MAX);
2063   printf ("<%d> <%s>\n", si, holder);
2064   printf ("<%d> <%s>\n\n", ai, h);
2065
2066   /* huh? */
2067   printf("/%%g/, 421.2345\n");
2068   snprintf(holder, sizeof holder, "/%g/\n", 421.2345);
2069   asprintf(&h, "/%g/\n", 421.2345);
2070   printf("/%g/\n", 421.2345);
2071   printf("%s", holder);
2072   printf("%s\n", h);
2073
2074   printf("/%%g/, 4214.2345\n");
2075   snprintf(holder, sizeof holder, "/%g/\n", 4214.2345);
2076   asprintf(&h, "/%g/\n", 4214.2345);
2077   printf("/%g/\n", 4214.2345);
2078   printf("%s", holder);
2079   printf("%s\n", h);
2080
2081   printf("/%%.5g/, 4214.2345\n");
2082   snprintf(holder, sizeof holder, "/%.5g/\n", 4214.2345);
2083   asprintf(&h, "/%.5g/\n", 4214.2345);
2084   printf("/%.5g/\n", 4214.2345);
2085   printf("%s", holder);
2086   printf("%s\n", h);
2087
2088   printf("/%%.4g/, 4214.2345\n");
2089   snprintf(holder, sizeof holder, "/%.4g/\n", 4214.2345);
2090   asprintf(&h, "/%.4g/\n", 4214.2345);
2091   printf("/%.4g/\n", 4214.2345);
2092   printf("%s", holder);
2093   printf("%s\n", h);
2094
2095   printf("/%%'ld %%'ld/, 12345, 1234567\n");
2096   snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 12345, 1234567);
2097   asprintf(&h, "/%'ld %'ld/\n", 12345, 1234567);
2098   printf("/%'ld %'ld/\n", 12345, 1234567);
2099   printf("%s", holder);
2100   printf("%s\n", h);
2101
2102   printf("/%%'ld %%'ld/, 336, 3336\n");
2103   snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 336, 3336);
2104   asprintf(&h, "/%'ld %'ld/\n", 336, 3336);
2105   printf("/%'ld %'ld/\n", 336, 3336);
2106   printf("%s", holder);
2107   printf("%s\n", h);
2108
2109   printf("/%%'ld %%'ld/, -42786, -142786\n");
2110   snprintf(holder, sizeof holder, "/%'ld %'ld/\n", -42786, -142786);
2111   asprintf(&h, "/%'ld %'ld/\n", -42786, -142786);
2112   printf("/%'ld %'ld/\n", -42786, -142786);
2113   printf("%s", holder);
2114   printf("%s\n", h);
2115
2116   printf("/%%'f %%'f/, 421.2345, 421234.56789\n");
2117   snprintf(holder, sizeof holder, "/%'f %'f/\n", 421.2345, 421234.56789);
2118   asprintf(&h, "/%'f %'f/\n", 421.2345, 421234.56789);
2119   printf("/%'f %'f/\n", 421.2345, 421234.56789);
2120   printf("%s", holder);
2121   printf("%s\n", h);
2122
2123   printf("/%%'f %%'f/, -421.2345, -421234.56789\n");
2124   snprintf(holder, sizeof holder, "/%'f %'f/\n", -421.2345, -421234.56789);
2125   asprintf(&h, "/%'f %'f/\n", -421.2345, -421234.56789);
2126   printf("/%'f %'f/\n", -421.2345, -421234.56789);
2127   printf("%s", holder);
2128   printf("%s\n", h);
2129
2130   printf("/%%'g %%'g/, 421.2345, 421234.56789\n");
2131   snprintf(holder, sizeof holder, "/%'g %'g/\n", 421.2345, 421234.56789);
2132   asprintf(&h, "/%'g %'g/\n", 421.2345, 421234.56789);
2133   printf("/%'g %'g/\n", 421.2345, 421234.56789);
2134   printf("%s", holder);
2135   printf("%s\n", h);
2136
2137   printf("/%%'g %%'g/, -421.2345, -421234.56789\n");
2138   snprintf(holder, sizeof holder, "/%'g %'g/\n", -421.2345, -421234.56789);
2139   asprintf(&h, "/%'g %'g/\n", -421.2345, -421234.56789);
2140   printf("/%'g %'g/\n", -421.2345, -421234.56789);
2141   printf("%s", holder);
2142   printf("%s\n", h);
2143 #endif
2144
2145   printf("/%%'g/, 4213455.8392\n");
2146   snprintf(holder, sizeof holder, "/%'g/\n", 4213455.8392);
2147   asprintf(&h, "/%'g/\n", 4213455.8392);
2148   printf("/%'g/\n", 4213455.8392);
2149   printf("%s", holder);
2150   printf("%s\n", h);
2151
2152   exit (0);
2153 }
2154 #endif