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 (could use isinf(), isnan())
52 * `C', `S' conversions
53 * support for `F' is imperfect, since underlying printf may not handle it
56 #define FLOATING_POINT
62 #if defined(DRIVER) && !defined(HAVE_CONFIG_H)
63 #define HAVE_LONG_LONG
64 #define HAVE_LONG_DOUBLE
66 #define HAVE_PRINTF_A_FORMAT
69 #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 <stdio.h> /* for sprintf */
109 # define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
110 # define FL_ADDBASE 0x02 /* add base# prefix to converted value */
111 # define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
112 # define FL_UNSIGNED 0x08 /* don't add any sign */
113 extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
114 extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
117 /* Bound on length of the string representing an integer value of type T.
118 Subtract one for the sign bit if T is signed;
119 302 / 1000 is log10 (2) rounded up;
120 add one for integer division truncation;
121 add one more for a minus sign if t is signed. */
122 #define INT_STRLEN_BOUND(t) \
123 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
124 + 1 + TYPE_SIGNED (t))
126 /* conversion flags */
127 #define PF_ALTFORM 0x00001 /* # */
128 #define PF_HEXPREFIX 0x00002 /* 0[Xx] */
129 #define PF_LADJUST 0x00004 /* - */
130 #define PF_ZEROPAD 0x00008 /* 0 */
131 #define PF_PLUS 0x00010 /* + */
132 #define PF_SPACE 0x00020 /* ' ' */
133 #define PF_COMMA 0x00040 /* , */
135 #define PF_DOT 0x00080 /* `.precision' */
136 #define PF_STAR_P 0x00100 /* `*' after precision */
137 #define PF_STAR_W 0x00200 /* `*' before or without precision */
139 /* length modifiers */
140 #define PF_SIGNEDCHAR 0x00400 /* hh */
141 #define PF_SHORTINT 0x00800 /* h */
142 #define PF_LONGINT 0x01000 /* l */
143 #define PF_LONGLONG 0x02000 /* ll */
144 #define PF_LONGDBL 0x04000 /* L */
145 #define PF_INTMAX_T 0x08000 /* j */
146 #define PF_SIZE_T 0x10000 /* z */
147 #define PF_PTRDIFF_T 0x20000 /* t */
149 #define PF_ALLOCBUF 0x40000 /* for asprintf, vasprintf */
151 #define PFM_SN 0x01 /* snprintf, vsnprintf */
152 #define PFM_AS 0x02 /* asprintf, vasprintf */
154 #define ASBUFSIZE 128
156 #define x_digs "0123456789abcdef"
157 #define X_digs "0123456789ABCDEF"
159 static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];
162 * For the FLOATING POINT FORMAT :
163 * the challenge was finding a way to
164 * manipulate the Real numbers without having
165 * to resort to mathematical function(it
166 * would require to link with -lm) and not
167 * going down to the bit pattern(not portable)
169 * so a number, a real is:
171 real = integral + fraction
173 integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
174 fraction = b(1)*10^-1 + b(2)*10^-2 + ...
180 from then it was simple math
184 * size of the buffer for the integral part
185 * and the fraction part
187 #define MAX_INT 99 + 1 /* 1 for the null */
188 #define MAX_FRACT 307 + 1
191 * These functions use static buffers to store the results,
192 * and so are not reentrant
194 #define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0);
195 #define dtoa(n, p, f) numtoa(n, 10, p, f)
197 #define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
199 /* Macros that do proper sign extension and handle length modifiers. Used
200 for the integer conversion specifiers. */
201 #define GETSIGNED(p) \
202 (((p)->flags & PF_LONGINT) \
203 ? va_arg(args, long) \
204 : (((p)->flags & PF_SHORTINT) ? (long)(short)va_arg(args, int) \
205 : (long)va_arg(args, int)))
207 #define GETUNSIGNED(p) \
208 (((p)->flags & PF_LONGINT) \
209 ? va_arg(args, unsigned long) \
210 : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)va_arg(args, int) \
211 : (unsigned long)va_arg(args, unsigned int)))
214 #ifdef HAVE_LONG_DOUBLE
215 #define GETLDOUBLE(p) va_arg(args, long double)
217 #define GETDOUBLE(p) va_arg(args, double)
219 #define SET_SIZE_FLAGS(p, type) \
220 if (sizeof (type) > sizeof (int)) \
221 (p)->flags |= PF_LONGINT; \
222 if (sizeof (type) > sizeof (long)) \
223 (p)->flags |= PF_LONGLONG;
225 /* this struct holds everything we need */
229 char *base; /* needed for [v]asprintf */
237 int width, precision;
241 /* the floating point stuff */
242 #ifdef FLOATING_POINT
243 static double pow_10 __P((int));
244 static int log_10 __P((double));
245 static double integral __P((double, double *));
246 static char *numtoa __P((double, int, int, char **));
249 static void init_data __P((struct DATA *, char *, size_t, const char *, int));
250 static void init_conv_flag __P((struct DATA *));
253 #ifdef FLOATING_POINT
254 static void floating __P((struct DATA *, double));
255 static void exponent __P((struct DATA *, double));
257 static void number __P((struct DATA *, unsigned long, int));
258 #ifdef HAVE_LONG_LONG
259 static void lnumber __P((struct DATA *, unsigned long long, int));
261 static void pointer __P((struct DATA *, unsigned long));
262 static void strings __P((struct DATA *, char *));
264 #ifdef FLOATING_POINT
265 # define FALLBACK_FMTSIZE 32
266 # define FALLBACK_BASE 4096
267 # define LFALLBACK_BASE 5120
268 # ifdef HAVE_LONG_DOUBLE
269 static void ldfallback __P((struct DATA *, const char *, const char *, long double));
271 static void dfallback __P((struct DATA *, const char *, const char *, double));
275 static void memory_error_and_abort ();
276 static void *xmalloc __P((size_t));
277 static void *xrealloc __P((void *, size_t));
278 static void xfree __P((void *));
280 # include <xmalloc.h>
283 /* those are defines specific to snprintf to hopefully
284 * make the code clearer :-)
292 /* round off to the precision */
293 #define ROUND(d, p) \
295 d - pow_10(-(p)->precision) * 0.5 : \
296 d + pow_10(-(p)->precision) * 0.5
298 /* set default precision */
299 #define DEF_PREC(p) \
300 if ((p)->precision == NOT_FOUND) \
303 /* put a char. increment the number of chars written even if we've exceeded
304 the vsnprintf/snprintf buffer size (for the return value) */
305 #define PUT_CHAR(c, p) \
308 if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \
310 (p)->length += ASBUFSIZE; \
311 (p)->base = (char *)xrealloc((p)->base, (p)->length); \
312 (p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \
314 if ((p)->counter < (p)->length) \
315 *(p)->holder++ = (c); \
320 #define PUT_PLUS(d, p, zero) \
321 if ((d) > zero && (p)->justify == RIGHT) \
324 #define PUT_SPACE(d, p, zero) \
325 if (((p)->flags & PF_SPACE) && (d) > zero) \
329 #define PAD_RIGHT(p) \
330 if ((p)->width > 0 && (p)->justify != LEFT) \
331 for (; (p)->width > 0; (p)->width--) \
332 PUT_CHAR((p)->pad, p)
335 #define PAD_LEFT(p) \
336 if ((p)->width > 0 && (p)->justify == LEFT) \
337 for (; (p)->width > 0; (p)->width--) \
338 PUT_CHAR((p)->pad, p)
340 /* if width and prec. in the args */
341 #define STAR_ARGS(p) \
342 if ((p)->flags & PF_STAR_W) \
343 (p)->width = va_arg(args, int); \
344 if ((p)->flags & PF_STAR_P) \
345 (p)->precision = va_arg(args, int)
347 #ifdef FLOATING_POINT
349 * Find the nth power of 10
357 /* handle common cases with fast switch statement. */
360 case -3: return .001;
366 case 3: return 1000.;
372 for (n += 4; n < 0; n++)
378 for (n -= 4; n > 0; n--)
386 * Find the integral part of the log in base 10
387 * Note: this not a real log10()
388 I just need and approximation(integerpart) of x in:
424 * This function return the fraction part of a double
425 * and set in ip the integral part.
426 * In many ways it resemble the modf() found on most Un*x
435 double real_integral = 0.;
437 /* take care of the obvious */
438 /* equal to zero ? */
445 /* negative number ? */
456 /* the real work :-) */
457 for (j = log_10(real); j >= 0; j--)
460 s = (real - real_integral)/p;
464 real_integral += i*p;
467 return (real - real_integral);
470 #define PRECISION 1.e-6
472 * return an ascii representation of the integral part of the number
473 * and set fract to be an ascii representation of the fraction part
474 * the container for the fraction and the integral part or staticly
475 * declare with fix size
478 numtoa(number, base, precision, fract)
484 double ip, fp; /* integer and fraction part */
486 int digits = MAX_INT - 1;
487 static char integral_part[MAX_INT];
488 static char fraction_part[MAX_FRACT];
492 /* taking care of the obvious case: 0.0 */
495 integral_part[0] = '0';
496 integral_part[1] = '\0';
497 fraction_part[0] = '0';
498 fraction_part[1] = '\0';
499 return integral_part;
502 /* for negative numbers */
503 if ((sign = number) < 0.)
506 digits--; /* sign consume one digit */
509 fraction = integral(number, &ip);
512 /* do the integral part */
515 integral_part[0] = '0';
520 for ( i = 0; i < digits && number != 0.; ++i)
523 fp = integral(number, &ip);
524 ch = (int)((fp + PRECISION)*base); /* force to round */
525 integral_part[i] = (ch <= 9) ? ch + '0' : ch + 'a' - 10;
526 if (! ISXDIGIT((unsigned char)integral_part[i]))
527 break; /* bail out overflow !! */
532 /* Oh No !! out of bound, ho well fill it up ! */
534 for (i = 0; i < digits; ++i)
535 integral_part[i] = '9';
539 integral_part[i++] = '-';
541 integral_part[i] = '\0';
543 /* reverse every thing */
544 for ( i--, j = 0; j < i; j++, i--)
545 SWAP_INT(integral_part[i], integral_part[j]);
547 /* the fractional part */
548 for (i=0, fp=fraction; precision > 0 && i < MAX_FRACT ; i++, precision--)
550 fraction_part[i] = (int)((fp + PRECISION)*10. + '0');
551 if (! DIGIT(fraction_part[i])) /* underflow ? */
553 fp = (fp*10.0) - (double)(long)((fp + PRECISION)*10.);
555 fraction_part[i] = '\0';
557 if (fract != (char **)0)
558 *fract = fraction_part;
560 return integral_part;
564 /* for %d and friends, it puts in holder
565 * the representation with the right padding
577 sd = d; /* signed for ' ' padding in base 10 */
578 flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
580 flags |= FL_HEXUPPER;
582 tmp = fmtulong (d, base, intbuf, sizeof(intbuf), flags);
583 p->width -= strlen(tmp);
593 if (p->flags & PF_ALTFORM)
597 if (p->flags & PF_ALTFORM)
614 #ifdef HAVE_LONG_LONG
616 * identical to number() but works for `long long'
621 unsigned long long d;
628 sd = d; /* signed for ' ' padding in base 10 */
629 flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0;
631 flags |= FL_HEXUPPER;
633 tmp = fmtullong (d, base, intbuf, sizeof(intbuf), flags);
634 p->width -= strlen(tmp);
644 if (p->flags & PF_ALTFORM)
648 if (p->flags & PF_ALTFORM)
673 tmp = fmtulong(d, 16, intbuf, sizeof(intbuf), 0);
674 p->width -= strlen(tmp);
677 /* prefix '0x' for pointers */
698 if (p->precision != NOT_FOUND) /* the smallest number */
699 i = (i < p->precision ? i : p->precision);
703 { /* put the sting */
710 #ifdef FLOATING_POINT
711 /* %f %F %g %G floating point representation */
722 tmp = dtoa(d, p->precision, &tmp2);
723 /* calculate the padding. 1 for the dot */
724 p->width = p->width -
725 ((d > 0. && p->justify == RIGHT) ? 1:0) -
726 ((p->flags & PF_SPACE) ? 1:0) -
727 strlen(tmp) - p->precision - 1;
736 if (p->precision != 0 || (p->flags & PF_ALTFORM))
737 PUT_CHAR('.', p); /* put the '.' */
738 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
739 /* smash the trailing zeros unless altform */
740 for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
742 for (; *tmp2; tmp2++)
743 PUT_CHAR(*tmp2, p); /* the fraction */
748 /* %e %E %g %G exponent representation */
755 int j, i, nsig, ndig;
759 d = d / pow_10(j); /* get the Mantissa */
761 tmp = dtoa(d, p->precision, &tmp2);
762 /* 1 for unit, 1 for the '.', 1 for 'e|E',
763 * 1 for '+|-', 2 for 'exp' */
764 /* calculate how much padding need */
765 p->width = p->width -
766 ((d > 0. && p->justify == RIGHT) ? 1:0) -
767 ((p->flags & PF_SPACE) ? 1:0) - p->precision - 6;
772 * When supplied %g or %G, an optional precision is the number of
773 * significant digits to print.
775 * nsig = number of significant digits we've printed (leading zeros are
777 * ndig = if non-zero, max number of significant digits to print (only
778 * applicable to %g/%G)
781 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_DOT))
782 ndig = (p->precision == 0) ? 1 : p->precision;
788 if (ndig && (++nsig >= ndig))
792 if ((p->precision != 0 || (p->flags & PF_ALTFORM)) && (ndig == 0 || nsig < ndig))
793 PUT_CHAR('.', p); /* the '.' */
794 if ((*p->pf == 'g' || *p->pf == 'G') && (p->flags & PF_ALTFORM) == 0)
795 /* smash the trailing zeros unless altform */
796 for (i = strlen(tmp2) - 1; i >= 0 && tmp2[i] == '0'; i--)
798 for (; *tmp2; tmp2++)
800 if (ndig && (nsig++ >= ndig))
802 PUT_CHAR(*tmp2, p); /* the fraction */
805 /* the exponent put the 'e|E' */
806 if (*p->pf == 'g' || *p->pf == 'e')
813 /* the sign of the exp */
825 /* pad out to at least two spaces. pad with `0' if the exponent is a
842 /* initialize the conversion specifiers */
847 p->flags &= PF_ALLOCBUF; /* preserve PF_ALLOCBUF flag */
848 p->precision = p->width = NOT_FOUND;
849 p->justify = NOT_FOUND;
854 init_data (p, string, length, format, mode)
861 p->length = length - 1; /* leave room for '\0' */
862 p->holder = p->base = string;
865 p->flags = (mode == PFM_AS) ? PF_ALLOCBUF : 0;
869 #if defined (__STDC__)
870 vsnprintf_internal(struct DATA *data, char *string, size_t length, const char *format, va_list args)
872 vsnprintf_internal(data, string, length, format, args)
880 double d; /* temporary holder */
881 #ifdef HAVE_LONG_DOUBLE
882 long double ld; /* for later */
885 #ifdef HAVE_LONG_LONG
886 unsigned long long ull;
890 const char *convstart;
892 /* Sanity check, the string must be > 1. C99 actually says that LENGTH
893 can be zero here, in the case of snprintf/vsnprintf (it's never 0 in
894 the case of asprintf/vasprintf), and the return value is the number
895 of characters that would have been written. */
902 for (; c = *(data->pf); data->pf++)
910 convstart = data->pf;
911 init_conv_flag (data); /* initialise format flags */
914 for (state = 1; state && *data->pf; )
917 /* fmtend = data->pf */
918 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
919 if (data->flags & PF_LONGDBL)
926 # ifdef HAVE_PRINTF_A_FORMAT
930 ld = GETLDOUBLE (data);
931 ldfallback (data, convstart, data->pf, ld);
935 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
939 /* Parse format flags */
940 case '\0': /* a NULL here ? ? bail out */
941 *data->holder = '\0';
942 return data->counter;
945 data->flags |= PF_ALTFORM;
948 data->flags |= PF_ZEROPAD;
952 if (data->flags & PF_DOT)
953 data->flags |= PF_STAR_P;
955 data->flags |= PF_STAR_W;
958 data->flags |= PF_LADJUST;
959 data->justify = LEFT;
962 if ((data->flags & PF_PLUS) == 0)
963 data->flags |= PF_SPACE;
966 data->flags |= PF_PLUS;
967 data->justify = RIGHT;
970 data->flags |= PF_COMMA; /* not implemented yet */
973 case '1': case '2': case '3':
974 case '4': case '5': case '6':
975 case '7': case '8': case '9':
979 n = n * 10 + TODIGIT(c);
983 data->pf--; /* went too far */
986 if (data->flags & PF_DOT)
992 /* optional precision */
994 data->flags |= PF_DOT;
998 /* length modifiers */
1000 data->flags |= (data->flags & PF_SHORTINT) ? PF_SIGNEDCHAR : PF_SHORTINT;
1003 data->flags |= (data->flags & PF_LONGINT) ? PF_LONGLONG : PF_LONGINT;
1006 data->flags |= PF_LONGDBL;
1009 data->flags |= PF_LONGLONG;
1012 data->flags |= PF_INTMAX_T;
1013 SET_SIZE_FLAGS(data, intmax_t);
1016 data->flags |= PF_SIZE_T;
1017 SET_SIZE_FLAGS(data, size_t);
1020 data->flags |= PF_PTRDIFF_T;
1021 SET_SIZE_FLAGS(data, ptrdiff_t);
1024 /* Conversion specifiers */
1025 #ifdef FLOATING_POINT
1026 case 'f': /* float, double */
1029 d = GETDOUBLE(data);
1038 d = GETDOUBLE(data);
1041 * for '%g|%G' ANSI: use f if exponent
1042 * is in the range or [-4,p] exclusively
1045 if (-4 < i && i < data->precision)
1052 case 'E': /* Exponent double */
1054 d = GETDOUBLE(data);
1058 # ifdef HAVE_PRINTF_A_FORMAT
1062 d = GETDOUBLE(data);
1063 dfallback(data, convstart, data->pf, d);
1066 # endif /* HAVE_PRINTF_A_FORMAT */
1067 #endif /* FLOATING_POINT */
1069 data->flags |= PF_LONGINT;
1073 #ifdef HAVE_LONG_LONG
1074 if (data->flags & PF_LONGLONG)
1076 ull = va_arg(args, unsigned long long);
1077 lnumber(data, ull, 10);
1082 ul = GETUNSIGNED(data);
1083 number(data, ul, 10);
1088 data->flags |= PF_LONGINT;
1090 case 'd': /* decimal */
1093 #ifdef HAVE_LONG_LONG
1094 if (data->flags & PF_LONGLONG)
1096 ull = va_arg(args, long long);
1097 lnumber(data, ull, 10);
1102 ul = GETSIGNED(data);
1103 number(data, ul, 10);
1107 case 'o': /* octal */
1109 #ifdef HAVE_LONG_LONG
1110 if (data->flags & PF_LONGLONG)
1112 ull = va_arg(args, unsigned long long);
1113 lnumber(data, ull, 8);
1118 ul = GETUNSIGNED(data);
1119 number(data, ul, 8);
1124 case 'X': /* hexadecimal */
1126 #ifdef HAVE_LONG_LONG
1127 if (data->flags & PF_LONGLONG)
1129 ull = va_arg(args, unsigned long long);
1130 lnumber(data, ull, 16);
1135 ul = GETUNSIGNED(data);
1136 number(data, ul, 16);
1142 ul = (unsigned long)va_arg(args, void *);
1146 case 'c': /* character */
1147 ul = va_arg(args, int);
1151 case 's': /* string */
1153 s = va_arg(args, char *);
1158 #ifdef HAVE_LONG_LONG
1159 if (data->flags & PF_LONGLONG)
1160 *(va_arg(args, long long *)) = data->counter;
1163 if (data->flags & PF_LONGINT)
1164 *(va_arg(args, long *)) = data->counter;
1165 else if (data->flags & PF_SHORTINT)
1166 *(va_arg(args, short *)) = data->counter;
1168 *(va_arg(args, int *)) = data->counter;
1171 case '%': /* nothing just % */
1172 PUT_CHAR('%', data);
1176 /* is this an error ? maybe bail out */
1180 } /* end of `%' for loop */
1181 } /* end of format string for loop */
1183 if (data->length >= 0)
1184 *data->holder = '\0'; /* the end ye ! */
1186 return data->counter;
1189 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1191 * Printing floating point numbers accurately is an art. I'm not good
1192 * at it. Fall back to sprintf for long double formats.
1195 ldfallback (data, fs, fe, ld)
1197 const char *fs, *fe;
1201 char fmtbuf[FALLBACK_FMTSIZE], *obuf;
1204 obuf = xmalloc(LFALLBACK_BASE + (data->precision < 6 ? 6 : data->precision) + 2);
1206 strncpy (fmtbuf, fs, fl);
1208 sprintf (obuf, fmtbuf, ld);
1209 for (x = obuf; *x; x++)
1210 PUT_CHAR (*x, data);
1213 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1215 #ifdef FLOATING_POINT
1216 /* Used for %a, %A if the libc printf supports them. */
1218 dfallback (data, fs, fe, d)
1220 const char *fs, *fe;
1224 char fmtbuf[FALLBACK_FMTSIZE], obuf[FALLBACK_BASE];
1228 strncpy (fmtbuf, fs, fl);
1230 sprintf (obuf, fmtbuf, d);
1231 for (x = obuf; *x; x++)
1232 PUT_CHAR (*x, data);
1234 #endif /* FLOATING_POINT */
1236 #ifndef HAVE_SNPRINTF
1239 #if defined (__STDC__)
1240 vsnprintf(char *string, size_t length, const char *format, va_list args)
1242 vsnprintf(string, length, format, args)
1251 init_data (&data, string, length, format, PFM_SN);
1252 return (vsnprintf_internal(&data, string, length, format, args));
1256 #if defined(PREFER_STDARG)
1257 snprintf(char *string, size_t length, const char * format, ...)
1259 snprintf(string, length, format, va_alist)
1270 #if defined(PREFER_STDARG)
1271 va_start(args, format);
1276 init_data (&data, string, length, format, PFM_SN);
1277 rval = vsnprintf_internal (&data, string, length, format, args);
1284 #endif /* HAVE_SNPRINTF */
1286 #ifndef HAVE_ASPRINTF
1289 #if defined (__STDC__)
1290 vasprintf(char **stringp, const char *format, va_list args)
1292 vasprintf(stringp, format, args)
1302 string = (char *)xmalloc(ASBUFSIZE);
1303 init_data (&data, string, ASBUFSIZE, format, PFM_AS);
1304 r = vsnprintf_internal(&data, string, ASBUFSIZE, format, args);
1305 *stringp = data.base; /* not string in case reallocated */
1310 #if defined(PREFER_STDARG)
1311 asprintf(char **stringp, const char * format, ...)
1313 asprintf(stringp, format, va_alist)
1322 #if defined(PREFER_STDARG)
1323 va_start(args, format);
1328 rval = vasprintf (stringp, format, args);
1342 memory_error_and_abort ()
1344 write (2, "out of virtual memory\n", 22);
1354 ret = malloc(bytes);
1356 memory_error_and_abort ();
1361 xrealloc (pointer, bytes)
1367 ret = pointer ? realloc(pointer, bytes) : malloc(bytes);
1369 memory_error_and_abort ();
1381 #ifdef FLOATING_POINT
1385 /* set of small tests for snprintf() */
1393 printf("Suite of test for snprintf:\n");
1394 printf("a_format\n");
1395 printf("printf() format\n");
1396 printf("snprintf() format\n\n");
1398 /* Checking the field widths */
1400 printf("/%%ld %%ld/, 336, 336\n");
1401 snprintf(holder, sizeof holder, "/%ld %ld/\n", 336, 336);
1402 asprintf(&h, "/%ld %ld/\n", 336, 336);
1403 printf("/%ld %ld/\n", 336, 336);
1404 printf("%s", holder);
1407 printf("/%%d/, 336\n");
1408 snprintf(holder, sizeof holder, "/%d/\n", 336);
1409 asprintf(&h, "/%d/\n", 336);
1410 printf("/%d/\n", 336);
1411 printf("%s", holder);
1414 printf("/%%2d/, 336\n");
1415 snprintf(holder, sizeof holder, "/%2d/\n", 336);
1416 asprintf(&h, "/%2d/\n", 336);
1417 printf("/%2d/\n", 336);
1418 printf("%s", holder);
1421 printf("/%%10d/, 336\n");
1422 snprintf(holder, sizeof holder, "/%10d/\n", 336);
1423 asprintf(&h, "/%10d/\n", 336);
1424 printf("/%10d/\n", 336);
1425 printf("%s", holder);
1428 printf("/%%-10d/, 336\n");
1429 snprintf(holder, sizeof holder, "/%-10d/\n", 336);
1430 asprintf(&h, "/%-10d/\n", 336);
1431 printf("/%-10d/\n", 336);
1432 printf("%s", holder);
1436 /* floating points */
1438 printf("/%%f/, 1234.56\n");
1439 snprintf(holder, sizeof holder, "/%f/\n", 1234.56);
1440 asprintf(&h, "/%f/\n", 1234.56);
1441 printf("/%f/\n", 1234.56);
1442 printf("%s", holder);
1445 printf("/%%e/, 1234.56\n");
1446 snprintf(holder, sizeof holder, "/%e/\n", 1234.56);
1447 asprintf(&h, "/%e/\n", 1234.56);
1448 printf("/%e/\n", 1234.56);
1449 printf("%s", holder);
1452 printf("/%%4.2f/, 1234.56\n");
1453 snprintf(holder, sizeof holder, "/%4.2f/\n", 1234.56);
1454 asprintf(&h, "/%4.2f/\n", 1234.56);
1455 printf("/%4.2f/\n", 1234.56);
1456 printf("%s", holder);
1459 printf("/%%3.1f/, 1234.56\n");
1460 snprintf(holder, sizeof holder, "/%3.1f/\n", 1234.56);
1461 asprintf(&h, "/%3.1f/\n", 1234.56);
1462 printf("/%3.1f/\n", 1234.56);
1463 printf("%s", holder);
1466 printf("/%%10.3f/, 1234.56\n");
1467 snprintf(holder, sizeof holder, "/%10.3f/\n", 1234.56);
1468 asprintf(&h, "/%10.3f/\n", 1234.56);
1469 printf("/%10.3f/\n", 1234.56);
1470 printf("%s", holder);
1473 printf("/%%10.3e/, 1234.56\n");
1474 snprintf(holder, sizeof holder, "/%10.3e/\n", 1234.56);
1475 asprintf(&h, "/%10.3e/\n", 1234.56);
1476 printf("/%10.3e/\n", 1234.56);
1477 printf("%s", holder);
1480 printf("/%%+4.2f/, 1234.56\n");
1481 snprintf(holder, sizeof holder, "/%+4.2f/\n", 1234.56);
1482 asprintf(&h, "/%+4.2f/\n", 1234.56);
1483 printf("/%+4.2f/\n", 1234.56);
1484 printf("%s", holder);
1487 printf("/%%010.2f/, 1234.56\n");
1488 snprintf(holder, sizeof holder, "/%010.2f/\n", 1234.56);
1489 asprintf(&h, "/%010.2f/\n", 1234.56);
1490 printf("/%010.2f/\n", 1234.56);
1491 printf("%s", holder);
1494 #define BLURB "Outstanding acting !"
1495 /* strings precisions */
1497 printf("/%%2s/, \"%s\"\n", BLURB);
1498 snprintf(holder, sizeof holder, "/%2s/\n", BLURB);
1499 asprintf(&h, "/%2s/\n", BLURB);
1500 printf("/%2s/\n", BLURB);
1501 printf("%s", holder);
1504 printf("/%%22s/ %s\n", BLURB);
1505 snprintf(holder, sizeof holder, "/%22s/\n", BLURB);
1506 asprintf(&h, "/%22s/\n", BLURB);
1507 printf("/%22s/\n", BLURB);
1508 printf("%s", holder);
1511 printf("/%%22.5s/ %s\n", BLURB);
1512 snprintf(holder, sizeof holder, "/%22.5s/\n", BLURB);
1513 asprintf(&h, "/%22.5s/\n", BLURB);
1514 printf("/%22.5s/\n", BLURB);
1515 printf("%s", holder);
1518 printf("/%%-22.5s/ %s\n", BLURB);
1519 snprintf(holder, sizeof holder, "/%-22.5s/\n", BLURB);
1520 asprintf(&h, "/%-22.5s/\n", BLURB);
1521 printf("/%-22.5s/\n", BLURB);
1522 printf("%s", holder);
1525 /* see some flags */
1527 printf("%%x %%X %%#x, 31, 31, 31\n");
1528 snprintf(holder, sizeof holder, "%x %X %#x\n", 31, 31, 31);
1529 asprintf(&h, "%x %X %#x\n", 31, 31, 31);
1530 printf("%x %X %#x\n", 31, 31, 31);
1531 printf("%s", holder);
1534 printf("**%%d**%% d**%% d**, 42, 42, -42\n");
1535 snprintf(holder, sizeof holder, "**%d**% d**% d**\n", 42, 42, -42);
1536 asprintf(&h, "**%d**% d**% d**\n", 42, 42, -42);
1537 printf("**%d**% d**% d**\n", 42, 42, -42);
1538 printf("%s", holder);
1543 printf("/%%g/, 31.4\n");
1544 snprintf(holder, sizeof holder, "/%g/\n", 31.4);
1545 asprintf(&h, "/%g/\n", 31.4);
1546 printf("/%g/\n", 31.4);
1547 printf("%s", holder);
1550 printf("/%%.6g/, 31.4\n");
1551 snprintf(holder, sizeof holder, "/%.6g/\n", 31.4);
1552 asprintf(&h, "/%.6g/\n", 31.4);
1553 printf("/%.6g/\n", 31.4);
1554 printf("%s", holder);
1557 printf("/%%.1G/, 31.4\n");
1558 snprintf(holder, sizeof holder, "/%.1G/\n", 31.4);
1559 asprintf(&h, "/%.1G/\n", 31.4);
1560 printf("/%.1G/\n", 31.4);
1561 printf("%s", holder);
1564 printf("/%%.1G/, 3100000000.4\n");
1565 snprintf(holder, sizeof holder, "/%.1G/\n", 3100000000.4);
1566 asprintf(&h, "/%.1G/\n", 3100000000.4);
1567 printf("/%.1G/\n", 3100000000.4);
1568 printf("%s", holder);
1572 printf("abc%n", &i); printf("%d\n", i);
1573 snprintf(holder, sizeof holder, "abc%n", &i);
1574 printf("%s", holder); printf("%d\n\n", i);
1575 asprintf(&h, "abc%n", &i);
1576 printf("%s", h); printf("%d\n\n", i);
1578 printf("%%*.*s --> 10.10\n");
1579 snprintf(holder, sizeof holder, "%*.*s\n", 10, 10, BLURB);
1580 asprintf(&h, "%*.*s\n", 10, 10, BLURB);
1581 printf("%*.*s\n", 10, 10, BLURB);
1582 printf("%s", holder);
1585 printf("%%%%%%%%\n");
1586 snprintf(holder, sizeof holder, "%%%%\n");
1587 asprintf(&h, "%%%%\n");
1589 printf("%s", holder);
1592 #define BIG "Hello this is a too big string for the buffer"
1593 /* printf("A buffer to small of 10, trying to put this:\n");*/
1594 printf("<%%>, %s\n", BIG);
1595 i = snprintf(holder, 10, "%s\n", BIG);
1596 i = asprintf(&h, "%s", BIG);
1597 printf("<%s>\n", BIG);
1598 printf("<%s>\n", holder);
1599 printf("<%s>\n\n", h);
1601 printf ("<%%p> vsnprintf\n");
1602 i = snprintf(holder, 100, "%p", vsnprintf);
1603 i = asprintf(&h, "%p", vsnprintf);
1604 printf("<%p>\n", vsnprintf);
1605 printf("<%s>\n", holder);
1606 printf("<%s>\n\n", h);
1608 printf ("<%%lu> LONG_MAX+1\n");
1609 i = snprintf(holder, 100, "%lu", (unsigned long)(LONG_MAX)+1);
1610 i = asprintf(&h, "%lu", (unsigned long)(LONG_MAX)+1);
1611 printf("<%lu>\n", (unsigned long)(LONG_MAX)+1);
1612 printf("<%s>\n", holder);
1613 printf("<%s>\n\n", h);
1615 #ifdef HAVE_LONG_LONG
1616 printf ("<%%llu> LLONG_MAX+1\n");
1617 i = snprintf(holder, 100, "%llu", (unsigned long long)(LLONG_MAX)+1);
1618 i = asprintf(&h, "%llu", (unsigned long long)(LLONG_MAX)+1);
1619 printf("<%llu>\n", (unsigned long long)(LLONG_MAX)+1);
1620 printf("<%s>\n", holder);
1621 printf("<%s>\n\n", h);
1624 #ifdef HAVE_LONG_DOUBLE
1625 printf ("<%%6.2LE> 42.42\n");
1626 i = snprintf(holder, 100, "%6.2LE", (long double)42.42);
1627 i = asprintf(&h, "%6.2LE", (long double)42.42);
1628 printf ("<%6.2LE>\n", (long double)42.42);
1629 printf ("<%s>\n", holder);
1630 printf ("<%s>\n\n", h);
1633 #ifdef HAVE_PRINTF_A_FORMAT
1634 printf ("<%%6.2A> 42.42\n");
1635 i = snprintf(holder, 100, "%6.2A", 42.42);
1636 i = asprintf(&h, "%6.2A", 42.42);
1637 printf ("<%6.2A>\n", 42.42);
1638 printf ("<%s>\n", holder);
1639 printf ("<%s>\n\n", h);
1641 printf ("<%%6.2LA> 42.42\n");
1642 i = snprintf(holder, 100, "%6.2LA", (long double)42.42);
1643 i = asprintf(&h, "%6.2LA", (long double)42.42);
1644 printf ("<%6.2LA>\n", (long double)42.42);
1645 printf ("<%s>\n", holder);
1646 printf ("<%s>\n\n", h);
1649 printf ("<%%.10240f> DBL_MAX\n");
1650 si = snprintf(holder, 100, "%.10240f", DBL_MAX);
1651 ai = asprintf(&h, "%.10240f", DBL_MAX);
1652 printf ("<%.10240f>\n", DBL_MAX);
1653 printf ("<%d> <%s>\n", si, holder);
1654 printf ("<%d> <%s>\n\n", ai, h);
1656 printf ("<%%.10240Lf> LDBL_MAX\n");
1657 si = snprintf(holder, 100, "%.10240Lf", (long double)LDBL_MAX);
1658 ai = asprintf(&h, "%.10240Lf", (long double)LDBL_MAX);
1659 printf ("<%.10240Lf>\n", (long double)LDBL_MAX);
1660 printf ("<%d> <%s>\n", si, holder);
1661 printf ("<%d> <%s>\n\n", ai, h);