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-2020 Free Software Foundation, Inc.
14 This file is part of GNU Bush, the Bourne Again SHell.
16 Bush 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 Bush 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 Bush. If not, see <http://www.gnu.org/licenses/>.
29 Original (pre-bush) 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 bush/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 <bushtypes.h>
92 #if defined(PREFER_STDARG)
101 #include <bushansi.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
PARAMS((unsigned long int, int, char *, size_t, int));
133 extern char *fmtullong
PARAMS((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 #ifndef INT_STRLEN_BOUND
146 #define INT_STRLEN_BOUND(t) \
147 ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
148 + 1 + TYPE_SIGNED (t))
151 /* conversion flags */
152 #define PF_ALTFORM 0x00001 /* # */
153 #define PF_HEXPREFIX 0x00002 /* 0[Xx] */
154 #define PF_LADJUST 0x00004 /* - */
155 #define PF_ZEROPAD 0x00008 /* 0 */
156 #define PF_PLUS 0x00010 /* + */
157 #define PF_SPACE 0x00020 /* ' ' */
158 #define PF_THOUSANDS 0x00040 /* ' */
160 #define PF_DOT 0x00080 /* `.precision' */
161 #define PF_STAR_P 0x00100 /* `*' after precision */
162 #define PF_STAR_W 0x00200 /* `*' before or without precision */
164 /* length modifiers */
165 #define PF_SIGNEDCHAR 0x00400 /* hh */
166 #define PF_SHORTINT 0x00800 /* h */
167 #define PF_LONGINT 0x01000 /* l */
168 #define PF_LONGLONG 0x02000 /* ll */
169 #define PF_LONGDBL 0x04000 /* L */
170 #define PF_INTMAX_T 0x08000 /* j */
171 #define PF_SIZE_T 0x10000 /* z */
172 #define PF_PTRDIFF_T 0x20000 /* t */
174 #define PF_ALLOCBUF 0x40000 /* for asprintf, vasprintf */
176 #define PFM_SN 0x01 /* snprintf, vsnprintf */
177 #define PFM_AS 0x02 /* asprintf, vasprintf */
179 #define ASBUFSIZE 128
181 #define x_digs "0123456789abcdef"
182 #define X_digs "0123456789ABCDEF"
184 static char intbuf
[INT_STRLEN_BOUND(unsigned long) + 1];
188 static char *grouping
;
191 * For the FLOATING POINT FORMAT :
192 * the challenge was finding a way to
193 * manipulate the Real numbers without having
194 * to resort to mathematical function(it
195 * would require to link with -lm) and not
196 * going down to the bit pattern(not portable)
198 * so a number, a real is:
200 real = integral + fraction
202 integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0
203 fraction = b(1)*10^-1 + b(2)*10^-2 + ...
209 from then it was simple math
213 * size of the buffer for the integral part
214 * and the fraction part
216 #define MAX_INT 99 + 1 /* 1 for the null */
217 #define MAX_FRACT 307 + 1
220 * These functions use static buffers to store the results,
221 * and so are not reentrant
223 #define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0);
224 #define dtoa(n, p, f) numtoa(n, 10, p, f)
226 #define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}
228 #define GETARG(type) (va_arg(args, type))
230 /* Macros that do proper sign extension and handle length modifiers. Used
231 for the integer conversion specifiers. */
232 #define GETSIGNED(p) \
233 (((p)->flags & PF_LONGINT) \
235 : (((p)->flags & PF_SHORTINT) ? (long)(short)GETARG (int) \
236 : (long)GETARG (int)))
238 #define GETUNSIGNED(p) \
239 (((p)->flags & PF_LONGINT) \
240 ? GETARG (unsigned long) \
241 : (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)GETARG (int) \
242 : (unsigned long)GETARG (unsigned int)))
245 #ifdef HAVE_LONG_DOUBLE
246 #define GETLDOUBLE(p) GETARG (long double)
248 #define GETDOUBLE(p) GETARG (double)
250 #define SET_SIZE_FLAGS(p, type) \
251 if (sizeof (type) > sizeof (int)) \
252 (p)->flags |= PF_LONGINT; \
253 if (sizeof (type) > sizeof (long)) \
254 (p)->flags |= PF_LONGLONG;
256 /* this struct holds everything we need */
260 char *base
; /* needed for [v]asprintf */
268 int width
, precision
;
272 /* the floating point stuff */
273 #ifdef FLOATING_POINT
274 static double pow_10
PARAMS((int));
275 static int log_10
PARAMS((double));
276 static double integral
PARAMS((double, double *));
277 static char *numtoa
PARAMS((double, int, int, char **));
280 static void init_data
PARAMS((struct DATA
*, char *, size_t, const char *, int));
281 static void init_conv_flag
PARAMS((struct DATA
*));
284 #ifdef FLOATING_POINT
285 static void floating
PARAMS((struct DATA
*, double));
286 static void exponent
PARAMS((struct DATA
*, double));
288 static void number
PARAMS((struct DATA
*, unsigned long, int));
289 #ifdef HAVE_LONG_LONG
290 static void lnumber
PARAMS((struct DATA
*, unsigned long long, int));
292 static void pointer
PARAMS((struct DATA
*, unsigned long));
293 static void strings
PARAMS((struct DATA
*, char *));
295 #ifdef FLOATING_POINT
296 # define FALLBACK_FMTSIZE 32
297 # define FALLBACK_BASE 4096
298 # define LFALLBACK_BASE 5120
299 # ifdef HAVE_LONG_DOUBLE
300 static void ldfallback
PARAMS((struct DATA
*, const char *, const char *, long double));
302 static void dfallback
PARAMS((struct DATA
*, const char *, const char *, double));
305 static char *groupnum
PARAMS((char *));
307 #if defined (HAVE_LONG_DOUBLE)
308 # define LONGDOUBLE long double
310 # define LONGDOUBLE double
314 static inline int isnan_f (float x
) { return x
!= x
; }
315 static inline int isnan_d (double x
) { return x
!= x
; }
316 static inline int isnan_ld (LONGDOUBLE x
) { return x
!= x
; }
318 (sizeof (x) == sizeof (LONGDOUBLE) ? isnan_ld (x) \
319 : sizeof (x) == sizeof (double) ? isnan_d (x) \
324 static inline int isinf_f (float x
) { return !isnan (x
) && isnan (x
- x
); }
325 static inline int isinf_d (double x
) { return !isnan (x
) && isnan (x
- x
); }
326 static inline int isinf_ld (LONGDOUBLE x
) { return !isnan (x
) && isnan (x
- x
); }
328 (sizeof (x) == sizeof (LONGDOUBLE) ? isinf_ld (x) \
329 : sizeof (x) == sizeof (double) ? isinf_d (x) \
334 static void memory_error_and_abort ();
335 static void *xmalloc
PARAMS((size_t));
336 static void *xrealloc
PARAMS((void *, size_t));
337 static void xfree
PARAMS((void *));
339 # include <xmalloc.h>
342 /* those are defines specific to snprintf to hopefully
343 * make the code clearer :-)
351 /* round off to the precision */
352 #define ROUND(d, p) \
354 d - pow_10(-(p)->precision) * 0.5 : \
355 d + pow_10(-(p)->precision) * 0.5
357 /* set default precision */
358 #define DEF_PREC(p) \
359 if ((p)->precision == NOT_FOUND) \
362 /* put a char. increment the number of chars written even if we've exceeded
363 the vsnprintf/snprintf buffer size (for the return value) */
364 #define PUT_CHAR(c, p) \
367 if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \
369 (p)->length += ASBUFSIZE; \
370 (p)->base = (char *)xrealloc((p)->base, (p)->length); \
371 (p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \
373 if ((p)->counter < (p)->length) \
374 *(p)->holder++ = (c); \
379 /* Output a string. P->WIDTH has already been adjusted for padding. */
380 #define PUT_STRING(string, len, p) \
384 while ((len)-- > 0) \
386 PUT_CHAR (*(string), (p)); \
393 #define PUT_PLUS(d, p, zero) \
394 if (((p)->flags & PF_PLUS) && (d) > zero) \
397 #define PUT_SPACE(d, p, zero) \
398 if (((p)->flags & PF_SPACE) && (d) > zero) \
402 #define PAD_RIGHT(p) \
403 if ((p)->width > 0 && (p)->justify != LEFT) \
404 for (; (p)->width > 0; (p)->width--) \
405 PUT_CHAR((p)->pad, p)
408 #define PAD_LEFT(p) \
409 if ((p)->width > 0 && (p)->justify == LEFT) \
410 for (; (p)->width > 0; (p)->width--) \
411 PUT_CHAR((p)->pad, p)
413 /* pad with zeros from decimal precision */
414 #define PAD_ZERO(p) \
415 if ((p)->precision > 0) \
416 for (; (p)->precision > 0; (p)->precision--) \
419 /* if width and prec. in the args */
420 #define STAR_ARGS(p) \
422 if ((p)->flags & PF_STAR_W) \
424 (p)->width = GETARG (int); \
425 if ((p)->width < 0) \
427 (p)->flags |= PF_LADJUST; \
428 (p)->justify = LEFT; \
429 (p)->width = -(p)->width; \
432 if ((p)->flags & PF_STAR_P) \
434 (p)->precision = GETARG (int); \
435 if ((p)->precision < 0) \
437 (p)->flags &= ~PF_STAR_P; \
438 (p)->precision = NOT_FOUND; \
443 #if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV)
444 # define GETLOCALEDATA(d, t, g) \
449 (d) = '.'; (t) = -1; (g) = 0; /* defaults */ \
453 if (lv->decimal_point && lv->decimal_point[0]) \
454 (d) = lv->decimal_point[0]; \
455 if (lv->thousands_sep && lv->thousands_sep[0]) \
456 (t) = lv->thousands_sep[0]; \
457 (g) = lv->grouping ? lv->grouping : ""; \
458 if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \
464 # define GETLOCALEDATA(d, t, g) \
465 ( (d) = '.', (t) = ',', g = "\003" )
468 #ifdef FLOATING_POINT
470 * Find the nth power of 10
478 /* handle common cases with fast switch statement. */
481 case -3: return .001;
487 case 3: return 1000.;
493 for (n
+= 4; n
< 0; n
++)
499 for (n
-= 4; n
> 0; n
--)
507 * Find the integral part of the log in base 10
508 * Note: this not a real log10()
509 I just need and approximation(integerpart) of x in:
514 * NOTE: do not call this with r == 0 -- an infinite loop results.
547 * This function return the fraction part of a double
548 * and set in ip the integral part.
549 * In many ways it resemble the modf() found on most Un*x
558 double real_integral
= 0.;
560 /* take care of the obvious */
561 /* equal to zero ? */
568 /* negative number ? */
579 /* the real work :-) */
580 for (j
= log_10(real
); j
>= 0; j
--)
583 s
= (real
- real_integral
)/p
;
587 real_integral
+= i
*p
;
590 return (real
- real_integral
);
593 #define PRECISION 1.e-6
595 * return an ascii representation of the integral part of the number
596 * and set fract to be an ascii representation of the fraction part
597 * the container for the fraction and the integral part or statically
598 * declare with fix size
601 numtoa(number
, base
, precision
, fract
)
607 double ip
, fp
; /* integer and fraction part */
610 static char integral_part
[MAX_INT
];
611 static char fraction_part
[MAX_FRACT
];
614 /* taking care of the obvious case: 0.0 */
617 integral_part
[0] = '0';
618 integral_part
[1] = '\0';
619 /* The fractional part has to take the precision into account */
620 for (ch
= 0; ch
< precision
-1; ch
++)
621 fraction_part
[ch
] = '0';
622 fraction_part
[ch
] = '0';
623 fraction_part
[ch
+1] = '\0';
625 *fract
= fraction_part
;
626 return integral_part
;
630 sign
= (number
== -0.) ? '-' : ((number
< 0.) ? '-' : '+');
631 digits
= MAX_INT
- 1;
633 /* for negative numbers */
637 digits
--; /* sign consume one digit */
640 fraction
= integral(number
, &ip
);
643 /* do the integral part */
646 integral_part
[0] = '0';
651 for ( i
= 0; i
< digits
&& number
!= 0.; ++i
)
654 fp
= integral(number
, &ip
);
655 ch
= (int)((fp
+ PRECISION
)*base
); /* force to round */
656 integral_part
[i
] = (ch
<= 9) ? ch
+ '0' : ch
+ 'a' - 10;
657 if (! ISXDIGIT((unsigned char)integral_part
[i
]))
658 break; /* bail out overflow !! */
663 /* Oh No !! out of bound, ho well fill it up ! */
665 for (i
= 0; i
< digits
; ++i
)
666 integral_part
[i
] = '9';
670 integral_part
[i
++] = '-';
672 integral_part
[i
] = '\0';
674 /* reverse every thing */
675 for ( i
--, j
= 0; j
< i
; j
++, i
--)
676 SWAP_INT(integral_part
[i
], integral_part
[j
]);
678 /* the fractional part */
679 for (i
=0, fp
=fraction
; precision
> 0 && i
< MAX_FRACT
; i
++, precision
--)
681 fraction_part
[i
] = (int)((fp
+ PRECISION
)*10. + '0');
682 if (! DIGIT(fraction_part
[i
])) /* underflow ? */
684 fp
= (fp
*10.0) - (double)(long)((fp
+ PRECISION
)*10.);
686 fraction_part
[i
] = '\0';
688 if (fract
!= (char **)0)
689 *fract
= fraction_part
;
691 return integral_part
;
695 /* for %d and friends, it puts in holder
696 * the representation with the right padding
708 /* An explicit precision turns off the zero-padding flag and sets the
709 pad character back to space. */
710 if ((p
->flags
& PF_ZEROPAD
) && p
->precision
>= 0 && (p
->flags
& PF_DOT
))
712 p
->flags
&= ~PF_ZEROPAD
;
716 sd
= d
; /* signed for ' ' padding in base 10 */
718 flags
= (*p
->pf
== 'x' || *p
->pf
== 'X' || *p
->pf
== 'o' || *p
->pf
== 'u' || *p
->pf
== 'U') ? FL_UNSIGNED
: 0;
720 flags
|= FL_HEXUPPER
;
722 tmp
= fmtulong (d
, base
, intbuf
, sizeof(intbuf
), flags
);
724 if ((p
->flags
& PF_THOUSANDS
))
726 GETLOCALEDATA(decpoint
, thoussep
, grouping
);
727 if (grouping
&& (t
= groupnum (tmp
)))
731 /* need to add one for any `+', but we only add one in base 10 */
732 p
->width
-= strlen(tmp
) + (base
== 10 && d
> 0 && (p
->flags
& PF_PLUS
));
735 if ((p
->flags
& PF_DOT
) && p
->precision
> 0)
737 p
->precision
-= strlen(tmp
);
748 if (p
->flags
& PF_ALTFORM
)
752 if (p
->flags
& PF_ALTFORM
)
770 #ifdef HAVE_LONG_LONG
772 * identical to number() but works for `long long'
777 unsigned long long d
;
784 /* An explicit precision turns off the zero-padding flag and sets the
785 pad character back to space. */
786 if ((p
->flags
& PF_ZEROPAD
) && p
->precision
>= 0 && (p
->flags
& PF_DOT
))
788 p
->flags
&= ~PF_ZEROPAD
;
792 sd
= d
; /* signed for ' ' padding in base 10 */
793 flags
= (*p
->pf
== 'x' || *p
->pf
== 'X' || *p
->pf
== 'o' || *p
->pf
== 'u' || *p
->pf
== 'U') ? FL_UNSIGNED
: 0;
795 flags
|= FL_HEXUPPER
;
797 tmp
= fmtullong (d
, base
, intbuf
, sizeof(intbuf
), flags
);
799 if ((p
->flags
& PF_THOUSANDS
))
801 GETLOCALEDATA(decpoint
, thoussep
, grouping
);
802 if (grouping
&& (t
= groupnum (tmp
)))
806 /* need to add one for any `+', but we only add one in base 10 */
807 p
->width
-= strlen(tmp
) + (base
== 10 && d
> 0 && (p
->flags
& PF_PLUS
));
810 if ((p
->flags
& PF_DOT
) && p
->precision
> 0)
812 p
->precision
-= strlen(tmp
);
823 if (p
->flags
& PF_ALTFORM
)
827 if (p
->flags
& PF_ALTFORM
)
853 tmp
= fmtulong(d
, 16, intbuf
, sizeof(intbuf
), 0);
854 p
->width
-= strlen(tmp
);
857 /* prefix '0x' for pointers */
879 if (p
->precision
!= NOT_FOUND
) /* the smallest number */
880 len
= (len
< p
->precision
? len
: p
->precision
);
883 PUT_STRING (tmp
, len
, p
);
887 /* %ls wide-character strings */
898 memset (&mbs
, '\0', sizeof (mbstate_t));
899 ws
= (const wchar_t *)tmp
;
902 if (p
->precision
!= NOT_FOUND
)
904 os
= (char *)xmalloc (p
->precision
+ 1);
905 len
= wcsrtombs (os
, &ws
, p
->precision
, &mbs
);
909 len
= wcsrtombs (NULL
, &ws
, 0, &mbs
);
910 if (len
!= (size_t)-1)
912 memset (&mbs
, '\0', sizeof (mbstate_t));
913 os
= (char *)xmalloc (len
+ 1);
914 (void)wcsrtombs (os
, &ws
, len
+ 1, &mbs
);
917 if (len
== (size_t)-1)
919 /* invalid multibyte sequence; bail now. */
925 PUT_STRING (os
, len
, p
);
938 lbuf
= (char *)malloc (MB_CUR_MAX
+1);
941 memset (&mbs
, '\0', sizeof (mbstate_t));
942 len
= wcrtomb (lbuf
, wc
, &mbs
);
943 if (len
== (size_t)-1)
944 /* conversion failed; bail now. */
948 PUT_STRING (l
, len
, p
);
951 #endif /* HANDLE_MULTIBYTE */
953 #ifdef FLOATING_POINT
955 /* Check for [+-]infinity and NaN. If MODE == 1, we check for Infinity, else
956 (mode == 2) we check for NaN. This does the necessary printing. Returns
957 1 if Inf or Nan, 0 if not. */
959 chkinfnan(p
, d
, mode
)
962 int mode
; /* == 1 for inf, == 2 for nan */
968 i
= (mode
== 1) ? isinf(d
) : isnan(d
);
971 big
= (mode
== 1) ? "INF" : "NAN";
972 small
= (mode
== 1) ? "inf" : "nan";
974 tmp
= (*p
->pf
== 'F' || *p
->pf
== 'G' || *p
->pf
== 'E') ? big
: small
;
988 /* %f %F %g %G floating point representation */
994 char *tmp
, *tmp2
, *t
;
997 if (d
!= 0 && (chkinfnan(p
, d
, 1) || chkinfnan(p
, d
, 2)))
998 return; /* already printed nan or inf */
1000 GETLOCALEDATA(decpoint
, thoussep
, grouping
);
1003 tmp
= dtoa(d
, p
->precision
, &tmp2
);
1005 if ((p
->flags
& PF_THOUSANDS
) && grouping
&& (t
= groupnum (tmp
)))
1008 if ((*p
->pf
== 'g' || *p
->pf
== 'G') && (p
->flags
& PF_ALTFORM
) == 0)
1010 /* smash the trailing zeros unless altform */
1011 for (i
= strlen(tmp2
) - 1; i
>= 0 && tmp2
[i
] == '0'; i
--)
1013 if (tmp2
[0] == '\0')
1017 /* calculate the padding. 1 for the dot */
1018 p
->width
= p
->width
-
1019 /* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
1021 ((d
> 0. && p
->justify
== RIGHT
) ? 1:0) -
1023 ((d
> 0. && (p
->flags
& PF_PLUS
)) ? 1:0) -
1025 ((p
->flags
& PF_SPACE
) ? 1:0) -
1026 strlen(tmp
) - p
->precision
-
1027 ((p
->precision
!= 0 || (p
->flags
& PF_ALTFORM
)) ? 1 : 0); /* radix char */
1037 PUT_CHAR(*tmp
++, p
);
1041 PUT_SPACE(d
, p
, 0.);
1045 PUT_CHAR(*tmp
, p
); /* the integral */
1050 if (p
->precision
!= 0 || (p
->flags
& PF_ALTFORM
))
1051 PUT_CHAR(decpoint
, p
); /* put the '.' */
1053 for (; *tmp2
; tmp2
++)
1054 PUT_CHAR(*tmp2
, p
); /* the fraction */
1059 /* %e %E %g %G exponent representation */
1068 if (d
!= 0 && (chkinfnan(p
, d
, 1) || chkinfnan(p
, d
, 2)))
1069 return; /* already printed nan or inf */
1071 GETLOCALEDATA(decpoint
, thoussep
, grouping
);
1078 d
= d
/ pow_10(j
); /* get the Mantissa */
1081 tmp
= dtoa(d
, p
->precision
, &tmp2
);
1083 /* 1 for unit, 1 for the '.', 1 for 'e|E',
1084 * 1 for '+|-', 2 for 'exp' (but no `.' if precision == 0 */
1085 /* calculate how much padding need */
1086 p
->width
= p
->width
-
1087 /* XXX - should this be d>0. && (p->flags & PF_PLUS) ? */
1089 ((d
> 0. && p
->justify
== RIGHT
) ? 1:0) -
1091 ((d
> 0. && (p
->flags
& PF_PLUS
)) ? 1:0) -
1093 (p
->precision
!= 0 || (p
->flags
& PF_ALTFORM
)) -
1094 ((p
->flags
& PF_SPACE
) ? 1:0) - p
->precision
- 5;
1104 PUT_CHAR(*tmp
++, p
);
1108 PUT_SPACE(d
, p
, 0.);
1116 if (p
->precision
!= 0 || (p
->flags
& PF_ALTFORM
))
1117 PUT_CHAR(decpoint
, p
); /* the '.' */
1119 if ((*p
->pf
== 'g' || *p
->pf
== 'G') && (p
->flags
& PF_ALTFORM
) == 0)
1120 /* smash the trailing zeros unless altform */
1121 for (i
= strlen(tmp2
) - 1; i
>= 0 && tmp2
[i
] == '0'; i
--)
1124 for (; *tmp2
; tmp2
++)
1125 PUT_CHAR(*tmp2
, p
); /* the fraction */
1127 /* the exponent put the 'e|E' */
1128 if (*p
->pf
== 'g' || *p
->pf
== 'e')
1133 /* the sign of the exp */
1143 /* pad out to at least two spaces. pad with `0' if the exponent is a
1159 /* Return a new string with the digits in S grouped according to the locale's
1160 grouping info and thousands separator. If no grouping should be performed,
1161 this returns NULL; the caller needs to check for it. */
1166 char *se
, *ret
, *re
, *g
;
1169 if (grouping
== 0 || *grouping
<= 0 || *grouping
== CHAR_MAX
)
1170 return ((char *)NULL
);
1172 /* find min grouping to size returned string */
1173 for (len
= *grouping
, g
= grouping
; *g
; g
++)
1174 if (*g
> 0 && *g
< len
)
1178 len
= slen
/ len
+ 1;
1179 ret
= (char *)xmalloc (slen
+ len
+ 1);
1180 re
= ret
+ slen
+ len
;
1191 /* handle `-' inserted by numtoa() and the fmtu* family here. */
1192 if (se
> s
&& se
[-1] == '-')
1195 /* begin new group. */
1196 if (--len
== 0 && se
> s
)
1199 len
= *++g
; /* was g++, but that uses first char twice (glibc bug, too) */
1201 len
= *--g
; /* use previous grouping */
1202 else if (*g
== CHAR_MAX
)
1214 memmove (ret
, re
, strlen (re
) + 1);
1222 /* initialize the conversion specifiers */
1227 p
->flags
&= PF_ALLOCBUF
; /* preserve PF_ALLOCBUF flag */
1228 p
->precision
= p
->width
= NOT_FOUND
;
1229 p
->justify
= NOT_FOUND
;
1234 init_data (p
, string
, length
, format
, mode
)
1241 p
->length
= length
- 1; /* leave room for '\0' */
1242 p
->holder
= p
->base
= string
;
1245 p
->flags
= (mode
== PFM_AS
) ? PF_ALLOCBUF
: 0;
1249 #if defined (__STDC__)
1250 vsnprintf_internal(struct DATA
*data
, char *string
, size_t length
, const char *format
, va_list args
)
1252 vsnprintf_internal(data
, string
, length
, format
, args
)
1260 double d
; /* temporary holder */
1261 #ifdef HAVE_LONG_DOUBLE
1262 long double ld
; /* for later */
1265 #ifdef HAVE_LONG_LONG
1266 unsigned long long ull
;
1270 #if HANDLE_MULTIBYTE
1274 const char *convstart
;
1277 /* Sanity check, the string length must be >= 0. C99 actually says that
1278 LENGTH can be zero here, in the case of snprintf/vsnprintf (it's never
1279 0 in the case of asprintf/vasprintf), and the return value is the number
1280 of characters that would have been written. */
1287 /* Reset these for each call because the locale might have changed. */
1288 decpoint
= thoussep
= 0;
1292 for (; c
= *(data
->pf
); data
->pf
++)
1300 convstart
= data
->pf
;
1301 init_conv_flag (data
); /* initialise format flags */
1304 for (state
= 1; state
&& *data
->pf
; )
1307 /* fmtend = data->pf */
1308 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1309 if (data
->flags
& PF_LONGDBL
)
1316 # ifdef HAVE_PRINTF_A_FORMAT
1320 ld
= GETLDOUBLE (data
);
1321 ldfallback (data
, convstart
, data
->pf
, ld
);
1325 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1329 /* Parse format flags */
1330 case '\0': /* a NULL here ? ? bail out */
1331 *data
->holder
= '\0';
1332 return data
->counter
;
1335 data
->flags
|= PF_ALTFORM
;
1338 if (data
->flags
& PF_DOT
)
1339 data
->flags
|= PF_STAR_P
;
1341 data
->flags
|= PF_STAR_W
;
1344 if ((data
->flags
& PF_DOT
) == 0)
1346 data
->flags
|= PF_LADJUST
;
1347 data
->justify
= LEFT
;
1353 if ((data
->flags
& PF_PLUS
) == 0)
1354 data
->flags
|= PF_SPACE
;
1357 if ((data
->flags
& PF_DOT
) == 0)
1359 data
->flags
|= PF_PLUS
;
1360 if ((data
->flags
& PF_LADJUST
) == 0)
1361 data
->justify
= RIGHT
;
1365 data
->flags
|= PF_THOUSANDS
;
1369 /* If we're not specifying precision (in which case we've seen
1370 a `.') and we're not performing left-adjustment (in which
1371 case the `0' is ignored), a `0' is taken as the zero-padding
1373 if ((data
->flags
& (PF_DOT
|PF_LADJUST
)) == 0)
1375 data
->flags
|= PF_ZEROPAD
;
1379 case '1': case '2': case '3':
1380 case '4': case '5': case '6':
1381 case '7': case '8': case '9':
1385 n
= n
* 10 + TODIGIT(c
);
1389 data
->pf
--; /* went too far */
1392 if (data
->flags
& PF_DOT
)
1393 data
->precision
= negprec
? NOT_FOUND
: n
;
1398 /* optional precision */
1400 data
->flags
|= PF_DOT
;
1401 data
->precision
= 0;
1404 /* length modifiers */
1406 data
->flags
|= (data
->flags
& PF_SHORTINT
) ? PF_SIGNEDCHAR
: PF_SHORTINT
;
1409 data
->flags
|= (data
->flags
& PF_LONGINT
) ? PF_LONGLONG
: PF_LONGINT
;
1412 data
->flags
|= PF_LONGDBL
;
1415 data
->flags
|= PF_LONGLONG
;
1418 data
->flags
|= PF_INTMAX_T
;
1419 SET_SIZE_FLAGS(data
, intmax_t);
1422 data
->flags
|= PF_SIZE_T
;
1423 SET_SIZE_FLAGS(data
, size_t);
1426 data
->flags
|= PF_PTRDIFF_T
;
1427 SET_SIZE_FLAGS(data
, ptrdiff_t);
1430 /* Conversion specifiers */
1431 #ifdef FLOATING_POINT
1432 case 'f': /* float, double */
1435 d
= GETDOUBLE(data
);
1444 d
= GETDOUBLE(data
);
1445 i
= (d
!= 0.) ? log_10(d
) : -1;
1447 * for '%g|%G' ANSI: use f if exponent
1448 * is in the range or [-4,p] exclusively
1451 if (-4 < i
&& i
< data
->precision
)
1453 /* reset precision */
1454 data
->precision
-= i
+ 1;
1459 /* reduce precision by 1 because of leading digit before
1460 decimal point in e format, unless specified as 0. */
1461 if (data
->precision
> 0)
1468 case 'E': /* Exponent double */
1470 d
= GETDOUBLE(data
);
1474 # ifdef HAVE_PRINTF_A_FORMAT
1478 d
= GETDOUBLE(data
);
1479 dfallback(data
, convstart
, data
->pf
, d
);
1482 # endif /* HAVE_PRINTF_A_FORMAT */
1483 #endif /* FLOATING_POINT */
1485 data
->flags
|= PF_LONGINT
;
1489 #ifdef HAVE_LONG_LONG
1490 if (data
->flags
& PF_LONGLONG
)
1492 ull
= GETARG (unsigned long long);
1493 lnumber(data
, ull
, 10);
1498 ul
= GETUNSIGNED(data
);
1499 number(data
, ul
, 10);
1504 data
->flags
|= PF_LONGINT
;
1506 case 'd': /* decimal */
1509 #ifdef HAVE_LONG_LONG
1510 if (data
->flags
& PF_LONGLONG
)
1512 ull
= GETARG (long long);
1513 lnumber(data
, ull
, 10);
1518 ul
= GETSIGNED(data
);
1519 number(data
, ul
, 10);
1523 case 'o': /* octal */
1525 #ifdef HAVE_LONG_LONG
1526 if (data
->flags
& PF_LONGLONG
)
1528 ull
= GETARG (unsigned long long);
1529 lnumber(data
, ull
, 8);
1534 ul
= GETUNSIGNED(data
);
1535 number(data
, ul
, 8);
1540 case 'X': /* hexadecimal */
1542 #ifdef HAVE_LONG_LONG
1543 if (data
->flags
& PF_LONGLONG
)
1545 ull
= GETARG (unsigned long long);
1546 lnumber(data
, ull
, 16);
1551 ul
= GETUNSIGNED(data
);
1552 number(data
, ul
, 16);
1558 ul
= (unsigned long)GETARG (void *);
1562 #if HANDLE_MULTIBYTE
1564 data
->flags
|= PF_LONGINT
;
1567 case 'c': /* character */
1569 #if HANDLE_MULTIBYTE
1570 if (data
->flags
& PF_LONGINT
)
1572 wc
= GETARG (wint_t);
1583 #if HANDLE_MULTIBYTE
1585 data
->flags
|= PF_LONGINT
;
1588 case 's': /* string */
1590 #if HANDLE_MULTIBYTE
1591 if (data
->flags
& PF_LONGINT
)
1593 ws
= GETARG (wchar_t *);
1594 wstrings (data
, ws
);
1599 s
= GETARG (char *);
1605 #ifdef HAVE_LONG_LONG
1606 if (data
->flags
& PF_LONGLONG
)
1607 *(GETARG (long long *)) = data
->counter
;
1610 if (data
->flags
& PF_LONGINT
)
1611 *(GETARG (long *)) = data
->counter
;
1612 else if (data
->flags
& PF_SHORTINT
)
1613 *(GETARG (short *)) = data
->counter
;
1615 *(GETARG (int *)) = data
->counter
;
1618 case '%': /* nothing just % */
1619 PUT_CHAR('%', data
);
1623 /* is this an error ? maybe bail out */
1627 } /* end of `%' for loop */
1628 } /* end of format string for loop */
1630 if (data
->length
>= 0)
1631 *data
->holder
= '\0'; /* the end ye ! */
1633 return data
->counter
;
1636 #if defined (FLOATING_POINT) && defined (HAVE_LONG_DOUBLE)
1638 * Printing floating point numbers accurately is an art. I'm not good
1639 * at it. Fall back to sprintf for long double formats.
1642 ldfallback (data
, fs
, fe
, ld
)
1644 const char *fs
, *fe
;
1648 char fmtbuf
[FALLBACK_FMTSIZE
], *obuf
;
1651 fl
= LFALLBACK_BASE
+ (data
->precision
< 6 ? 6 : data
->precision
) + 2;
1652 obuf
= (char *)xmalloc (fl
);
1654 strncpy (fmtbuf
, fs
, fl
);
1657 if ((data
->flags
& PF_STAR_W
) && (data
->flags
& PF_STAR_P
))
1658 sprintf (obuf
, fmtbuf
, data
->width
, data
->precision
, ld
);
1659 else if (data
->flags
& PF_STAR_W
)
1660 sprintf (obuf
, fmtbuf
, data
->width
, ld
);
1661 else if (data
->flags
& PF_STAR_P
)
1662 sprintf (obuf
, fmtbuf
, data
->precision
, ld
);
1664 sprintf (obuf
, fmtbuf
, ld
);
1666 for (x
= obuf
; *x
; x
++)
1667 PUT_CHAR (*x
, data
);
1670 #endif /* FLOATING_POINT && HAVE_LONG_DOUBLE */
1672 #ifdef FLOATING_POINT
1673 /* Used for %a, %A if the libc printf supports them. */
1675 dfallback (data
, fs
, fe
, d
)
1677 const char *fs
, *fe
;
1681 char fmtbuf
[FALLBACK_FMTSIZE
], obuf
[FALLBACK_BASE
];
1685 strncpy (fmtbuf
, fs
, fl
);
1688 if ((data
->flags
& PF_STAR_W
) && (data
->flags
& PF_STAR_P
))
1689 sprintf (obuf
, fmtbuf
, data
->width
, data
->precision
, d
);
1690 else if (data
->flags
& PF_STAR_W
)
1691 sprintf (obuf
, fmtbuf
, data
->width
, d
);
1692 else if (data
->flags
& PF_STAR_P
)
1693 sprintf (obuf
, fmtbuf
, data
->precision
, d
);
1695 sprintf (obuf
, fmtbuf
, d
);
1697 for (x
= obuf
; *x
; x
++)
1698 PUT_CHAR (*x
, data
);
1700 #endif /* FLOATING_POINT */
1705 #if defined (__STDC__)
1706 vsnprintf(char *string
, size_t length
, const char *format
, va_list args
)
1708 vsnprintf(string
, length
, format
, args
)
1717 if (string
== 0 && length
!= 0)
1719 init_data (&data
, string
, length
, format
, PFM_SN
);
1720 return (vsnprintf_internal(&data
, string
, length
, format
, args
));
1724 #if defined(PREFER_STDARG)
1725 snprintf(char *string
, size_t length
, const char * format
, ...)
1727 snprintf(string
, length
, format
, va_alist
)
1738 SH_VA_START(args
, format
);
1740 if (string
== 0 && length
!= 0)
1742 init_data (&data
, string
, length
, format
, PFM_SN
);
1743 rval
= vsnprintf_internal (&data
, string
, length
, format
, args
);
1750 #endif /* HAVE_SNPRINTF */
1755 #if defined (__STDC__)
1756 vasprintf(char **stringp
, const char *format
, va_list args
)
1758 vasprintf(stringp
, format
, args
)
1768 string
= (char *)xmalloc(ASBUFSIZE
);
1769 init_data (&data
, string
, ASBUFSIZE
, format
, PFM_AS
);
1770 r
= vsnprintf_internal(&data
, string
, ASBUFSIZE
, format
, args
);
1771 *stringp
= data
.base
; /* not string in case reallocated */
1776 #if defined(PREFER_STDARG)
1777 asprintf(char **stringp
, const char * format
, ...)
1779 asprintf(stringp
, format
, va_alist
)
1788 SH_VA_START(args
, format
);
1790 rval
= vasprintf (stringp
, format
, args
);
1797 #endif /* !HAVE_ASPRINTF */
1799 #endif /* !HAVE_SNPRINTF || !HAVE_ASPRINTF */
1804 memory_error_and_abort ()
1806 write (2, "out of virtual memory\n", 22);
1816 ret
= malloc(bytes
);
1818 memory_error_and_abort ();
1823 xrealloc (pointer
, bytes
)
1829 ret
= pointer
? realloc(pointer
, bytes
) : malloc(bytes
);
1831 memory_error_and_abort ();
1843 /* set of small tests for snprintf() */
1850 #ifdef HAVE_LOCALE_H
1851 setlocale(LC_ALL
, "");
1855 si
= snprintf((char *)NULL
, 0, "abcde\n");
1856 printf("snprintf returns %d with NULL first argument and size of 0\n", si
);
1857 si
= snprintf(holder
, 0, "abcde\n");
1858 printf("snprintf returns %d with non-NULL first argument and size of 0\n", si
);
1859 si
= snprintf((char *)NULL
, 16, "abcde\n");
1860 printf("snprintf returns %d with NULL first argument and non-zero size\n", si
);
1863 printf("Suite of test for snprintf:\n");
1864 printf("a_format\n");
1865 printf("printf() format\n");
1866 printf("snprintf() format\n\n");
1868 /* Checking the field widths */
1870 printf("/%%ld %%ld/, 336, 336\n");
1871 snprintf(holder
, sizeof holder
, "/%ld %ld/\n", 336, 336);
1872 asprintf(&h
, "/%ld %ld/\n", 336, 336);
1873 printf("/%ld %ld/\n", 336, 336);
1874 printf("%s", holder
);
1877 printf("/%%d/, 336\n");
1878 snprintf(holder
, sizeof holder
, "/%d/\n", 336);
1879 asprintf(&h
, "/%d/\n", 336);
1880 printf("/%d/\n", 336);
1881 printf("%s", holder
);
1884 printf("/%%2d/, 336\n");
1885 snprintf(holder
, sizeof holder
, "/%2d/\n", 336);
1886 asprintf(&h
, "/%2d/\n", 336);
1887 printf("/%2d/\n", 336);
1888 printf("%s", holder
);
1891 printf("/%%10d/, 336\n");
1892 snprintf(holder
, sizeof holder
, "/%10d/\n", 336);
1893 asprintf(&h
, "/%10d/\n", 336);
1894 printf("/%10d/\n", 336);
1895 printf("%s", holder
);
1898 printf("/%%-10d/, 336\n");
1899 snprintf(holder
, sizeof holder
, "/%-10d/\n", 336);
1900 asprintf(&h
, "/%-10d/\n", 336);
1901 printf("/%-10d/\n", 336);
1902 printf("%s", holder
);
1906 /* floating points */
1908 printf("/%%f/, 1234.56\n");
1909 snprintf(holder
, sizeof holder
, "/%f/\n", 1234.56);
1910 asprintf(&h
, "/%f/\n", 1234.56);
1911 printf("/%f/\n", 1234.56);
1912 printf("%s", holder
);
1915 printf("/%%e/, 1234.56\n");
1916 snprintf(holder
, sizeof holder
, "/%e/\n", 1234.56);
1917 asprintf(&h
, "/%e/\n", 1234.56);
1918 printf("/%e/\n", 1234.56);
1919 printf("%s", holder
);
1922 printf("/%%4.2f/, 1234.56\n");
1923 snprintf(holder
, sizeof holder
, "/%4.2f/\n", 1234.56);
1924 asprintf(&h
, "/%4.2f/\n", 1234.56);
1925 printf("/%4.2f/\n", 1234.56);
1926 printf("%s", holder
);
1929 printf("/%%3.1f/, 1234.56\n");
1930 snprintf(holder
, sizeof holder
, "/%3.1f/\n", 1234.56);
1931 asprintf(&h
, "/%3.1f/\n", 1234.56);
1932 printf("/%3.1f/\n", 1234.56);
1933 printf("%s", holder
);
1936 printf("/%%10.3f/, 1234.56\n");
1937 snprintf(holder
, sizeof holder
, "/%10.3f/\n", 1234.56);
1938 asprintf(&h
, "/%10.3f/\n", 1234.56);
1939 printf("/%10.3f/\n", 1234.56);
1940 printf("%s", holder
);
1943 printf("/%%10.3e/, 1234.56\n");
1944 snprintf(holder
, sizeof holder
, "/%10.3e/\n", 1234.56);
1945 asprintf(&h
, "/%10.3e/\n", 1234.56);
1946 printf("/%10.3e/\n", 1234.56);
1947 printf("%s", holder
);
1950 printf("/%%+4.2f/, 1234.56\n");
1951 snprintf(holder
, sizeof holder
, "/%+4.2f/\n", 1234.56);
1952 asprintf(&h
, "/%+4.2f/\n", 1234.56);
1953 printf("/%+4.2f/\n", 1234.56);
1954 printf("%s", holder
);
1957 printf("/%%010.2f/, 1234.56\n");
1958 snprintf(holder
, sizeof holder
, "/%010.2f/\n", 1234.56);
1959 asprintf(&h
, "/%010.2f/\n", 1234.56);
1960 printf("/%010.2f/\n", 1234.56);
1961 printf("%s", holder
);
1964 #define BLURB "Outstanding acting !"
1965 /* strings precisions */
1967 printf("/%%2s/, \"%s\"\n", BLURB
);
1968 snprintf(holder
, sizeof holder
, "/%2s/\n", BLURB
);
1969 asprintf(&h
, "/%2s/\n", BLURB
);
1970 printf("/%2s/\n", BLURB
);
1971 printf("%s", holder
);
1974 printf("/%%22s/ %s\n", BLURB
);
1975 snprintf(holder
, sizeof holder
, "/%22s/\n", BLURB
);
1976 asprintf(&h
, "/%22s/\n", BLURB
);
1977 printf("/%22s/\n", BLURB
);
1978 printf("%s", holder
);
1981 printf("/%%22.5s/ %s\n", BLURB
);
1982 snprintf(holder
, sizeof holder
, "/%22.5s/\n", BLURB
);
1983 asprintf(&h
, "/%22.5s/\n", BLURB
);
1984 printf("/%22.5s/\n", BLURB
);
1985 printf("%s", holder
);
1988 printf("/%%-22.5s/ %s\n", BLURB
);
1989 snprintf(holder
, sizeof holder
, "/%-22.5s/\n", BLURB
);
1990 asprintf(&h
, "/%-22.5s/\n", BLURB
);
1991 printf("/%-22.5s/\n", BLURB
);
1992 printf("%s", holder
);
1995 /* see some flags */
1997 printf("%%x %%X %%#x, 31, 31, 31\n");
1998 snprintf(holder
, sizeof holder
, "%x %X %#x\n", 31, 31, 31);
1999 asprintf(&h
, "%x %X %#x\n", 31, 31, 31);
2000 printf("%x %X %#x\n", 31, 31, 31);
2001 printf("%s", holder
);
2004 printf("**%%d**%% d**%% d**, 42, 42, -42\n");
2005 snprintf(holder
, sizeof holder
, "**%d**% d**% d**\n", 42, 42, -42);
2006 asprintf(&h
, "**%d**% d**% d**\n", 42, 42, -42);
2007 printf("**%d**% d**% d**\n", 42, 42, -42);
2008 printf("%s", holder
);
2013 printf("/%%g/, 31.4\n");
2014 snprintf(holder
, sizeof holder
, "/%g/\n", 31.4);
2015 asprintf(&h
, "/%g/\n", 31.4);
2016 printf("/%g/\n", 31.4);
2017 printf("%s", holder
);
2020 printf("/%%.6g/, 31.4\n");
2021 snprintf(holder
, sizeof holder
, "/%.6g/\n", 31.4);
2022 asprintf(&h
, "/%.6g/\n", 31.4);
2023 printf("/%.6g/\n", 31.4);
2024 printf("%s", holder
);
2027 printf("/%%.1G/, 31.4\n");
2028 snprintf(holder
, sizeof holder
, "/%.1G/\n", 31.4);
2029 asprintf(&h
, "/%.1G/\n", 31.4);
2030 printf("/%.1G/\n", 31.4);
2031 printf("%s", holder
);
2034 printf("/%%.1G/, 3100000000.4\n");
2035 snprintf(holder
, sizeof holder
, "/%.1G/\n", 3100000000.4);
2036 asprintf(&h
, "/%.1G/\n", 3100000000.4);
2037 printf("/%.1G/\n", 3100000000.4);
2038 printf("%s", holder
);
2042 printf("abc%n", &i
); printf("%d\n", i
);
2043 snprintf(holder
, sizeof holder
, "abc%n", &i
);
2044 printf("%s", holder
); printf("%d\n\n", i
);
2045 asprintf(&h
, "abc%n", &i
);
2046 printf("%s", h
); printf("%d\n\n", i
);
2048 printf("%%*.*s --> 10.10\n");
2049 snprintf(holder
, sizeof holder
, "%*.*s\n", 10, 10, BLURB
);
2050 asprintf(&h
, "%*.*s\n", 10, 10, BLURB
);
2051 printf("%*.*s\n", 10, 10, BLURB
);
2052 printf("%s", holder
);
2055 printf("%%%%%%%%\n");
2056 snprintf(holder
, sizeof holder
, "%%%%\n");
2057 asprintf(&h
, "%%%%\n");
2059 printf("%s", holder
);
2062 #define BIG "Hello this is a too big string for the buffer"
2063 /* printf("A buffer to small of 10, trying to put this:\n");*/
2064 printf("<%%>, %s\n", BIG
);
2065 i
= snprintf(holder
, 10, "%s\n", BIG
);
2066 i
= asprintf(&h
, "%s", BIG
);
2067 printf("<%s>\n", BIG
);
2068 printf("<%s>\n", holder
);
2069 printf("<%s>\n\n", h
);
2071 printf ("<%%p> vsnprintf\n");
2072 i
= snprintf(holder
, 100, "%p", vsnprintf
);
2073 i
= asprintf(&h
, "%p", vsnprintf
);
2074 printf("<%p>\n", vsnprintf
);
2075 printf("<%s>\n", holder
);
2076 printf("<%s>\n\n", h
);
2078 printf ("<%%lu> LONG_MAX+1\n");
2079 i
= snprintf(holder
, 100, "%lu", (unsigned long)(LONG_MAX
)+1);
2080 i
= asprintf(&h
, "%lu", (unsigned long)(LONG_MAX
)+1);
2081 printf("<%lu>\n", (unsigned long)(LONG_MAX
)+1);
2082 printf("<%s>\n", holder
);
2083 printf("<%s>\n\n", h
);
2085 #ifdef HAVE_LONG_LONG
2086 printf ("<%%llu> LLONG_MAX+1\n");
2087 i
= snprintf(holder
, 100, "%llu", (unsigned long long)(LLONG_MAX
)+1);
2088 i
= asprintf(&h
, "%llu", (unsigned long long)(LLONG_MAX
)+1);
2089 printf("<%llu>\n", (unsigned long long)(LLONG_MAX
)+1);
2090 printf("<%s>\n", holder
);
2091 printf("<%s>\n\n", h
);
2094 #ifdef HAVE_LONG_DOUBLE
2095 printf ("<%%6.2LE> 42.42\n");
2096 i
= snprintf(holder
, 100, "%6.2LE", (long double)42.42);
2097 i
= asprintf(&h
, "%6.2LE", (long double)42.42);
2098 printf ("<%6.2LE>\n", (long double)42.42);
2099 printf ("<%s>\n", holder
);
2100 printf ("<%s>\n\n", h
);
2103 #ifdef HAVE_PRINTF_A_FORMAT
2104 printf ("<%%6.2A> 42.42\n");
2105 i
= snprintf(holder
, 100, "%6.2A", 42.42);
2106 i
= asprintf(&h
, "%6.2A", 42.42);
2107 printf ("<%6.2A>\n", 42.42);
2108 printf ("<%s>\n", holder
);
2109 printf ("<%s>\n\n", h
);
2111 printf ("<%%6.2LA> 42.42\n");
2112 i
= snprintf(holder
, 100, "%6.2LA", (long double)42.42);
2113 i
= asprintf(&h
, "%6.2LA", (long double)42.42);
2114 printf ("<%6.2LA>\n", (long double)42.42);
2115 printf ("<%s>\n", holder
);
2116 printf ("<%s>\n\n", h
);
2119 printf ("<%%.10240f> DBL_MAX\n");
2120 si
= snprintf(holder
, 100, "%.10240f", DBL_MAX
);
2121 ai
= asprintf(&h
, "%.10240f", DBL_MAX
);
2122 printf ("<%.10240f>\n", DBL_MAX
);
2123 printf ("<%d> <%s>\n", si
, holder
);
2124 printf ("<%d> <%s>\n\n", ai
, h
);
2126 printf ("<%%.10240Lf> LDBL_MAX\n");
2127 si
= snprintf(holder
, 100, "%.10240Lf", (long double)LDBL_MAX
);
2128 ai
= asprintf(&h
, "%.10240Lf", (long double)LDBL_MAX
);
2129 printf ("<%.10240Lf>\n", (long double)LDBL_MAX
);
2130 printf ("<%d> <%s>\n", si
, holder
);
2131 printf ("<%d> <%s>\n\n", ai
, h
);
2134 printf("/%%g/, 421.2345\n");
2135 snprintf(holder
, sizeof holder
, "/%g/\n", 421.2345);
2136 asprintf(&h
, "/%g/\n", 421.2345);
2137 printf("/%g/\n", 421.2345);
2138 printf("%s", holder
);
2141 printf("/%%g/, 4214.2345\n");
2142 snprintf(holder
, sizeof holder
, "/%g/\n", 4214.2345);
2143 asprintf(&h
, "/%g/\n", 4214.2345);
2144 printf("/%g/\n", 4214.2345);
2145 printf("%s", holder
);
2148 printf("/%%.5g/, 4214.2345\n");
2149 snprintf(holder
, sizeof holder
, "/%.5g/\n", 4214.2345);
2150 asprintf(&h
, "/%.5g/\n", 4214.2345);
2151 printf("/%.5g/\n", 4214.2345);
2152 printf("%s", holder
);
2155 printf("/%%.4g/, 4214.2345\n");
2156 snprintf(holder
, sizeof holder
, "/%.4g/\n", 4214.2345);
2157 asprintf(&h
, "/%.4g/\n", 4214.2345);
2158 printf("/%.4g/\n", 4214.2345);
2159 printf("%s", holder
);
2162 printf("/%%'ld %%'ld/, 12345, 1234567\n");
2163 snprintf(holder
, sizeof holder
, "/%'ld %'ld/\n", 12345, 1234567);
2164 asprintf(&h
, "/%'ld %'ld/\n", 12345, 1234567);
2165 printf("/%'ld %'ld/\n", 12345, 1234567);
2166 printf("%s", holder
);
2169 printf("/%%'ld %%'ld/, 336, 3336\n");
2170 snprintf(holder
, sizeof holder
, "/%'ld %'ld/\n", 336, 3336);
2171 asprintf(&h
, "/%'ld %'ld/\n", 336, 3336);
2172 printf("/%'ld %'ld/\n", 336, 3336);
2173 printf("%s", holder
);
2176 printf("/%%'ld %%'ld/, -42786, -142786\n");
2177 snprintf(holder
, sizeof holder
, "/%'ld %'ld/\n", -42786, -142786);
2178 asprintf(&h
, "/%'ld %'ld/\n", -42786, -142786);
2179 printf("/%'ld %'ld/\n", -42786, -142786);
2180 printf("%s", holder
);
2183 printf("/%%'f %%'f/, 421.2345, 421234.56789\n");
2184 snprintf(holder
, sizeof holder
, "/%'f %'f/\n", 421.2345, 421234.56789);
2185 asprintf(&h
, "/%'f %'f/\n", 421.2345, 421234.56789);
2186 printf("/%'f %'f/\n", 421.2345, 421234.56789);
2187 printf("%s", holder
);
2190 printf("/%%'f %%'f/, -421.2345, -421234.56789\n");
2191 snprintf(holder
, sizeof holder
, "/%'f %'f/\n", -421.2345, -421234.56789);
2192 asprintf(&h
, "/%'f %'f/\n", -421.2345, -421234.56789);
2193 printf("/%'f %'f/\n", -421.2345, -421234.56789);
2194 printf("%s", holder
);
2197 printf("/%%'g %%'g/, 421.2345, 421234.56789\n");
2198 snprintf(holder
, sizeof holder
, "/%'g %'g/\n", 421.2345, 421234.56789);
2199 asprintf(&h
, "/%'g %'g/\n", 421.2345, 421234.56789);
2200 printf("/%'g %'g/\n", 421.2345, 421234.56789);
2201 printf("%s", holder
);
2204 printf("/%%'g %%'g/, -421.2345, -421234.56789\n");
2205 snprintf(holder
, sizeof holder
, "/%'g %'g/\n", -421.2345, -421234.56789);
2206 asprintf(&h
, "/%'g %'g/\n", -421.2345, -421234.56789);
2207 printf("/%'g %'g/\n", -421.2345, -421234.56789);
2208 printf("%s", holder
);
2212 printf("/%%'g/, 4213455.8392\n");
2213 snprintf(holder
, sizeof holder
, "/%'g/\n", 4213455.8392);
2214 asprintf(&h
, "/%'g/\n", 4213455.8392);
2215 printf("/%'g/\n", 4213455.8392);
2216 printf("%s", holder
);