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