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