2 build a test version with
3 gcc -g -DDRIVER -I../.. -I../../include -o test-snprintf snprintf.c fmtu*long.o
7 Unix snprintf implementation.
8 derived from inetutils/libinetutils/snprintf.c Version 1.1
10 Copyright (C) 2001 Free Software Foundation, Inc.
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General License for more details.
22 You should have received a copy of the GNU General License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 * added changes from Miles Bader
30 * corrected a bug with %f
31 * added support for %#g
32 * added more comments :-)
34 * supporting must ANSI syntaxic_sugars
38 THANKS(for the patches and ideas):
47 * Currently doesn't handle (and bash/readline doesn't use):
48 * *M$ width, precision specifications
49 * %N$ numbered argument conversions
50 * inf, nan floating values imperfect (if isinf(), isnan() not in libc)
51 * support for `F' is imperfect, since underlying printf may not handle it
54 #define FLOATING_POINT
60 #if defined(DRIVER) && !defined(HAVE_CONFIG_H)
61 #define HAVE_LONG_LONG
62 #define HAVE_LONG_DOUBLE
64 #define HAVE_PRINTF_A_FORMAT
66 #define HAVE_ISINF_IN_LIBC
68 #define HAVE_STRINGIZE
75 #if !defined (HAVE_SNPRINTF) || !defined (HAVE_ASPRINTF)
77 #include <bashtypes.h>
79 #if defined(PREFER_STDARG)
92 #include <chartypes.h>
99 # include <float.h> /* for manifest constants */
100 # include <stdio.h> /* for sprintf */
110 #include <shmbutil.h>
115 # define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
116 # define FL_ADDBASE 0x02 /* add base# prefix to converted value */
117 # define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
118 # define FL_UNSIGNED 0x08 /* don't add any sign */
119 extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
120 extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
124 # define FREE(x) if (x) free (x)
127 /* Bound on length of the string representing an integer value of type T.
128 Subtract one for the sign bit if T is signed;
129 302 / 1000 is log10 (2) rounded up;
130 add one for integer division truncation;
131 add one more for a minus sign if t is signed. */
132 #define INT_STRLEN_BOUND(t) \
133 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
134 + 1 + TYPE_SIGNED (t))
136 /* conversion flags */
137 #define PF_ALTFORM 0x00001 /* # */
138 #define PF_HEXPREFIX 0x00002 /* 0[Xx] */
139 #define PF_LADJUST 0x00004 /* - */
140 #define PF_ZEROPAD 0x00008 /* 0 */
141 #define PF_PLUS 0x00010 /* + */
142 #define PF_SPACE 0x00020 /* ' ' */
143 #define PF_THOUSANDS 0x00040 /* ' */
145 #define PF_DOT 0x00080 /* `.precision' */
146 #define PF_STAR_P 0x00100 /* `*' after precision */
147 #define PF_STAR_W 0x00200 /* `*' before or without precision */
149 /* length modifiers */
150 #define PF_SIGNEDCHAR 0x00400 /* hh */
151 #define PF_SHORTINT 0x00800 /* h */
152 #define PF_LONGINT 0x01000 /* l */
153 #define PF_LONGLONG 0x02000 /* ll */
154 #define PF_LONGDBL 0x04000 /* L */
155 #define PF_INTMAX_T 0x08000 /* j */
156 #define PF_SIZE_T 0x10000 /* z */
157 #define PF_PTRDIFF_T 0x20000 /* t */
159 #define PF_ALLOCBUF 0x40000 /* for asprintf, vasprintf */
161 #define PFM_SN 0x01 /* snprintf, vsnprintf */
162 #define PFM_AS 0x02 /* asprintf, vasprintf */
164 #define ASBUFSIZE 128
166 #define x_digs "0123456789abcdef"
167 #define X_digs "0123456789ABCDEF"
169 static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
173 static char *grouping;
176 * For the FLOATING POINT FORMAT :
177 * the challenge was finding a way to
178 * manipulate the Real numbers without having
179 * to resort to mathematical function(it
180 * would require to link with -lm) and not
181 * going down to the bit pattern(not portable)
183 * so a number, a real is:
185 real = integral + fraction
187 integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
188 fraction = b(1)*10^-1 + b(2)*10^-2 + ...
194 from then it was simple math
198 * size of the buffer for the integral part
199 * and the fraction part
201 #define MAX_INT 99 + 1 /* 1 for the null */
202 #define MAX_FRACT 307 + 1
205 * These functions use static buffers to store the results,
206 * and so are not reentrant
208 #define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0);
209 #define dtoa(n, p, f) numtoa(n, 10, p, f)
211 #define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
213 #define GETARG(type) (va_arg(args, type))
215 /* Macros that do proper sign extension and handle length modifiers. Used
216 for the integer conversion specifiers. */
217 #define GETSIGNED(p) \
218 (((p)->flags & PF_LONGINT) \
220 : (((p)->flags & PF_SHORTINT) ? (long)(short)GETARG (int) \
221 : (long)GETARG (int)))
223 #define GETUNSIGNED(p) \
224 (((p)->flags & PF_LONGINT) \
225 ? GETARG (unsigned long) \
226 : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)GETARG (int) \
227 : (unsigned long)GETARG (unsigned int)))
230 #ifdef HAVE_LONG_DOUBLE
231 #define GETLDOUBLE(p) GETARG (long double)
233 #define GETDOUBLE(p) GETARG (double)
235 #define SET_SIZE_FLAGS(p, type) \
236 if (sizeof (type) > sizeof (int)) \
237 (p)->flags |= PF_LONGINT; \
238 if (sizeof (type) > sizeof (long)) \
239 (p)->flags |= PF_LONGLONG;
241 /* this struct holds everything we need */
245 char *base; /* needed for [v]asprintf */
253 int width, precision;
257 /* the floating point stuff */
258 #ifdef FLOATING_POINT
259 static double pow_10 __P((int));
260 static int log_10 __P((double));
261 static double integral __P((double, double *));
262 static char *numtoa __P((double, int, int, char **));
265 static void init_data __P((struct DATA *, char *, size_t, const char *, int));
266 static void init_conv_flag __P((struct DATA *));
269 #ifdef FLOATING_POINT
270 static void floating __P((struct DATA *, double));
271 static void exponent __P((struct DATA *, double));
273 static void number __P((struct DATA *, unsigned long, int));
274 #ifdef HAVE_LONG_LONG
275 static void lnumber __P((struct DATA *, unsigned long long, int));
277 static void pointer __P((struct DATA *, unsigned long));
278 static void strings __P((struct DATA *, char *));
280 #ifdef FLOATING_POINT
281 # define FALLBACK_FMTSIZE 32
282 # define FALLBACK_BASE 4096
283 # define LFALLBACK_BASE 5120
284 # ifdef HAVE_LONG_DOUBLE
285 static void ldfallback __P((struct DATA *, const char *, const char *, long double));
287 static void dfallback __P((struct DATA *, const char *, const char *, double));
290 static char *groupnum __P((char *));
293 static void memory_error_and_abort ();
294 static void *xmalloc __P((size_t));
295 static void *xrealloc __P((void *, size_t));
296 static void xfree __P((void *));
298 # include <xmalloc.h>
301 /* those are defines specific to snprintf to hopefully
302 * make the code clearer :-)
310 /* round off to the precision */
311 #define ROUND(d, p) \
313 d - pow_10(-(p)->precision) * 0.5 : \
314 d + pow_10(-(p)->precision) * 0.5
316 /* set default precision */
317 #define DEF_PREC(p) \
318 if ((p)->precision == NOT_FOUND) \
321 /* put a char. increment the number of chars written even if we've exceeded
322 the vsnprintf/snprintf buffer size (for the return value) */
323 #define PUT_CHAR(c, p) \
326 if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \
328 (p)->length += ASBUFSIZE; \
329 (p)->base = (char *)xrealloc((p)->base, (p)->length); \
330 (p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \
332 if ((p)->counter < (p)->length) \
333 *(p)->holder++ = (c); \
338 /* Output a string. P->WIDTH has already been adjusted for padding. */
339 #define PUT_STRING(string, len, p) \
343 while ((len)-- > 0) \
345 PUT_CHAR (*(string), (p)); \
352 #define PUT_PLUS(d, p, zero) \
353 if ((d) > zero && (p)->justify == RIGHT) \
356 #define PUT_SPACE(d, p, zero) \
357 if (((p)->flags & PF_SPACE) && (d) > zero) \
361 #define PAD_RIGHT(p) \
362 if ((p)->width > 0 && (p)->justify != LEFT) \
363 for (; (p)->width > 0; (p)->width--) \
364 PUT_CHAR((p)->pad, p)
367 #define PAD_LEFT(p) \
368 if ((p)->width > 0 && (p)->justify == LEFT) \
369 for (; (p)->width > 0; (p)->width--) \
370 PUT_CHAR((p)->pad, p)
372 /* if width and prec. in the args */
373 #define STAR_ARGS(p) \
374 if ((p)->flags & PF_STAR_W) \
375 (p)->width = GETARG (int); \
376 if ((p)->flags & PF_STAR_P) \
377 (p)->precision = GETARG (int)
379 #if defined (HAVE_LOCALE_H)
380 # define GETLOCALEDATA(d, t, g) \
385 (d) = '.'; (t) = -1; (g) = 0; /* defaults */ \
389 if (lv->decimal_point && lv->decimal_point[0]) \
390 (d) = lv->decimal_point[0]; \
391 if (lv->thousands_sep && lv->thousands_sep[0]) \
392 (t) = lv->thousands_sep[0]; \
393 (g) = lv->grouping ? lv->grouping : ""; \
394 if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \
400 # define GETLOCALEDATA(d, t, g) \
401 ( (d) = '.', (t) = ',', g = "\003" )
404 #ifdef FLOATING_POINT
406 * Find the nth power of 10
414 /* handle common cases with fast switch statement. */
417 case -3: return .001;
423 case 3: return 1000.;
429 for (n += 4; n < 0; n++)
435 for (n -= 4; n > 0; n--)
443 * Find the integral part of the log in base 10
444 * Note: this not a real log10()
445 I just need and approximation(integerpart) of x in:
481 * This function return the fraction part of a double
482 * and set in ip the integral part.
483 * In many ways it resemble the modf() found on most Un*x
492 double real_integral = 0.;
494 /* take care of the obvious */
495 /* equal to zero ? */
502 /* negative number ? */
513 /* the real work :-) */
514 for (j = log_10(real); j >= 0; j--)
517 s = (real - real_integral)/p;
521 real_integral += i*p;
524 return (real - real_integral);
527 #define PRECISION 1.e-6
529 * return an ascii representation of the integral part of the number
530 * and set fract to be an ascii representation of the fraction part
531 * the container for the fraction and the integral part or staticly
532 * declare with fix size
535 numtoa(number, base, precision, fract)
541 double ip, fp; /* integer and fraction part */
543 int digits = MAX_INT - 1;
544 static char integral_part[MAX_INT];
545 static char fraction_part[MAX_FRACT];
549 /* taking care of the obvious case: 0.0 */
552 integral_part[0] = '0';
553 integral_part[1] = '\0';
554 fraction_part[0] = '0';
555 fraction_part[1] = '\0';
557 *fract = fraction_part;
558 return integral_part;
561 /* for negative numbers */
562 if ((sign = number) < 0.)
565 digits--; /* sign consume one digit */
568 fraction = integral(number, &ip);
571 /* do the integral part */
574 integral_part[0] = '0';
579 for ( i = 0; i < digits && number != 0.; ++i)
582 fp = integral(number, &ip);
583 ch = (int)((fp + PRECISION)*base); /* force to round */
584 integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
585 if (! ISXDIGIT((unsigned char)integral_part[i]))
586 break; /* bail out overflow !! */
591 /* Oh No !! out of bound, ho well fill it up ! */
593 for (i = 0; i < digits; ++i)
594 integral_part[i] = '9';
598 integral_part[i++] = '-';
600 integral_part[i] = '\0';
602 /* reverse every thing */
603 for ( i--, j = 0; j < i; j++, i--)
604 SWAP_INT(integral_part[i], integral_part[j]);
606 /* the fractional part */
607 for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--)
609 fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
610 if (! DIGIT(fraction_part[i])) /* underflow ? */
612 fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
614 fraction_part[i] = '\0';
616 if (fract != (char **)0)
617 *fract = fraction_part;
619 return integral_part;
623 /* for %d and friends, it puts in holder
624 * the representation with the right padding
636 sd = d; /* signed for ' ' padding in base 10 */
637 flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
639 flags |= FL_HEXUPPER;
641 tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags);
643 if ((p->flags & PF_THOUSANDS))
645 GETLOCALEDATA(decpoint, thoussep, grouping);
646 if (grouping && (t = groupnum (tmp)))
650 p->width -= strlen(tmp);
660 if (p->flags & PF_ALTFORM)
664 if (p->flags & PF_ALTFORM)
682 #ifdef HAVE_LONG_LONG
684 * identical to number() but works for `long long'
689 unsigned long long d;
696 sd = d; /* signed for ' ' padding in base 10 */
697 flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
699 flags |= FL_HEXUPPER;
701 tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags);
703 if ((p->flags & PF_THOUSANDS))
705 GETLOCALEDATA(decpoint, thoussep, grouping);
706 if (grouping && (t = groupnum (tmp)))
710 p->width -= strlen(tmp);
720 if (p->flags & PF_ALTFORM)
724 if (p->flags & PF_ALTFORM)
750 tmp = fmtulong(d, 16, intbuf, sizeof(intbuf), 0);
751 p->width -= strlen(tmp);
754 /* prefix '0x' for pointers */
775 if (p->precision != NOT_FOUND) /* the smallest number */
776 len = (len < p->precision ? len : p->precision);
779 PUT_STRING (tmp, len, p);
783 /* %ls wide-character strings */
794 memset (&mbs, '\0', sizeof (mbstate_t));
795 ws = (const wchar_t *)tmp;
798 if (p->precision != NOT_FOUND)
800 os = (char *)xmalloc (p->precision + 1);
801 len = wcsrtombs (os, &ws, p->precision, &mbs);
805 len = wcsrtombs (NULL, &ws, 0, &mbs);
806 if (len != (size_t)-1)
808 memset (&mbs, '\0', sizeof (mbstate_t));
809 os = (char *)xmalloc (len + 1);
810 (void)wcsrtombs (os, &ws, len + 1, &mbs);
813 if (len == (size_t)-1)
815 /* invalid multibyte sequence; bail now. */
821 PUT_STRING (os, len, p);
834 lbuf = (char *)malloc (MB_CUR_MAX+1);
837 memset (&mbs, '\0', sizeof (mbstate_t));
838 len = wcrtomb (lbuf, wc, &mbs);
839 if (len == (size_t)-1)
840 /* conversion failed; bail now. */
844 PUT_STRING (l, len, p);
847 #endif /* HANDLE_MULTIBYTE */
849 #ifdef FLOATING_POINT
851 #ifndef HAVE_ISINF_IN_LIBC
852 /* Half-assed versions, since we don't want to link with libm. */
860 else if (d > DBL_MAX)
875 /* Check for [+-]infinity and NaN. If MODE == 1, we check for Infinity, else
876 (mode == 2) we check for NaN. This does the necessary printing. Returns
877 1 if Inf or Nan, 0 if not. */
879 chkinfnan(p, d, mode)
882 int mode; /* == 1 for inf, == 2 for nan */
888 i = (mode == 1) ? isinf(d) : isnan(d);
891 big = (mode == 1) ? "INF" : "NAN";
892 small = (mode == 1) ? "inf" : "nan";
894 tmp = (*p->pf == 'F' || *p->pf == 'G' || *p->pf == 'E') ? big : small;
908 /* %f %F %g %G floating point representation */
914 char *tmp, *tmp2, *t;
917 if (chkinfnan(p, d, 1) || chkinfnan(p, d, 2))
918 return; /* already printed nan or inf */
920 GETLOCALEDATA(decpoint, thoussep, grouping);
923 tmp = dtoa(d, p->precision, &tmp2);
925 if ((p->flags & PF_THOUSANDS) && grouping && (t = groupnum (tmp)))
928 /* calculate the padding. 1 for the dot */
929 p->width = p->width -
930 ((d > 0. && p->justify == RIGHT) ? 1:0) -
931 ((p->flags & PF_SPACE) ? 1:0) -
932 strlen(tmp) - p->precision - 1;
944 if (p->precision != 0 || (p->flags & PF_ALTFORM))
945 PUT_CHAR(decpoint, p); /* put the '.' */
947 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
948 /* smash the trailing zeros unless altform */
949 for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
952 for (; *tmp2; tmp2++)
953 PUT_CHAR(*tmp2, p); /* the fraction */
958 /* %e %E %g %G exponent representation */
967 if (chkinfnan(p, d, 1) || chkinfnan(p, d, 2))
968 return; /* already printed nan or inf */
970 GETLOCALEDATA(decpoint, thoussep, grouping);
973 d = d / pow_10(j); /* get the Mantissa */
975 tmp = dtoa(d, p->precision, &tmp2);
977 /* 1 for unit, 1 for the '.', 1 for 'e|E',
978 * 1 for '+|-', 2 for 'exp' */
979 /* calculate how much padding need */
980 p->width = p->width -
981 ((d > 0. && p->justify == RIGHT) ? 1:0) -
982 ((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
994 if (p->precision != 0 || (p->flags & PF_ALTFORM))
995 PUT_CHAR(decpoint, p); /* the '.' */
997 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
998 /* smash the trailing zeros unless altform */
999 for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
1002 for (; *tmp2; tmp2++)
1003 PUT_CHAR(*tmp2, p); /* the fraction */
1005 /* the exponent put the 'e|E' */
1006 if (*p->pf == 'g' || *p->pf == 'e')
1011 /* the sign of the exp */
1021 /* pad out to at least two spaces. pad with `0' if the exponent is a
1036 /* Return a new string with the digits in S grouped according to the locale's
1037 grouping info and thousands separator. If no grouping should be performed,
1038 this returns NULL; the caller needs to check for it. */
1043 char *se, *ret, *re, *g;
1046 if (grouping == 0 || *grouping <= 0 || *grouping == CHAR_MAX)
1047 return ((char *)NULL);
1049 /* find min grouping to size returned string */
1050 for (len = *grouping, g = grouping; *g; g++)
1051 if (*g > 0 && *g < len)
1055 len = slen / len + 1;
1056 ret = (char *)xmalloc (slen + len + 1);
1057 re = ret + slen + len;
1068 /* handle `-' inserted by numtoa() and the fmtu* family here. */
1069 if (se > s && se[-1] == '-')
1072 /* begin new group. */
1073 if (--len == 0 && se > s)
1076 len = *++g; /* was g++, but that uses first char twice (glibc bug, too) */
1078 len = *--g; /* use previous grouping */
1079 else if (*g == CHAR_MAX)
1091 memmove (ret, re, strlen (re) + 1);
1099 /* initialize the conversion specifiers */
1104 p->flags &= PF_ALLOCBUF; /* preserve PF_ALLOCBUF flag */
1105 p->precision = p->width = NOT_FOUND;
1106 p->justify = NOT_FOUND;
1111 init_data (p, string, length, format, mode)
1118 p->length = length - 1; /* leave room for '\0' */
1119 p->holder = p->base = string;
1122 p->flags = (mode == PFM_AS) ? PF_ALLOCBUF : 0;
1126 #if defined (__STDC__)
1127 vsnprintf_internal(struct DATA *data, char *string, size_t length, const char *format, va_list args)
1129 vsnprintf_internal(data, string, length, format, args)
1137 double d; /* temporary holder */
1138 #ifdef HAVE_LONG_DOUBLE
1139 long double ld; /* for later */
1142 #ifdef HAVE_LONG_LONG
1143 unsigned long long ull;
1147 #if HANDLE_MULTIBYTE
1151 const char *convstart;
1153 /* Sanity check, the string length must be >= 0. C99 actually says that
1154 LENGTH can be zero here, in the case of snprintf/vsnprintf (it's never
1155 0 in the case of asprintf/vasprintf), and the return value is the number
1156 of characters that would have been written. */
1163 /* Reset these for each call because the locale might have changed. */
1164 decpoint = thoussep = 0;
1167 for (; c = *(data->pf); data->pf++)
1175 convstart = data->pf;
1176 init_conv_flag (data); /* initialise format flags */
1179 for (state = 1; state && *data->pf; )
1182 /* fmtend = data->pf */
1183 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1184 if (data->flags & PF_LONGDBL)
1191 # ifdef HAVE_PRINTF_A_FORMAT
1195 ld = GETLDOUBLE (data);
1196 ldfallback (data, convstart, data->pf, ld);
1200 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1204 /* Parse format flags */
1205 case '\0': /* a NULL here ? ? bail out */
1206 *data->holder = '\0';
1207 return data->counter;
1210 data->flags |= PF_ALTFORM;
1213 data->flags |= PF_ZEROPAD;
1217 if (data->flags & PF_DOT)
1218 data->flags |= PF_STAR_P;
1220 data->flags |= PF_STAR_W;
1223 data->flags |= PF_LADJUST;
1224 data->justify = LEFT;
1227 if ((data->flags & PF_PLUS) == 0)
1228 data->flags |= PF_SPACE;
1231 data->flags |= PF_PLUS;
1232 data->justify = RIGHT;
1235 data->flags |= PF_THOUSANDS;
1238 case '1': case '2': case '3':
1239 case '4': case '5': case '6':
1240 case '7': case '8': case '9':
1244 n = n * 10 + TODIGIT(c);
1248 data->pf--; /* went too far */
1251 if (data->flags & PF_DOT)
1252 data->precision = n;
1257 /* optional precision */
1259 data->flags |= PF_DOT;
1260 data->precision = 0;
1263 /* length modifiers */
1265 data->flags |= (data->flags & PF_SHORTINT) ? PF_SIGNEDCHAR : PF_SHORTINT;
1268 data->flags |= (data->flags & PF_LONGINT) ? PF_LONGLONG : PF_LONGINT;
1271 data->flags |= PF_LONGDBL;
1274 data->flags |= PF_LONGLONG;
1277 data->flags |= PF_INTMAX_T;
1278 SET_SIZE_FLAGS(data, intmax_t);
1281 data->flags |= PF_SIZE_T;
1282 SET_SIZE_FLAGS(data, size_t);
1285 data->flags |= PF_PTRDIFF_T;
1286 SET_SIZE_FLAGS(data, ptrdiff_t);
1289 /* Conversion specifiers */
1290 #ifdef FLOATING_POINT
1291 case 'f': /* float, double */
1294 d = GETDOUBLE(data);
1303 d = GETDOUBLE(data);
1306 * for '%g|%G' ANSI: use f if exponent
1307 * is in the range or [-4,p] exclusively
1310 if (-4 < i && i < data->precision)
1312 /* reset precision */
1313 data->precision -= i + 1;
1318 /* reduce precision by 1 because of leading digit before
1319 decimal point in e format. */
1326 case 'E': /* Exponent double */
1328 d = GETDOUBLE(data);
1332 # ifdef HAVE_PRINTF_A_FORMAT
1336 d = GETDOUBLE(data);
1337 dfallback(data, convstart, data->pf, d);
1340 # endif /* HAVE_PRINTF_A_FORMAT */
1341 #endif /* FLOATING_POINT */
1343 data->flags |= PF_LONGINT;
1347 #ifdef HAVE_LONG_LONG
1348 if (data->flags & PF_LONGLONG)
1350 ull = GETARG (unsigned long long);
1351 lnumber(data, ull, 10);
1356 ul = GETUNSIGNED(data);
1357 number(data, ul, 10);
1362 data->flags |= PF_LONGINT;
1364 case 'd': /* decimal */
1367 #ifdef HAVE_LONG_LONG
1368 if (data->flags & PF_LONGLONG)
1370 ull = GETARG (long long);
1371 lnumber(data, ull, 10);
1376 ul = GETSIGNED(data);
1377 number(data, ul, 10);
1381 case 'o': /* octal */
1383 #ifdef HAVE_LONG_LONG
1384 if (data->flags & PF_LONGLONG)
1386 ull = GETARG (unsigned long long);
1387 lnumber(data, ull, 8);
1392 ul = GETUNSIGNED(data);
1393 number(data, ul, 8);
1398 case 'X': /* hexadecimal */
1400 #ifdef HAVE_LONG_LONG
1401 if (data->flags & PF_LONGLONG)
1403 ull = GETARG (unsigned long long);
1404 lnumber(data, ull, 16);
1409 ul = GETUNSIGNED(data);
1410 number(data, ul, 16);
1416 ul = (unsigned long)GETARG (void *);
1420 #if HANDLE_MULTIBYTE
1422 data->flags |= PF_LONGINT;
1425 case 'c': /* character */
1427 #if HANDLE_MULTIBYTE
1428 if (data->flags & PF_LONGINT)
1430 wc = GETARG (wint_t);
1441 #if HANDLE_MULTIBYTE
1443 data->flags |= PF_LONGINT;
1446 case 's': /* string */
1448 #if HANDLE_MULTIBYTE
1449 if (data->flags & PF_LONGINT)
1451 ws = GETARG (wchar_t *);
1452 wstrings (data, ws);
1457 s = GETARG (char *);
1463 #ifdef HAVE_LONG_LONG
1464 if (data->flags & PF_LONGLONG)
1465 *(GETARG (long long *)) = data->counter;
1468 if (data->flags & PF_LONGINT)
1469 *(GETARG (long *)) = data->counter;
1470 else if (data->flags & PF_SHORTINT)
1471 *(GETARG (short *)) = data->counter;
1473 *(GETARG (int *)) = data->counter;
1476 case '%': /* nothing just % */
1477 PUT_CHAR('%', data);
1481 /* is this an error ? maybe bail out */
1485 } /* end of `%' for loop */
1486 } /* end of format string for loop */
1488 if (data->length >= 0)
1489 *data->holder = '\0'; /* the end ye ! */
1491 return data->counter;
1494 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1496 * Printing floating point numbers accurately is an art. I'm not good
1497 * at it. Fall back to sprintf for long double formats.
1500 ldfallback (data, fs, fe, ld)
1502 const char *fs, *fe;
1506 char fmtbuf[FALLBACK_FMTSIZE], *obuf;
1509 obuf = (char *)xmalloc(LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2);
1511 strncpy (fmtbuf, fs, fl);
1513 sprintf (obuf, fmtbuf, ld);
1514 for (x = obuf; *x; x++)
1515 PUT_CHAR (*x, data);
1518 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1520 #ifdef FLOATING_POINT
1521 /* Used for %a, %A if the libc printf supports them. */
1523 dfallback (data, fs, fe, d)
1525 const char *fs, *fe;
1529 char fmtbuf[FALLBACK_FMTSIZE], obuf[FALLBACK_BASE];
1533 strncpy (fmtbuf, fs, fl);
1535 sprintf (obuf, fmtbuf, d);
1536 for (x = obuf; *x; x++)
1537 PUT_CHAR (*x, data);
1539 #endif /* FLOATING_POINT */
1541 #ifndef HAVE_SNPRINTF
1544 #if defined (__STDC__)
1545 vsnprintf(char *string, size_t length, const char *format, va_list args)
1547 vsnprintf(string, length, format, args)
1556 if (string == 0 && length != 0)
1558 init_data (&data, string, length, format, PFM_SN);
1559 return (vsnprintf_internal(&data, string, length, format, args));
1563 #if defined(PREFER_STDARG)
1564 snprintf(char *string, size_t length, const char * format, ...)
1566 snprintf(string, length, format, va_alist)
1577 SH_VA_START(args, format);
1579 if (string == 0 && length != 0)
1581 init_data (&data, string, length, format, PFM_SN);
1582 rval = vsnprintf_internal (&data, string, length, format, args);
1589 #endif /* HAVE_SNPRINTF */
1591 #ifndef HAVE_ASPRINTF
1594 #if defined (__STDC__)
1595 vasprintf(char **stringp, const char *format, va_list args)
1597 vasprintf(stringp, format, args)
1607 string = (char *)xmalloc(ASBUFSIZE);
1608 init_data (&data, string, ASBUFSIZE, format, PFM_AS);
1609 r = vsnprintf_internal(&data, string, ASBUFSIZE, format, args);
1610 *stringp = data.base; /* not string in case reallocated */
1615 #if defined(PREFER_STDARG)
1616 asprintf(char **stringp, const char * format, ...)
1618 asprintf(stringp, format, va_alist)
1627 SH_VA_START(args, format);
1629 rval = vasprintf (stringp, format, args);
1643 memory_error_and_abort ()
1645 write (2, "out of virtual memory\n", 22);
1655 ret = malloc(bytes);
1657 memory_error_and_abort ();
1662 xrealloc (pointer, bytes)
1668 ret = pointer ? realloc(pointer, bytes) : malloc(bytes);
1670 memory_error_and_abort ();
1682 /* set of small tests for snprintf() */
1689 #ifdef HAVE_LOCALE_H
1690 setlocale(LC_ALL, "");
1694 si = snprintf((char *)NULL, 0, "abcde\n");
1695 printf("snprintf returns %d with NULL first argument and size of 0\n", si);
1696 si = snprintf(holder, 0, "abcde\n");
1697 printf("snprintf returns %d with non-NULL first argument and size of 0\n", si);
1698 si = snprintf((char *)NULL, 16, "abcde\n");
1699 printf("snprintf returns %d with NULL first argument and non-zero size\n", si);
1702 printf("Suite of test for snprintf:\n");
1703 printf("a_format\n");
1704 printf("printf() format\n");
1705 printf("snprintf() format\n\n");
1707 /* Checking the field widths */
1709 printf("/%%ld %%ld/, 336, 336\n");
1710 snprintf(holder, sizeof holder, "/%ld %ld/\n", 336, 336);
1711 asprintf(&h, "/%ld %ld/\n", 336, 336);
1712 printf("/%ld %ld/\n", 336, 336);
1713 printf("%s", holder);
1716 printf("/%%d/, 336\n");
1717 snprintf(holder, sizeof holder, "/%d/\n", 336);
1718 asprintf(&h, "/%d/\n", 336);
1719 printf("/%d/\n", 336);
1720 printf("%s", holder);
1723 printf("/%%2d/, 336\n");
1724 snprintf(holder, sizeof holder, "/%2d/\n", 336);
1725 asprintf(&h, "/%2d/\n", 336);
1726 printf("/%2d/\n", 336);
1727 printf("%s", holder);
1730 printf("/%%10d/, 336\n");
1731 snprintf(holder, sizeof holder, "/%10d/\n", 336);
1732 asprintf(&h, "/%10d/\n", 336);
1733 printf("/%10d/\n", 336);
1734 printf("%s", holder);
1737 printf("/%%-10d/, 336\n");
1738 snprintf(holder, sizeof holder, "/%-10d/\n", 336);
1739 asprintf(&h, "/%-10d/\n", 336);
1740 printf("/%-10d/\n", 336);
1741 printf("%s", holder);
1745 /* floating points */
1747 printf("/%%f/, 1234.56\n");
1748 snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
1749 asprintf(&h, "/%f/\n", 1234.56);
1750 printf("/%f/\n", 1234.56);
1751 printf("%s", holder);
1754 printf("/%%e/, 1234.56\n");
1755 snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
1756 asprintf(&h, "/%e/\n", 1234.56);
1757 printf("/%e/\n", 1234.56);
1758 printf("%s", holder);
1761 printf("/%%4.2f/, 1234.56\n");
1762 snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
1763 asprintf(&h, "/%4.2f/\n", 1234.56);
1764 printf("/%4.2f/\n", 1234.56);
1765 printf("%s", holder);
1768 printf("/%%3.1f/, 1234.56\n");
1769 snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
1770 asprintf(&h, "/%3.1f/\n", 1234.56);
1771 printf("/%3.1f/\n", 1234.56);
1772 printf("%s", holder);
1775 printf("/%%10.3f/, 1234.56\n");
1776 snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
1777 asprintf(&h, "/%10.3f/\n", 1234.56);
1778 printf("/%10.3f/\n", 1234.56);
1779 printf("%s", holder);
1782 printf("/%%10.3e/, 1234.56\n");
1783 snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
1784 asprintf(&h, "/%10.3e/\n", 1234.56);
1785 printf("/%10.3e/\n", 1234.56);
1786 printf("%s", holder);
1789 printf("/%%+4.2f/, 1234.56\n");
1790 snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
1791 asprintf(&h, "/%+4.2f/\n", 1234.56);
1792 printf("/%+4.2f/\n", 1234.56);
1793 printf("%s", holder);
1796 printf("/%%010.2f/, 1234.56\n");
1797 snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
1798 asprintf(&h, "/%010.2f/\n", 1234.56);
1799 printf("/%010.2f/\n", 1234.56);
1800 printf("%s", holder);
1803 #define BLURB "Outstanding acting !"
1804 /* strings precisions */
1806 printf("/%%2s/, \"%s\"\n", BLURB);
1807 snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
1808 asprintf(&h, "/%2s/\n", BLURB);
1809 printf("/%2s/\n", BLURB);
1810 printf("%s", holder);
1813 printf("/%%22s/ %s\n", BLURB);
1814 snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
1815 asprintf(&h, "/%22s/\n", BLURB);
1816 printf("/%22s/\n", BLURB);
1817 printf("%s", holder);
1820 printf("/%%22.5s/ %s\n", BLURB);
1821 snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
1822 asprintf(&h, "/%22.5s/\n", BLURB);
1823 printf("/%22.5s/\n", BLURB);
1824 printf("%s", holder);
1827 printf("/%%-22.5s/ %s\n", BLURB);
1828 snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
1829 asprintf(&h, "/%-22.5s/\n", BLURB);
1830 printf("/%-22.5s/\n", BLURB);
1831 printf("%s", holder);
1834 /* see some flags */
1836 printf("%%x %%X %%#x, 31, 31, 31\n");
1837 snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
1838 asprintf(&h, "%x %X %#x\n", 31, 31, 31);
1839 printf("%x %X %#x\n", 31, 31, 31);
1840 printf("%s", holder);
1843 printf("**%%d**%% d**%% d**, 42, 42, -42\n");
1844 snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
1845 asprintf(&h, "**%d**% d**% d**\n", 42, 42, -42);
1846 printf("**%d**% d**% d**\n", 42, 42, -42);
1847 printf("%s", holder);
1852 printf("/%%g/, 31.4\n");
1853 snprintf(holder, sizeof holder, "/%g/\n", 31.4);
1854 asprintf(&h, "/%g/\n", 31.4);
1855 printf("/%g/\n", 31.4);
1856 printf("%s", holder);
1859 printf("/%%.6g/, 31.4\n");
1860 snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
1861 asprintf(&h, "/%.6g/\n", 31.4);
1862 printf("/%.6g/\n", 31.4);
1863 printf("%s", holder);
1866 printf("/%%.1G/, 31.4\n");
1867 snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
1868 asprintf(&h, "/%.1G/\n", 31.4);
1869 printf("/%.1G/\n", 31.4);
1870 printf("%s", holder);
1873 printf("/%%.1G/, 3100000000.4\n");
1874 snprintf(holder, sizeof holder, "/%.1G/\n", 3100000000.4);
1875 asprintf(&h, "/%.1G/\n", 3100000000.4);
1876 printf("/%.1G/\n", 3100000000.4);
1877 printf("%s", holder);
1881 printf("abc%n", &i); printf("%d\n", i);
1882 snprintf(holder, sizeof holder, "abc%n", &i);
1883 printf("%s", holder); printf("%d\n\n", i);
1884 asprintf(&h, "abc%n", &i);
1885 printf("%s", h); printf("%d\n\n", i);
1887 printf("%%*.*s --> 10.10\n");
1888 snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
1889 asprintf(&h, "%*.*s\n", 10, 10, BLURB);
1890 printf("%*.*s\n", 10, 10, BLURB);
1891 printf("%s", holder);
1894 printf("%%%%%%%%\n");
1895 snprintf(holder, sizeof holder, "%%%%\n");
1896 asprintf(&h, "%%%%\n");
1898 printf("%s", holder);
1901 #define BIG "Hello this is a too big string for the buffer"
1902 /* printf("A buffer to small of 10, trying to put this:\n");*/
1903 printf("<%%>, %s\n", BIG);
1904 i = snprintf(holder, 10, "%s\n", BIG);
1905 i = asprintf(&h, "%s", BIG);
1906 printf("<%s>\n", BIG);
1907 printf("<%s>\n", holder);
1908 printf("<%s>\n\n", h);
1910 printf ("<%%p> vsnprintf\n");
1911 i = snprintf(holder, 100, "%p", vsnprintf);
1912 i = asprintf(&h, "%p", vsnprintf);
1913 printf("<%p>\n", vsnprintf);
1914 printf("<%s>\n", holder);
1915 printf("<%s>\n\n", h);
1917 printf ("<%%lu> LONG_MAX+1\n");
1918 i = snprintf(holder, 100, "%lu", (unsigned long)(LONG_MAX)+1);
1919 i = asprintf(&h, "%lu", (unsigned long)(LONG_MAX)+1);
1920 printf("<%lu>\n", (unsigned long)(LONG_MAX)+1);
1921 printf("<%s>\n", holder);
1922 printf("<%s>\n\n", h);
1924 #ifdef HAVE_LONG_LONG
1925 printf ("<%%llu> LLONG_MAX+1\n");
1926 i = snprintf(holder, 100, "%llu", (unsigned long long)(LLONG_MAX)+1);
1927 i = asprintf(&h, "%llu", (unsigned long long)(LLONG_MAX)+1);
1928 printf("<%llu>\n", (unsigned long long)(LLONG_MAX)+1);
1929 printf("<%s>\n", holder);
1930 printf("<%s>\n\n", h);
1933 #ifdef HAVE_LONG_DOUBLE
1934 printf ("<%%6.2LE> 42.42\n");
1935 i = snprintf(holder, 100, "%6.2LE", (long double)42.42);
1936 i = asprintf(&h, "%6.2LE", (long double)42.42);
1937 printf ("<%6.2LE>\n", (long double)42.42);
1938 printf ("<%s>\n", holder);
1939 printf ("<%s>\n\n", h);
1942 #ifdef HAVE_PRINTF_A_FORMAT
1943 printf ("<%%6.2A> 42.42\n");
1944 i = snprintf(holder, 100, "%6.2A", 42.42);
1945 i = asprintf(&h, "%6.2A", 42.42);
1946 printf ("<%6.2A>\n", 42.42);
1947 printf ("<%s>\n", holder);
1948 printf ("<%s>\n\n", h);
1950 printf ("<%%6.2LA> 42.42\n");
1951 i = snprintf(holder, 100, "%6.2LA", (long double)42.42);
1952 i = asprintf(&h, "%6.2LA", (long double)42.42);
1953 printf ("<%6.2LA>\n", (long double)42.42);
1954 printf ("<%s>\n", holder);
1955 printf ("<%s>\n\n", h);
1958 printf ("<%%.10240f> DBL_MAX\n");
1959 si = snprintf(holder, 100, "%.10240f", DBL_MAX);
1960 ai = asprintf(&h, "%.10240f", DBL_MAX);
1961 printf ("<%.10240f>\n", DBL_MAX);
1962 printf ("<%d> <%s>\n", si, holder);
1963 printf ("<%d> <%s>\n\n", ai, h);
1965 printf ("<%%.10240Lf> LDBL_MAX\n");
1966 si = snprintf(holder, 100, "%.10240Lf", (long double)LDBL_MAX);
1967 ai = asprintf(&h, "%.10240Lf", (long double)LDBL_MAX);
1968 printf ("<%.10240Lf>\n", (long double)LDBL_MAX);
1969 printf ("<%d> <%s>\n", si, holder);
1970 printf ("<%d> <%s>\n\n", ai, h);
1973 printf("/%%g/, 421.2345\n");
1974 snprintf(holder, sizeof holder, "/%g/\n", 421.2345);
1975 asprintf(&h, "/%g/\n", 421.2345);
1976 printf("/%g/\n", 421.2345);
1977 printf("%s", holder);
1980 printf("/%%g/, 4214.2345\n");
1981 snprintf(holder, sizeof holder, "/%g/\n", 4214.2345);
1982 asprintf(&h, "/%g/\n", 4214.2345);
1983 printf("/%g/\n", 4214.2345);
1984 printf("%s", holder);
1987 printf("/%%.5g/, 4214.2345\n");
1988 snprintf(holder, sizeof holder, "/%.5g/\n", 4214.2345);
1989 asprintf(&h, "/%.5g/\n", 4214.2345);
1990 printf("/%.5g/\n", 4214.2345);
1991 printf("%s", holder);
1994 printf("/%%.4g/, 4214.2345\n");
1995 snprintf(holder, sizeof holder, "/%.4g/\n", 4214.2345);
1996 asprintf(&h, "/%.4g/\n", 4214.2345);
1997 printf("/%.4g/\n", 4214.2345);
1998 printf("%s", holder);
2001 printf("/%%'ld %%'ld/, 12345, 1234567\n");
2002 snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 12345, 1234567);
2003 asprintf(&h, "/%'ld %'ld/\n", 12345, 1234567);
2004 printf("/%'ld %'ld/\n", 12345, 1234567);
2005 printf("%s", holder);
2008 printf("/%%'ld %%'ld/, 336, 3336\n");
2009 snprintf(holder, sizeof holder, "/%'ld %'ld/\n", 336, 3336);
2010 asprintf(&h, "/%'ld %'ld/\n", 336, 3336);
2011 printf("/%'ld %'ld/\n", 336, 3336);
2012 printf("%s", holder);
2015 printf("/%%'ld %%'ld/, -42786, -142786\n");
2016 snprintf(holder, sizeof holder, "/%'ld %'ld/\n", -42786, -142786);
2017 asprintf(&h, "/%'ld %'ld/\n", -42786, -142786);
2018 printf("/%'ld %'ld/\n", -42786, -142786);
2019 printf("%s", holder);
2022 printf("/%%'f %%'f/, 421.2345, 421234.56789\n");
2023 snprintf(holder, sizeof holder, "/%'f %'f/\n", 421.2345, 421234.56789);
2024 asprintf(&h, "/%'f %'f/\n", 421.2345, 421234.56789);
2025 printf("/%'f %'f/\n", 421.2345, 421234.56789);
2026 printf("%s", holder);
2029 printf("/%%'f %%'f/, -421.2345, -421234.56789\n");
2030 snprintf(holder, sizeof holder, "/%'f %'f/\n", -421.2345, -421234.56789);
2031 asprintf(&h, "/%'f %'f/\n", -421.2345, -421234.56789);
2032 printf("/%'f %'f/\n", -421.2345, -421234.56789);
2033 printf("%s", holder);
2036 printf("/%%'g %%'g/, 421.2345, 421234.56789\n");
2037 snprintf(holder, sizeof holder, "/%'g %'g/\n", 421.2345, 421234.56789);
2038 asprintf(&h, "/%'g %'g/\n", 421.2345, 421234.56789);
2039 printf("/%'g %'g/\n", 421.2345, 421234.56789);
2040 printf("%s", holder);
2043 printf("/%%'g %%'g/, -421.2345, -421234.56789\n");
2044 snprintf(holder, sizeof holder, "/%'g %'g/\n", -421.2345, -421234.56789);
2045 asprintf(&h, "/%'g %'g/\n", -421.2345, -421234.56789);
2046 printf("/%'g %'g/\n", -421.2345, -421234.56789);
2047 printf("%s", holder);
2051 printf("/%%'g/, 4213455.8392\n");
2052 snprintf(holder, sizeof holder, "/%'g/\n", 4213455.8392);
2053 asprintf(&h, "/%'g/\n", 4213455.8392);
2054 printf("/%'g/\n", 4213455.8392);
2055 printf("%s", holder);