Imported from ../bash-2.05a.tar.gz.
[platform/upstream/bash.git] / lib / sh / snprintf.c
1 /*
2  build a test version with
3    gcc -g -DDRIVER -I../.. -I../../include -o test-snprintf snprintf.c fmtu*long.o
4 */
5  
6 /*
7    Unix snprintf implementation.
8    derived from inetutils/libinetutils/snprintf.c Version 1.1
9
10    Copyright (C) 2001 Free Software Foundation, Inc.
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General License for more details.
21    
22    You should have received a copy of the GNU General License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25    
26    Revision History:
27
28    1.1:
29       *  added changes from Miles Bader
30       *  corrected a bug with %f
31       *  added support for %#g
32       *  added more comments :-)
33    1.0:
34       *  supporting must ANSI syntaxic_sugars
35    0.0:
36       *  support %s %c %d
37
38  THANKS(for the patches and ideas):
39      Miles Bader
40      Cyrille Rustom
41      Jacek Slabocewiz
42      Mike Parker(mouse)
43
44 */
45
46 /*
47  * Currently doesn't handle (and bash/readline doesn't use):
48  *      *M$ width, precision specifications
49  *      %N$ numbered argument conversions
50  *      inf, nan floating values (could use isinf(), isnan())
51  *      `,', `'' flags 
52  *      `C', `S' conversions
53  *      support for `F' is imperfect, since underlying printf may not handle it
54  */
55
56 #define FLOATING_POINT
57
58 #ifdef HAVE_CONFIG_H
59 #  include <config.h>
60 #endif
61
62 #if defined(DRIVER) && !defined(HAVE_CONFIG_H)
63 #define HAVE_LONG_LONG
64 #define HAVE_LONG_DOUBLE
65 #ifdef __linux__
66 #define HAVE_PRINTF_A_FORMAT
67 #endif
68 #define PREFER_STDARG
69 #define HAVE_STRINGIZE
70 #define HAVE_LIMITS_H
71 #define HAVE_STDDEF_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 <stdio.h>    /* for sprintf */
100 #endif
101
102 #include <typemax.h>
103
104 #include "stdc.h"
105
106 #ifndef DRIVER
107 #  include "shell.h"
108 #else
109 #  define FL_PREFIX     0x01    /* add 0x, 0X, or 0 prefix as appropriate */
110 #  define FL_ADDBASE    0x02    /* add base# prefix to converted value */
111 #  define FL_HEXUPPER   0x04    /* use uppercase when converting to hex */
112 #  define FL_UNSIGNED   0x08    /* don't add any sign */
113 extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
114 extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
115 #endif
116
117 /* Bound on length of the string representing an integer value of type T.
118    Subtract one for the sign bit if T is signed;
119    302 / 1000 is log10 (2) rounded up;
120    add one for integer division truncation;
121    add one more for a minus sign if t is signed.  */
122 #define INT_STRLEN_BOUND(t) \
123   ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
124      + 1 + TYPE_SIGNED (t))
125
126 /* conversion flags */
127 #define PF_ALTFORM      0x00001         /* # */
128 #define PF_HEXPREFIX    0x00002         /* 0[Xx] */
129 #define PF_LADJUST      0x00004         /* - */
130 #define PF_ZEROPAD      0x00008         /* 0 */
131 #define PF_PLUS         0x00010         /* + */
132 #define PF_SPACE        0x00020         /* ' ' */
133 #define PF_COMMA        0x00040         /* , */
134
135 #define PF_DOT          0x00080         /* `.precision' */
136 #define PF_STAR_P       0x00100         /* `*' after precision */
137 #define PF_STAR_W       0x00200         /* `*' before or without precision */
138
139 /* length modifiers */
140 #define PF_SIGNEDCHAR   0x00400         /* hh */
141 #define PF_SHORTINT     0x00800         /* h */
142 #define PF_LONGINT      0x01000         /* l */
143 #define PF_LONGLONG     0x02000         /* ll */
144 #define PF_LONGDBL      0x04000         /* L */
145 #define PF_INTMAX_T     0x08000         /* j */
146 #define PF_SIZE_T       0x10000         /* z */
147 #define PF_PTRDIFF_T    0x20000         /* t */
148
149 #define PF_ALLOCBUF     0x40000         /* for asprintf, vasprintf */
150
151 #define PFM_SN          0x01            /* snprintf, vsnprintf */
152 #define PFM_AS          0x02            /* asprintf, vasprintf */
153
154 #define ASBUFSIZE       128
155
156 #define x_digs  "0123456789abcdef"
157 #define X_digs  "0123456789ABCDEF"
158
159 static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
160
161 /* 
162  * For the FLOATING POINT FORMAT :
163  *  the challenge was finding a way to
164  *  manipulate the Real numbers without having
165  *  to resort to mathematical function(it
166  *  would require to link with -lm) and not
167  *  going down to the bit pattern(not portable)
168  *
169  *  so a number, a real is:
170
171       real = integral + fraction
172
173       integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
174       fraction = b(1)*10^-1 + b(2)*10^-2 + ...
175
176       where:
177        0 <= a(i) => 9 
178        0 <= b(i) => 9 
179  
180     from then it was simple math
181  */
182
183 /*
184  * size of the buffer for the integral part
185  * and the fraction part 
186  */
187 #define MAX_INT  99 + 1 /* 1 for the null */
188 #define MAX_FRACT 307 + 1
189
190 /* 
191  * These functions use static buffers to store the results,
192  * and so are not reentrant
193  */
194 #define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0);
195 #define dtoa(n, p, f) numtoa(n, 10, p, f)
196
197 #define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
198
199 /* Macros that do proper sign extension and handle length modifiers.  Used
200    for the integer conversion specifiers. */
201 #define GETSIGNED(p) \
202   (((p)->flags & PF_LONGINT) \
203         ? va_arg(args, long) \
204         : (((p)->flags & PF_SHORTINT) ? (long)(short)va_arg(args, int) \
205                                       : (long)va_arg(args, int)))
206
207 #define GETUNSIGNED(p) \
208   (((p)->flags & PF_LONGINT) \
209         ? va_arg(args, unsigned long) \
210         : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)va_arg(args, int) \
211                                       : (unsigned long)va_arg(args, unsigned int)))
212
213
214 #ifdef HAVE_LONG_DOUBLE
215 #define GETLDOUBLE(p) va_arg(args, long double)
216 #endif
217 #define GETDOUBLE(p) va_arg(args, double)
218
219 #define SET_SIZE_FLAGS(p, type) \
220   if (sizeof (type) > sizeof (int)) \
221     (p)->flags |= PF_LONGINT; \
222   if (sizeof (type) > sizeof (long)) \
223     (p)->flags |= PF_LONGLONG;
224
225 /* this struct holds everything we need */
226 struct DATA
227 {
228   int length;
229   char *base;           /* needed for [v]asprintf */
230   char *holder;
231   int counter;
232   const char *pf;
233
234 /* FLAGS */
235   int flags;
236   int justify;
237   int width, precision;
238   char pad;
239 };
240
241 /* the floating point stuff */
242 #ifdef FLOATING_POINT
243 static double pow_10 __P((int));
244 static int log_10 __P((double));
245 static double integral __P((double, double *));
246 static char *numtoa __P((double, int, int, char **));
247 #endif
248
249 static void init_data __P((struct DATA *, char *, size_t, const char *, int));
250 static void init_conv_flag __P((struct DATA *));
251
252 /* for the format */
253 #ifdef FLOATING_POINT
254 static void floating __P((struct DATA *, double));
255 static void exponent __P((struct DATA *, double));
256 #endif
257 static void number __P((struct DATA *, unsigned long, int));
258 #ifdef HAVE_LONG_LONG
259 static void lnumber __P((struct DATA *, unsigned long long, int));
260 #endif
261 static void pointer __P((struct DATA *, unsigned long));
262 static void strings __P((struct DATA *, char *));
263
264 #ifdef FLOATING_POINT
265 #  define FALLBACK_FMTSIZE      32
266 #  define FALLBACK_BASE         4096
267 #  define LFALLBACK_BASE        5120
268 #  ifdef HAVE_LONG_DOUBLE
269 static void ldfallback __P((struct DATA *, const char *, const char *, long double));
270 #  endif
271 static void dfallback __P((struct DATA *, const char *, const char *, double));
272 #endif
273
274 #ifdef DRIVER
275 static void memory_error_and_abort ();
276 static void *xmalloc __P((size_t));
277 static void *xrealloc __P((void *, size_t));
278 static void xfree __P((void *));
279 #else
280 #  include <xmalloc.h>
281 #endif
282
283 /* those are defines specific to snprintf to hopefully
284  * make the code clearer :-)
285  */
286 #define RIGHT 1
287 #define LEFT  0
288 #define NOT_FOUND -1
289 #define FOUND 1
290 #define MAX_FIELD 15
291
292 /* round off to the precision */
293 #define ROUND(d, p) \
294             (d < 0.) ? \
295              d - pow_10(-(p)->precision) * 0.5 : \
296              d + pow_10(-(p)->precision) * 0.5
297
298 /* set default precision */
299 #define DEF_PREC(p) \
300             if ((p)->precision == NOT_FOUND) \
301               (p)->precision = 6
302
303 /* put a char.  increment the number of chars written even if we've exceeded
304    the vsnprintf/snprintf buffer size (for the return value) */
305 #define PUT_CHAR(c, p) \
306         do \
307           { \
308             if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \
309               { \
310                 (p)->length += ASBUFSIZE; \
311                 (p)->base = (char *)xrealloc((p)->base, (p)->length); \
312                 (p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \
313               } \
314             if ((p)->counter < (p)->length) \
315               *(p)->holder++ = (c); \
316             (p)->counter++; \
317           } \
318         while (0)
319
320 #define PUT_PLUS(d, p, zero) \
321             if ((d) > zero && (p)->justify == RIGHT) \
322               PUT_CHAR('+', p)
323
324 #define PUT_SPACE(d, p, zero) \
325             if (((p)->flags & PF_SPACE) && (d) > zero) \
326               PUT_CHAR(' ', p)
327
328 /* pad right */ 
329 #define PAD_RIGHT(p) \
330             if ((p)->width > 0 && (p)->justify != LEFT) \
331               for (; (p)->width > 0; (p)->width--) \
332                  PUT_CHAR((p)->pad, p)
333
334 /* pad left */
335 #define PAD_LEFT(p) \
336             if ((p)->width > 0 && (p)->justify == LEFT) \
337               for (; (p)->width > 0; (p)->width--) \
338                  PUT_CHAR((p)->pad, p)
339
340 /* if width and prec. in the args */
341 #define STAR_ARGS(p) \
342             if ((p)->flags & PF_STAR_W) \
343               (p)->width = va_arg(args, int); \
344             if ((p)->flags & PF_STAR_P) \
345               (p)->precision = va_arg(args, int)
346
347 #ifdef FLOATING_POINT
348 /*
349  * Find the nth power of 10
350  */
351 static double
352 pow_10(n)
353      int n;
354
355   double P;
356
357   /* handle common cases with fast switch statement. */
358   switch (n)
359     {
360     case -3:    return .001;
361     case -2:    return .01;
362     case -1:    return .1;
363     case 0:     return 1.;
364     case 1:     return 10.;
365     case 2:     return 100.;
366     case 3:     return 1000.;
367     }
368
369   if (n < 0)
370     {
371       P = .0001;
372       for (n += 4; n < 0; n++)
373         P /= 10.;
374     }
375   else
376     {
377       P = 10000.;
378       for (n -= 4; n > 0; n--)
379         P *= 10.;
380     }
381
382   return P;
383 }
384
385 /*
386  * Find the integral part of the log in base 10 
387  * Note: this not a real log10()
388          I just need and approximation(integerpart) of x in:
389           10^x ~= r
390  * log_10(200) = 2;
391  * log_10(250) = 2;
392  */
393 static int
394 log_10(r)
395      double r;
396
397   int i = 0;
398   double result = 1.;
399
400   if (r < 0.)
401     r = -r;
402
403   if (r < 1.)
404     {
405       while (result >= r)
406         {
407           result /= 10.;
408           i++;
409         }
410       return (-i);
411     }
412   else
413     {
414       while (result <= r)
415         {
416           result *= 10.;
417           i++;
418         }
419       return (i - 1);
420     }
421 }
422
423 /*
424  * This function return the fraction part of a double
425  * and set in ip the integral part.
426  * In many ways it resemble the modf() found on most Un*x
427  */
428 static double
429 integral(real, ip)
430      double real;
431      double *ip;
432
433   int j;
434   double i, s, p;
435   double real_integral = 0.;
436
437   /* take care of the obvious */
438   /* equal to zero ? */
439   if (real == 0.)
440     {
441       *ip = 0.;
442       return (0.);
443     }
444
445   /* negative number ? */
446   if (real < 0.)
447     real = -real;
448
449   /* a fraction ? */
450   if ( real < 1.)
451     {
452       *ip = 0.;
453       return real;
454     }
455
456   /* the real work :-) */
457   for (j = log_10(real); j >= 0; j--)
458     {
459       p = pow_10(j);
460       s = (real - real_integral)/p;
461       i = 0.;
462       while (i + 1. <= s)
463         i++;
464       real_integral += i*p;
465     }
466   *ip = real_integral;
467   return (real - real_integral);
468 }
469
470 #define PRECISION 1.e-6
471 /* 
472  * return an ascii representation of the integral part of the number
473  * and set fract to be an ascii representation of the fraction part
474  * the container for the fraction and the integral part or staticly
475  * declare with fix size 
476  */
477 static char *
478 numtoa(number, base, precision, fract)
479      double number;
480      int base, precision;
481      char **fract;
482 {
483   register int i, j;
484   double ip, fp; /* integer and fraction part */
485   double fraction;
486   int digits = MAX_INT - 1;
487   static char integral_part[MAX_INT];
488   static char fraction_part[MAX_FRACT];
489   double sign;
490   int ch;
491
492   /* taking care of the obvious case: 0.0 */
493   if (number == 0.)
494     { 
495       integral_part[0] = '0';
496       integral_part[1] = '\0';
497       fraction_part[0] = '0';
498       fraction_part[1] = '\0';
499       return integral_part;
500     }
501
502   /* for negative numbers */
503   if ((sign = number) < 0.)
504     {
505       number = -number;
506       digits--; /* sign consume one digit */
507     }
508
509   fraction = integral(number, &ip);
510   number = ip;
511
512   /* do the integral part */
513   if (ip == 0.)
514     {
515       integral_part[0] = '0';
516       i = 1;
517     }
518   else
519     {
520       for ( i = 0; i < digits && number != 0.; ++i)
521         {
522           number /= base;
523           fp = integral(number, &ip);
524           ch = (int)((fp + PRECISION)*base); /* force to round */
525           integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
526           if (! ISXDIGIT((unsigned char)integral_part[i]))
527             break;      /* bail out overflow !! */
528           number = ip;
529          }
530     }
531      
532   /* Oh No !! out of bound, ho well fill it up ! */
533   if (number != 0.)
534     for (i = 0; i < digits; ++i)
535       integral_part[i] = '9';
536
537   /* put the sign ? */
538   if (sign < 0.)
539     integral_part[i++] = '-';
540
541   integral_part[i] = '\0';
542
543   /* reverse every thing */
544   for ( i--, j = 0; j < i; j++, i--)
545     SWAP_INT(integral_part[i], integral_part[j]);  
546
547   /* the fractional part */
548   for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--)
549     {
550       fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
551       if (! DIGIT(fraction_part[i])) /* underflow ? */
552         break;
553       fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
554     }
555   fraction_part[i] = '\0';
556
557   if (fract != (char **)0)
558     *fract = fraction_part;
559
560   return integral_part;
561 }
562 #endif
563
564 /* for %d and friends, it puts in holder
565  * the representation with the right padding
566  */
567 static void
568 number(p, d, base)
569      struct DATA *p;
570      unsigned long d;
571      int base;
572 {
573   char *tmp;
574   long sd;
575   int flags;
576
577   sd = d;       /* signed for ' ' padding in base 10 */
578   flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
579   if (*p->pf == 'X')
580     flags |= FL_HEXUPPER;
581
582   tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags);
583   p->width -= strlen(tmp);
584   PAD_RIGHT(p);
585
586   switch (base)
587     {
588     case 10:
589       PUT_PLUS(sd, p, 0);
590       PUT_SPACE(sd, p, 0);
591       break;
592     case 8:
593       if (p->flags & PF_ALTFORM)
594         PUT_CHAR('0', p);
595       break;
596     case 16:
597       if (p->flags & PF_ALTFORM)
598         {
599           PUT_CHAR('0', p);
600           PUT_CHAR(*p->pf, p);
601         }
602       break;
603     }
604
605   while (*tmp)
606     {
607       PUT_CHAR(*tmp, p);
608       tmp++;
609     }
610
611   PAD_LEFT(p);
612 }
613
614 #ifdef HAVE_LONG_LONG
615 /*
616  * identical to number() but works for `long long'
617  */
618 static void
619 lnumber(p, d, base)
620      struct DATA *p;
621      unsigned long long d;
622      int base;
623 {
624   char *tmp;
625   long long sd;
626   int flags;
627
628   sd = d;       /* signed for ' ' padding in base 10 */
629   flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
630   if (*p->pf == 'X')
631     flags |= FL_HEXUPPER;
632
633   tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags);
634   p->width -= strlen(tmp);
635   PAD_RIGHT(p);
636
637   switch (base)
638     {
639     case 10:
640       PUT_PLUS(sd, p, 0);
641       PUT_SPACE(sd, p, 0);
642       break;
643     case 8:
644       if (p->flags & PF_ALTFORM)
645         PUT_CHAR('0', p);
646       break;
647     case 16:
648       if (p->flags & PF_ALTFORM)
649         {
650           PUT_CHAR('0', p);
651           PUT_CHAR(*p->pf, p);
652         }
653       break;
654     }
655
656   while (*tmp)
657     {
658       PUT_CHAR(*tmp, p);
659       tmp++;
660     }
661
662   PAD_LEFT(p);
663 }
664 #endif
665
666 static void
667 pointer(p, d)
668      struct DATA *p;
669      unsigned long d;
670 {
671   char *tmp;
672
673   tmp = fmtulong(d, 16, intbuf, sizeof(intbuf), 0);
674   p->width -= strlen(tmp);
675   PAD_RIGHT(p);
676
677   /* prefix '0x' for pointers */
678   PUT_CHAR('0', p);
679   PUT_CHAR('x', p);
680
681   while (*tmp)
682     {
683       PUT_CHAR(*tmp, p);
684       tmp++;
685     }
686   PAD_LEFT(p);
687 }
688
689 /* %s strings */
690 static void
691 strings(p, tmp)
692      struct DATA *p;
693      char *tmp;
694 {
695   int i;
696
697   i = strlen(tmp);
698   if (p->precision != NOT_FOUND) /* the smallest number */
699     i = (i < p->precision ? i : p->precision);
700   p->width -= i;
701   PAD_RIGHT(p);
702   while (i-- > 0)
703     { /* put the sting */
704       PUT_CHAR(*tmp, p);
705       tmp++;
706     }
707   PAD_LEFT(p);
708 }
709
710 #ifdef FLOATING_POINT
711 /* %f %F %g %G floating point representation */
712 static void
713 floating(p, d)
714      struct DATA *p;
715      double d;
716 {
717   char *tmp, *tmp2;
718   int i;
719
720   DEF_PREC(p);
721   d = ROUND(d, p);
722   tmp = dtoa(d, p->precision, &tmp2);
723   /* calculate the padding. 1 for the dot */
724   p->width = p->width -
725             ((d > 0. && p->justify == RIGHT) ? 1:0) -
726             ((p->flags & PF_SPACE) ? 1:0) -
727             strlen(tmp) - p->precision - 1;
728   PAD_RIGHT(p);  
729   PUT_PLUS(d, p, 0.);
730   PUT_SPACE(d, p, 0.);
731   while (*tmp)
732     { /* the integral */
733       PUT_CHAR(*tmp, p);
734       tmp++;
735     }
736   if (p->precision != 0 || (p->flags & PF_ALTFORM))
737     PUT_CHAR('.', p);  /* put the '.' */
738   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
739     /* smash the trailing zeros unless altform */
740     for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
741        tmp2[i] = '\0'; 
742   for (; *tmp2; tmp2++)
743     PUT_CHAR(*tmp2, p); /* the fraction */
744   
745   PAD_LEFT(p);
746
747
748 /* %e %E %g %G exponent representation */
749 static void
750 exponent(p, d)
751      struct DATA *p;
752      double d;
753 {
754   char *tmp, *tmp2;
755   int j, i, nsig, ndig;
756
757   DEF_PREC(p);
758   j = log_10(d);
759   d = d / pow_10(j);  /* get the Mantissa */
760   d = ROUND(d, p);                
761   tmp = dtoa(d, p->precision, &tmp2);
762   /* 1 for unit, 1 for the '.', 1 for 'e|E',
763    * 1 for '+|-', 2 for 'exp' */
764   /* calculate how much padding need */
765   p->width = p->width - 
766              ((d > 0. && p->justify == RIGHT) ? 1:0) -
767              ((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
768   PAD_RIGHT(p);
769   PUT_PLUS(d, p, 0.);
770   PUT_SPACE(d, p, 0.);
771   /*
772    * When supplied %g or %G, an optional precision is the number of
773    * significant digits to print.
774    *
775    * nsig = number of significant digits we've printed (leading zeros are
776    *        never significant)
777    * ndig = if non-zero, max number of significant digits to print (only
778    *        applicable to %g/%G)
779    */
780   nsig = ndig = 0;
781   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_DOT))
782     ndig = (p->precision == 0) ? 1 : p->precision;
783
784   while (*tmp)
785     {
786       PUT_CHAR(*tmp, p);
787       tmp++;
788       if (ndig && (++nsig >= ndig))
789         break;
790     }
791
792   if ((p->precision != 0 || (p->flags & PF_ALTFORM)) && (ndig == 0 || nsig < ndig))
793       PUT_CHAR('.', p);  /* the '.' */
794   if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
795     /* smash the trailing zeros unless altform */
796     for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
797        tmp2[i] = '\0'; 
798   for (; *tmp2; tmp2++)
799     {
800       if (ndig && (nsig++ >= ndig))
801         break;
802       PUT_CHAR(*tmp2, p); /* the fraction */
803     }
804
805   /* the exponent put the 'e|E' */
806   if (*p->pf == 'g' || *p->pf == 'e')
807     {
808       PUT_CHAR('e', p);
809     }
810   else
811      PUT_CHAR('E', p);
812
813   /* the sign of the exp */
814   if (j > 0)
815     {
816       PUT_CHAR('+', p);
817     }
818   else
819     {
820       PUT_CHAR('-', p);
821       j = -j;
822     }
823
824    tmp = itoa(j);
825    /* pad out to at least two spaces.  pad with `0' if the exponent is a
826       single digit. */
827    if (j <= 9)
828      {
829        PUT_CHAR('0', p);
830      }
831
832    /* the exponent */
833    while (*tmp)
834      {
835        PUT_CHAR(*tmp, p);
836        tmp++;
837      }
838    PAD_LEFT(p);
839 }
840 #endif
841
842 /* initialize the conversion specifiers */
843 static void
844 init_conv_flag (p)
845      struct DATA *p;
846 {
847   p->flags &= PF_ALLOCBUF;              /* preserve PF_ALLOCBUF flag */
848   p->precision = p->width = NOT_FOUND;
849   p->justify = NOT_FOUND;
850   p->pad = ' ';
851 }
852
853 static void
854 init_data (p, string, length, format, mode)
855      struct DATA *p;
856      char *string;
857      size_t length;
858      const char *format;
859      int mode;
860 {
861   p->length = length - 1; /* leave room for '\0' */
862   p->holder = p->base = string;
863   p->pf = format;
864   p->counter = 0;
865   p->flags = (mode == PFM_AS) ? PF_ALLOCBUF : 0;
866 }
867
868 static int
869 #if defined (__STDC__)
870 vsnprintf_internal(struct DATA *data, char *string, size_t length, const char *format, va_list args)
871 #else
872 vsnprintf_internal(data, string, length, format, args)
873      struct DATA *data;
874      char *string;
875      size_t length;
876      const char *format;
877      va_list args;
878 #endif
879 {
880   double d; /* temporary holder */
881 #ifdef HAVE_LONG_DOUBLE
882   long double ld;       /* for later */
883 #endif
884   unsigned long ul;
885 #ifdef HAVE_LONG_LONG
886   unsigned long long ull;
887 #endif
888   int state, i, c, n;
889   char *s;
890   const char *convstart;
891
892   /* Sanity check, the string must be > 1.  C99 actually says that LENGTH
893      can be zero here, in the case of snprintf/vsnprintf (it's never 0 in
894      the case of asprintf/vasprintf), and the return value is the number
895      of characters that would have been written. */
896   if (length < 1)
897     return -1;
898
899   if (format == 0)
900     return 0;
901
902   for (; c = *(data->pf); data->pf++)
903     {
904       if (c != '%')
905         {
906           PUT_CHAR (c, data);
907           continue;
908         }
909
910       convstart = data->pf;
911       init_conv_flag (data); /* initialise format flags */
912
913       state = 1;
914       for (state = 1; state && *data->pf; )
915         {
916           c = *(++data->pf);
917               /* fmtend = data->pf */
918 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
919           if (data->flags & PF_LONGDBL)
920             {
921               switch (c)
922                 {
923                 case 'f': case 'F':
924                 case 'e': case 'E':
925                 case 'g': case 'G':
926 #  ifdef HAVE_PRINTF_A_FORMAT
927                 case 'a': case 'A':
928 #  endif
929                   STAR_ARGS (data);
930                   ld = GETLDOUBLE (data);
931                   ldfallback (data, convstart, data->pf, ld);
932                   goto conv_break;
933                 }
934             }
935 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
936
937           switch (c)
938             {
939               /* Parse format flags */
940               case '\0': /* a NULL here ? ? bail out */
941                 *data->holder = '\0';
942                 return data->counter;
943                 break;
944               case '#':
945                 data->flags |= PF_ALTFORM;
946                 continue;
947               case '0':
948                 data->flags |= PF_ZEROPAD;
949                 data->pad = '0';
950                 continue;
951               case '*':
952                 if (data->flags & PF_DOT)
953                   data->flags |= PF_STAR_P;
954                 else
955                   data->flags |= PF_STAR_W;
956                 continue;
957               case '-':
958                 data->flags |= PF_LADJUST;
959                 data->justify = LEFT;
960                 continue;
961               case ' ':
962                 if ((data->flags & PF_PLUS) == 0)
963                   data->flags |= PF_SPACE;
964                 continue;
965               case '+':
966                 data->flags |= PF_PLUS;
967                 data->justify = RIGHT;
968                 continue;
969               case ',':
970                 data->flags |= PF_COMMA;                /* not implemented yet */
971                 continue;
972
973               case '1': case '2': case '3':
974               case '4': case '5': case '6':
975               case '7': case '8': case '9':
976                 n = 0;
977                 do
978                   {
979                     n = n * 10 + TODIGIT(c);
980                     c = *(++data->pf);
981                   }
982                 while (DIGIT(c));
983                 data->pf--;             /* went too far */
984                 if (n < 0)
985                   n = 0;
986                 if (data->flags & PF_DOT)
987                   data->precision = n;
988                 else
989                   data->width = n;
990                 continue;
991
992               /* optional precision */
993               case '.':
994                 data->flags |= PF_DOT;
995                 data->precision = 0;
996                 continue;
997
998               /* length modifiers */
999               case 'h':
1000                 data->flags |= (data->flags & PF_SHORTINT) ? PF_SIGNEDCHAR : PF_SHORTINT;
1001                 continue;
1002               case 'l':
1003                 data->flags |= (data->flags & PF_LONGINT) ? PF_LONGLONG : PF_LONGINT;
1004                 continue;
1005               case 'L':
1006                 data->flags |= PF_LONGDBL;
1007                 continue;
1008               case 'q':
1009                 data->flags |= PF_LONGLONG;
1010                 continue;
1011               case 'j':
1012                 data->flags |= PF_INTMAX_T;
1013                 SET_SIZE_FLAGS(data, intmax_t);
1014                 continue;
1015               case 'z':
1016                 data->flags |= PF_SIZE_T;
1017                 SET_SIZE_FLAGS(data, size_t);
1018                 continue;
1019               case 't':
1020                 data->flags |= PF_PTRDIFF_T;
1021                 SET_SIZE_FLAGS(data, ptrdiff_t);
1022                 continue;
1023                 
1024               /* Conversion specifiers */
1025 #ifdef FLOATING_POINT
1026               case 'f':  /* float, double */
1027               case 'F':
1028                 STAR_ARGS(data);
1029                 d = GETDOUBLE(data);
1030                 floating(data, d);
1031 conv_break:             
1032                 state = 0;
1033                 break;
1034               case 'g': 
1035               case 'G':
1036                 STAR_ARGS(data);
1037                 DEF_PREC(data);
1038                 d = GETDOUBLE(data);
1039                 i = log_10(d);
1040                 /*
1041                  * for '%g|%G' ANSI: use f if exponent
1042                  * is in the range or [-4,p] exclusively
1043                  * else use %e|%E
1044                  */
1045                 if (-4 < i && i < data->precision)
1046                   floating(data, d);
1047                 else
1048                   exponent(data, d);
1049                 state = 0;
1050                 break;
1051               case 'e':
1052               case 'E':  /* Exponent double */
1053                 STAR_ARGS(data);
1054                 d = GETDOUBLE(data);
1055                 exponent(data, d);
1056                 state = 0;
1057                 break;
1058 #  ifdef HAVE_PRINTF_A_FORMAT
1059               case 'a':
1060               case 'A':
1061                 STAR_ARGS(data);
1062                 d = GETDOUBLE(data);
1063                 dfallback(data, convstart, data->pf, d);
1064                 state = 0;
1065                 break;
1066 #  endif /* HAVE_PRINTF_A_FORMAT */
1067 #endif /* FLOATING_POINT */
1068               case 'U':
1069                 data->flags |= PF_LONGINT;
1070                 /* FALLTHROUGH */
1071               case 'u':
1072                 STAR_ARGS(data);
1073 #ifdef HAVE_LONG_LONG
1074                 if (data->flags & PF_LONGLONG)
1075                   {
1076                     ull = va_arg(args, unsigned long long);
1077                     lnumber(data, ull, 10);
1078                   }
1079                 else
1080 #endif
1081                   {
1082                     ul = GETUNSIGNED(data);
1083                     number(data, ul, 10);
1084                   }
1085                 state = 0;
1086                 break;
1087               case 'D':
1088                 data->flags |= PF_LONGINT;
1089                 /* FALLTHROUGH */
1090               case 'd':  /* decimal */
1091               case 'i':
1092                 STAR_ARGS(data);
1093 #ifdef HAVE_LONG_LONG
1094                 if (data->flags & PF_LONGLONG)
1095                   {
1096                     ull = va_arg(args, long long);
1097                     lnumber(data, ull, 10);
1098                   }
1099                 else
1100 #endif
1101                   {
1102                     ul = GETSIGNED(data);
1103                     number(data, ul, 10);
1104                   }
1105                 state = 0;
1106                 break;
1107               case 'o':  /* octal */
1108                 STAR_ARGS(data);
1109 #ifdef HAVE_LONG_LONG
1110                 if (data->flags & PF_LONGLONG)
1111                   {
1112                     ull = va_arg(args, unsigned long long);
1113                     lnumber(data, ull, 8);
1114                   }
1115                 else
1116 #endif
1117                   {
1118                     ul = GETUNSIGNED(data);
1119                     number(data, ul, 8);
1120                   }
1121                 state = 0;
1122                 break;
1123               case 'x': 
1124               case 'X':  /* hexadecimal */
1125                 STAR_ARGS(data);
1126 #ifdef HAVE_LONG_LONG
1127                 if (data->flags & PF_LONGLONG)
1128                   {
1129                     ull = va_arg(args, unsigned long long);
1130                     lnumber(data, ull, 16);
1131                   }
1132                 else
1133 #endif
1134                   {
1135                     ul = GETUNSIGNED(data);
1136                     number(data, ul, 16);
1137                   }
1138                 state = 0;
1139                 break;
1140               case 'p':
1141                 STAR_ARGS(data);
1142                 ul = (unsigned long)va_arg(args, void *);
1143                 pointer(data, ul);
1144                 state = 0;
1145                 break;
1146               case 'c': /* character */
1147                 ul = va_arg(args, int);
1148                 PUT_CHAR(ul, data);
1149                 state = 0;
1150                 break;
1151               case 's':  /* string */
1152                 STAR_ARGS(data);
1153                 s = va_arg(args, char *);
1154                 strings(data, s);
1155                 state = 0;
1156                 break;
1157               case 'n':
1158 #ifdef HAVE_LONG_LONG
1159                 if (data->flags & PF_LONGLONG)
1160                   *(va_arg(args, long long *)) = data->counter;
1161                 else
1162 #endif
1163                 if (data->flags & PF_LONGINT)
1164                   *(va_arg(args, long *)) = data->counter;
1165                 else if (data->flags & PF_SHORTINT)
1166                   *(va_arg(args, short *)) = data->counter;
1167                 else
1168                   *(va_arg(args, int *)) = data->counter;
1169                 state = 0;
1170                 break;
1171               case '%':  /* nothing just % */
1172                 PUT_CHAR('%', data);
1173                 state = 0;
1174                 break;
1175               default:
1176                 /* is this an error ? maybe bail out */
1177                 state = 0;
1178                 break;
1179         } /* end switch */
1180       } /* end of `%' for loop */
1181     } /* end of format string for loop */
1182
1183   if (data->length >= 0)
1184     *data->holder = '\0'; /* the end ye ! */
1185
1186   return data->counter;
1187 }
1188
1189 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1190 /*
1191  * Printing floating point numbers accurately is an art.  I'm not good
1192  * at it.  Fall back to sprintf for long double formats.
1193  */
1194 static void
1195 ldfallback (data, fs, fe, ld)
1196      struct DATA *data;
1197      const char *fs, *fe;
1198      long double ld;
1199 {
1200   register char *x;
1201   char fmtbuf[FALLBACK_FMTSIZE], *obuf;
1202   int fl;
1203
1204   obuf = xmalloc(LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2);
1205   fl = fe - fs + 1;
1206   strncpy (fmtbuf, fs, fl);
1207   fmtbuf[fl] = '\0';
1208   sprintf (obuf, fmtbuf, ld);
1209   for (x = obuf; *x; x++)
1210     PUT_CHAR (*x, data);    
1211   xfree (obuf);
1212 }
1213 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1214
1215 #ifdef FLOATING_POINT
1216 /* Used for %a, %A if the libc printf supports them. */
1217 static void
1218 dfallback (data, fs, fe, d)
1219      struct DATA *data;
1220      const char *fs, *fe;
1221      double d;
1222 {
1223   register char *x;
1224   char fmtbuf[FALLBACK_FMTSIZE], obuf[FALLBACK_BASE];
1225   int fl;
1226
1227   fl = fe - fs + 1;
1228   strncpy (fmtbuf, fs, fl);
1229   fmtbuf[fl] = '\0';
1230   sprintf (obuf, fmtbuf, d);
1231   for (x = obuf; *x; x++)
1232     PUT_CHAR (*x, data);    
1233 }
1234 #endif /* FLOATING_POINT */
1235
1236 #ifndef HAVE_SNPRINTF
1237
1238 int
1239 #if defined (__STDC__)
1240 vsnprintf(char *string, size_t length, const char *format, va_list args)
1241 #else
1242 vsnprintf(string, length, format, args)
1243      char *string;
1244      size_t length;
1245      const char *format;
1246      va_list args;
1247 #endif
1248 {
1249   struct DATA data;
1250
1251   init_data (&data, string, length, format, PFM_SN);
1252   return (vsnprintf_internal(&data, string, length, format, args));
1253 }
1254
1255 int
1256 #if defined(PREFER_STDARG)
1257 snprintf(char *string, size_t length, const char * format, ...)
1258 #else
1259 snprintf(string, length, format, va_alist)
1260      char *string;
1261      size_t length;
1262      const char *format;
1263      va_dcl
1264 #endif
1265 {
1266   struct DATA data;
1267   int rval;
1268   va_list args;
1269
1270 #if defined(PREFER_STDARG)
1271   va_start(args, format);
1272 #else
1273   va_start(args);
1274 #endif
1275
1276   init_data (&data, string, length, format, PFM_SN);
1277   rval = vsnprintf_internal (&data, string, length, format, args);
1278
1279   va_end(args);
1280
1281   return rval;
1282 }
1283
1284 #endif /* HAVE_SNPRINTF */
1285
1286 #ifndef HAVE_ASPRINTF
1287
1288 int
1289 #if defined (__STDC__)
1290 vasprintf(char **stringp, const char *format, va_list args)
1291 #else
1292 vasprintf(stringp, format, args)
1293      char **stringp;
1294      const char *format;
1295      va_list args;
1296 #endif
1297 {
1298   struct DATA data;
1299   char *string;
1300   int r;
1301
1302   string = (char *)xmalloc(ASBUFSIZE);
1303   init_data (&data, string, ASBUFSIZE, format, PFM_AS);
1304   r = vsnprintf_internal(&data, string, ASBUFSIZE, format, args);
1305   *stringp = data.base;         /* not string in case reallocated */
1306   return r;
1307 }
1308
1309 int
1310 #if defined(PREFER_STDARG)
1311 asprintf(char **stringp, const char * format, ...)
1312 #else
1313 asprintf(stringp, format, va_alist)
1314      char **stringp;
1315      const char *format;
1316      va_dcl
1317 #endif
1318 {
1319   int rval;
1320   va_list args;
1321
1322 #if defined(PREFER_STDARG)
1323   va_start(args, format);
1324 #else
1325   va_start(args);
1326 #endif
1327
1328   rval = vasprintf (stringp, format, args);
1329
1330   va_end(args);
1331
1332   return rval;
1333 }
1334
1335 #endif
1336
1337 #endif
1338
1339 #ifdef DRIVER
1340
1341 static void
1342 memory_error_and_abort ()
1343 {
1344   write (2, "out of virtual memory\n", 22);
1345   abort ();
1346 }
1347
1348 static void *
1349 xmalloc(bytes)
1350      size_t bytes;
1351 {
1352   void *ret;
1353
1354   ret = malloc(bytes);
1355   if (ret == 0)
1356     memory_error_and_abort ();
1357   return ret;
1358 }
1359
1360 static void *
1361 xrealloc (pointer, bytes)
1362      void *pointer;
1363      size_t bytes;
1364 {
1365   void *ret;
1366
1367   ret = pointer ? realloc(pointer, bytes) : malloc(bytes);
1368   if (ret == 0)
1369     memory_error_and_abort ();
1370   return ret;
1371 }
1372
1373 static void
1374 xfree(x)
1375      void *x;
1376 {
1377   if (x)
1378     free (x);
1379 }
1380
1381 #ifdef FLOATING_POINT
1382 #  include <float.h>
1383 #endif
1384
1385 /* set of small tests for snprintf() */
1386 main()
1387 {
1388   char holder[100];
1389   char *h;
1390   int i, si, ai;
1391
1392 /*
1393   printf("Suite of test for snprintf:\n");
1394   printf("a_format\n");
1395   printf("printf() format\n");
1396   printf("snprintf() format\n\n");
1397 */
1398 /* Checking the field widths */
1399
1400   printf("/%%ld %%ld/, 336, 336\n");
1401   snprintf(holder, sizeof holder, "/%ld %ld/\n", 336, 336);
1402   asprintf(&h, "/%ld %ld/\n", 336, 336);
1403   printf("/%ld %ld/\n", 336, 336);
1404   printf("%s", holder);
1405   printf("%s\n", h);
1406
1407   printf("/%%d/, 336\n");
1408   snprintf(holder, sizeof holder, "/%d/\n", 336);
1409   asprintf(&h, "/%d/\n", 336);
1410   printf("/%d/\n", 336);
1411   printf("%s", holder);
1412   printf("%s\n", h);
1413
1414   printf("/%%2d/, 336\n");
1415   snprintf(holder, sizeof holder, "/%2d/\n", 336);
1416   asprintf(&h, "/%2d/\n", 336);
1417   printf("/%2d/\n", 336);
1418   printf("%s", holder);
1419   printf("%s\n", h);
1420
1421   printf("/%%10d/, 336\n");
1422   snprintf(holder, sizeof holder, "/%10d/\n", 336);
1423   asprintf(&h, "/%10d/\n", 336);
1424   printf("/%10d/\n", 336);
1425   printf("%s", holder);
1426   printf("%s\n", h);
1427
1428   printf("/%%-10d/, 336\n");
1429   snprintf(holder, sizeof holder, "/%-10d/\n", 336);
1430   asprintf(&h, "/%-10d/\n", 336);
1431   printf("/%-10d/\n", 336);
1432   printf("%s", holder);
1433   printf("%s\n", h);
1434
1435
1436 /* floating points */
1437
1438   printf("/%%f/, 1234.56\n");
1439   snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
1440   asprintf(&h, "/%f/\n", 1234.56);
1441   printf("/%f/\n", 1234.56);
1442   printf("%s", holder);
1443   printf("%s\n", h);
1444
1445   printf("/%%e/, 1234.56\n");
1446   snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
1447   asprintf(&h, "/%e/\n", 1234.56);
1448   printf("/%e/\n", 1234.56);
1449   printf("%s", holder);
1450   printf("%s\n", h);
1451
1452   printf("/%%4.2f/, 1234.56\n");
1453   snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
1454   asprintf(&h, "/%4.2f/\n", 1234.56);
1455   printf("/%4.2f/\n", 1234.56);
1456   printf("%s", holder);
1457   printf("%s\n", h);
1458
1459   printf("/%%3.1f/, 1234.56\n");
1460   snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
1461   asprintf(&h, "/%3.1f/\n", 1234.56);
1462   printf("/%3.1f/\n", 1234.56);
1463   printf("%s", holder);
1464   printf("%s\n", h);
1465
1466   printf("/%%10.3f/, 1234.56\n");
1467   snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
1468   asprintf(&h, "/%10.3f/\n", 1234.56);
1469   printf("/%10.3f/\n", 1234.56);
1470   printf("%s", holder);
1471   printf("%s\n", h);
1472
1473   printf("/%%10.3e/, 1234.56\n");
1474   snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
1475   asprintf(&h, "/%10.3e/\n", 1234.56);
1476   printf("/%10.3e/\n", 1234.56);
1477   printf("%s", holder);
1478   printf("%s\n", h);
1479
1480   printf("/%%+4.2f/, 1234.56\n");
1481   snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
1482   asprintf(&h, "/%+4.2f/\n", 1234.56);
1483   printf("/%+4.2f/\n", 1234.56);
1484   printf("%s", holder);
1485   printf("%s\n", h);
1486
1487   printf("/%%010.2f/, 1234.56\n");
1488   snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
1489   asprintf(&h, "/%010.2f/\n", 1234.56);
1490   printf("/%010.2f/\n", 1234.56);
1491   printf("%s", holder);
1492   printf("%s\n", h);
1493
1494 #define BLURB "Outstanding acting !"
1495 /* strings precisions */
1496
1497   printf("/%%2s/, \"%s\"\n", BLURB);
1498   snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
1499   asprintf(&h, "/%2s/\n", BLURB);
1500   printf("/%2s/\n", BLURB);
1501   printf("%s", holder);
1502   printf("%s\n", h);
1503
1504   printf("/%%22s/ %s\n", BLURB);
1505   snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
1506   asprintf(&h, "/%22s/\n", BLURB);
1507   printf("/%22s/\n", BLURB);
1508   printf("%s", holder);
1509   printf("%s\n", h);
1510
1511   printf("/%%22.5s/ %s\n", BLURB);
1512   snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
1513   asprintf(&h, "/%22.5s/\n", BLURB);
1514   printf("/%22.5s/\n", BLURB);
1515   printf("%s", holder);
1516   printf("%s\n", h);
1517
1518   printf("/%%-22.5s/ %s\n", BLURB);
1519   snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
1520   asprintf(&h, "/%-22.5s/\n", BLURB);
1521   printf("/%-22.5s/\n", BLURB);
1522   printf("%s", holder);
1523   printf("%s\n", h);
1524
1525 /* see some flags */
1526
1527   printf("%%x %%X %%#x, 31, 31, 31\n");
1528   snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
1529   asprintf(&h, "%x %X %#x\n", 31, 31, 31);
1530   printf("%x %X %#x\n", 31, 31, 31);
1531   printf("%s", holder);
1532   printf("%s\n", h);
1533
1534   printf("**%%d**%% d**%% d**, 42, 42, -42\n");
1535   snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
1536   asprintf(&h, "**%d**% d**% d**\n", 42, 42, -42);
1537   printf("**%d**% d**% d**\n", 42, 42, -42);
1538   printf("%s", holder);
1539   printf("%s\n", h);
1540
1541 /* other flags */
1542
1543   printf("/%%g/, 31.4\n");
1544   snprintf(holder, sizeof holder, "/%g/\n", 31.4);
1545   asprintf(&h, "/%g/\n", 31.4);
1546   printf("/%g/\n", 31.4);
1547   printf("%s", holder);
1548   printf("%s\n", h);
1549
1550   printf("/%%.6g/, 31.4\n");
1551   snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
1552   asprintf(&h, "/%.6g/\n", 31.4);
1553   printf("/%.6g/\n", 31.4);
1554   printf("%s", holder);
1555   printf("%s\n", h);
1556
1557   printf("/%%.1G/, 31.4\n");
1558   snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
1559   asprintf(&h, "/%.1G/\n", 31.4);
1560   printf("/%.1G/\n", 31.4);
1561   printf("%s", holder);
1562   printf("%s\n", h);
1563
1564   printf("/%%.1G/, 3100000000.4\n");
1565   snprintf(holder, sizeof holder, "/%.1G/\n", 3100000000.4);  
1566   asprintf(&h, "/%.1G/\n", 3100000000.4);  
1567   printf("/%.1G/\n", 3100000000.4); 
1568   printf("%s", holder);
1569   printf("%s\n", h);
1570
1571   printf("abc%%n\n");
1572   printf("abc%n", &i); printf("%d\n", i);
1573   snprintf(holder, sizeof holder, "abc%n", &i);
1574   printf("%s", holder); printf("%d\n\n", i);
1575   asprintf(&h, "abc%n", &i);
1576   printf("%s", h); printf("%d\n\n", i);
1577   
1578   printf("%%*.*s --> 10.10\n");
1579   snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
1580   asprintf(&h, "%*.*s\n", 10, 10, BLURB);
1581   printf("%*.*s\n", 10, 10, BLURB);
1582   printf("%s", holder);
1583   printf("%s\n", h);
1584
1585   printf("%%%%%%%%\n");
1586   snprintf(holder, sizeof holder, "%%%%\n");
1587   asprintf(&h, "%%%%\n");
1588   printf("%%%%\n");
1589   printf("%s", holder);
1590   printf("%s\n", h);
1591
1592 #define BIG "Hello this is a too big string for the buffer"
1593 /*  printf("A buffer to small of 10, trying to put this:\n");*/
1594   printf("<%%>, %s\n", BIG); 
1595   i = snprintf(holder, 10, "%s\n", BIG);
1596   i = asprintf(&h, "%s", BIG);
1597   printf("<%s>\n", BIG);
1598   printf("<%s>\n", holder);
1599   printf("<%s>\n\n", h);
1600
1601   printf ("<%%p> vsnprintf\n");
1602   i = snprintf(holder, 100, "%p", vsnprintf);
1603   i = asprintf(&h, "%p", vsnprintf);
1604   printf("<%p>\n", vsnprintf);
1605   printf("<%s>\n", holder);  
1606   printf("<%s>\n\n", h);
1607
1608   printf ("<%%lu> LONG_MAX+1\n");
1609   i = snprintf(holder, 100, "%lu", (unsigned long)(LONG_MAX)+1);
1610   i = asprintf(&h, "%lu", (unsigned long)(LONG_MAX)+1);
1611   printf("<%lu>\n", (unsigned long)(LONG_MAX)+1);
1612   printf("<%s>\n", holder);
1613   printf("<%s>\n\n", h);
1614
1615 #ifdef HAVE_LONG_LONG
1616   printf ("<%%llu> LLONG_MAX+1\n");
1617   i = snprintf(holder, 100, "%llu", (unsigned long long)(LLONG_MAX)+1);
1618   i = asprintf(&h, "%llu", (unsigned long long)(LLONG_MAX)+1);
1619   printf("<%llu>\n", (unsigned long long)(LLONG_MAX)+1);
1620   printf("<%s>\n", holder);
1621   printf("<%s>\n\n", h);
1622 #endif
1623
1624 #ifdef HAVE_LONG_DOUBLE
1625   printf ("<%%6.2LE> 42.42\n");
1626   i = snprintf(holder, 100, "%6.2LE", (long double)42.42);
1627   i = asprintf(&h, "%6.2LE", (long double)42.42);
1628   printf ("<%6.2LE>\n", (long double)42.42);
1629   printf ("<%s>\n", holder);
1630   printf ("<%s>\n\n", h);
1631 #endif
1632
1633 #ifdef HAVE_PRINTF_A_FORMAT
1634   printf ("<%%6.2A> 42.42\n");
1635   i = snprintf(holder, 100, "%6.2A", 42.42);
1636   i = asprintf(&h, "%6.2A", 42.42);
1637   printf ("<%6.2A>\n", 42.42);
1638   printf ("<%s>\n", holder);
1639   printf ("<%s>\n\n", h);
1640
1641   printf ("<%%6.2LA> 42.42\n");
1642   i = snprintf(holder, 100, "%6.2LA", (long double)42.42);
1643   i = asprintf(&h, "%6.2LA", (long double)42.42);
1644   printf ("<%6.2LA>\n", (long double)42.42);
1645   printf ("<%s>\n", holder);
1646   printf ("<%s>\n\n", h);
1647 #endif
1648
1649   printf ("<%%.10240f> DBL_MAX\n");
1650   si = snprintf(holder, 100, "%.10240f", DBL_MAX);
1651   ai = asprintf(&h, "%.10240f", DBL_MAX);
1652   printf ("<%.10240f>\n", DBL_MAX);
1653   printf ("<%d> <%s>\n", si, holder);
1654   printf ("<%d> <%s>\n\n", ai, h);
1655
1656   printf ("<%%.10240Lf> LDBL_MAX\n");
1657   si = snprintf(holder, 100, "%.10240Lf", (long double)LDBL_MAX);
1658   ai = asprintf(&h, "%.10240Lf", (long double)LDBL_MAX);
1659   printf ("<%.10240Lf>\n", (long double)LDBL_MAX);
1660   printf ("<%d> <%s>\n", si, holder);
1661   printf ("<%d> <%s>\n\n", ai, h);
1662
1663   exit (0);
1664 }
1665 #endif