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