1 /* snprintf - formatted output to strings, with bounds checking and allocation */
4 build a test version with
5 gcc -g -DDRIVER -I../.. -I../../include -o test-snprintf snprintf.c fmtu*long.o
9 Unix snprintf implementation.
10 derived from inetutils/libinetutils/snprintf.c Version 1.1
12 Copyright (C) 2001,2006,2010,2012 Free Software Foundation, Inc.
14 This file is part of GNU Bash, the Bourne Again SHell.
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.
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.
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/>.
29 Original (pre-bash) Revision History:
32 * added changes from Miles Bader
33 * corrected a bug with %f
34 * added support for %#g
35 * added more comments :-)
37 * supporting must ANSI syntaxic_sugars
41 THANKS(for the patches and ideas):
50 * Currently doesn't handle (and bash/readline doesn't use):
51 * * *M$ width, precision specifications
52 * * %N$ numbered argument conversions
53 * * support for `F' is imperfect with ldfallback(), since underlying
54 * printf may not handle it -- should ideally have another autoconf test
57 #define FLOATING_POINT
63 /* GCC 4.2 on Snow Leopard doesn't like the snprintf prototype */
64 #if defined(DEBUG) && !defined (MACOSX)
68 # define HAVE_SNPRINTF 0
69 # define HAVE_ASPRINTF 0
72 #if defined(DRIVER) && !defined(HAVE_CONFIG_H)
73 #define HAVE_LONG_LONG
74 #define HAVE_LONG_DOUBLE
76 #define HAVE_PRINTF_A_FORMAT
78 #define HAVE_ISINF_IN_LIBC
79 #define HAVE_ISNAN_IN_LIBC
81 #define HAVE_STRINGIZE
88 #if !HAVE_SNPRINTF || !HAVE_ASPRINTF
90 #include <bashtypes.h>
92 #if defined(PREFER_STDARG)
101 #include <bashansi.h>
105 #include <chartypes.h>
111 #ifdef FLOATING_POINT
112 # include <float.h> /* for manifest constants */
113 # include <stdio.h> /* for sprintf */
123 #include <shmbutil.h>
128 # define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
129 # define FL_ADDBASE 0x02 /* add base# prefix to converted value */
130 # define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
131 # define FL_UNSIGNED 0x08 /* don't add any sign */
132 extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
133 extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
137 # define FREE(x) if (x) free (x)
140 /* Bound on length of the string representing an integer value of type T.
141 Subtract one for the sign bit if T is signed;
142 302 / 1000 is log10 (2) rounded up;
143 add one for integer division truncation;
144 add one more for a minus sign if t is signed. */
145 #define INT_STRLEN_BOUND(t) \
146 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
147 + 1 + TYPE_SIGNED (t))
149 /* conversion flags */
150 #define PF_ALTFORM 0x00001 /* # */
151 #define PF_HEXPREFIX 0x00002 /* 0[Xx] */
152 #define PF_LADJUST 0x00004 /* - */
153 #define PF_ZEROPAD 0x00008 /* 0 */
154 #define PF_PLUS 0x00010 /* + */
155 #define PF_SPACE 0x00020 /* ' ' */
156 #define PF_THOUSANDS 0x00040 /* ' */
158 #define PF_DOT 0x00080 /* `.precision' */
159 #define PF_STAR_P 0x00100 /* `*' after precision */
160 #define PF_STAR_W 0x00200 /* `*' before or without precision */
162 /* length modifiers */
163 #define PF_SIGNEDCHAR 0x00400 /* hh */
164 #define PF_SHORTINT 0x00800 /* h */
165 #define PF_LONGINT 0x01000 /* l */
166 #define PF_LONGLONG 0x02000 /* ll */
167 #define PF_LONGDBL 0x04000 /* L */
168 #define PF_INTMAX_T 0x08000 /* j */
169 #define PF_SIZE_T 0x10000 /* z */
170 #define PF_PTRDIFF_T 0x20000 /* t */
172 #define PF_ALLOCBUF 0x40000 /* for asprintf, vasprintf */
174 #define PFM_SN 0x01 /* snprintf, vsnprintf */
175 #define PFM_AS 0x02 /* asprintf, vasprintf */
177 #define ASBUFSIZE 128
179 #define x_digs "0123456789abcdef"
180 #define X_digs "0123456789ABCDEF"
182 static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
186 static char *grouping;
189 * For the FLOATING POINT FORMAT :
190 * the challenge was finding a way to
191 * manipulate the Real numbers without having
192 * to resort to mathematical function(it
193 * would require to link with -lm) and not
194 * going down to the bit pattern(not portable)
196 * so a number, a real is:
198 real = integral + fraction
200 integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
201 fraction = b(1)*10^-1 + b(2)*10^-2 + ...
207 from then it was simple math
211 * size of the buffer for the integral part
212 * and the fraction part
214 #define MAX_INT 99 + 1 /* 1 for the null */
215 #define MAX_FRACT 307 + 1
218 * These functions use static buffers to store the results,
219 * and so are not reentrant
221 #define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0);
222 #define dtoa(n, p, f) numtoa(n, 10, p, f)
224 #define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
226 #define GETARG(type) (va_arg(args, type))
228 /* Macros that do proper sign extension and handle length modifiers. Used
229 for the integer conversion specifiers. */
230 #define GETSIGNED(p) \
231 (((p)->flags & PF_LONGINT) \
233 : (((p)->flags & PF_SHORTINT) ? (long)(short)GETARG (int) \
234 : (long)GETARG (int)))
236 #define GETUNSIGNED(p) \
237 (((p)->flags & PF_LONGINT) \
238 ? GETARG (unsigned long) \
239 : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)GETARG (int) \
240 : (unsigned long)GETARG (unsigned int)))
243 #ifdef HAVE_LONG_DOUBLE
244 #define GETLDOUBLE(p) GETARG (long double)
246 #define GETDOUBLE(p) GETARG (double)
248 #define SET_SIZE_FLAGS(p, type) \
249 if (sizeof (type) > sizeof (int)) \
250 (p)->flags |= PF_LONGINT; \
251 if (sizeof (type) > sizeof (long)) \
252 (p)->flags |= PF_LONGLONG;
254 /* this struct holds everything we need */
258 char *base; /* needed for [v]asprintf */
266 int width, precision;
270 /* the floating point stuff */
271 #ifdef FLOATING_POINT
272 static double pow_10 __P((int));
273 static int log_10 __P((double));
274 static double integral __P((double, double *));
275 static char *numtoa __P((double, int, int, char **));
278 static void init_data __P((struct DATA *, char *, size_t, const char *, int));
279 static void init_conv_flag __P((struct DATA *));
282 #ifdef FLOATING_POINT
283 static void floating __P((struct DATA *, double));
284 static void exponent __P((struct DATA *, double));
286 static void number __P((struct DATA *, unsigned long, int));
287 #ifdef HAVE_LONG_LONG
288 static void lnumber __P((struct DATA *, unsigned long long, int));
290 static void pointer __P((struct DATA *, unsigned long));
291 static void strings __P((struct DATA *, char *));
293 #ifdef FLOATING_POINT
294 # define FALLBACK_FMTSIZE 32
295 # define FALLBACK_BASE 4096
296 # define LFALLBACK_BASE 5120
297 # ifdef HAVE_LONG_DOUBLE
298 static void ldfallback __P((struct DATA *, const char *, const char *, long double));
300 static void dfallback __P((struct DATA *, const char *, const char *, double));
303 static char *groupnum __P((char *));
305 #if defined (HAVE_LONG_DOUBLE)
306 # define LONGDOUBLE long double
308 # define LONGDOUBLE double
312 static inline int isnan_f (float x) { return x != x; }
313 static inline int isnan_d (double x) { return x != x; }
314 static inline int isnan_ld (LONGDOUBLE x) { return x != x; }
316 (sizeof (x) == sizeof (LONGDOUBLE) ? isnan_ld (x) \
317 : sizeof (x) == sizeof (double) ? isnan_d (x) \
322 static inline int isinf_f (float x) { return !isnan (x) && isnan (x - x); }
323 static inline int isinf_d (double x) { return !isnan (x) && isnan (x - x); }
324 static inline int isinf_ld (LONGDOUBLE x) { return !isnan (x) && isnan (x - x); }
326 (sizeof (x) == sizeof (LONGDOUBLE) ? isinf_ld (x) \
327 : sizeof (x) == sizeof (double) ? isinf_d (x) \
332 static void memory_error_and_abort ();
333 static void *xmalloc __P((size_t));
334 static void *xrealloc __P((void *, size_t));
335 static void xfree __P((void *));
337 # include <xmalloc.h>
340 /* those are defines specific to snprintf to hopefully
341 * make the code clearer :-)
349 /* round off to the precision */
350 #define ROUND(d, p) \
352 d - pow_10(-(p)->precision) * 0.5 : \
353 d + pow_10(-(p)->precision) * 0.5
355 /* set default precision */
356 #define DEF_PREC(p) \
357 if ((p)->precision == NOT_FOUND) \
360 /* put a char. increment the number of chars written even if we've exceeded
361 the vsnprintf/snprintf buffer size (for the return value) */
362 #define PUT_CHAR(c, p) \
365 if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \
367 (p)->length += ASBUFSIZE; \
368 (p)->base = (char *)xrealloc((p)->base, (p)->length); \
369 (p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \
371 if ((p)->counter < (p)->length) \
372 *(p)->holder++ = (c); \
377 /* Output a string. P->WIDTH has already been adjusted for padding. */
378 #define PUT_STRING(string, len, p) \
382 while ((len)-- > 0) \
384 PUT_CHAR (*(string), (p)); \
391 #define PUT_PLUS(d, p, zero) \
392 if (((p)->flags & PF_PLUS) && (d) > zero) \
395 #define PUT_SPACE(d, p, zero) \
396 if (((p)->flags & PF_SPACE) && (d) > zero) \
400 #define PAD_RIGHT(p) \
401 if ((p)->width > 0 && (p)->justify != LEFT) \
402 for (; (p)->width > 0; (p)->width--) \
403 PUT_CHAR((p)->pad, p)
406 #define PAD_LEFT(p) \
407 if ((p)->width > 0 && (p)->justify == LEFT) \
408 for (; (p)->width > 0; (p)->width--) \
409 PUT_CHAR((p)->pad, p)
411 /* pad with zeros from decimal precision */
412 #define PAD_ZERO(p) \
413 if ((p)->precision > 0) \
414 for (; (p)->precision > 0; (p)->precision--) \
417 /* if width and prec. in the args */
418 #define STAR_ARGS(p) \
420 if ((p)->flags & PF_STAR_W) \
422 (p)->width = GETARG (int); \
423 if ((p)->width < 0) \
425 (p)->flags |= PF_LADJUST; \
426 (p)->justify = LEFT; \
427 (p)->width = -(p)->width; \
430 if ((p)->flags & PF_STAR_P) \
432 (p)->precision = GETARG (int); \
433 if ((p)->precision < 0) \
435 (p)->flags &= ~PF_STAR_P; \
436 (p)->precision = NOT_FOUND; \
441 #if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV)
442 # define GETLOCALEDATA(d, t, g) \
447 (d) = '.'; (t) = -1; (g) = 0; /* defaults */ \
451 if (lv->decimal_point && lv->decimal_point[0]) \
452 (d) = lv->decimal_point[0]; \
453 if (lv->thousands_sep && lv->thousands_sep[0]) \
454 (t) = lv->thousands_sep[0]; \
455 (g) = lv->grouping ? lv->grouping : ""; \
456 if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \
462 # define GETLOCALEDATA(d, t, g) \
463 ( (d) = '.', (t) = ',', g = "\003" )
466 #ifdef FLOATING_POINT
468 * Find the nth power of 10
476 /* handle common cases with fast switch statement. */
479 case -3: return .001;
485 case 3: return 1000.;
491 for (n += 4; n < 0; n++)
497 for (n -= 4; n > 0; n--)
505 * Find the integral part of the log in base 10
506 * Note: this not a real log10()
507 I just need and approximation(integerpart) of x in:
512 * NOTE: do not call this with r == 0 -- an infinite loop results.
545 * This function return the fraction part of a double
546 * and set in ip the integral part.
547 * In many ways it resemble the modf() found on most Un*x
556 double real_integral = 0.;
558 /* take care of the obvious */
559 /* equal to zero ? */
566 /* negative number ? */
577 /* the real work :-) */
578 for (j = log_10(real); j >= 0; j--)
581 s = (real - real_integral)/p;
585 real_integral += i*p;
588 return (real - real_integral);
591 #define PRECISION 1.e-6
593 * return an ascii representation of the integral part of the number
594 * and set fract to be an ascii representation of the fraction part
595 * the container for the fraction and the integral part or statically
596 * declare with fix size
599 numtoa(number, base, precision, fract)
605 double ip, fp; /* integer and fraction part */
608 static char integral_part[MAX_INT];
609 static char fraction_part[MAX_FRACT];
612 /* taking care of the obvious case: 0.0 */
615 integral_part[0] = '0';
616 integral_part[1] = '\0';
617 /* The fractional part has to take the precision into account */
618 for (ch = 0; ch < precision-1; ch++)
619 fraction_part[ch] = '0';
620 fraction_part[ch] = '0';
621 fraction_part[ch+1] = '\0';
623 *fract = fraction_part;
624 return integral_part;
628 sign = (number == -0.) ? '-' : ((number < 0.) ? '-' : '+');
629 digits = MAX_INT - 1;
631 /* for negative numbers */
635 digits--; /* sign consume one digit */
638 fraction = integral(number, &ip);
641 /* do the integral part */
644 integral_part[0] = '0';
649 for ( i = 0; i < digits && number != 0.; ++i)
652 fp = integral(number, &ip);
653 ch = (int)((fp + PRECISION)*base); /* force to round */
654 integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
655 if (! ISXDIGIT((unsigned char)integral_part[i]))
656 break; /* bail out overflow !! */
661 /* Oh No !! out of bound, ho well fill it up ! */
663 for (i = 0; i < digits; ++i)
664 integral_part[i] = '9';
668 integral_part[i++] = '-';
670 integral_part[i] = '\0';
672 /* reverse every thing */
673 for ( i--, j = 0; j < i; j++, i--)
674 SWAP_INT(integral_part[i], integral_part[j]);
676 /* the fractional part */
677 for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--)
679 fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
680 if (! DIGIT(fraction_part[i])) /* underflow ? */
682 fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
684 fraction_part[i] = '\0';
686 if (fract != (char **)0)
687 *fract = fraction_part;
689 return integral_part;
693 /* for %d and friends, it puts in holder
694 * the representation with the right padding
706 /* An explicit precision turns off the zero-padding flag and sets the
707 pad character back to space. */
708 if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
710 p->flags &= ~PF_ZEROPAD;
714 sd = d; /* signed for ' ' padding in base 10 */
716 flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
718 flags |= FL_HEXUPPER;
720 tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags);
722 if ((p->flags & PF_THOUSANDS))
724 GETLOCALEDATA(decpoint, thoussep, grouping);
725 if (grouping && (t = groupnum (tmp)))
729 /* need to add one for any `+', but we only add one in base 10 */
730 p->width -= strlen(tmp) + (base == 10 && d > 0 && (p->flags & PF_PLUS));
733 if ((p->flags & PF_DOT) && p->precision > 0)
735 p->precision -= strlen(tmp);
746 if (p->flags & PF_ALTFORM)
750 if (p->flags & PF_ALTFORM)
768 #ifdef HAVE_LONG_LONG
770 * identical to number() but works for `long long'
775 unsigned long long d;
782 /* An explicit precision turns off the zero-padding flag and sets the
783 pad character back to space. */
784 if ((p->flags & PF_ZEROPAD) && p->precision >= 0 && (p->flags & PF_DOT))
786 p->flags &= ~PF_ZEROPAD;
790 sd = d; /* signed for ' ' padding in base 10 */
791 flags = (*p->pf == 'x' || *p->pf == 'X' || *p->pf == 'o' || *p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
793 flags |= FL_HEXUPPER;
795 tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags);
797 if ((p->flags & PF_THOUSANDS))
799 GETLOCALEDATA(decpoint, thoussep, grouping);
800 if (grouping && (t = groupnum (tmp)))
804 /* need to add one for any `+', but we only add one in base 10 */
805 p->width -= strlen(tmp) + (base == 10 && d > 0 && (p->flags & PF_PLUS));
808 if ((p->flags & PF_DOT) && p->precision > 0)
810 p->precision -= strlen(tmp);
821 if (p->flags & PF_ALTFORM)
825 if (p->flags & PF_ALTFORM)
851 tmp = fmtulong(d, 16, intbuf, sizeof(intbuf), 0);
852 p->width -= strlen(tmp);
855 /* prefix '0x' for pointers */
877 if (p->precision != NOT_FOUND) /* the smallest number */
878 len = (len < p->precision ? len : p->precision);
881 PUT_STRING (tmp, len, p);
885 /* %ls wide-character strings */
896 memset (&mbs, '\0', sizeof (mbstate_t));
897 ws = (const wchar_t *)tmp;
900 if (p->precision != NOT_FOUND)
902 os = (char *)xmalloc (p->precision + 1);
903 len = wcsrtombs (os, &ws, p->precision, &mbs);
907 len = wcsrtombs (NULL, &ws, 0, &mbs);
908 if (len != (size_t)-1)
910 memset (&mbs, '\0', sizeof (mbstate_t));
911 os = (char *)xmalloc (len + 1);
912 (void)wcsrtombs (os, &ws, len + 1, &mbs);
915 if (len == (size_t)-1)
917 /* invalid multibyte sequence; bail now. */
923 PUT_STRING (os, len, p);
936 lbuf = (char *)malloc (MB_CUR_MAX+1);
939 memset (&mbs, '\0', sizeof (mbstate_t));
940 len = wcrtomb (lbuf, wc, &mbs);
941 if (len == (size_t)-1)
942 /* conversion failed; bail now. */
946 PUT_STRING (l, len, p);
949 #endif /* HANDLE_MULTIBYTE */
951 #ifdef FLOATING_POINT
953 /* Check for [+-]infinity and NaN. If MODE == 1, we check for Infinity, else
954 (mode == 2) we check for NaN. This does the necessary printing. Returns
955 1 if Inf or Nan, 0 if not. */
957 chkinfnan(p, d, mode)
960 int mode; /* == 1 for inf, == 2 for nan */
966 i = (mode == 1) ? isinf(d) : isnan(d);
969 big = (mode == 1) ? "INF" : "NAN";
970 small = (mode == 1) ? "inf" : "nan";
972 tmp = (*p->pf == 'F' || *p->pf == 'G' || *p->pf == 'E') ? big : small;
986 /* %f %F %g %G floating point representation */
992 char *tmp, *tmp2, *t;
995 if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)))
996 return; /* already printed nan or inf */
998 GETLOCALEDATA(decpoint, thoussep, grouping);
1001 tmp = dtoa(d, p->precision, &tmp2);
1003 if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp)))
1006 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
1008 /* smash the trailing zeros unless altform */
1009 for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
1011 if (tmp2[0] == '\0')
1015 /* calculate the padding. 1 for the dot */
1016 p->width = p->width -
1017 /* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
1019 ((d > 0. && p->justify == RIGHT) ? 1:0) -
1021 ((d > 0. && (p->flags & PF_PLUS)) ? 1:0) -
1023 ((p->flags & PF_SPACE) ? 1:0) -
1024 strlen(tmp) - p->precision -
1025 ((p->precision != 0 || (p->flags & PF_ALTFORM)) ? 1 : 0); /* radix char */
1035 PUT_CHAR(*tmp++, p);
1039 PUT_SPACE(d, p, 0.);
1043 PUT_CHAR(*tmp, p); /* the integral */
1048 if (p->precision != 0 || (p->flags & PF_ALTFORM))
1049 PUT_CHAR(decpoint, p); /* put the '.' */
1051 for (; *tmp2; tmp2++)
1052 PUT_CHAR(*tmp2, p); /* the fraction */
1057 /* %e %E %g %G exponent representation */
1066 if (d != 0 && (chkinfnan(p, d, 1) || chkinfnan(p, d, 2)))
1067 return; /* already printed nan or inf */
1069 GETLOCALEDATA(decpoint, thoussep, grouping);
1076 d = d / pow_10(j); /* get the Mantissa */
1079 tmp = dtoa(d, p->precision, &tmp2);
1081 /* 1 for unit, 1 for the '.', 1 for 'e|E',
1082 * 1 for '+|-', 2 for 'exp' (but no `.' if precision == 0 */
1083 /* calculate how much padding need */
1084 p->width = p->width -
1085 /* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
1087 ((d > 0. && p->justify == RIGHT) ? 1:0) -
1089 ((d > 0. && (p->flags & PF_PLUS)) ? 1:0) -
1091 (p->precision != 0 || (p->flags & PF_ALTFORM)) -
1092 ((p->flags & PF_SPACE) ? 1:0) - p->precision - 5;
1102 PUT_CHAR(*tmp++, p);
1106 PUT_SPACE(d, p, 0.);
1114 if (p->precision != 0 || (p->flags & PF_ALTFORM))
1115 PUT_CHAR(decpoint, p); /* the '.' */
1117 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
1118 /* smash the trailing zeros unless altform */
1119 for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
1122 for (; *tmp2; tmp2++)
1123 PUT_CHAR(*tmp2, p); /* the fraction */
1125 /* the exponent put the 'e|E' */
1126 if (*p->pf == 'g' || *p->pf == 'e')
1131 /* the sign of the exp */
1141 /* pad out to at least two spaces. pad with `0' if the exponent is a
1157 /* Return a new string with the digits in S grouped according to the locale's
1158 grouping info and thousands separator. If no grouping should be performed,
1159 this returns NULL; the caller needs to check for it. */
1164 char *se, *ret, *re, *g;
1167 if (grouping == 0 || *grouping <= 0 || *grouping == CHAR_MAX)
1168 return ((char *)NULL);
1170 /* find min grouping to size returned string */
1171 for (len = *grouping, g = grouping; *g; g++)
1172 if (*g > 0 && *g < len)
1176 len = slen / len + 1;
1177 ret = (char *)xmalloc (slen + len + 1);
1178 re = ret + slen + len;
1189 /* handle `-' inserted by numtoa() and the fmtu* family here. */
1190 if (se > s && se[-1] == '-')
1193 /* begin new group. */
1194 if (--len == 0 && se > s)
1197 len = *++g; /* was g++, but that uses first char twice (glibc bug, too) */
1199 len = *--g; /* use previous grouping */
1200 else if (*g == CHAR_MAX)
1212 memmove (ret, re, strlen (re) + 1);
1220 /* initialize the conversion specifiers */
1225 p->flags &= PF_ALLOCBUF; /* preserve PF_ALLOCBUF flag */
1226 p->precision = p->width = NOT_FOUND;
1227 p->justify = NOT_FOUND;
1232 init_data (p, string, length, format, mode)
1239 p->length = length - 1; /* leave room for '\0' */
1240 p->holder = p->base = string;
1243 p->flags = (mode == PFM_AS) ? PF_ALLOCBUF : 0;
1247 #if defined (__STDC__)
1248 vsnprintf_internal(struct DATA *data, char *string, size_t length, const char *format, va_list args)
1250 vsnprintf_internal(data, string, length, format, args)
1258 double d; /* temporary holder */
1259 #ifdef HAVE_LONG_DOUBLE
1260 long double ld; /* for later */
1263 #ifdef HAVE_LONG_LONG
1264 unsigned long long ull;
1268 #if HANDLE_MULTIBYTE
1272 const char *convstart;
1275 /* Sanity check, the string length must be >= 0. C99 actually says that
1276 LENGTH can be zero here, in the case of snprintf/vsnprintf (it's never
1277 0 in the case of asprintf/vasprintf), and the return value is the number
1278 of characters that would have been written. */
1285 /* Reset these for each call because the locale might have changed. */
1286 decpoint = thoussep = 0;
1290 for (; c = *(data->pf); data->pf++)
1298 convstart = data->pf;
1299 init_conv_flag (data); /* initialise format flags */
1302 for (state = 1; state && *data->pf; )
1305 /* fmtend = data->pf */
1306 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1307 if (data->flags & PF_LONGDBL)
1314 # ifdef HAVE_PRINTF_A_FORMAT
1318 ld = GETLDOUBLE (data);
1319 ldfallback (data, convstart, data->pf, ld);
1323 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1327 /* Parse format flags */
1328 case '\0': /* a NULL here ? ? bail out */
1329 *data->holder = '\0';
1330 return data->counter;
1333 data->flags |= PF_ALTFORM;
1336 if (data->flags & PF_DOT)
1337 data->flags |= PF_STAR_P;
1339 data->flags |= PF_STAR_W;
1342 if ((data->flags & PF_DOT) == 0)
1344 data->flags |= PF_LADJUST;
1345 data->justify = LEFT;
1351 if ((data->flags & PF_PLUS) == 0)
1352 data->flags |= PF_SPACE;
1355 if ((data->flags & PF_DOT) == 0)
1357 data->flags |= PF_PLUS;
1358 if ((data->flags & PF_LADJUST) == 0)
1359 data->justify = RIGHT;
1363 data->flags |= PF_THOUSANDS;
1367 /* If we're not specifying precision (in which case we've seen
1368 a `.') and we're not performing left-adjustment (in which
1369 case the `0' is ignored), a `0' is taken as the zero-padding
1371 if ((data->flags & (PF_DOT|PF_LADJUST)) == 0)
1373 data->flags |= PF_ZEROPAD;
1377 case '1': case '2': case '3':
1378 case '4': case '5': case '6':
1379 case '7': case '8': case '9':
1383 n = n * 10 + TODIGIT(c);
1387 data->pf--; /* went too far */
1390 if (data->flags & PF_DOT)
1391 data->precision = negprec ? NOT_FOUND : n;
1396 /* optional precision */
1398 data->flags |= PF_DOT;
1399 data->precision = 0;
1402 /* length modifiers */
1404 data->flags |= (data->flags & PF_SHORTINT) ? PF_SIGNEDCHAR : PF_SHORTINT;
1407 data->flags |= (data->flags & PF_LONGINT) ? PF_LONGLONG : PF_LONGINT;
1410 data->flags |= PF_LONGDBL;
1413 data->flags |= PF_LONGLONG;
1416 data->flags |= PF_INTMAX_T;
1417 SET_SIZE_FLAGS(data, intmax_t);
1420 data->flags |= PF_SIZE_T;
1421 SET_SIZE_FLAGS(data, size_t);
1424 data->flags |= PF_PTRDIFF_T;
1425 SET_SIZE_FLAGS(data, ptrdiff_t);
1428 /* Conversion specifiers */
1429 #ifdef FLOATING_POINT
1430 case 'f': /* float, double */
1433 d = GETDOUBLE(data);
1442 d = GETDOUBLE(data);
1443 i = (d != 0.) ? log_10(d) : -1;
1445 * for '%g|%G' ANSI: use f if exponent
1446 * is in the range or [-4,p] exclusively
1449 if (-4 < i && i < data->precision)
1451 /* reset precision */
1452 data->precision -= i + 1;
1457 /* reduce precision by 1 because of leading digit before
1458 decimal point in e format, unless specified as 0. */
1459 if (data->precision > 0)
1466 case 'E': /* Exponent double */
1468 d = GETDOUBLE(data);
1472 # ifdef HAVE_PRINTF_A_FORMAT
1476 d = GETDOUBLE(data);
1477 dfallback(data, convstart, data->pf, d);
1480 # endif /* HAVE_PRINTF_A_FORMAT */
1481 #endif /* FLOATING_POINT */
1483 data->flags |= PF_LONGINT;
1487 #ifdef HAVE_LONG_LONG
1488 if (data->flags & PF_LONGLONG)
1490 ull = GETARG (unsigned long long);
1491 lnumber(data, ull, 10);
1496 ul = GETUNSIGNED(data);
1497 number(data, ul, 10);
1502 data->flags |= PF_LONGINT;
1504 case 'd': /* decimal */
1507 #ifdef HAVE_LONG_LONG
1508 if (data->flags & PF_LONGLONG)
1510 ull = GETARG (long long);
1511 lnumber(data, ull, 10);
1516 ul = GETSIGNED(data);
1517 number(data, ul, 10);
1521 case 'o': /* octal */
1523 #ifdef HAVE_LONG_LONG
1524 if (data->flags & PF_LONGLONG)
1526 ull = GETARG (unsigned long long);
1527 lnumber(data, ull, 8);
1532 ul = GETUNSIGNED(data);
1533 number(data, ul, 8);
1538 case 'X': /* hexadecimal */
1540 #ifdef HAVE_LONG_LONG
1541 if (data->flags & PF_LONGLONG)
1543 ull = GETARG (unsigned long long);
1544 lnumber(data, ull, 16);
1549 ul = GETUNSIGNED(data);
1550 number(data, ul, 16);
1556 ul = (unsigned long)GETARG (void *);
1560 #if HANDLE_MULTIBYTE
1562 data->flags |= PF_LONGINT;
1565 case 'c': /* character */
1567 #if HANDLE_MULTIBYTE
1568 if (data->flags & PF_LONGINT)
1570 wc = GETARG (wint_t);
1581 #if HANDLE_MULTIBYTE
1583 data->flags |= PF_LONGINT;
1586 case 's': /* string */
1588 #if HANDLE_MULTIBYTE
1589 if (data->flags & PF_LONGINT)
1591 ws = GETARG (wchar_t *);
1592 wstrings (data, ws);
1597 s = GETARG (char *);
1603 #ifdef HAVE_LONG_LONG
1604 if (data->flags & PF_LONGLONG)
1605 *(GETARG (long long *)) = data->counter;
1608 if (data->flags & PF_LONGINT)
1609 *(GETARG (long *)) = data->counter;
1610 else if (data->flags & PF_SHORTINT)
1611 *(GETARG (short *)) = data->counter;
1613 *(GETARG (int *)) = data->counter;
1616 case '%': /* nothing just % */
1617 PUT_CHAR('%', data);
1621 /* is this an error ? maybe bail out */
1625 } /* end of `%' for loop */
1626 } /* end of format string for loop */
1628 if (data->length >= 0)
1629 *data->holder = '\0'; /* the end ye ! */
1631 return data->counter;
1634 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1636 * Printing floating point numbers accurately is an art. I'm not good
1637 * at it. Fall back to sprintf for long double formats.
1640 ldfallback (data, fs, fe, ld)
1642 const char *fs, *fe;
1646 char fmtbuf[FALLBACK_FMTSIZE], *obuf;
1649 fl = LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2;
1650 obuf = (char *)xmalloc (fl);
1652 strncpy (fmtbuf, fs, fl);
1655 if ((data->flags & PF_STAR_W) && (data->flags & PF_STAR_P))
1656 sprintf (obuf, fmtbuf, data->width, data->precision, ld);
1657 else if (data->flags & PF_STAR_W)
1658 sprintf (obuf, fmtbuf, data->width, ld);
1659 else if (data->flags & PF_STAR_P)
1660 sprintf (obuf, fmtbuf, data->precision, ld);
1662 sprintf (obuf, fmtbuf, ld);
1664 for (x = obuf; *x; x++)
1665 PUT_CHAR (*x, data);
1668 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1670 #ifdef FLOATING_POINT
1671 /* Used for %a, %A if the libc printf supports them. */
1673 dfallback (data, fs, fe, d)
1675 const char *fs, *fe;
1679 char fmtbuf[FALLBACK_FMTSIZE], obuf[FALLBACK_BASE];
1683 strncpy (fmtbuf, fs, fl);
1686 if ((data->flags & PF_STAR_W) && (data->flags & PF_STAR_P))
1687 sprintf (obuf, fmtbuf, data->width, data->precision, d);
1688 else if (data->flags & PF_STAR_W)
1689 sprintf (obuf, fmtbuf, data->width, d);
1690 else if (data->flags & PF_STAR_P)
1691 sprintf (obuf, fmtbuf, data->precision, d);
1693 sprintf (obuf, fmtbuf, d);
1695 for (x = obuf; *x; x++)
1696 PUT_CHAR (*x, data);
1698 #endif /* FLOATING_POINT */
1703 #if defined (__STDC__)
1704 vsnprintf(char *string, size_t length, const char *format, va_list args)
1706 vsnprintf(string, length, format, args)
1715 if (string == 0 && length != 0)
1717 init_data (&data, string, length, format, PFM_SN);
1718 return (vsnprintf_internal(&data, string, length, format, args));
1722 #if defined(PREFER_STDARG)
1723 snprintf(char *string, size_t length, const char * format, ...)
1725 snprintf(string, length, format, va_alist)
1736 SH_VA_START(args, format);
1738 if (string == 0 && length != 0)
1740 init_data (&data, string, length, format, PFM_SN);
1741 rval = vsnprintf_internal (&data, string, length, format, args);
1748 #endif /* HAVE_SNPRINTF */
1753 #if defined (__STDC__)
1754 vasprintf(char **stringp, const char *format, va_list args)
1756 vasprintf(stringp, format, args)
1766 string = (char *)xmalloc(ASBUFSIZE);
1767 init_data (&data, string, ASBUFSIZE, format, PFM_AS);
1768 r = vsnprintf_internal(&data, string, ASBUFSIZE, format, args);
1769 *stringp = data.base; /* not string in case reallocated */
1774 #if defined(PREFER_STDARG)
1775 asprintf(char **stringp, const char * format, ...)
1777 asprintf(stringp, format, va_alist)
1786 SH_VA_START(args, format);
1788 rval = vasprintf (stringp, format, args);
1795 #endif /* !HAVE_ASPRINTF */
1797 #endif /* !HAVE_SNPRINTF || !HAVE_ASPRINTF */
1802 memory_error_and_abort ()
1804 write (2, "out of virtual memory\n", 22);
1814 ret = malloc(bytes);
1816 memory_error_and_abort ();
1821 xrealloc (pointer, bytes)
1827 ret = pointer ? realloc(pointer, bytes) : malloc(bytes);
1829 memory_error_and_abort ();
1841 /* set of small tests for snprintf() */
1848 #ifdef HAVE_LOCALE_H
1849 setlocale(LC_ALL, "");
1853 si = snprintf((char *)NULL, 0, "abcde\n");
1854 printf("snprintf returns %d with NULL first argument and size of 0\n", si);
1855 si = snprintf(holder, 0, "abcde\n");
1856 printf("snprintf returns %d with non-NULL first argument and size of 0\n", si);
1857 si = snprintf((char *)NULL, 16, "abcde\n");
1858 printf("snprintf returns %d with NULL first argument and non-zero size\n", si);
1861 printf("Suite of test for snprintf:\n");
1862 printf("a_format\n");
1863 printf("printf() format\n");
1864 printf("snprintf() format\n\n");
1866 /* Checking the field widths */
1868 printf("/%%ld %%ld/, 336, 336\n");
1869 snprintf(holder, sizeof holder, "/%ld %ld/\n", 336, 336);
1870 asprintf(&h, "/%ld %ld/\n", 336, 336);
1871 printf("/%ld %ld/\n", 336, 336);
1872 printf("%s", holder);
1875 printf("/%%d/, 336\n");
1876 snprintf(holder, sizeof holder, "/%d/\n", 336);
1877 asprintf(&h, "/%d/\n", 336);
1878 printf("/%d/\n", 336);
1879 printf("%s", holder);
1882 printf("/%%2d/, 336\n");
1883 snprintf(holder, sizeof holder, "/%2d/\n", 336);
1884 asprintf(&h, "/%2d/\n", 336);
1885 printf("/%2d/\n", 336);
1886 printf("%s", holder);
1889 printf("/%%10d/, 336\n");
1890 snprintf(holder, sizeof holder, "/%10d/\n", 336);
1891 asprintf(&h, "/%10d/\n", 336);
1892 printf("/%10d/\n", 336);
1893 printf("%s", holder);
1896 printf("/%%-10d/, 336\n");
1897 snprintf(holder, sizeof holder, "/%-10d/\n", 336);
1898 asprintf(&h, "/%-10d/\n", 336);
1899 printf("/%-10d/\n", 336);
1900 printf("%s", holder);
1904 /* floating points */
1906 printf("/%%f/, 1234.56\n");
1907 snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
1908 asprintf(&h, "/%f/\n", 1234.56);
1909 printf("/%f/\n", 1234.56);
1910 printf("%s", holder);
1913 printf("/%%e/, 1234.56\n");
1914 snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
1915 asprintf(&h, "/%e/\n", 1234.56);
1916 printf("/%e/\n", 1234.56);
1917 printf("%s", holder);
1920 printf("/%%4.2f/, 1234.56\n");
1921 snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
1922 asprintf(&h, "/%4.2f/\n", 1234.56);
1923 printf("/%4.2f/\n", 1234.56);
1924 printf("%s", holder);
1927 printf("/%%3.1f/, 1234.56\n");
1928 snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
1929 asprintf(&h, "/%3.1f/\n", 1234.56);
1930 printf("/%3.1f/\n", 1234.56);
1931 printf("%s", holder);
1934 printf("/%%10.3f/, 1234.56\n");
1935 snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
1936 asprintf(&h, "/%10.3f/\n", 1234.56);
1937 printf("/%10.3f/\n", 1234.56);
1938 printf("%s", holder);
1941 printf("/%%10.3e/, 1234.56\n");
1942 snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
1943 asprintf(&h, "/%10.3e/\n", 1234.56);
1944 printf("/%10.3e/\n", 1234.56);
1945 printf("%s", holder);
1948 printf("/%%+4.2f/, 1234.56\n");
1949 snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
1950 asprintf(&h, "/%+4.2f/\n", 1234.56);
1951 printf("/%+4.2f/\n", 1234.56);
1952 printf("%s", holder);
1955 printf("/%%010.2f/, 1234.56\n");
1956 snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
1957 asprintf(&h, "/%010.2f/\n", 1234.56);
1958 printf("/%010.2f/\n", 1234.56);
1959 printf("%s", holder);
1962 #define BLURB "Outstanding acting !"
1963 /* strings precisions */
1965 printf("/%%2s/, \"%s\"\n", BLURB);
1966 snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
1967 asprintf(&h, "/%2s/\n", BLURB);
1968 printf("/%2s/\n", BLURB);
1969 printf("%s", holder);
1972 printf("/%%22s/ %s\n", BLURB);
1973 snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
1974 asprintf(&h, "/%22s/\n", BLURB);
1975 printf("/%22s/\n", BLURB);
1976 printf("%s", holder);
1979 printf("/%%22.5s/ %s\n", BLURB);
1980 snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
1981 asprintf(&h, "/%22.5s/\n", BLURB);
1982 printf("/%22.5s/\n", BLURB);
1983 printf("%s", holder);
1986 printf("/%%-22.5s/ %s\n", BLURB);
1987 snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
1988 asprintf(&h, "/%-22.5s/\n", BLURB);
1989 printf("/%-22.5s/\n", BLURB);
1990 printf("%s", holder);
1993 /* see some flags */
1995 printf("%%x %%X %%#x, 31, 31, 31\n");
1996 snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
1997 asprintf(&h, "%x %X %#x\n", 31, 31, 31);
1998 printf("%x %X %#x\n", 31, 31, 31);
1999 printf("%s", holder);
2002 printf("**%%d**%% d**%% d**, 42, 42, -42\n");
2003 snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
2004 asprintf(&h, "**%d**% d**% d**\n", 42, 42, -42);
2005 printf("**%d**% d**% d**\n", 42, 42, -42);
2006 printf("%s", holder);
2011 printf("/%%g/, 31.4\n");
2012 snprintf(holder, sizeof holder, "/%g/\n", 31.4);
2013 asprintf(&h, "/%g/\n", 31.4);
2014 printf("/%g/\n", 31.4);
2015 printf("%s", holder);
2018 printf("/%%.6g/, 31.4\n");
2019 snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
2020 asprintf(&h, "/%.6g/\n", 31.4);
2021 printf("/%.6g/\n", 31.4);
2022 printf("%s", holder);
2025 printf("/%%.1G/, 31.4\n");
2026 snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
2027 asprintf(&h, "/%.1G/\n", 31.4);
2028 printf("/%.1G/\n", 31.4);
2029 printf("%s", holder);
2032 printf("/%%.1G/, 3100000000.4\n");
2033 snprintf(holder, sizeof holder, "/%.1G/\n", 3100000000.4);
2034 asprintf(&h, "/%.1G/\n", 3100000000.4);
2035 printf("/%.1G/\n", 3100000000.4);
2036 printf("%s", holder);
2040 printf("abc%n", &i); printf("%d\n", i);
2041 snprintf(holder, sizeof holder, "abc%n", &i);
2042 printf("%s", holder); printf("%d\n\n", i);
2043 asprintf(&h, "abc%n", &i);
2044 printf("%s", h); printf("%d\n\n", i);
2046 printf("%%*.*s --> 10.10\n");
2047 snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
2048 asprintf(&h, "%*.*s\n", 10, 10, BLURB);
2049 printf("%*.*s\n", 10, 10, BLURB);
2050 printf("%s", holder);
2053 printf("%%%%%%%%\n");
2054 snprintf(holder, sizeof holder, "%%%%\n");
2055 asprintf(&h, "%%%%\n");
2057 printf("%s", holder);
2060 #define BIG "Hello this is a too big string for the buffer"
2061 /* printf("A buffer to small of 10, trying to put this:\n");*/
2062 printf("<%%>, %s\n", BIG);
2063 i = snprintf(holder, 10, "%s\n", BIG);
2064 i = asprintf(&h, "%s", BIG);
2065 printf("<%s>\n", BIG);
2066 printf("<%s>\n", holder);
2067 printf("<%s>\n\n", h);
2069 printf ("<%%p> vsnprintf\n");
2070 i = snprintf(holder, 100, "%p", vsnprintf);
2071 i = asprintf(&h, "%p", vsnprintf);
2072 printf("<%p>\n", vsnprintf);
2073 printf("<%s>\n", holder);
2074 printf("<%s>\n\n", h);
2076 printf ("<%%lu> LONG_MAX+1\n");
2077 i = snprintf(holder, 100, "%lu", (unsigned long)(LONG_MAX)+1);
2078 i = asprintf(&h, "%lu", (unsigned long)(LONG_MAX)+1);
2079 printf("<%lu>\n", (unsigned long)(LONG_MAX)+1);
2080 printf("<%s>\n", holder);
2081 printf("<%s>\n\n", h);
2083 #ifdef HAVE_LONG_LONG
2084 printf ("<%%llu> LLONG_MAX+1\n");
2085 i = snprintf(holder, 100, "%llu", (unsigned long long)(LLONG_MAX)+1);
2086 i = asprintf(&h, "%llu", (unsigned long long)(LLONG_MAX)+1);
2087 printf("<%llu>\n", (unsigned long long)(LLONG_MAX)+1);
2088 printf("<%s>\n", holder);
2089 printf("<%s>\n\n", h);
2092 #ifdef HAVE_LONG_DOUBLE
2093 printf ("<%%6.2LE> 42.42\n");
2094 i = snprintf(holder, 100, "%6.2LE", (long double)42.42);
2095 i = asprintf(&h, "%6.2LE", (long double)42.42);
2096 printf ("<%6.2LE>\n", (long double)42.42);
2097 printf ("<%s>\n", holder);
2098 printf ("<%s>\n\n", h);
2101 #ifdef HAVE_PRINTF_A_FORMAT
2102 printf ("<%%6.2A> 42.42\n");
2103 i = snprintf(holder, 100, "%6.2A", 42.42);
2104 i = asprintf(&h, "%6.2A", 42.42);
2105 printf ("<%6.2A>\n", 42.42);
2106 printf ("<%s>\n", holder);
2107 printf ("<%s>\n\n", h);
2109 printf ("<%%6.2LA> 42.42\n");
2110 i = snprintf(holder, 100, "%6.2LA", (long double)42.42);
2111 i = asprintf(&h, "%6.2LA", (long double)42.42);
2112 printf ("<%6.2LA>\n", (long double)42.42);
2113 printf ("<%s>\n", holder);
2114 printf ("<%s>\n\n", h);
2117 printf ("<%%.10240f> DBL_MAX\n");
2118 si = snprintf(holder, 100, "%.10240f", DBL_MAX);
2119 ai = asprintf(&h, "%.10240f", DBL_MAX);
2120 printf ("<%.10240f>\n", DBL_MAX);
2121 printf ("<%d> <%s>\n", si, holder);
2122 printf ("<%d> <%s>\n\n", ai, h);
2124 printf ("<%%.10240Lf> LDBL_MAX\n");
2125 si = snprintf(holder, 100, "%.10240Lf", (long double)LDBL_MAX);
2126 ai = asprintf(&h, "%.10240Lf", (long double)LDBL_MAX);
2127 printf ("<%.10240Lf>\n", (long double)LDBL_MAX);
2128 printf ("<%d> <%s>\n", si, holder);
2129 printf ("<%d> <%s>\n\n", ai, h);
2132 printf("/%%g/, 421.2345\n");
2133 snprintf(holder, sizeof holder, "/%g/\n", 421.2345);
2134 asprintf(&h, "/%g/\n", 421.2345);
2135 printf("/%g/\n", 421.2345);
2136 printf("%s", holder);
2139 printf("/%%g/, 4214.2345\n");
2140 snprintf(holder, sizeof holder, "/%g/\n", 4214.2345);
2141 asprintf(&h, "/%g/\n", 4214.2345);
2142 printf("/%g/\n", 4214.2345);
2143 printf("%s", holder);
2146 printf("/%%.5g/, 4214.2345\n");
2147 snprintf(holder, sizeof holder, "/%.5g/\n", 4214.2345);
2148 asprintf(&h, "/%.5g/\n", 4214.2345);
2149 printf("/%.5g/\n", 4214.2345);
2150 printf("%s", holder);
2153 printf("/%%.4g/, 4214.2345\n");
2154 snprintf(holder, sizeof holder, "/%.4g/\n", 4214.2345);
2155 asprintf(&h, "/%.4g/\n", 4214.2345);
2156 printf("/%.4g/\n", 4214.2345);
2157 printf("%s", holder);
2160 printf("/%%'ld %%'ld/, 12345, 1234567\n");
2161 snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 12345, 1234567);
2162 asprintf(&h, "/%'ld %'ld/\n", 12345, 1234567);
2163 printf("/%'ld %'ld/\n", 12345, 1234567);
2164 printf("%s", holder);
2167 printf("/%%'ld %%'ld/, 336, 3336\n");
2168 snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 336, 3336);
2169 asprintf(&h, "/%'ld %'ld/\n", 336, 3336);
2170 printf("/%'ld %'ld/\n", 336, 3336);
2171 printf("%s", holder);
2174 printf("/%%'ld %%'ld/, -42786, -142786\n");
2175 snprintf(holder, sizeof holder, "/%'ld %'ld/\n", -42786, -142786);
2176 asprintf(&h, "/%'ld %'ld/\n", -42786, -142786);
2177 printf("/%'ld %'ld/\n", -42786, -142786);
2178 printf("%s", holder);
2181 printf("/%%'f %%'f/, 421.2345, 421234.56789\n");
2182 snprintf(holder, sizeof holder, "/%'f %'f/\n", 421.2345, 421234.56789);
2183 asprintf(&h, "/%'f %'f/\n", 421.2345, 421234.56789);
2184 printf("/%'f %'f/\n", 421.2345, 421234.56789);
2185 printf("%s", holder);
2188 printf("/%%'f %%'f/, -421.2345, -421234.56789\n");
2189 snprintf(holder, sizeof holder, "/%'f %'f/\n", -421.2345, -421234.56789);
2190 asprintf(&h, "/%'f %'f/\n", -421.2345, -421234.56789);
2191 printf("/%'f %'f/\n", -421.2345, -421234.56789);
2192 printf("%s", holder);
2195 printf("/%%'g %%'g/, 421.2345, 421234.56789\n");
2196 snprintf(holder, sizeof holder, "/%'g %'g/\n", 421.2345, 421234.56789);
2197 asprintf(&h, "/%'g %'g/\n", 421.2345, 421234.56789);
2198 printf("/%'g %'g/\n", 421.2345, 421234.56789);
2199 printf("%s", holder);
2202 printf("/%%'g %%'g/, -421.2345, -421234.56789\n");
2203 snprintf(holder, sizeof holder, "/%'g %'g/\n", -421.2345, -421234.56789);
2204 asprintf(&h, "/%'g %'g/\n", -421.2345, -421234.56789);
2205 printf("/%'g %'g/\n", -421.2345, -421234.56789);
2206 printf("%s", holder);
2210 printf("/%%'g/, 4213455.8392\n");
2211 snprintf(holder, sizeof holder, "/%'g/\n", 4213455.8392);
2212 asprintf(&h, "/%'g/\n", 4213455.8392);
2213 printf("/%'g/\n", 4213455.8392);
2214 printf("%s", holder);