xref: /freebsd/contrib/ntp/libntp/snprintf.c (revision 2b15cb3d0922bd70ea592f0da9b4a5b167f4d53f)
1*2b15cb3dSCy Schubert /*
2*2b15cb3dSCy Schubert  * Modified by Dave Hart for integration into NTP 4.2.7 <hart@ntp.org>
3*2b15cb3dSCy Schubert  *
4*2b15cb3dSCy Schubert  * Changed in a backwards-incompatible way to separate HAVE_SNPRINTF
5*2b15cb3dSCy Schubert  * from HW_WANT_RPL_SNPRINTF, etc. for each of the four replaced
6*2b15cb3dSCy Schubert  * functions.
7*2b15cb3dSCy Schubert  *
8*2b15cb3dSCy Schubert  * Changed to honor hw_force_rpl_snprintf=yes, etc.  This is used by NTP
9*2b15cb3dSCy Schubert  * to test rpl_snprintf() and rpl_vsnprintf() on platforms which provide
10*2b15cb3dSCy Schubert  * C99-compliant implementations.
11*2b15cb3dSCy Schubert  */
12*2b15cb3dSCy Schubert 
13*2b15cb3dSCy Schubert /* $Id: snprintf.c,v 1.9 2008/01/20 14:02:00 holger Exp $ */
14*2b15cb3dSCy Schubert 
15*2b15cb3dSCy Schubert /*
16*2b15cb3dSCy Schubert  * Copyright (c) 1995 Patrick Powell.
17*2b15cb3dSCy Schubert  *
18*2b15cb3dSCy Schubert  * This code is based on code written by Patrick Powell <papowell@astart.com>.
19*2b15cb3dSCy Schubert  * It may be used for any purpose as long as this notice remains intact on all
20*2b15cb3dSCy Schubert  * source code distributions.
21*2b15cb3dSCy Schubert  */
22*2b15cb3dSCy Schubert 
23*2b15cb3dSCy Schubert /*
24*2b15cb3dSCy Schubert  * Copyright (c) 2008 Holger Weiss.
25*2b15cb3dSCy Schubert  *
26*2b15cb3dSCy Schubert  * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
27*2b15cb3dSCy Schubert  * My changes to the code may freely be used, modified and/or redistributed for
28*2b15cb3dSCy Schubert  * any purpose.  It would be nice if additions and fixes to this file (including
29*2b15cb3dSCy Schubert  * trivial code cleanups) would be sent back in order to let me include them in
30*2b15cb3dSCy Schubert  * the version available at <http://www.jhweiss.de/software/snprintf.html>.
31*2b15cb3dSCy Schubert  * However, this is not a requirement for using or redistributing (possibly
32*2b15cb3dSCy Schubert  * modified) versions of this file, nor is leaving this notice intact mandatory.
33*2b15cb3dSCy Schubert  */
34*2b15cb3dSCy Schubert 
35*2b15cb3dSCy Schubert /*
36*2b15cb3dSCy Schubert  * History
37*2b15cb3dSCy Schubert  *
38*2b15cb3dSCy Schubert  * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
39*2b15cb3dSCy Schubert  *
40*2b15cb3dSCy Schubert  * 	Fixed the detection of infinite floating point values on IRIX (and
41*2b15cb3dSCy Schubert  * 	possibly other systems) and applied another few minor cleanups.
42*2b15cb3dSCy Schubert  *
43*2b15cb3dSCy Schubert  * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
44*2b15cb3dSCy Schubert  *
45*2b15cb3dSCy Schubert  * 	Added a lot of new features, fixed many bugs, and incorporated various
46*2b15cb3dSCy Schubert  * 	improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
47*2b15cb3dSCy Schubert  * 	<rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
48*2b15cb3dSCy Schubert  * 	<djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
49*2b15cb3dSCy Schubert  * 	projects.  The additions include: support the "e", "E", "g", "G", and
50*2b15cb3dSCy Schubert  * 	"F" conversion specifiers (and use conversion style "f" or "F" for the
51*2b15cb3dSCy Schubert  * 	still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
52*2b15cb3dSCy Schubert  * 	"t", and "z" length modifiers; support the "#" flag and the (non-C99)
53*2b15cb3dSCy Schubert  * 	"'" flag; use localeconv(3) (if available) to get both the current
54*2b15cb3dSCy Schubert  * 	locale's decimal point character and the separator between groups of
55*2b15cb3dSCy Schubert  * 	digits; fix the handling of various corner cases of field width and
56*2b15cb3dSCy Schubert  * 	precision specifications; fix various floating point conversion bugs;
57*2b15cb3dSCy Schubert  * 	handle infinite and NaN floating point values; don't attempt to write to
58*2b15cb3dSCy Schubert  * 	the output buffer (which may be NULL) if a size of zero was specified;
59*2b15cb3dSCy Schubert  * 	check for integer overflow of the field width, precision, and return
60*2b15cb3dSCy Schubert  * 	values and during the floating point conversion; use the OUTCHAR() macro
61*2b15cb3dSCy Schubert  * 	instead of a function for better performance; provide asprintf(3) and
62*2b15cb3dSCy Schubert  * 	vasprintf(3) functions; add new test cases.  The replacement functions
63*2b15cb3dSCy Schubert  * 	have been renamed to use an "rpl_" prefix, the function calls in the
64*2b15cb3dSCy Schubert  * 	main project (and in this file) must be redefined accordingly for each
65*2b15cb3dSCy Schubert  * 	replacement function which is needed (by using Autoconf or other means).
66*2b15cb3dSCy Schubert  * 	Various other minor improvements have been applied and the coding style
67*2b15cb3dSCy Schubert  * 	was cleaned up for consistency.
68*2b15cb3dSCy Schubert  *
69*2b15cb3dSCy Schubert  * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
70*2b15cb3dSCy Schubert  *
71*2b15cb3dSCy Schubert  * 	C99 compliant snprintf(3) and vsnprintf(3) functions return the number
72*2b15cb3dSCy Schubert  * 	of characters that would have been written to a sufficiently sized
73*2b15cb3dSCy Schubert  * 	buffer (excluding the '\0').  The original code simply returned the
74*2b15cb3dSCy Schubert  * 	length of the resulting output string, so that's been fixed.
75*2b15cb3dSCy Schubert  *
76*2b15cb3dSCy Schubert  * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
77*2b15cb3dSCy Schubert  *
78*2b15cb3dSCy Schubert  * 	The original code assumed that both snprintf(3) and vsnprintf(3) were
79*2b15cb3dSCy Schubert  * 	missing.  Some systems only have snprintf(3) but not vsnprintf(3), so
80*2b15cb3dSCy Schubert  * 	the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
81*2b15cb3dSCy Schubert  *
82*2b15cb3dSCy Schubert  * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
83*2b15cb3dSCy Schubert  *
84*2b15cb3dSCy Schubert  * 	The PGP code was using unsigned hexadecimal formats.  Unfortunately,
85*2b15cb3dSCy Schubert  * 	unsigned formats simply didn't work.
86*2b15cb3dSCy Schubert  *
87*2b15cb3dSCy Schubert  * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
88*2b15cb3dSCy Schubert  *
89*2b15cb3dSCy Schubert  * 	Ok, added some minimal floating point support, which means this probably
90*2b15cb3dSCy Schubert  * 	requires libm on most operating systems.  Don't yet support the exponent
91*2b15cb3dSCy Schubert  * 	(e,E) and sigfig (g,G).  Also, fmtint() was pretty badly broken, it just
92*2b15cb3dSCy Schubert  * 	wasn't being exercised in ways which showed it, so that's been fixed.
93*2b15cb3dSCy Schubert  * 	Also, formatted the code to Mutt conventions, and removed dead code left
94*2b15cb3dSCy Schubert  * 	over from the original.  Also, there is now a builtin-test, run with:
95*2b15cb3dSCy Schubert  * 	gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
96*2b15cb3dSCy Schubert  *
97*2b15cb3dSCy Schubert  * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
98*2b15cb3dSCy Schubert  *
99*2b15cb3dSCy Schubert  * 	This was ugly.  It is still ugly.  I opted out of floating point
100*2b15cb3dSCy Schubert  * 	numbers, but the formatter understands just about everything from the
101*2b15cb3dSCy Schubert  * 	normal C string format, at least as far as I can tell from the Solaris
102*2b15cb3dSCy Schubert  * 	2.5 printf(3S) man page.
103*2b15cb3dSCy Schubert  */
104*2b15cb3dSCy Schubert 
105*2b15cb3dSCy Schubert /*
106*2b15cb3dSCy Schubert  * ToDo
107*2b15cb3dSCy Schubert  *
108*2b15cb3dSCy Schubert  * - Add wide character support.
109*2b15cb3dSCy Schubert  * - Add support for "%a" and "%A" conversions.
110*2b15cb3dSCy Schubert  * - Create test routines which predefine the expected results.  Our test cases
111*2b15cb3dSCy Schubert  *   usually expose bugs in system implementations rather than in ours :-)
112*2b15cb3dSCy Schubert  */
113*2b15cb3dSCy Schubert 
114*2b15cb3dSCy Schubert /*
115*2b15cb3dSCy Schubert  * Usage
116*2b15cb3dSCy Schubert  *
117*2b15cb3dSCy Schubert  * 1) The following preprocessor macros should be defined to 1 if the feature or
118*2b15cb3dSCy Schubert  *    file in question is available on the target system (by using Autoconf or
119*2b15cb3dSCy Schubert  *    other means), though basic functionality should be available as long as
120*2b15cb3dSCy Schubert  *    HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
121*2b15cb3dSCy Schubert  *
122*2b15cb3dSCy Schubert  *	HW_WANT_RPL_VSNPRINTF
123*2b15cb3dSCy Schubert  *	HW_WANT_RPL_SNPRINTF
124*2b15cb3dSCy Schubert  *	HW_WANT_RPL_VASPRINTF
125*2b15cb3dSCy Schubert  *	HW_WANT_RPL_ASPRINTF
126*2b15cb3dSCy Schubert  *	HAVE_VSNPRINTF	// define to 1 #if HW_WANT_RPL_VSNPRINTF
127*2b15cb3dSCy Schubert  *	HAVE_SNPRINTF	// define to 1 #if HW_WANT_RPL_SNPRINTF
128*2b15cb3dSCy Schubert  *	HAVE_VASPRINTF	// define to 1 #if HW_WANT_RPL_VASPRINTF
129*2b15cb3dSCy Schubert  *	HAVE_ASPRINTF	// define to 1 #if HW_WANT_RPL_ASPRINTF
130*2b15cb3dSCy Schubert  *	HAVE_STDARG_H
131*2b15cb3dSCy Schubert  *	HAVE_STDDEF_H
132*2b15cb3dSCy Schubert  *	HAVE_STDINT_H
133*2b15cb3dSCy Schubert  *	HAVE_STDLIB_H
134*2b15cb3dSCy Schubert  *	HAVE_INTTYPES_H
135*2b15cb3dSCy Schubert  *	HAVE_LOCALE_H
136*2b15cb3dSCy Schubert  *	HAVE_LOCALECONV
137*2b15cb3dSCy Schubert  *	HAVE_LCONV_DECIMAL_POINT
138*2b15cb3dSCy Schubert  *	HAVE_LCONV_THOUSANDS_SEP
139*2b15cb3dSCy Schubert  *	HAVE_LONG_DOUBLE
140*2b15cb3dSCy Schubert  *	HAVE_LONG_LONG_INT
141*2b15cb3dSCy Schubert  *	HAVE_UNSIGNED_LONG_LONG_INT
142*2b15cb3dSCy Schubert  *	HAVE_INTMAX_T
143*2b15cb3dSCy Schubert  *	HAVE_UINTMAX_T
144*2b15cb3dSCy Schubert  *	HAVE_UINTPTR_T
145*2b15cb3dSCy Schubert  *	HAVE_PTRDIFF_T
146*2b15cb3dSCy Schubert  *	HAVE_VA_COPY
147*2b15cb3dSCy Schubert  *	HAVE___VA_COPY
148*2b15cb3dSCy Schubert  *
149*2b15cb3dSCy Schubert  * 2) The calls to the functions which should be replaced must be redefined
150*2b15cb3dSCy Schubert  *    throughout the project files (by using Autoconf or other means):
151*2b15cb3dSCy Schubert  *
152*2b15cb3dSCy Schubert  *	#if HW_WANT_RPL_VSNPRINTF
153*2b15cb3dSCy Schubert  *	#define vsnprintf rpl_vsnprintf
154*2b15cb3dSCy Schubert  *	#endif
155*2b15cb3dSCy Schubert  *	#if HW_WANT_RPL_SNPRINTF
156*2b15cb3dSCy Schubert  *	#define snprintf rpl_snprintf
157*2b15cb3dSCy Schubert  *	#endif
158*2b15cb3dSCy Schubert  *	#if HW_WANT_RPL_VASPRINTF
159*2b15cb3dSCy Schubert  *	#define vasprintf rpl_vasprintf
160*2b15cb3dSCy Schubert  *	#endif
161*2b15cb3dSCy Schubert  *	#if HW_WANT_RPL_ASPRINTF
162*2b15cb3dSCy Schubert  *	#define asprintf rpl_asprintf
163*2b15cb3dSCy Schubert  *	#endif
164*2b15cb3dSCy Schubert  *
165*2b15cb3dSCy Schubert  * 3) The required replacement functions should be declared in some header file
166*2b15cb3dSCy Schubert  *    included throughout the project files:
167*2b15cb3dSCy Schubert  *
168*2b15cb3dSCy Schubert  *	#if HAVE_CONFIG_H
169*2b15cb3dSCy Schubert  *	#include <config.h>
170*2b15cb3dSCy Schubert  *	#endif
171*2b15cb3dSCy Schubert  *	#if HAVE_STDARG_H
172*2b15cb3dSCy Schubert  *	#include <stdarg.h>
173*2b15cb3dSCy Schubert  *	#if HW_WANT_RPL_VSNPRINTF
174*2b15cb3dSCy Schubert  *	int rpl_vsnprintf(char *, size_t, const char *, va_list);
175*2b15cb3dSCy Schubert  *	#endif
176*2b15cb3dSCy Schubert  *	#if HW_WANT_RPL_SNPRINTF
177*2b15cb3dSCy Schubert  *	int rpl_snprintf(char *, size_t, const char *, ...);
178*2b15cb3dSCy Schubert  *	#endif
179*2b15cb3dSCy Schubert  *	#if HW_WANT_RPL_VASPRINTF
180*2b15cb3dSCy Schubert  *	int rpl_vasprintf(char **, const char *, va_list);
181*2b15cb3dSCy Schubert  *	#endif
182*2b15cb3dSCy Schubert  *	#if HW_WANT_RPL_ASPRINTF
183*2b15cb3dSCy Schubert  *	int rpl_asprintf(char **, const char *, ...);
184*2b15cb3dSCy Schubert  *	#endif
185*2b15cb3dSCy Schubert  *	#endif
186*2b15cb3dSCy Schubert  *
187*2b15cb3dSCy Schubert  * Autoconf macros for handling step 1 and step 2 are available at
188*2b15cb3dSCy Schubert  * <http://www.jhweiss.de/software/snprintf.html>.
189*2b15cb3dSCy Schubert  */
190*2b15cb3dSCy Schubert 
191*2b15cb3dSCy Schubert #if HAVE_CONFIG_H
192224ba2bdSOllivier Robert #include <config.h>
193*2b15cb3dSCy Schubert #endif	/* HAVE_CONFIG_H */
194224ba2bdSOllivier Robert 
195*2b15cb3dSCy Schubert #if TEST_SNPRINTF
196*2b15cb3dSCy Schubert #include <math.h>	/* For pow(3), NAN, and INFINITY. */
197*2b15cb3dSCy Schubert #include <string.h>	/* For strcmp(3). */
198*2b15cb3dSCy Schubert #if defined(__NetBSD__) || \
199*2b15cb3dSCy Schubert     defined(__FreeBSD__) || \
200*2b15cb3dSCy Schubert     defined(__OpenBSD__) || \
201*2b15cb3dSCy Schubert     defined(__NeXT__) || \
202*2b15cb3dSCy Schubert     defined(__bsd__)
203*2b15cb3dSCy Schubert #define OS_BSD 1
204*2b15cb3dSCy Schubert #elif defined(sgi) || defined(__sgi)
205*2b15cb3dSCy Schubert #ifndef __c99
206*2b15cb3dSCy Schubert #define __c99	/* Force C99 mode to get <stdint.h> included on IRIX 6.5.30. */
207*2b15cb3dSCy Schubert #endif	/* !defined(__c99) */
208*2b15cb3dSCy Schubert #define OS_IRIX 1
209*2b15cb3dSCy Schubert #define OS_SYSV 1
210*2b15cb3dSCy Schubert #elif defined(__svr4__)
211*2b15cb3dSCy Schubert #define OS_SYSV 1
212*2b15cb3dSCy Schubert #elif defined(__linux__)
213*2b15cb3dSCy Schubert #define OS_LINUX 1
214*2b15cb3dSCy Schubert #endif	/* defined(__NetBSD__) || defined(__FreeBSD__) || [...] */
215*2b15cb3dSCy Schubert #if HAVE_CONFIG_H	/* Undefine definitions possibly done in config.h. */
216*2b15cb3dSCy Schubert #ifdef HAVE_SNPRINTF
217*2b15cb3dSCy Schubert #undef HAVE_SNPRINTF
218*2b15cb3dSCy Schubert #endif	/* defined(HAVE_SNPRINTF) */
219*2b15cb3dSCy Schubert #ifdef HAVE_VSNPRINTF
220*2b15cb3dSCy Schubert #undef HAVE_VSNPRINTF
221*2b15cb3dSCy Schubert #endif	/* defined(HAVE_VSNPRINTF) */
222*2b15cb3dSCy Schubert #ifdef HAVE_ASPRINTF
223*2b15cb3dSCy Schubert #undef HAVE_ASPRINTF
224*2b15cb3dSCy Schubert #endif	/* defined(HAVE_ASPRINTF) */
225*2b15cb3dSCy Schubert #ifdef HAVE_VASPRINTF
226*2b15cb3dSCy Schubert #undef HAVE_VASPRINTF
227*2b15cb3dSCy Schubert #endif	/* defined(HAVE_VASPRINTF) */
228*2b15cb3dSCy Schubert #ifdef snprintf
229*2b15cb3dSCy Schubert #undef snprintf
230*2b15cb3dSCy Schubert #endif	/* defined(snprintf) */
231*2b15cb3dSCy Schubert #ifdef vsnprintf
232*2b15cb3dSCy Schubert #undef vsnprintf
233*2b15cb3dSCy Schubert #endif	/* defined(vsnprintf) */
234*2b15cb3dSCy Schubert #ifdef asprintf
235*2b15cb3dSCy Schubert #undef asprintf
236*2b15cb3dSCy Schubert #endif	/* defined(asprintf) */
237*2b15cb3dSCy Schubert #ifdef vasprintf
238*2b15cb3dSCy Schubert #undef vasprintf
239*2b15cb3dSCy Schubert #endif	/* defined(vasprintf) */
240*2b15cb3dSCy Schubert #else	/* By default, we assume a modern system for testing. */
241*2b15cb3dSCy Schubert #ifndef HAVE_STDARG_H
242*2b15cb3dSCy Schubert #define HAVE_STDARG_H 1
243*2b15cb3dSCy Schubert #endif	/* HAVE_STDARG_H */
244*2b15cb3dSCy Schubert #ifndef HAVE_STDDEF_H
245*2b15cb3dSCy Schubert #define HAVE_STDDEF_H 1
246*2b15cb3dSCy Schubert #endif	/* HAVE_STDDEF_H */
247*2b15cb3dSCy Schubert #ifndef HAVE_STDINT_H
248*2b15cb3dSCy Schubert #define HAVE_STDINT_H 1
249*2b15cb3dSCy Schubert #endif	/* HAVE_STDINT_H */
250*2b15cb3dSCy Schubert #ifndef HAVE_STDLIB_H
251*2b15cb3dSCy Schubert #define HAVE_STDLIB_H 1
252*2b15cb3dSCy Schubert #endif	/* HAVE_STDLIB_H */
253*2b15cb3dSCy Schubert #ifndef HAVE_INTTYPES_H
254*2b15cb3dSCy Schubert #define HAVE_INTTYPES_H 1
255*2b15cb3dSCy Schubert #endif	/* HAVE_INTTYPES_H */
256*2b15cb3dSCy Schubert #ifndef HAVE_LOCALE_H
257*2b15cb3dSCy Schubert #define HAVE_LOCALE_H 1
258*2b15cb3dSCy Schubert #endif	/* HAVE_LOCALE_H */
259*2b15cb3dSCy Schubert #ifndef HAVE_LOCALECONV
260*2b15cb3dSCy Schubert #define HAVE_LOCALECONV 1
261*2b15cb3dSCy Schubert #endif	/* !defined(HAVE_LOCALECONV) */
262*2b15cb3dSCy Schubert #ifndef HAVE_LCONV_DECIMAL_POINT
263*2b15cb3dSCy Schubert #define HAVE_LCONV_DECIMAL_POINT 1
264*2b15cb3dSCy Schubert #endif	/* HAVE_LCONV_DECIMAL_POINT */
265*2b15cb3dSCy Schubert #ifndef HAVE_LCONV_THOUSANDS_SEP
266*2b15cb3dSCy Schubert #define HAVE_LCONV_THOUSANDS_SEP 1
267*2b15cb3dSCy Schubert #endif	/* HAVE_LCONV_THOUSANDS_SEP */
268*2b15cb3dSCy Schubert #ifndef HAVE_LONG_DOUBLE
269*2b15cb3dSCy Schubert #define HAVE_LONG_DOUBLE 1
270*2b15cb3dSCy Schubert #endif	/* !defined(HAVE_LONG_DOUBLE) */
271*2b15cb3dSCy Schubert #ifndef HAVE_LONG_LONG_INT
272*2b15cb3dSCy Schubert #define HAVE_LONG_LONG_INT 1
273*2b15cb3dSCy Schubert #endif	/* !defined(HAVE_LONG_LONG_INT) */
274*2b15cb3dSCy Schubert #ifndef HAVE_UNSIGNED_LONG_LONG_INT
275*2b15cb3dSCy Schubert #define HAVE_UNSIGNED_LONG_LONG_INT 1
276*2b15cb3dSCy Schubert #endif	/* !defined(HAVE_UNSIGNED_LONG_LONG_INT) */
277*2b15cb3dSCy Schubert #ifndef HAVE_INTMAX_T
278*2b15cb3dSCy Schubert #define HAVE_INTMAX_T 1
279*2b15cb3dSCy Schubert #endif	/* !defined(HAVE_INTMAX_T) */
280*2b15cb3dSCy Schubert #ifndef HAVE_UINTMAX_T
281*2b15cb3dSCy Schubert #define HAVE_UINTMAX_T 1
282*2b15cb3dSCy Schubert #endif	/* !defined(HAVE_UINTMAX_T) */
283*2b15cb3dSCy Schubert #ifndef HAVE_UINTPTR_T
284*2b15cb3dSCy Schubert #define HAVE_UINTPTR_T 1
285*2b15cb3dSCy Schubert #endif	/* !defined(HAVE_UINTPTR_T) */
286*2b15cb3dSCy Schubert #ifndef HAVE_PTRDIFF_T
287*2b15cb3dSCy Schubert #define HAVE_PTRDIFF_T 1
288*2b15cb3dSCy Schubert #endif	/* !defined(HAVE_PTRDIFF_T) */
289*2b15cb3dSCy Schubert #ifndef HAVE_VA_COPY
290*2b15cb3dSCy Schubert #define HAVE_VA_COPY 1
291*2b15cb3dSCy Schubert #endif	/* !defined(HAVE_VA_COPY) */
292*2b15cb3dSCy Schubert #ifndef HAVE___VA_COPY
293*2b15cb3dSCy Schubert #define HAVE___VA_COPY 1
294*2b15cb3dSCy Schubert #endif	/* !defined(HAVE___VA_COPY) */
295*2b15cb3dSCy Schubert #endif	/* HAVE_CONFIG_H */
296*2b15cb3dSCy Schubert #define snprintf rpl_snprintf
297*2b15cb3dSCy Schubert #define vsnprintf rpl_vsnprintf
298*2b15cb3dSCy Schubert #define asprintf rpl_asprintf
299*2b15cb3dSCy Schubert #define vasprintf rpl_vasprintf
300*2b15cb3dSCy Schubert #endif	/* TEST_SNPRINTF */
301224ba2bdSOllivier Robert 
302*2b15cb3dSCy Schubert #if HW_WANT_RPL_SNPRINTF || HW_WANT_RPL_VSNPRINTF || HW_WANT_RPL_ASPRINTF || HW_WANT_RPL_VASPRINTF
303*2b15cb3dSCy Schubert #include <stdio.h>	/* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
304*2b15cb3dSCy Schubert #ifdef VA_START
305*2b15cb3dSCy Schubert #undef VA_START
306*2b15cb3dSCy Schubert #endif	/* defined(VA_START) */
307*2b15cb3dSCy Schubert #ifdef VA_SHIFT
308*2b15cb3dSCy Schubert #undef VA_SHIFT
309*2b15cb3dSCy Schubert #endif	/* defined(VA_SHIFT) */
310*2b15cb3dSCy Schubert #if HAVE_STDARG_H
311224ba2bdSOllivier Robert #include <stdarg.h>
312*2b15cb3dSCy Schubert #define VA_START(ap, last) va_start(ap, last)
313*2b15cb3dSCy Schubert #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
314*2b15cb3dSCy Schubert #else	/* Assume <varargs.h> is available. */
315224ba2bdSOllivier Robert #include <varargs.h>
316*2b15cb3dSCy Schubert #define VA_START(ap, last) va_start(ap)	/* "last" is ignored. */
317*2b15cb3dSCy Schubert #define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
318*2b15cb3dSCy Schubert #endif	/* HAVE_STDARG_H */
319224ba2bdSOllivier Robert 
320*2b15cb3dSCy Schubert #if HW_WANT_RPL_VASPRINTF
321*2b15cb3dSCy Schubert #if HAVE_STDLIB_H
322*2b15cb3dSCy Schubert #include <stdlib.h>	/* For malloc(3). */
323*2b15cb3dSCy Schubert #endif	/* HAVE_STDLIB_H */
324*2b15cb3dSCy Schubert #ifdef VA_COPY
325*2b15cb3dSCy Schubert #undef VA_COPY
326*2b15cb3dSCy Schubert #endif	/* defined(VA_COPY) */
327*2b15cb3dSCy Schubert #ifdef VA_END_COPY
328*2b15cb3dSCy Schubert #undef VA_END_COPY
329*2b15cb3dSCy Schubert #endif	/* defined(VA_END_COPY) */
330*2b15cb3dSCy Schubert #if HAVE_VA_COPY
331*2b15cb3dSCy Schubert #define VA_COPY(dest, src) va_copy(dest, src)
332*2b15cb3dSCy Schubert #define VA_END_COPY(ap) va_end(ap)
333*2b15cb3dSCy Schubert #elif HAVE___VA_COPY
334*2b15cb3dSCy Schubert #define VA_COPY(dest, src) __va_copy(dest, src)
335*2b15cb3dSCy Schubert #define VA_END_COPY(ap) va_end(ap)
336*2b15cb3dSCy Schubert #else
337*2b15cb3dSCy Schubert #define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list))
338*2b15cb3dSCy Schubert #define VA_END_COPY(ap) /* No-op. */
339*2b15cb3dSCy Schubert #define NEED_MYMEMCPY 1
340*2b15cb3dSCy Schubert static void *mymemcpy(void *, void *, size_t);
341*2b15cb3dSCy Schubert #endif	/* HAVE_VA_COPY */
342*2b15cb3dSCy Schubert #endif	/* HW_WANT_RPL_VASPRINTF */
3439c2daa00SOllivier Robert 
344*2b15cb3dSCy Schubert #if HW_WANT_RPL_VSNPRINTF
345*2b15cb3dSCy Schubert #include <errno.h>	/* For ERANGE and errno. */
346*2b15cb3dSCy Schubert #include <limits.h>	/* For *_MAX. */
347*2b15cb3dSCy Schubert #if HAVE_INTTYPES_H
348*2b15cb3dSCy Schubert #include <inttypes.h>	/* For intmax_t (if not defined in <stdint.h>). */
349*2b15cb3dSCy Schubert #endif	/* HAVE_INTTYPES_H */
350*2b15cb3dSCy Schubert #if HAVE_LOCALE_H
351*2b15cb3dSCy Schubert #include <locale.h>	/* For localeconv(3). */
352*2b15cb3dSCy Schubert #endif	/* HAVE_LOCALE_H */
353*2b15cb3dSCy Schubert #if HAVE_STDDEF_H
354*2b15cb3dSCy Schubert #include <stddef.h>	/* For ptrdiff_t. */
355*2b15cb3dSCy Schubert #endif	/* HAVE_STDDEF_H */
356*2b15cb3dSCy Schubert #if HAVE_STDINT_H
357*2b15cb3dSCy Schubert #include <stdint.h>	/* For intmax_t. */
358*2b15cb3dSCy Schubert #endif	/* HAVE_STDINT_H */
359*2b15cb3dSCy Schubert 
360*2b15cb3dSCy Schubert /* Support for unsigned long long int.  We may also need ULLONG_MAX. */
361*2b15cb3dSCy Schubert #ifndef ULONG_MAX	/* We may need ULONG_MAX as a fallback. */
362*2b15cb3dSCy Schubert #ifdef UINT_MAX
363*2b15cb3dSCy Schubert #define ULONG_MAX UINT_MAX
364224ba2bdSOllivier Robert #else
365*2b15cb3dSCy Schubert #define ULONG_MAX INT_MAX
366*2b15cb3dSCy Schubert #endif	/* defined(UINT_MAX) */
367*2b15cb3dSCy Schubert #endif	/* !defined(ULONG_MAX) */
368*2b15cb3dSCy Schubert #ifdef ULLONG
369*2b15cb3dSCy Schubert #undef ULLONG
370*2b15cb3dSCy Schubert #endif	/* defined(ULLONG) */
371*2b15cb3dSCy Schubert #if HAVE_UNSIGNED_LONG_LONG_INT
372*2b15cb3dSCy Schubert #define ULLONG unsigned long long int
373*2b15cb3dSCy Schubert #ifndef ULLONG_MAX
374*2b15cb3dSCy Schubert #define ULLONG_MAX ULONG_MAX
375*2b15cb3dSCy Schubert #endif	/* !defined(ULLONG_MAX) */
376224ba2bdSOllivier Robert #else
377*2b15cb3dSCy Schubert #define ULLONG unsigned long int
378*2b15cb3dSCy Schubert #ifdef ULLONG_MAX
379*2b15cb3dSCy Schubert #undef ULLONG_MAX
380*2b15cb3dSCy Schubert #endif	/* defined(ULLONG_MAX) */
381*2b15cb3dSCy Schubert #define ULLONG_MAX ULONG_MAX
382*2b15cb3dSCy Schubert #endif	/* HAVE_LONG_LONG_INT */
383*2b15cb3dSCy Schubert 
384*2b15cb3dSCy Schubert /* Support for uintmax_t.  We also need UINTMAX_MAX. */
385*2b15cb3dSCy Schubert #ifdef UINTMAX_T
386*2b15cb3dSCy Schubert #undef UINTMAX_T
387*2b15cb3dSCy Schubert #endif	/* defined(UINTMAX_T) */
388*2b15cb3dSCy Schubert #if HAVE_UINTMAX_T || defined(uintmax_t)
389*2b15cb3dSCy Schubert #define UINTMAX_T uintmax_t
390*2b15cb3dSCy Schubert #ifndef UINTMAX_MAX
391*2b15cb3dSCy Schubert #define UINTMAX_MAX ULLONG_MAX
392*2b15cb3dSCy Schubert #endif	/* !defined(UINTMAX_MAX) */
393224ba2bdSOllivier Robert #else
394*2b15cb3dSCy Schubert #define UINTMAX_T ULLONG
395*2b15cb3dSCy Schubert #ifdef UINTMAX_MAX
396*2b15cb3dSCy Schubert #undef UINTMAX_MAX
397*2b15cb3dSCy Schubert #endif	/* defined(UINTMAX_MAX) */
398*2b15cb3dSCy Schubert #define UINTMAX_MAX ULLONG_MAX
399*2b15cb3dSCy Schubert #endif	/* HAVE_UINTMAX_T || defined(uintmax_t) */
400*2b15cb3dSCy Schubert 
401*2b15cb3dSCy Schubert /* Support for long double. */
402*2b15cb3dSCy Schubert #ifndef LDOUBLE
403*2b15cb3dSCy Schubert #if HAVE_LONG_DOUBLE
404*2b15cb3dSCy Schubert #define LDOUBLE long double
405*2b15cb3dSCy Schubert #else
406*2b15cb3dSCy Schubert #define LDOUBLE double
407*2b15cb3dSCy Schubert #endif	/* HAVE_LONG_DOUBLE */
408*2b15cb3dSCy Schubert #endif	/* !defined(LDOUBLE) */
409*2b15cb3dSCy Schubert 
410*2b15cb3dSCy Schubert /* Support for long long int. */
411*2b15cb3dSCy Schubert #ifndef LLONG
412*2b15cb3dSCy Schubert #if HAVE_LONG_LONG_INT
413*2b15cb3dSCy Schubert #define LLONG long long int
414*2b15cb3dSCy Schubert #else
415*2b15cb3dSCy Schubert #define LLONG long int
416*2b15cb3dSCy Schubert #endif	/* HAVE_LONG_LONG_INT */
417*2b15cb3dSCy Schubert #endif	/* !defined(LLONG) */
418*2b15cb3dSCy Schubert 
419*2b15cb3dSCy Schubert /* Support for intmax_t. */
420*2b15cb3dSCy Schubert #ifndef INTMAX_T
421*2b15cb3dSCy Schubert #if HAVE_INTMAX_T || defined(intmax_t)
422*2b15cb3dSCy Schubert #define INTMAX_T intmax_t
423*2b15cb3dSCy Schubert #else
424*2b15cb3dSCy Schubert #define INTMAX_T LLONG
425*2b15cb3dSCy Schubert #endif	/* HAVE_INTMAX_T || defined(intmax_t) */
426*2b15cb3dSCy Schubert #endif	/* !defined(INTMAX_T) */
427*2b15cb3dSCy Schubert 
428*2b15cb3dSCy Schubert /* Support for uintptr_t. */
429*2b15cb3dSCy Schubert #ifndef UINTPTR_T
430*2b15cb3dSCy Schubert #if HAVE_UINTPTR_T || defined(uintptr_t)
431*2b15cb3dSCy Schubert #define UINTPTR_T uintptr_t
432*2b15cb3dSCy Schubert #else
433*2b15cb3dSCy Schubert #define UINTPTR_T unsigned long int
434*2b15cb3dSCy Schubert #endif	/* HAVE_UINTPTR_T || defined(uintptr_t) */
435*2b15cb3dSCy Schubert #endif	/* !defined(UINTPTR_T) */
436*2b15cb3dSCy Schubert 
437*2b15cb3dSCy Schubert /* Support for ptrdiff_t. */
438*2b15cb3dSCy Schubert #ifndef PTRDIFF_T
439*2b15cb3dSCy Schubert #if HAVE_PTRDIFF_T || defined(ptrdiff_t)
440*2b15cb3dSCy Schubert #define PTRDIFF_T ptrdiff_t
441*2b15cb3dSCy Schubert #else
442*2b15cb3dSCy Schubert #define PTRDIFF_T long int
443*2b15cb3dSCy Schubert #endif	/* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
444*2b15cb3dSCy Schubert #endif	/* !defined(PTRDIFF_T) */
445*2b15cb3dSCy Schubert 
446*2b15cb3dSCy Schubert /*
447*2b15cb3dSCy Schubert  * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
448*2b15cb3dSCy Schubert  * 7.19.6.1, 7).  However, we'll simply use PTRDIFF_T and convert it to an
449*2b15cb3dSCy Schubert  * unsigned type if necessary.  This should work just fine in practice.
450*2b15cb3dSCy Schubert  */
451*2b15cb3dSCy Schubert #ifndef UPTRDIFF_T
452*2b15cb3dSCy Schubert #define UPTRDIFF_T PTRDIFF_T
453*2b15cb3dSCy Schubert #endif	/* !defined(UPTRDIFF_T) */
454*2b15cb3dSCy Schubert 
455*2b15cb3dSCy Schubert /*
456*2b15cb3dSCy Schubert  * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
457*2b15cb3dSCy Schubert  * However, we'll simply use size_t and convert it to a signed type if
458*2b15cb3dSCy Schubert  * necessary.  This should work just fine in practice.
459*2b15cb3dSCy Schubert  */
460*2b15cb3dSCy Schubert #ifndef SSIZE_T
461*2b15cb3dSCy Schubert #define SSIZE_T size_t
462*2b15cb3dSCy Schubert #endif	/* !defined(SSIZE_T) */
463*2b15cb3dSCy Schubert 
464*2b15cb3dSCy Schubert /* Either ERANGE or E2BIG should be available everywhere. */
465*2b15cb3dSCy Schubert #ifndef ERANGE
466*2b15cb3dSCy Schubert #define ERANGE E2BIG
467*2b15cb3dSCy Schubert #endif	/* !defined(ERANGE) */
468*2b15cb3dSCy Schubert #ifndef EOVERFLOW
469*2b15cb3dSCy Schubert #define EOVERFLOW ERANGE
470*2b15cb3dSCy Schubert #endif	/* !defined(EOVERFLOW) */
471*2b15cb3dSCy Schubert 
472*2b15cb3dSCy Schubert /*
473*2b15cb3dSCy Schubert  * Buffer size to hold the octal string representation of UINT128_MAX without
474*2b15cb3dSCy Schubert  * nul-termination ("3777777777777777777777777777777777777777777").
475*2b15cb3dSCy Schubert  */
476*2b15cb3dSCy Schubert #ifdef MAX_CONVERT_LENGTH
477*2b15cb3dSCy Schubert #undef MAX_CONVERT_LENGTH
478*2b15cb3dSCy Schubert #endif	/* defined(MAX_CONVERT_LENGTH) */
479*2b15cb3dSCy Schubert #define MAX_CONVERT_LENGTH      43
480*2b15cb3dSCy Schubert 
481*2b15cb3dSCy Schubert /* Format read states. */
482*2b15cb3dSCy Schubert #define PRINT_S_DEFAULT         0
483*2b15cb3dSCy Schubert #define PRINT_S_FLAGS           1
484*2b15cb3dSCy Schubert #define PRINT_S_WIDTH           2
485*2b15cb3dSCy Schubert #define PRINT_S_DOT             3
486*2b15cb3dSCy Schubert #define PRINT_S_PRECISION       4
487*2b15cb3dSCy Schubert #define PRINT_S_MOD             5
488*2b15cb3dSCy Schubert #define PRINT_S_CONV            6
489*2b15cb3dSCy Schubert 
490*2b15cb3dSCy Schubert /* Format flags. */
491*2b15cb3dSCy Schubert #define PRINT_F_MINUS           (1 << 0)
492*2b15cb3dSCy Schubert #define PRINT_F_PLUS            (1 << 1)
493*2b15cb3dSCy Schubert #define PRINT_F_SPACE           (1 << 2)
494*2b15cb3dSCy Schubert #define PRINT_F_NUM             (1 << 3)
495*2b15cb3dSCy Schubert #define PRINT_F_ZERO            (1 << 4)
496*2b15cb3dSCy Schubert #define PRINT_F_QUOTE           (1 << 5)
497*2b15cb3dSCy Schubert #define PRINT_F_UP              (1 << 6)
498*2b15cb3dSCy Schubert #define PRINT_F_UNSIGNED        (1 << 7)
499*2b15cb3dSCy Schubert #define PRINT_F_TYPE_G          (1 << 8)
500*2b15cb3dSCy Schubert #define PRINT_F_TYPE_E          (1 << 9)
501*2b15cb3dSCy Schubert 
502*2b15cb3dSCy Schubert /* Conversion flags. */
503*2b15cb3dSCy Schubert #define PRINT_C_CHAR            1
504*2b15cb3dSCy Schubert #define PRINT_C_SHORT           2
505*2b15cb3dSCy Schubert #define PRINT_C_LONG            3
506*2b15cb3dSCy Schubert #define PRINT_C_LLONG           4
507*2b15cb3dSCy Schubert #define PRINT_C_LDOUBLE         5
508*2b15cb3dSCy Schubert #define PRINT_C_SIZE            6
509*2b15cb3dSCy Schubert #define PRINT_C_PTRDIFF         7
510*2b15cb3dSCy Schubert #define PRINT_C_INTMAX          8
511*2b15cb3dSCy Schubert 
512*2b15cb3dSCy Schubert #ifndef MAX
513*2b15cb3dSCy Schubert #define MAX(x, y) ((x >= y) ? x : y)
514*2b15cb3dSCy Schubert #endif	/* !defined(MAX) */
515*2b15cb3dSCy Schubert #ifndef CHARTOINT
516*2b15cb3dSCy Schubert #define CHARTOINT(ch) (ch - '0')
517*2b15cb3dSCy Schubert #endif	/* !defined(CHARTOINT) */
518*2b15cb3dSCy Schubert #ifndef ISDIGIT
519*2b15cb3dSCy Schubert #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
520*2b15cb3dSCy Schubert #endif	/* !defined(ISDIGIT) */
521*2b15cb3dSCy Schubert #ifndef ISNAN
522*2b15cb3dSCy Schubert #define ISNAN(x) (x != x)
523*2b15cb3dSCy Schubert #endif	/* !defined(ISNAN) */
524*2b15cb3dSCy Schubert #ifndef ISINF
525*2b15cb3dSCy Schubert #define ISINF(x) (x != 0.0 && x + x == x)
526*2b15cb3dSCy Schubert #endif	/* !defined(ISINF) */
527*2b15cb3dSCy Schubert 
528*2b15cb3dSCy Schubert #ifdef OUTCHAR
529*2b15cb3dSCy Schubert #undef OUTCHAR
530*2b15cb3dSCy Schubert #endif	/* defined(OUTCHAR) */
531*2b15cb3dSCy Schubert #define OUTCHAR(str, len, size, ch)                                          \
532*2b15cb3dSCy Schubert do {                                                                         \
533*2b15cb3dSCy Schubert 	if (len + 1 < size)                                                  \
534*2b15cb3dSCy Schubert 		str[len] = ch;                                               \
535*2b15cb3dSCy Schubert 	(len)++;                                                             \
536*2b15cb3dSCy Schubert } while (/* CONSTCOND */ 0)
537*2b15cb3dSCy Schubert 
538*2b15cb3dSCy Schubert static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
539*2b15cb3dSCy Schubert static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
540*2b15cb3dSCy Schubert static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
541*2b15cb3dSCy Schubert static void printsep(char *, size_t *, size_t);
542*2b15cb3dSCy Schubert static int getnumsep(int);
543*2b15cb3dSCy Schubert static int getexponent(LDOUBLE);
544*2b15cb3dSCy Schubert static int convert(UINTMAX_T, char *, size_t, int, int);
545*2b15cb3dSCy Schubert static UINTMAX_T cast(LDOUBLE);
546*2b15cb3dSCy Schubert static UINTMAX_T myround(LDOUBLE);
547*2b15cb3dSCy Schubert static LDOUBLE mypow10(int);
548224ba2bdSOllivier Robert 
549224ba2bdSOllivier Robert int
550*2b15cb3dSCy Schubert rpl_vsnprintf(char *str, size_t size, const char *format, va_list args);
551*2b15cb3dSCy Schubert 
552*2b15cb3dSCy Schubert int
553*2b15cb3dSCy Schubert rpl_vsnprintf(char *str, size_t size, const char *format, va_list args)
554224ba2bdSOllivier Robert {
555*2b15cb3dSCy Schubert 	LDOUBLE fvalue;
556*2b15cb3dSCy Schubert 	INTMAX_T value;
557*2b15cb3dSCy Schubert 	unsigned char cvalue;
558*2b15cb3dSCy Schubert 	const char *strvalue;
559*2b15cb3dSCy Schubert 	INTMAX_T *intmaxptr;
560*2b15cb3dSCy Schubert 	PTRDIFF_T *ptrdiffptr;
561*2b15cb3dSCy Schubert 	SSIZE_T *sizeptr;
562*2b15cb3dSCy Schubert 	LLONG *llongptr;
563*2b15cb3dSCy Schubert 	long int *longptr;
564*2b15cb3dSCy Schubert 	int *intptr;
565*2b15cb3dSCy Schubert 	short int *shortptr;
566*2b15cb3dSCy Schubert 	signed char *charptr;
567*2b15cb3dSCy Schubert 	size_t len = 0;
568*2b15cb3dSCy Schubert 	int overflow = 0;
569*2b15cb3dSCy Schubert 	int base = 0;
570*2b15cb3dSCy Schubert 	int cflags = 0;
571*2b15cb3dSCy Schubert 	int flags = 0;
572*2b15cb3dSCy Schubert 	int width = 0;
573*2b15cb3dSCy Schubert 	int precision = -1;
574*2b15cb3dSCy Schubert 	int state = PRINT_S_DEFAULT;
575*2b15cb3dSCy Schubert 	char ch = *format++;
576*2b15cb3dSCy Schubert 
577*2b15cb3dSCy Schubert 	/*
578*2b15cb3dSCy Schubert 	 * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
579*2b15cb3dSCy Schubert 	 * pointer." (7.19.6.5, 2)  We're forgiving and allow a NULL pointer
580*2b15cb3dSCy Schubert 	 * even if a size larger than zero was specified.  At least NetBSD's
581*2b15cb3dSCy Schubert 	 * snprintf(3) does the same, as well as other versions of this file.
582*2b15cb3dSCy Schubert 	 * (Though some of these versions will write to a non-NULL buffer even
583*2b15cb3dSCy Schubert 	 * if a size of zero was specified, which violates the standard.)
584*2b15cb3dSCy Schubert 	 */
585*2b15cb3dSCy Schubert 	if (str == NULL && size != 0)
586*2b15cb3dSCy Schubert 		size = 0;
587*2b15cb3dSCy Schubert 
588*2b15cb3dSCy Schubert 	while (ch != '\0')
589*2b15cb3dSCy Schubert 		switch (state) {
590*2b15cb3dSCy Schubert 		case PRINT_S_DEFAULT:
591*2b15cb3dSCy Schubert 			if (ch == '%')
592*2b15cb3dSCy Schubert 				state = PRINT_S_FLAGS;
593*2b15cb3dSCy Schubert 			else
594*2b15cb3dSCy Schubert 				OUTCHAR(str, len, size, ch);
595*2b15cb3dSCy Schubert 			ch = *format++;
596*2b15cb3dSCy Schubert 			break;
597*2b15cb3dSCy Schubert 		case PRINT_S_FLAGS:
598*2b15cb3dSCy Schubert 			switch (ch) {
599*2b15cb3dSCy Schubert 			case '-':
600*2b15cb3dSCy Schubert 				flags |= PRINT_F_MINUS;
601*2b15cb3dSCy Schubert 				ch = *format++;
602*2b15cb3dSCy Schubert 				break;
603*2b15cb3dSCy Schubert 			case '+':
604*2b15cb3dSCy Schubert 				flags |= PRINT_F_PLUS;
605*2b15cb3dSCy Schubert 				ch = *format++;
606*2b15cb3dSCy Schubert 				break;
607*2b15cb3dSCy Schubert 			case ' ':
608*2b15cb3dSCy Schubert 				flags |= PRINT_F_SPACE;
609*2b15cb3dSCy Schubert 				ch = *format++;
610*2b15cb3dSCy Schubert 				break;
611*2b15cb3dSCy Schubert 			case '#':
612*2b15cb3dSCy Schubert 				flags |= PRINT_F_NUM;
613*2b15cb3dSCy Schubert 				ch = *format++;
614*2b15cb3dSCy Schubert 				break;
615*2b15cb3dSCy Schubert 			case '0':
616*2b15cb3dSCy Schubert 				flags |= PRINT_F_ZERO;
617*2b15cb3dSCy Schubert 				ch = *format++;
618*2b15cb3dSCy Schubert 				break;
619*2b15cb3dSCy Schubert 			case '\'':	/* SUSv2 flag (not in C99). */
620*2b15cb3dSCy Schubert 				flags |= PRINT_F_QUOTE;
621*2b15cb3dSCy Schubert 				ch = *format++;
622*2b15cb3dSCy Schubert 				break;
623*2b15cb3dSCy Schubert 			default:
624*2b15cb3dSCy Schubert 				state = PRINT_S_WIDTH;
625*2b15cb3dSCy Schubert 				break;
626224ba2bdSOllivier Robert 			}
627*2b15cb3dSCy Schubert 			break;
628*2b15cb3dSCy Schubert 		case PRINT_S_WIDTH:
629*2b15cb3dSCy Schubert 			if (ISDIGIT(ch)) {
630*2b15cb3dSCy Schubert 				ch = CHARTOINT(ch);
631*2b15cb3dSCy Schubert 				if (width > (INT_MAX - ch) / 10) {
632*2b15cb3dSCy Schubert 					overflow = 1;
633*2b15cb3dSCy Schubert 					goto out;
634*2b15cb3dSCy Schubert 				}
635*2b15cb3dSCy Schubert 				width = 10 * width + ch;
636*2b15cb3dSCy Schubert 				ch = *format++;
637*2b15cb3dSCy Schubert 			} else if (ch == '*') {
638*2b15cb3dSCy Schubert 				/*
639*2b15cb3dSCy Schubert 				 * C99 says: "A negative field width argument is
640*2b15cb3dSCy Schubert 				 * taken as a `-' flag followed by a positive
641*2b15cb3dSCy Schubert 				 * field width." (7.19.6.1, 5)
642*2b15cb3dSCy Schubert 				 */
643*2b15cb3dSCy Schubert 				if ((width = va_arg(args, int)) < 0) {
644*2b15cb3dSCy Schubert 					flags |= PRINT_F_MINUS;
645*2b15cb3dSCy Schubert 					width = -width;
646*2b15cb3dSCy Schubert 				}
647*2b15cb3dSCy Schubert 				ch = *format++;
648*2b15cb3dSCy Schubert 				state = PRINT_S_DOT;
649*2b15cb3dSCy Schubert 			} else
650*2b15cb3dSCy Schubert 				state = PRINT_S_DOT;
651*2b15cb3dSCy Schubert 			break;
652*2b15cb3dSCy Schubert 		case PRINT_S_DOT:
653*2b15cb3dSCy Schubert 			if (ch == '.') {
654*2b15cb3dSCy Schubert 				state = PRINT_S_PRECISION;
655*2b15cb3dSCy Schubert 				ch = *format++;
656*2b15cb3dSCy Schubert 			} else
657*2b15cb3dSCy Schubert 				state = PRINT_S_MOD;
658*2b15cb3dSCy Schubert 			break;
659*2b15cb3dSCy Schubert 		case PRINT_S_PRECISION:
660*2b15cb3dSCy Schubert 			if (precision == -1)
661*2b15cb3dSCy Schubert 				precision = 0;
662*2b15cb3dSCy Schubert 			if (ISDIGIT(ch)) {
663*2b15cb3dSCy Schubert 				ch = CHARTOINT(ch);
664*2b15cb3dSCy Schubert 				if (precision > (INT_MAX - ch) / 10) {
665*2b15cb3dSCy Schubert 					overflow = 1;
666*2b15cb3dSCy Schubert 					goto out;
667*2b15cb3dSCy Schubert 				}
668*2b15cb3dSCy Schubert 				precision = 10 * precision + ch;
669*2b15cb3dSCy Schubert 				ch = *format++;
670*2b15cb3dSCy Schubert 			} else if (ch == '*') {
671*2b15cb3dSCy Schubert 				/*
672*2b15cb3dSCy Schubert 				 * C99 says: "A negative precision argument is
673*2b15cb3dSCy Schubert 				 * taken as if the precision were omitted."
674*2b15cb3dSCy Schubert 				 * (7.19.6.1, 5)
675*2b15cb3dSCy Schubert 				 */
676*2b15cb3dSCy Schubert 				if ((precision = va_arg(args, int)) < 0)
677*2b15cb3dSCy Schubert 					precision = -1;
678*2b15cb3dSCy Schubert 				ch = *format++;
679*2b15cb3dSCy Schubert 				state = PRINT_S_MOD;
680*2b15cb3dSCy Schubert 			} else
681*2b15cb3dSCy Schubert 				state = PRINT_S_MOD;
682*2b15cb3dSCy Schubert 			break;
683*2b15cb3dSCy Schubert 		case PRINT_S_MOD:
684*2b15cb3dSCy Schubert 			switch (ch) {
685*2b15cb3dSCy Schubert 			case 'h':
686*2b15cb3dSCy Schubert 				ch = *format++;
687*2b15cb3dSCy Schubert 				if (ch == 'h') {	/* It's a char. */
688*2b15cb3dSCy Schubert 					ch = *format++;
689*2b15cb3dSCy Schubert 					cflags = PRINT_C_CHAR;
690*2b15cb3dSCy Schubert 				} else
691*2b15cb3dSCy Schubert 					cflags = PRINT_C_SHORT;
692*2b15cb3dSCy Schubert 				break;
693*2b15cb3dSCy Schubert 			case 'l':
694*2b15cb3dSCy Schubert 				ch = *format++;
695*2b15cb3dSCy Schubert 				if (ch == 'l') {	/* It's a long long. */
696*2b15cb3dSCy Schubert 					ch = *format++;
697*2b15cb3dSCy Schubert 					cflags = PRINT_C_LLONG;
698*2b15cb3dSCy Schubert 				} else
699*2b15cb3dSCy Schubert 					cflags = PRINT_C_LONG;
700*2b15cb3dSCy Schubert 				break;
701*2b15cb3dSCy Schubert 			case 'L':
702*2b15cb3dSCy Schubert 				cflags = PRINT_C_LDOUBLE;
703*2b15cb3dSCy Schubert 				ch = *format++;
704*2b15cb3dSCy Schubert 				break;
705*2b15cb3dSCy Schubert 			case 'j':
706*2b15cb3dSCy Schubert 				cflags = PRINT_C_INTMAX;
707*2b15cb3dSCy Schubert 				ch = *format++;
708*2b15cb3dSCy Schubert 				break;
709*2b15cb3dSCy Schubert 			case 't':
710*2b15cb3dSCy Schubert 				cflags = PRINT_C_PTRDIFF;
711*2b15cb3dSCy Schubert 				ch = *format++;
712*2b15cb3dSCy Schubert 				break;
713*2b15cb3dSCy Schubert 			case 'z':
714*2b15cb3dSCy Schubert 				cflags = PRINT_C_SIZE;
715*2b15cb3dSCy Schubert 				ch = *format++;
716*2b15cb3dSCy Schubert 				break;
717*2b15cb3dSCy Schubert 			}
718*2b15cb3dSCy Schubert 			state = PRINT_S_CONV;
719*2b15cb3dSCy Schubert 			break;
720*2b15cb3dSCy Schubert 		case PRINT_S_CONV:
721*2b15cb3dSCy Schubert 			switch (ch) {
722*2b15cb3dSCy Schubert 			case 'd':
723*2b15cb3dSCy Schubert 				/* FALLTHROUGH */
724*2b15cb3dSCy Schubert 			case 'i':
725*2b15cb3dSCy Schubert 				switch (cflags) {
726*2b15cb3dSCy Schubert 				case PRINT_C_CHAR:
727*2b15cb3dSCy Schubert 					value = (signed char)va_arg(args, int);
728*2b15cb3dSCy Schubert 					break;
729*2b15cb3dSCy Schubert 				case PRINT_C_SHORT:
730*2b15cb3dSCy Schubert 					value = (short int)va_arg(args, int);
731*2b15cb3dSCy Schubert 					break;
732*2b15cb3dSCy Schubert 				case PRINT_C_LONG:
733*2b15cb3dSCy Schubert 					value = va_arg(args, long int);
734*2b15cb3dSCy Schubert 					break;
735*2b15cb3dSCy Schubert 				case PRINT_C_LLONG:
736*2b15cb3dSCy Schubert 					value = va_arg(args, LLONG);
737*2b15cb3dSCy Schubert 					break;
738*2b15cb3dSCy Schubert 				case PRINT_C_SIZE:
739*2b15cb3dSCy Schubert 					value = va_arg(args, SSIZE_T);
740*2b15cb3dSCy Schubert 					break;
741*2b15cb3dSCy Schubert 				case PRINT_C_INTMAX:
742*2b15cb3dSCy Schubert 					value = va_arg(args, INTMAX_T);
743*2b15cb3dSCy Schubert 					break;
744*2b15cb3dSCy Schubert 				case PRINT_C_PTRDIFF:
745*2b15cb3dSCy Schubert 					value = va_arg(args, PTRDIFF_T);
746*2b15cb3dSCy Schubert 					break;
747*2b15cb3dSCy Schubert 				default:
748*2b15cb3dSCy Schubert 					value = va_arg(args, int);
749*2b15cb3dSCy Schubert 					break;
750*2b15cb3dSCy Schubert 				}
751*2b15cb3dSCy Schubert 				fmtint(str, &len, size, value, 10, width,
752*2b15cb3dSCy Schubert 				    precision, flags);
753*2b15cb3dSCy Schubert 				break;
754*2b15cb3dSCy Schubert 			case 'X':
755*2b15cb3dSCy Schubert 				flags |= PRINT_F_UP;
756*2b15cb3dSCy Schubert 				/* FALLTHROUGH */
757*2b15cb3dSCy Schubert 			case 'x':
758*2b15cb3dSCy Schubert 				base = 16;
759*2b15cb3dSCy Schubert 				/* FALLTHROUGH */
760*2b15cb3dSCy Schubert 			case 'o':
761*2b15cb3dSCy Schubert 				if (base == 0)
762*2b15cb3dSCy Schubert 					base = 8;
763*2b15cb3dSCy Schubert 				/* FALLTHROUGH */
764*2b15cb3dSCy Schubert 			case 'u':
765*2b15cb3dSCy Schubert 				if (base == 0)
766*2b15cb3dSCy Schubert 					base = 10;
767*2b15cb3dSCy Schubert 				flags |= PRINT_F_UNSIGNED;
768*2b15cb3dSCy Schubert 				switch (cflags) {
769*2b15cb3dSCy Schubert 				case PRINT_C_CHAR:
770*2b15cb3dSCy Schubert 					value = (unsigned char)va_arg(args,
771*2b15cb3dSCy Schubert 					    unsigned int);
772*2b15cb3dSCy Schubert 					break;
773*2b15cb3dSCy Schubert 				case PRINT_C_SHORT:
774*2b15cb3dSCy Schubert 					value = (unsigned short int)va_arg(args,
775*2b15cb3dSCy Schubert 					    unsigned int);
776*2b15cb3dSCy Schubert 					break;
777*2b15cb3dSCy Schubert 				case PRINT_C_LONG:
778*2b15cb3dSCy Schubert 					value = va_arg(args, unsigned long int);
779*2b15cb3dSCy Schubert 					break;
780*2b15cb3dSCy Schubert 				case PRINT_C_LLONG:
781*2b15cb3dSCy Schubert 					value = va_arg(args, ULLONG);
782*2b15cb3dSCy Schubert 					break;
783*2b15cb3dSCy Schubert 				case PRINT_C_SIZE:
784*2b15cb3dSCy Schubert 					value = va_arg(args, size_t);
785*2b15cb3dSCy Schubert 					break;
786*2b15cb3dSCy Schubert 				case PRINT_C_INTMAX:
787*2b15cb3dSCy Schubert 					value = va_arg(args, UINTMAX_T);
788*2b15cb3dSCy Schubert 					break;
789*2b15cb3dSCy Schubert 				case PRINT_C_PTRDIFF:
790*2b15cb3dSCy Schubert 					value = va_arg(args, UPTRDIFF_T);
791*2b15cb3dSCy Schubert 					break;
792*2b15cb3dSCy Schubert 				default:
793*2b15cb3dSCy Schubert 					value = va_arg(args, unsigned int);
794*2b15cb3dSCy Schubert 					break;
795*2b15cb3dSCy Schubert 				}
796*2b15cb3dSCy Schubert 				fmtint(str, &len, size, value, base, width,
797*2b15cb3dSCy Schubert 				    precision, flags);
798*2b15cb3dSCy Schubert 				break;
799*2b15cb3dSCy Schubert 			case 'A':
800*2b15cb3dSCy Schubert 				/* Not yet supported, we'll use "%F". */
801*2b15cb3dSCy Schubert 				/* FALLTHROUGH */
802*2b15cb3dSCy Schubert 			case 'F':
803*2b15cb3dSCy Schubert 				flags |= PRINT_F_UP;
804*2b15cb3dSCy Schubert 				/* FALLTHROUGH */
805*2b15cb3dSCy Schubert 			case 'a':
806*2b15cb3dSCy Schubert 				/* Not yet supported, we'll use "%f". */
807*2b15cb3dSCy Schubert 				/* FALLTHROUGH */
808*2b15cb3dSCy Schubert 			case 'f':
809*2b15cb3dSCy Schubert 				if (cflags == PRINT_C_LDOUBLE)
810*2b15cb3dSCy Schubert 					fvalue = va_arg(args, LDOUBLE);
811*2b15cb3dSCy Schubert 				else
812*2b15cb3dSCy Schubert 					fvalue = va_arg(args, double);
813*2b15cb3dSCy Schubert 				fmtflt(str, &len, size, fvalue, width,
814*2b15cb3dSCy Schubert 				    precision, flags, &overflow);
815*2b15cb3dSCy Schubert 				if (overflow)
816*2b15cb3dSCy Schubert 					goto out;
817*2b15cb3dSCy Schubert 				break;
818*2b15cb3dSCy Schubert 			case 'E':
819*2b15cb3dSCy Schubert 				flags |= PRINT_F_UP;
820*2b15cb3dSCy Schubert 				/* FALLTHROUGH */
821*2b15cb3dSCy Schubert 			case 'e':
822*2b15cb3dSCy Schubert 				flags |= PRINT_F_TYPE_E;
823*2b15cb3dSCy Schubert 				if (cflags == PRINT_C_LDOUBLE)
824*2b15cb3dSCy Schubert 					fvalue = va_arg(args, LDOUBLE);
825*2b15cb3dSCy Schubert 				else
826*2b15cb3dSCy Schubert 					fvalue = va_arg(args, double);
827*2b15cb3dSCy Schubert 				fmtflt(str, &len, size, fvalue, width,
828*2b15cb3dSCy Schubert 				    precision, flags, &overflow);
829*2b15cb3dSCy Schubert 				if (overflow)
830*2b15cb3dSCy Schubert 					goto out;
831*2b15cb3dSCy Schubert 				break;
832*2b15cb3dSCy Schubert 			case 'G':
833*2b15cb3dSCy Schubert 				flags |= PRINT_F_UP;
834*2b15cb3dSCy Schubert 				/* FALLTHROUGH */
835*2b15cb3dSCy Schubert 			case 'g':
836*2b15cb3dSCy Schubert 				flags |= PRINT_F_TYPE_G;
837*2b15cb3dSCy Schubert 				if (cflags == PRINT_C_LDOUBLE)
838*2b15cb3dSCy Schubert 					fvalue = va_arg(args, LDOUBLE);
839*2b15cb3dSCy Schubert 				else
840*2b15cb3dSCy Schubert 					fvalue = va_arg(args, double);
841*2b15cb3dSCy Schubert 				/*
842*2b15cb3dSCy Schubert 				 * If the precision is zero, it is treated as
843*2b15cb3dSCy Schubert 				 * one (cf. C99: 7.19.6.1, 8).
844*2b15cb3dSCy Schubert 				 */
845*2b15cb3dSCy Schubert 				if (precision == 0)
846*2b15cb3dSCy Schubert 					precision = 1;
847*2b15cb3dSCy Schubert 				fmtflt(str, &len, size, fvalue, width,
848*2b15cb3dSCy Schubert 				    precision, flags, &overflow);
849*2b15cb3dSCy Schubert 				if (overflow)
850*2b15cb3dSCy Schubert 					goto out;
851*2b15cb3dSCy Schubert 				break;
852*2b15cb3dSCy Schubert 			case 'c':
853*2b15cb3dSCy Schubert 				cvalue = va_arg(args, int);
854*2b15cb3dSCy Schubert 				OUTCHAR(str, len, size, cvalue);
855*2b15cb3dSCy Schubert 				break;
856*2b15cb3dSCy Schubert 			case 's':
857*2b15cb3dSCy Schubert 				strvalue = va_arg(args, char *);
858*2b15cb3dSCy Schubert 				fmtstr(str, &len, size, strvalue, width,
859*2b15cb3dSCy Schubert 				    precision, flags);
860*2b15cb3dSCy Schubert 				break;
861*2b15cb3dSCy Schubert 			case 'p':
862*2b15cb3dSCy Schubert 				/*
863*2b15cb3dSCy Schubert 				 * C99 says: "The value of the pointer is
864*2b15cb3dSCy Schubert 				 * converted to a sequence of printing
865*2b15cb3dSCy Schubert 				 * characters, in an implementation-defined
866*2b15cb3dSCy Schubert 				 * manner." (C99: 7.19.6.1, 8)
867*2b15cb3dSCy Schubert 				 */
868*2b15cb3dSCy Schubert 				if ((strvalue = va_arg(args, void *)) == NULL)
869*2b15cb3dSCy Schubert 					/*
870*2b15cb3dSCy Schubert 					 * We use the glibc format.  BSD prints
871*2b15cb3dSCy Schubert 					 * "0x0", SysV "0".
872*2b15cb3dSCy Schubert 					 */
873*2b15cb3dSCy Schubert 					fmtstr(str, &len, size, "(nil)", width,
874*2b15cb3dSCy Schubert 					    -1, flags);
875*2b15cb3dSCy Schubert 				else {
876*2b15cb3dSCy Schubert 					/*
877*2b15cb3dSCy Schubert 					 * We use the BSD/glibc format.  SysV
878*2b15cb3dSCy Schubert 					 * omits the "0x" prefix (which we emit
879*2b15cb3dSCy Schubert 					 * using the PRINT_F_NUM flag).
880*2b15cb3dSCy Schubert 					 */
881*2b15cb3dSCy Schubert 					flags |= PRINT_F_NUM;
882*2b15cb3dSCy Schubert 					flags |= PRINT_F_UNSIGNED;
883*2b15cb3dSCy Schubert 					fmtint(str, &len, size,
884*2b15cb3dSCy Schubert 					    (UINTPTR_T)strvalue, 16, width,
885*2b15cb3dSCy Schubert 					    precision, flags);
886*2b15cb3dSCy Schubert 				}
887*2b15cb3dSCy Schubert 				break;
888*2b15cb3dSCy Schubert 			case 'n':
889*2b15cb3dSCy Schubert 				switch (cflags) {
890*2b15cb3dSCy Schubert 				case PRINT_C_CHAR:
891*2b15cb3dSCy Schubert 					charptr = va_arg(args, signed char *);
892*2b15cb3dSCy Schubert 					*charptr = len;
893*2b15cb3dSCy Schubert 					break;
894*2b15cb3dSCy Schubert 				case PRINT_C_SHORT:
895*2b15cb3dSCy Schubert 					shortptr = va_arg(args, short int *);
896*2b15cb3dSCy Schubert 					*shortptr = len;
897*2b15cb3dSCy Schubert 					break;
898*2b15cb3dSCy Schubert 				case PRINT_C_LONG:
899*2b15cb3dSCy Schubert 					longptr = va_arg(args, long int *);
900*2b15cb3dSCy Schubert 					*longptr = len;
901*2b15cb3dSCy Schubert 					break;
902*2b15cb3dSCy Schubert 				case PRINT_C_LLONG:
903*2b15cb3dSCy Schubert 					llongptr = va_arg(args, LLONG *);
904*2b15cb3dSCy Schubert 					*llongptr = len;
905*2b15cb3dSCy Schubert 					break;
906*2b15cb3dSCy Schubert 				case PRINT_C_SIZE:
907*2b15cb3dSCy Schubert 					/*
908*2b15cb3dSCy Schubert 					 * C99 says that with the "z" length
909*2b15cb3dSCy Schubert 					 * modifier, "a following `n' conversion
910*2b15cb3dSCy Schubert 					 * specifier applies to a pointer to a
911*2b15cb3dSCy Schubert 					 * signed integer type corresponding to
912*2b15cb3dSCy Schubert 					 * size_t argument." (7.19.6.1, 7)
913*2b15cb3dSCy Schubert 					 */
914*2b15cb3dSCy Schubert 					sizeptr = va_arg(args, SSIZE_T *);
915*2b15cb3dSCy Schubert 					*sizeptr = len;
916*2b15cb3dSCy Schubert 					break;
917*2b15cb3dSCy Schubert 				case PRINT_C_INTMAX:
918*2b15cb3dSCy Schubert 					intmaxptr = va_arg(args, INTMAX_T *);
919*2b15cb3dSCy Schubert 					*intmaxptr = len;
920*2b15cb3dSCy Schubert 					break;
921*2b15cb3dSCy Schubert 				case PRINT_C_PTRDIFF:
922*2b15cb3dSCy Schubert 					ptrdiffptr = va_arg(args, PTRDIFF_T *);
923*2b15cb3dSCy Schubert 					*ptrdiffptr = len;
924*2b15cb3dSCy Schubert 					break;
925*2b15cb3dSCy Schubert 				default:
926*2b15cb3dSCy Schubert 					intptr = va_arg(args, int *);
927*2b15cb3dSCy Schubert 					*intptr = len;
928*2b15cb3dSCy Schubert 					break;
929*2b15cb3dSCy Schubert 				}
930*2b15cb3dSCy Schubert 				break;
931*2b15cb3dSCy Schubert 			case '%':	/* Print a "%" character verbatim. */
932*2b15cb3dSCy Schubert 				OUTCHAR(str, len, size, ch);
933*2b15cb3dSCy Schubert 				break;
934*2b15cb3dSCy Schubert 			default:	/* Skip other characters. */
935*2b15cb3dSCy Schubert 				break;
936*2b15cb3dSCy Schubert 			}
937*2b15cb3dSCy Schubert 			ch = *format++;
938*2b15cb3dSCy Schubert 			state = PRINT_S_DEFAULT;
939*2b15cb3dSCy Schubert 			base = cflags = flags = width = 0;
940*2b15cb3dSCy Schubert 			precision = -1;
941*2b15cb3dSCy Schubert 			break;
942*2b15cb3dSCy Schubert 		}
943*2b15cb3dSCy Schubert out:
944*2b15cb3dSCy Schubert 	if (len < size)
945*2b15cb3dSCy Schubert 		str[len] = '\0';
946*2b15cb3dSCy Schubert 	else if (size > 0)
947*2b15cb3dSCy Schubert 		str[size - 1] = '\0';
948*2b15cb3dSCy Schubert 
949*2b15cb3dSCy Schubert 	if (overflow || len >= INT_MAX) {
950*2b15cb3dSCy Schubert 		errno = overflow ? EOVERFLOW : ERANGE;
951*2b15cb3dSCy Schubert 		return -1;
952*2b15cb3dSCy Schubert 	}
953*2b15cb3dSCy Schubert 	return (int)len;
954*2b15cb3dSCy Schubert }
955*2b15cb3dSCy Schubert 
956*2b15cb3dSCy Schubert static void
957*2b15cb3dSCy Schubert fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
958*2b15cb3dSCy Schubert        int precision, int flags)
959*2b15cb3dSCy Schubert {
960*2b15cb3dSCy Schubert 	int padlen, strln;	/* Amount to pad. */
961*2b15cb3dSCy Schubert 	int noprecision = (precision == -1);
962*2b15cb3dSCy Schubert 
963*2b15cb3dSCy Schubert 	if (value == NULL)	/* We're forgiving. */
964*2b15cb3dSCy Schubert 		value = "(null)";
965*2b15cb3dSCy Schubert 
966*2b15cb3dSCy Schubert 	/* If a precision was specified, don't read the string past it. */
967*2b15cb3dSCy Schubert 	for (strln = 0; value[strln] != '\0' &&
968*2b15cb3dSCy Schubert 	    (noprecision || strln < precision); strln++)
969*2b15cb3dSCy Schubert 		continue;
970*2b15cb3dSCy Schubert 
971*2b15cb3dSCy Schubert 	if ((padlen = width - strln) < 0)
972*2b15cb3dSCy Schubert 		padlen = 0;
973*2b15cb3dSCy Schubert 	if (flags & PRINT_F_MINUS)	/* Left justify. */
974*2b15cb3dSCy Schubert 		padlen = -padlen;
975*2b15cb3dSCy Schubert 
976*2b15cb3dSCy Schubert 	while (padlen > 0) {	/* Leading spaces. */
977*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, ' ');
978*2b15cb3dSCy Schubert 		padlen--;
979*2b15cb3dSCy Schubert 	}
980*2b15cb3dSCy Schubert 	while (*value != '\0' && (noprecision || precision-- > 0)) {
981*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, *value);
982*2b15cb3dSCy Schubert 		value++;
983*2b15cb3dSCy Schubert 	}
984*2b15cb3dSCy Schubert 	while (padlen < 0) {	/* Trailing spaces. */
985*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, ' ');
986*2b15cb3dSCy Schubert 		padlen++;
987*2b15cb3dSCy Schubert 	}
988*2b15cb3dSCy Schubert }
989*2b15cb3dSCy Schubert 
990*2b15cb3dSCy Schubert static void
991*2b15cb3dSCy Schubert fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
992*2b15cb3dSCy Schubert        int precision, int flags)
993*2b15cb3dSCy Schubert {
994*2b15cb3dSCy Schubert 	UINTMAX_T uvalue;
995*2b15cb3dSCy Schubert 	char iconvert[MAX_CONVERT_LENGTH];
996*2b15cb3dSCy Schubert 	char sign = 0;
997*2b15cb3dSCy Schubert 	char hexprefix = 0;
998*2b15cb3dSCy Schubert 	int spadlen = 0;	/* Amount to space pad. */
999*2b15cb3dSCy Schubert 	int zpadlen = 0;	/* Amount to zero pad. */
1000*2b15cb3dSCy Schubert 	int pos;
1001*2b15cb3dSCy Schubert 	int separators = (flags & PRINT_F_QUOTE);
1002*2b15cb3dSCy Schubert 	int noprecision = (precision == -1);
1003*2b15cb3dSCy Schubert 
1004*2b15cb3dSCy Schubert 	if (flags & PRINT_F_UNSIGNED)
1005*2b15cb3dSCy Schubert 		uvalue = value;
1006*2b15cb3dSCy Schubert 	else {
1007*2b15cb3dSCy Schubert 		uvalue = (value >= 0) ? value : -value;
1008*2b15cb3dSCy Schubert 		if (value < 0)
1009*2b15cb3dSCy Schubert 			sign = '-';
1010*2b15cb3dSCy Schubert 		else if (flags & PRINT_F_PLUS)	/* Do a sign. */
1011*2b15cb3dSCy Schubert 			sign = '+';
1012*2b15cb3dSCy Schubert 		else if (flags & PRINT_F_SPACE)
1013*2b15cb3dSCy Schubert 			sign = ' ';
1014*2b15cb3dSCy Schubert 	}
1015*2b15cb3dSCy Schubert 
1016*2b15cb3dSCy Schubert 	pos = convert(uvalue, iconvert, sizeof(iconvert), base,
1017*2b15cb3dSCy Schubert 	    flags & PRINT_F_UP);
1018*2b15cb3dSCy Schubert 
1019*2b15cb3dSCy Schubert 	if (flags & PRINT_F_NUM && uvalue != 0) {
1020*2b15cb3dSCy Schubert 		/*
1021*2b15cb3dSCy Schubert 		 * C99 says: "The result is converted to an `alternative form'.
1022*2b15cb3dSCy Schubert 		 * For `o' conversion, it increases the precision, if and only
1023*2b15cb3dSCy Schubert 		 * if necessary, to force the first digit of the result to be a
1024*2b15cb3dSCy Schubert 		 * zero (if the value and precision are both 0, a single 0 is
1025*2b15cb3dSCy Schubert 		 * printed).  For `x' (or `X') conversion, a nonzero result has
1026*2b15cb3dSCy Schubert 		 * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
1027*2b15cb3dSCy Schubert 		 */
1028*2b15cb3dSCy Schubert 		switch (base) {
1029*2b15cb3dSCy Schubert 		case 8:
1030*2b15cb3dSCy Schubert 			if (precision <= pos)
1031*2b15cb3dSCy Schubert 				precision = pos + 1;
1032*2b15cb3dSCy Schubert 			break;
1033*2b15cb3dSCy Schubert 		case 16:
1034*2b15cb3dSCy Schubert 			hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
1035*2b15cb3dSCy Schubert 			break;
1036*2b15cb3dSCy Schubert 		}
1037*2b15cb3dSCy Schubert 	}
1038*2b15cb3dSCy Schubert 
1039*2b15cb3dSCy Schubert 	if (separators)	/* Get the number of group separators we'll print. */
1040*2b15cb3dSCy Schubert 		separators = getnumsep(pos);
1041*2b15cb3dSCy Schubert 
1042*2b15cb3dSCy Schubert 	zpadlen = precision - pos - separators;
1043*2b15cb3dSCy Schubert 	spadlen = width                         /* Minimum field width. */
1044*2b15cb3dSCy Schubert 	    - separators                        /* Number of separators. */
1045*2b15cb3dSCy Schubert 	    - MAX(precision, pos)               /* Number of integer digits. */
1046*2b15cb3dSCy Schubert 	    - ((sign != 0) ? 1 : 0)             /* Will we print a sign? */
1047*2b15cb3dSCy Schubert 	    - ((hexprefix != 0) ? 2 : 0);       /* Will we print a prefix? */
1048*2b15cb3dSCy Schubert 
1049*2b15cb3dSCy Schubert 	if (zpadlen < 0)
1050*2b15cb3dSCy Schubert 		zpadlen = 0;
1051*2b15cb3dSCy Schubert 	if (spadlen < 0)
1052*2b15cb3dSCy Schubert 		spadlen = 0;
1053*2b15cb3dSCy Schubert 
1054*2b15cb3dSCy Schubert 	/*
1055*2b15cb3dSCy Schubert 	 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
1056*2b15cb3dSCy Schubert 	 * ignored.  For `d', `i', `o', `u', `x', and `X' conversions, if a
1057*2b15cb3dSCy Schubert 	 * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
1058*2b15cb3dSCy Schubert 	 */
1059*2b15cb3dSCy Schubert 	if (flags & PRINT_F_MINUS)	/* Left justify. */
1060*2b15cb3dSCy Schubert 		spadlen = -spadlen;
1061*2b15cb3dSCy Schubert 	else if (flags & PRINT_F_ZERO && noprecision) {
1062*2b15cb3dSCy Schubert 		zpadlen += spadlen;
1063*2b15cb3dSCy Schubert 		spadlen = 0;
1064*2b15cb3dSCy Schubert 	}
1065*2b15cb3dSCy Schubert 	while (spadlen > 0) {	/* Leading spaces. */
1066*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, ' ');
1067*2b15cb3dSCy Schubert 		spadlen--;
1068*2b15cb3dSCy Schubert 	}
1069*2b15cb3dSCy Schubert 	if (sign != 0)	/* Sign. */
1070*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, sign);
1071*2b15cb3dSCy Schubert 	if (hexprefix != 0) {	/* A "0x" or "0X" prefix. */
1072*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, '0');
1073*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, hexprefix);
1074*2b15cb3dSCy Schubert 	}
1075*2b15cb3dSCy Schubert 	while (zpadlen > 0) {	/* Leading zeros. */
1076*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, '0');
1077*2b15cb3dSCy Schubert 		zpadlen--;
1078*2b15cb3dSCy Schubert 	}
1079*2b15cb3dSCy Schubert 	while (pos > 0) {	/* The actual digits. */
1080*2b15cb3dSCy Schubert 		pos--;
1081*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, iconvert[pos]);
1082*2b15cb3dSCy Schubert 		if (separators > 0 && pos > 0 && pos % 3 == 0)
1083*2b15cb3dSCy Schubert 			printsep(str, len, size);
1084*2b15cb3dSCy Schubert 	}
1085*2b15cb3dSCy Schubert 	while (spadlen < 0) {	/* Trailing spaces. */
1086*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, ' ');
1087*2b15cb3dSCy Schubert 		spadlen++;
1088*2b15cb3dSCy Schubert 	}
1089*2b15cb3dSCy Schubert }
1090*2b15cb3dSCy Schubert 
1091*2b15cb3dSCy Schubert static void
1092*2b15cb3dSCy Schubert fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
1093*2b15cb3dSCy Schubert        int precision, int flags, int *overflow)
1094*2b15cb3dSCy Schubert {
1095*2b15cb3dSCy Schubert 	LDOUBLE ufvalue;
1096*2b15cb3dSCy Schubert 	UINTMAX_T intpart;
1097*2b15cb3dSCy Schubert 	UINTMAX_T fracpart;
1098*2b15cb3dSCy Schubert 	UINTMAX_T mask;
1099*2b15cb3dSCy Schubert 	const char *infnan = NULL;
1100*2b15cb3dSCy Schubert 	char iconvert[MAX_CONVERT_LENGTH];
1101*2b15cb3dSCy Schubert 	char fconvert[MAX_CONVERT_LENGTH];
1102*2b15cb3dSCy Schubert 	char econvert[4];	/* "e-12" (without nul-termination). */
1103*2b15cb3dSCy Schubert 	char esign = 0;
1104*2b15cb3dSCy Schubert 	char sign = 0;
1105*2b15cb3dSCy Schubert 	int leadfraczeros = 0;
1106*2b15cb3dSCy Schubert 	int exponent = 0;
1107*2b15cb3dSCy Schubert 	int emitpoint = 0;
1108*2b15cb3dSCy Schubert 	int omitzeros = 0;
1109*2b15cb3dSCy Schubert 	int omitcount = 0;
1110*2b15cb3dSCy Schubert 	int padlen = 0;
1111*2b15cb3dSCy Schubert 	int epos = 0;
1112*2b15cb3dSCy Schubert 	int fpos = 0;
1113*2b15cb3dSCy Schubert 	int ipos = 0;
1114*2b15cb3dSCy Schubert 	int separators = (flags & PRINT_F_QUOTE);
1115*2b15cb3dSCy Schubert 	int estyle = (flags & PRINT_F_TYPE_E);
1116*2b15cb3dSCy Schubert #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
1117*2b15cb3dSCy Schubert 	struct lconv *lc = localeconv();
1118*2b15cb3dSCy Schubert #endif	/* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
1119*2b15cb3dSCy Schubert 
1120*2b15cb3dSCy Schubert 	/*
1121*2b15cb3dSCy Schubert 	 * AIX' man page says the default is 0, but C99 and at least Solaris'
1122*2b15cb3dSCy Schubert 	 * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
1123*2b15cb3dSCy Schubert 	 * defaults to 6.
1124*2b15cb3dSCy Schubert 	 */
1125*2b15cb3dSCy Schubert 	if (precision == -1)
1126*2b15cb3dSCy Schubert 		precision = 6;
1127*2b15cb3dSCy Schubert 
1128*2b15cb3dSCy Schubert 	if (fvalue < 0.0)
1129*2b15cb3dSCy Schubert 		sign = '-';
1130*2b15cb3dSCy Schubert 	else if (flags & PRINT_F_PLUS)	/* Do a sign. */
1131*2b15cb3dSCy Schubert 		sign = '+';
1132*2b15cb3dSCy Schubert 	else if (flags & PRINT_F_SPACE)
1133*2b15cb3dSCy Schubert 		sign = ' ';
1134*2b15cb3dSCy Schubert 
1135*2b15cb3dSCy Schubert 	if (ISNAN(fvalue))
1136*2b15cb3dSCy Schubert 		infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
1137*2b15cb3dSCy Schubert 	else if (ISINF(fvalue))
1138*2b15cb3dSCy Schubert 		infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
1139*2b15cb3dSCy Schubert 
1140*2b15cb3dSCy Schubert 	if (infnan != NULL) {
1141*2b15cb3dSCy Schubert 		if (sign != 0)
1142*2b15cb3dSCy Schubert 			iconvert[ipos++] = sign;
1143*2b15cb3dSCy Schubert 		while (*infnan != '\0')
1144*2b15cb3dSCy Schubert 			iconvert[ipos++] = *infnan++;
1145*2b15cb3dSCy Schubert 		fmtstr(str, len, size, iconvert, width, ipos, flags);
1146*2b15cb3dSCy Schubert 		return;
1147*2b15cb3dSCy Schubert 	}
1148*2b15cb3dSCy Schubert 
1149*2b15cb3dSCy Schubert 	/* "%e" (or "%E") or "%g" (or "%G") conversion. */
1150*2b15cb3dSCy Schubert 	if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
1151*2b15cb3dSCy Schubert 		if (flags & PRINT_F_TYPE_G) {
1152*2b15cb3dSCy Schubert 			/*
1153*2b15cb3dSCy Schubert 			 * For "%g" (and "%G") conversions, the precision
1154*2b15cb3dSCy Schubert 			 * specifies the number of significant digits, which
1155*2b15cb3dSCy Schubert 			 * includes the digits in the integer part.  The
1156*2b15cb3dSCy Schubert 			 * conversion will or will not be using "e-style" (like
1157*2b15cb3dSCy Schubert 			 * "%e" or "%E" conversions) depending on the precision
1158*2b15cb3dSCy Schubert 			 * and on the exponent.  However, the exponent can be
1159*2b15cb3dSCy Schubert 			 * affected by rounding the converted value, so we'll
1160*2b15cb3dSCy Schubert 			 * leave this decision for later.  Until then, we'll
1161*2b15cb3dSCy Schubert 			 * assume that we're going to do an "e-style" conversion
1162*2b15cb3dSCy Schubert 			 * (in order to get the exponent calculated).  For
1163*2b15cb3dSCy Schubert 			 * "e-style", the precision must be decremented by one.
1164*2b15cb3dSCy Schubert 			 */
1165*2b15cb3dSCy Schubert 			precision--;
1166*2b15cb3dSCy Schubert 			/*
1167*2b15cb3dSCy Schubert 			 * For "%g" (and "%G") conversions, trailing zeros are
1168*2b15cb3dSCy Schubert 			 * removed from the fractional portion of the result
1169*2b15cb3dSCy Schubert 			 * unless the "#" flag was specified.
1170*2b15cb3dSCy Schubert 			 */
1171*2b15cb3dSCy Schubert 			if (!(flags & PRINT_F_NUM))
1172*2b15cb3dSCy Schubert 				omitzeros = 1;
1173*2b15cb3dSCy Schubert 		}
1174*2b15cb3dSCy Schubert 		exponent = getexponent(fvalue);
1175*2b15cb3dSCy Schubert 		estyle = 1;
1176*2b15cb3dSCy Schubert 	}
1177*2b15cb3dSCy Schubert 
1178*2b15cb3dSCy Schubert again:
1179*2b15cb3dSCy Schubert 	/*
1180*2b15cb3dSCy Schubert 	 * Sorry, we only support 9, 19, or 38 digits (that is, the number of
1181*2b15cb3dSCy Schubert 	 * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
1182*2b15cb3dSCy Schubert 	 * minus one) past the decimal point due to our conversion method.
1183*2b15cb3dSCy Schubert 	 */
1184*2b15cb3dSCy Schubert 	switch (sizeof(UINTMAX_T)) {
1185*2b15cb3dSCy Schubert 	case 16:
1186*2b15cb3dSCy Schubert 		if (precision > 38)
1187*2b15cb3dSCy Schubert 			precision = 38;
1188*2b15cb3dSCy Schubert 		break;
1189*2b15cb3dSCy Schubert 	case 8:
1190*2b15cb3dSCy Schubert 		if (precision > 19)
1191*2b15cb3dSCy Schubert 			precision = 19;
1192*2b15cb3dSCy Schubert 		break;
1193*2b15cb3dSCy Schubert 	default:
1194*2b15cb3dSCy Schubert 		if (precision > 9)
1195*2b15cb3dSCy Schubert 			precision = 9;
1196*2b15cb3dSCy Schubert 		break;
1197*2b15cb3dSCy Schubert 	}
1198*2b15cb3dSCy Schubert 
1199*2b15cb3dSCy Schubert 	ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
1200*2b15cb3dSCy Schubert 	if (estyle)	/* We want exactly one integer digit. */
1201*2b15cb3dSCy Schubert 		ufvalue /= mypow10(exponent);
1202*2b15cb3dSCy Schubert 
1203*2b15cb3dSCy Schubert 	if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
1204*2b15cb3dSCy Schubert 		*overflow = 1;
1205*2b15cb3dSCy Schubert 		return;
1206*2b15cb3dSCy Schubert 	}
1207*2b15cb3dSCy Schubert 
1208*2b15cb3dSCy Schubert 	/*
1209*2b15cb3dSCy Schubert 	 * Factor of ten with the number of digits needed for the fractional
1210*2b15cb3dSCy Schubert 	 * part.  For example, if the precision is 3, the mask will be 1000.
1211*2b15cb3dSCy Schubert 	 */
1212*2b15cb3dSCy Schubert 	mask = mypow10(precision);
1213*2b15cb3dSCy Schubert 	/*
1214*2b15cb3dSCy Schubert 	 * We "cheat" by converting the fractional part to integer by
1215*2b15cb3dSCy Schubert 	 * multiplying by a factor of ten.
1216*2b15cb3dSCy Schubert 	 */
1217*2b15cb3dSCy Schubert 	if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
1218*2b15cb3dSCy Schubert 		/*
1219*2b15cb3dSCy Schubert 		 * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
1220*2b15cb3dSCy Schubert 		 * (because precision = 3).  Now, myround(1000 * 0.99962) will
1221*2b15cb3dSCy Schubert 		 * return 1000.  So, the integer part must be incremented by one
1222*2b15cb3dSCy Schubert 		 * and the fractional part must be set to zero.
1223*2b15cb3dSCy Schubert 		 */
1224*2b15cb3dSCy Schubert 		intpart++;
1225*2b15cb3dSCy Schubert 		fracpart = 0;
1226*2b15cb3dSCy Schubert 		if (estyle && intpart == 10) {
1227*2b15cb3dSCy Schubert 			/*
1228*2b15cb3dSCy Schubert 			 * The value was rounded up to ten, but we only want one
1229*2b15cb3dSCy Schubert 			 * integer digit if using "e-style".  So, the integer
1230*2b15cb3dSCy Schubert 			 * part must be set to one and the exponent must be
1231*2b15cb3dSCy Schubert 			 * incremented by one.
1232*2b15cb3dSCy Schubert 			 */
1233*2b15cb3dSCy Schubert 			intpart = 1;
1234*2b15cb3dSCy Schubert 			exponent++;
1235*2b15cb3dSCy Schubert 		}
1236*2b15cb3dSCy Schubert 	}
1237*2b15cb3dSCy Schubert 
1238*2b15cb3dSCy Schubert 	/*
1239*2b15cb3dSCy Schubert 	 * Now that we know the real exponent, we can check whether or not to
1240*2b15cb3dSCy Schubert 	 * use "e-style" for "%g" (and "%G") conversions.  If we don't need
1241*2b15cb3dSCy Schubert 	 * "e-style", the precision must be adjusted and the integer and
1242*2b15cb3dSCy Schubert 	 * fractional parts must be recalculated from the original value.
1243*2b15cb3dSCy Schubert 	 *
1244*2b15cb3dSCy Schubert 	 * C99 says: "Let P equal the precision if nonzero, 6 if the precision
1245*2b15cb3dSCy Schubert 	 * is omitted, or 1 if the precision is zero.  Then, if a conversion
1246*2b15cb3dSCy Schubert 	 * with style `E' would have an exponent of X:
1247*2b15cb3dSCy Schubert 	 *
1248*2b15cb3dSCy Schubert 	 * - if P > X >= -4, the conversion is with style `f' (or `F') and
1249*2b15cb3dSCy Schubert 	 *   precision P - (X + 1).
1250*2b15cb3dSCy Schubert 	 *
1251*2b15cb3dSCy Schubert 	 * - otherwise, the conversion is with style `e' (or `E') and precision
1252*2b15cb3dSCy Schubert 	 *   P - 1." (7.19.6.1, 8)
1253*2b15cb3dSCy Schubert 	 *
1254*2b15cb3dSCy Schubert 	 * Note that we had decremented the precision by one.
1255*2b15cb3dSCy Schubert 	 */
1256*2b15cb3dSCy Schubert 	if (flags & PRINT_F_TYPE_G && estyle &&
1257*2b15cb3dSCy Schubert 	    precision + 1 > exponent && exponent >= -4) {
1258*2b15cb3dSCy Schubert 		precision -= exponent;
1259*2b15cb3dSCy Schubert 		estyle = 0;
1260*2b15cb3dSCy Schubert 		goto again;
1261*2b15cb3dSCy Schubert 	}
1262*2b15cb3dSCy Schubert 
1263*2b15cb3dSCy Schubert 	if (estyle) {
1264*2b15cb3dSCy Schubert 		if (exponent < 0) {
1265*2b15cb3dSCy Schubert 			exponent = -exponent;
1266*2b15cb3dSCy Schubert 			esign = '-';
1267*2b15cb3dSCy Schubert 		} else
1268*2b15cb3dSCy Schubert 			esign = '+';
1269*2b15cb3dSCy Schubert 
1270*2b15cb3dSCy Schubert 		/*
1271*2b15cb3dSCy Schubert 		 * Convert the exponent.  The sizeof(econvert) is 4.  So, the
1272*2b15cb3dSCy Schubert 		 * econvert buffer can hold e.g. "e+99" and "e-99".  We don't
1273*2b15cb3dSCy Schubert 		 * support an exponent which contains more than two digits.
1274*2b15cb3dSCy Schubert 		 * Therefore, the following stores are safe.
1275*2b15cb3dSCy Schubert 		 */
1276*2b15cb3dSCy Schubert 		epos = convert(exponent, econvert, 2, 10, 0);
1277*2b15cb3dSCy Schubert 		/*
1278*2b15cb3dSCy Schubert 		 * C99 says: "The exponent always contains at least two digits,
1279*2b15cb3dSCy Schubert 		 * and only as many more digits as necessary to represent the
1280*2b15cb3dSCy Schubert 		 * exponent." (7.19.6.1, 8)
1281*2b15cb3dSCy Schubert 		 */
1282*2b15cb3dSCy Schubert 		if (epos == 1)
1283*2b15cb3dSCy Schubert 			econvert[epos++] = '0';
1284*2b15cb3dSCy Schubert 		econvert[epos++] = esign;
1285*2b15cb3dSCy Schubert 		econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
1286*2b15cb3dSCy Schubert 	}
1287*2b15cb3dSCy Schubert 
1288*2b15cb3dSCy Schubert 	/* Convert the integer part and the fractional part. */
1289*2b15cb3dSCy Schubert 	ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
1290*2b15cb3dSCy Schubert 	if (fracpart != 0)	/* convert() would return 1 if fracpart == 0. */
1291*2b15cb3dSCy Schubert 		fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
1292*2b15cb3dSCy Schubert 
1293*2b15cb3dSCy Schubert 	leadfraczeros = precision - fpos;
1294*2b15cb3dSCy Schubert 
1295*2b15cb3dSCy Schubert 	if (omitzeros) {
1296*2b15cb3dSCy Schubert 		if (fpos > 0)	/* Omit trailing fractional part zeros. */
1297*2b15cb3dSCy Schubert 			while (omitcount < fpos && fconvert[omitcount] == '0')
1298*2b15cb3dSCy Schubert 				omitcount++;
1299*2b15cb3dSCy Schubert 		else {	/* The fractional part is zero, omit it completely. */
1300*2b15cb3dSCy Schubert 			omitcount = precision;
1301*2b15cb3dSCy Schubert 			leadfraczeros = 0;
1302*2b15cb3dSCy Schubert 		}
1303*2b15cb3dSCy Schubert 		precision -= omitcount;
1304*2b15cb3dSCy Schubert 	}
1305*2b15cb3dSCy Schubert 
1306*2b15cb3dSCy Schubert 	/*
1307*2b15cb3dSCy Schubert 	 * Print a decimal point if either the fractional part is non-zero
1308*2b15cb3dSCy Schubert 	 * and/or the "#" flag was specified.
1309*2b15cb3dSCy Schubert 	 */
1310*2b15cb3dSCy Schubert 	if (precision > 0 || flags & PRINT_F_NUM)
1311*2b15cb3dSCy Schubert 		emitpoint = 1;
1312*2b15cb3dSCy Schubert 	if (separators)	/* Get the number of group separators we'll print. */
1313*2b15cb3dSCy Schubert 		separators = getnumsep(ipos);
1314*2b15cb3dSCy Schubert 
1315*2b15cb3dSCy Schubert 	padlen = width                  /* Minimum field width. */
1316*2b15cb3dSCy Schubert 	    - ipos                      /* Number of integer digits. */
1317*2b15cb3dSCy Schubert 	    - epos                      /* Number of exponent characters. */
1318*2b15cb3dSCy Schubert 	    - precision                 /* Number of fractional digits. */
1319*2b15cb3dSCy Schubert 	    - separators                /* Number of group separators. */
1320*2b15cb3dSCy Schubert 	    - (emitpoint ? 1 : 0)       /* Will we print a decimal point? */
1321*2b15cb3dSCy Schubert 	    - ((sign != 0) ? 1 : 0);    /* Will we print a sign character? */
1322*2b15cb3dSCy Schubert 
1323*2b15cb3dSCy Schubert 	if (padlen < 0)
1324*2b15cb3dSCy Schubert 		padlen = 0;
1325*2b15cb3dSCy Schubert 
1326*2b15cb3dSCy Schubert 	/*
1327*2b15cb3dSCy Schubert 	 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
1328*2b15cb3dSCy Schubert 	 * ignored." (7.19.6.1, 6)
1329*2b15cb3dSCy Schubert 	 */
1330*2b15cb3dSCy Schubert 	if (flags & PRINT_F_MINUS)	/* Left justifty. */
1331*2b15cb3dSCy Schubert 		padlen = -padlen;
1332*2b15cb3dSCy Schubert 	else if (flags & PRINT_F_ZERO && padlen > 0) {
1333*2b15cb3dSCy Schubert 		if (sign != 0) {	/* Sign. */
1334*2b15cb3dSCy Schubert 			OUTCHAR(str, *len, size, sign);
1335*2b15cb3dSCy Schubert 			sign = 0;
1336*2b15cb3dSCy Schubert 		}
1337*2b15cb3dSCy Schubert 		while (padlen > 0) {	/* Leading zeros. */
1338*2b15cb3dSCy Schubert 			OUTCHAR(str, *len, size, '0');
1339*2b15cb3dSCy Schubert 			padlen--;
1340*2b15cb3dSCy Schubert 		}
1341*2b15cb3dSCy Schubert 	}
1342*2b15cb3dSCy Schubert 	while (padlen > 0) {	/* Leading spaces. */
1343*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, ' ');
1344*2b15cb3dSCy Schubert 		padlen--;
1345*2b15cb3dSCy Schubert 	}
1346*2b15cb3dSCy Schubert 	if (sign != 0)	/* Sign. */
1347*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, sign);
1348*2b15cb3dSCy Schubert 	while (ipos > 0) {	/* Integer part. */
1349*2b15cb3dSCy Schubert 		ipos--;
1350*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, iconvert[ipos]);
1351*2b15cb3dSCy Schubert 		if (separators > 0 && ipos > 0 && ipos % 3 == 0)
1352*2b15cb3dSCy Schubert 			printsep(str, len, size);
1353*2b15cb3dSCy Schubert 	}
1354*2b15cb3dSCy Schubert 	if (emitpoint) {	/* Decimal point. */
1355*2b15cb3dSCy Schubert #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
1356*2b15cb3dSCy Schubert 		if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
1357*2b15cb3dSCy Schubert 			OUTCHAR(str, *len, size, *lc->decimal_point);
1358*2b15cb3dSCy Schubert 		else	/* We'll always print some decimal point character. */
1359*2b15cb3dSCy Schubert #endif	/* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
1360*2b15cb3dSCy Schubert 			OUTCHAR(str, *len, size, '.');
1361*2b15cb3dSCy Schubert 	}
1362*2b15cb3dSCy Schubert 	while (leadfraczeros > 0) {	/* Leading fractional part zeros. */
1363*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, '0');
1364*2b15cb3dSCy Schubert 		leadfraczeros--;
1365*2b15cb3dSCy Schubert 	}
1366*2b15cb3dSCy Schubert 	while (fpos > omitcount) {	/* The remaining fractional part. */
1367*2b15cb3dSCy Schubert 		fpos--;
1368*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, fconvert[fpos]);
1369*2b15cb3dSCy Schubert 	}
1370*2b15cb3dSCy Schubert 	while (epos > 0) {	/* Exponent. */
1371*2b15cb3dSCy Schubert 		epos--;
1372*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, econvert[epos]);
1373*2b15cb3dSCy Schubert 	}
1374*2b15cb3dSCy Schubert 	while (padlen < 0) {	/* Trailing spaces. */
1375*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, ' ');
1376*2b15cb3dSCy Schubert 		padlen++;
1377*2b15cb3dSCy Schubert 	}
1378*2b15cb3dSCy Schubert }
1379*2b15cb3dSCy Schubert 
1380*2b15cb3dSCy Schubert static void
1381*2b15cb3dSCy Schubert printsep(char *str, size_t *len, size_t size)
1382*2b15cb3dSCy Schubert {
1383*2b15cb3dSCy Schubert #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
1384*2b15cb3dSCy Schubert 	struct lconv *lc = localeconv();
1385*2b15cb3dSCy Schubert 	int i;
1386*2b15cb3dSCy Schubert 
1387*2b15cb3dSCy Schubert 	if (lc->thousands_sep != NULL)
1388*2b15cb3dSCy Schubert 		for (i = 0; lc->thousands_sep[i] != '\0'; i++)
1389*2b15cb3dSCy Schubert 			OUTCHAR(str, *len, size, lc->thousands_sep[i]);
1390*2b15cb3dSCy Schubert 	else
1391*2b15cb3dSCy Schubert #endif	/* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
1392*2b15cb3dSCy Schubert 		OUTCHAR(str, *len, size, ',');
1393*2b15cb3dSCy Schubert }
1394*2b15cb3dSCy Schubert 
1395*2b15cb3dSCy Schubert static int
1396*2b15cb3dSCy Schubert getnumsep(int digits)
1397*2b15cb3dSCy Schubert {
1398*2b15cb3dSCy Schubert 	int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
1399*2b15cb3dSCy Schubert #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
1400*2b15cb3dSCy Schubert 	int strln;
1401*2b15cb3dSCy Schubert 	struct lconv *lc = localeconv();
1402*2b15cb3dSCy Schubert 
1403*2b15cb3dSCy Schubert 	/* We support an arbitrary separator length (including zero). */
1404*2b15cb3dSCy Schubert 	if (lc->thousands_sep != NULL) {
1405*2b15cb3dSCy Schubert 		for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
1406*2b15cb3dSCy Schubert 			continue;
1407*2b15cb3dSCy Schubert 		separators *= strln;
1408*2b15cb3dSCy Schubert 	}
1409*2b15cb3dSCy Schubert #endif	/* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
1410*2b15cb3dSCy Schubert 	return separators;
1411*2b15cb3dSCy Schubert }
1412*2b15cb3dSCy Schubert 
1413*2b15cb3dSCy Schubert static int
1414*2b15cb3dSCy Schubert getexponent(LDOUBLE value)
1415*2b15cb3dSCy Schubert {
1416*2b15cb3dSCy Schubert 	LDOUBLE tmp = (value >= 0.0) ? value : -value;
1417*2b15cb3dSCy Schubert 	int exponent = 0;
1418*2b15cb3dSCy Schubert 
1419*2b15cb3dSCy Schubert 	/*
1420*2b15cb3dSCy Schubert 	 * We check for 99 > exponent > -99 in order to work around possible
1421*2b15cb3dSCy Schubert 	 * endless loops which could happen (at least) in the second loop (at
1422*2b15cb3dSCy Schubert 	 * least) if we're called with an infinite value.  However, we checked
1423*2b15cb3dSCy Schubert 	 * for infinity before calling this function using our ISINF() macro, so
1424*2b15cb3dSCy Schubert 	 * this might be somewhat paranoid.
1425*2b15cb3dSCy Schubert 	 */
1426*2b15cb3dSCy Schubert 	while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
1427*2b15cb3dSCy Schubert 		tmp *= 10;
1428*2b15cb3dSCy Schubert 	while (tmp >= 10.0 && ++exponent < 99)
1429*2b15cb3dSCy Schubert 		tmp /= 10;
1430*2b15cb3dSCy Schubert 
1431*2b15cb3dSCy Schubert 	return exponent;
1432*2b15cb3dSCy Schubert }
1433*2b15cb3dSCy Schubert 
1434*2b15cb3dSCy Schubert static int
1435*2b15cb3dSCy Schubert convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
1436*2b15cb3dSCy Schubert {
1437*2b15cb3dSCy Schubert 	const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
1438*2b15cb3dSCy Schubert 	size_t pos = 0;
1439*2b15cb3dSCy Schubert 
1440*2b15cb3dSCy Schubert 	/* We return an unterminated buffer with the digits in reverse order. */
1441*2b15cb3dSCy Schubert 	do {
1442*2b15cb3dSCy Schubert 		buf[pos++] = digits[value % base];
1443*2b15cb3dSCy Schubert 		value /= base;
1444*2b15cb3dSCy Schubert 	} while (value != 0 && pos < size);
1445*2b15cb3dSCy Schubert 
1446*2b15cb3dSCy Schubert 	return (int)pos;
1447*2b15cb3dSCy Schubert }
1448*2b15cb3dSCy Schubert 
1449*2b15cb3dSCy Schubert static UINTMAX_T
1450*2b15cb3dSCy Schubert cast(LDOUBLE value)
1451*2b15cb3dSCy Schubert {
1452*2b15cb3dSCy Schubert 	UINTMAX_T result;
1453*2b15cb3dSCy Schubert 
1454*2b15cb3dSCy Schubert 	/*
1455*2b15cb3dSCy Schubert 	 * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
1456*2b15cb3dSCy Schubert 	 * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
1457*2b15cb3dSCy Schubert 	 * it may be increased to the nearest higher representable value for the
1458*2b15cb3dSCy Schubert 	 * comparison (cf. C99: 6.3.1.4, 2).  It might then equal the LDOUBLE
1459*2b15cb3dSCy Schubert 	 * value although converting the latter to UINTMAX_T would overflow.
1460*2b15cb3dSCy Schubert 	 */
1461*2b15cb3dSCy Schubert 	if (value >= UINTMAX_MAX)
1462*2b15cb3dSCy Schubert 		return UINTMAX_MAX;
1463*2b15cb3dSCy Schubert 
1464*2b15cb3dSCy Schubert 	result = value;
1465*2b15cb3dSCy Schubert 	/*
1466*2b15cb3dSCy Schubert 	 * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
1467*2b15cb3dSCy Schubert 	 * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
1468*2b15cb3dSCy Schubert 	 * the standard).  Sigh.
1469*2b15cb3dSCy Schubert 	 */
1470*2b15cb3dSCy Schubert 	return (result <= value) ? result : result - 1;
1471*2b15cb3dSCy Schubert }
1472*2b15cb3dSCy Schubert 
1473*2b15cb3dSCy Schubert static UINTMAX_T
1474*2b15cb3dSCy Schubert myround(LDOUBLE value)
1475*2b15cb3dSCy Schubert {
1476*2b15cb3dSCy Schubert 	UINTMAX_T intpart = cast(value);
1477*2b15cb3dSCy Schubert 
1478*2b15cb3dSCy Schubert 	return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
1479*2b15cb3dSCy Schubert }
1480*2b15cb3dSCy Schubert 
1481*2b15cb3dSCy Schubert static LDOUBLE
1482*2b15cb3dSCy Schubert mypow10(int exponent)
1483*2b15cb3dSCy Schubert {
1484*2b15cb3dSCy Schubert 	LDOUBLE result = 1;
1485*2b15cb3dSCy Schubert 
1486*2b15cb3dSCy Schubert 	while (exponent > 0) {
1487*2b15cb3dSCy Schubert 		result *= 10;
1488*2b15cb3dSCy Schubert 		exponent--;
1489*2b15cb3dSCy Schubert 	}
1490*2b15cb3dSCy Schubert 	while (exponent < 0) {
1491*2b15cb3dSCy Schubert 		result /= 10;
1492*2b15cb3dSCy Schubert 		exponent++;
1493*2b15cb3dSCy Schubert 	}
1494*2b15cb3dSCy Schubert 	return result;
1495*2b15cb3dSCy Schubert }
1496*2b15cb3dSCy Schubert #endif	/* HW_WANT_RPL_VSNPRINTF */
1497*2b15cb3dSCy Schubert 
1498*2b15cb3dSCy Schubert #if HW_WANT_RPL_VASPRINTF
1499*2b15cb3dSCy Schubert #if NEED_MYMEMCPY
1500*2b15cb3dSCy Schubert void *
1501*2b15cb3dSCy Schubert mymemcpy(void *dst, void *src, size_t len)
1502*2b15cb3dSCy Schubert {
1503*2b15cb3dSCy Schubert 	const char *from = src;
1504*2b15cb3dSCy Schubert 	char *to = dst;
1505*2b15cb3dSCy Schubert 
1506*2b15cb3dSCy Schubert 	/* No need for optimization, we use this only to replace va_copy(3). */
1507*2b15cb3dSCy Schubert 	while (len-- > 0)
1508*2b15cb3dSCy Schubert 		*to++ = *from++;
1509*2b15cb3dSCy Schubert 	return dst;
1510*2b15cb3dSCy Schubert }
1511*2b15cb3dSCy Schubert #endif	/* NEED_MYMEMCPY */
1512*2b15cb3dSCy Schubert 
1513*2b15cb3dSCy Schubert int
1514*2b15cb3dSCy Schubert rpl_vasprintf(char **ret, const char *format, va_list ap);
1515*2b15cb3dSCy Schubert 
1516*2b15cb3dSCy Schubert int
1517*2b15cb3dSCy Schubert rpl_vasprintf(char **ret, const char *format, va_list ap)
1518*2b15cb3dSCy Schubert {
1519*2b15cb3dSCy Schubert 	size_t size;
1520*2b15cb3dSCy Schubert 	int len;
1521*2b15cb3dSCy Schubert 	va_list aq;
1522*2b15cb3dSCy Schubert 
1523*2b15cb3dSCy Schubert 	VA_COPY(aq, ap);
1524*2b15cb3dSCy Schubert 	len = vsnprintf(NULL, 0, format, aq);
1525*2b15cb3dSCy Schubert 	VA_END_COPY(aq);
1526*2b15cb3dSCy Schubert 	if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
1527*2b15cb3dSCy Schubert 		return -1;
1528*2b15cb3dSCy Schubert 	return vsnprintf(*ret, size, format, ap);
1529*2b15cb3dSCy Schubert }
1530*2b15cb3dSCy Schubert #endif	/* HW_WANT_RPL_VASPRINTF */
1531*2b15cb3dSCy Schubert 
1532*2b15cb3dSCy Schubert #if HW_WANT_RPL_SNPRINTF
1533*2b15cb3dSCy Schubert #if HAVE_STDARG_H
1534*2b15cb3dSCy Schubert int
1535*2b15cb3dSCy Schubert rpl_snprintf(char *str, size_t size, const char *format, ...);
1536*2b15cb3dSCy Schubert 
1537*2b15cb3dSCy Schubert int
1538*2b15cb3dSCy Schubert rpl_snprintf(char *str, size_t size, const char *format, ...)
1539ce265a54SOllivier Robert #else
1540*2b15cb3dSCy Schubert int
1541*2b15cb3dSCy Schubert rpl_snprintf(va_alist) va_dcl
1542*2b15cb3dSCy Schubert #endif	/* HAVE_STDARG_H */
1543*2b15cb3dSCy Schubert {
1544*2b15cb3dSCy Schubert #if !HAVE_STDARG_H
1545*2b15cb3dSCy Schubert 	char *str;
1546*2b15cb3dSCy Schubert 	size_t size;
1547*2b15cb3dSCy Schubert 	char *format;
1548*2b15cb3dSCy Schubert #endif	/* HAVE_STDARG_H */
1549*2b15cb3dSCy Schubert 	va_list ap;
1550*2b15cb3dSCy Schubert 	int len;
1551*2b15cb3dSCy Schubert 
1552*2b15cb3dSCy Schubert 	VA_START(ap, format);
1553*2b15cb3dSCy Schubert 	VA_SHIFT(ap, str, char *);
1554*2b15cb3dSCy Schubert 	VA_SHIFT(ap, size, size_t);
1555*2b15cb3dSCy Schubert 	VA_SHIFT(ap, format, const char *);
1556*2b15cb3dSCy Schubert 	len = vsnprintf(str, size, format, ap);
1557*2b15cb3dSCy Schubert 	va_end(ap);
1558*2b15cb3dSCy Schubert 	return len;
1559*2b15cb3dSCy Schubert }
1560*2b15cb3dSCy Schubert #endif	/* HW_WANT_RPL_SNPRINTF */
1561*2b15cb3dSCy Schubert 
1562*2b15cb3dSCy Schubert #if HW_WANT_RPL_ASPRINTF
1563*2b15cb3dSCy Schubert #if HAVE_STDARG_H
1564*2b15cb3dSCy Schubert int
1565*2b15cb3dSCy Schubert rpl_asprintf(char **ret, const char *format, ...);
1566*2b15cb3dSCy Schubert 
1567*2b15cb3dSCy Schubert int
1568*2b15cb3dSCy Schubert rpl_asprintf(char **ret, const char *format, ...)
1569*2b15cb3dSCy Schubert #else
1570*2b15cb3dSCy Schubert int
1571*2b15cb3dSCy Schubert rpl_asprintf(va_alist) va_dcl
1572*2b15cb3dSCy Schubert #endif	/* HAVE_STDARG_H */
1573*2b15cb3dSCy Schubert {
1574*2b15cb3dSCy Schubert #if !HAVE_STDARG_H
1575*2b15cb3dSCy Schubert 	char **ret;
1576*2b15cb3dSCy Schubert 	char *format;
1577*2b15cb3dSCy Schubert #endif	/* HAVE_STDARG_H */
1578*2b15cb3dSCy Schubert 	va_list ap;
1579*2b15cb3dSCy Schubert 	int len;
1580*2b15cb3dSCy Schubert 
1581*2b15cb3dSCy Schubert 	VA_START(ap, format);
1582*2b15cb3dSCy Schubert 	VA_SHIFT(ap, ret, char **);
1583*2b15cb3dSCy Schubert 	VA_SHIFT(ap, format, const char *);
1584*2b15cb3dSCy Schubert 	len = vasprintf(ret, format, ap);
1585*2b15cb3dSCy Schubert 	va_end(ap);
1586*2b15cb3dSCy Schubert 	return len;
1587*2b15cb3dSCy Schubert }
1588*2b15cb3dSCy Schubert #endif	/* HW_WANT_RPL_ASPRINTF */
1589*2b15cb3dSCy Schubert #else	/* Dummy declaration to avoid empty translation unit warnings. */
1590*2b15cb3dSCy Schubert int main(void);
1591*2b15cb3dSCy Schubert #endif	/* HW_WANT_RPL_SNPRINTF || HW_WANT_RPL_VSNPRINTF || HW_WANT_RPL_ASPRINTF || [...] */
1592*2b15cb3dSCy Schubert 
1593*2b15cb3dSCy Schubert #if TEST_SNPRINTF
1594*2b15cb3dSCy Schubert int
1595*2b15cb3dSCy Schubert main(void)
1596*2b15cb3dSCy Schubert {
1597*2b15cb3dSCy Schubert 	const char *float_fmt[] = {
1598*2b15cb3dSCy Schubert 		/* "%E" and "%e" formats. */
1599*2b15cb3dSCy Schubert #if HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX
1600*2b15cb3dSCy Schubert 		"%.16e",
1601*2b15cb3dSCy Schubert 		"%22.16e",
1602*2b15cb3dSCy Schubert 		"%022.16e",
1603*2b15cb3dSCy Schubert 		"%-22.16e",
1604*2b15cb3dSCy Schubert 		"%#+'022.16e",
1605*2b15cb3dSCy Schubert #endif	/* HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX */
1606*2b15cb3dSCy Schubert 		"foo|%#+0123.9E|bar",
1607*2b15cb3dSCy Schubert 		"%-123.9e",
1608*2b15cb3dSCy Schubert 		"%123.9e",
1609*2b15cb3dSCy Schubert 		"%+23.9e",
1610*2b15cb3dSCy Schubert 		"%+05.8e",
1611*2b15cb3dSCy Schubert 		"%-05.8e",
1612*2b15cb3dSCy Schubert 		"%05.8e",
1613*2b15cb3dSCy Schubert 		"%+5.8e",
1614*2b15cb3dSCy Schubert 		"%-5.8e",
1615*2b15cb3dSCy Schubert 		"% 5.8e",
1616*2b15cb3dSCy Schubert 		"%5.8e",
1617*2b15cb3dSCy Schubert 		"%+4.9e",
1618*2b15cb3dSCy Schubert #if !OS_LINUX	/* glibc sometimes gets these wrong. */
1619*2b15cb3dSCy Schubert 		"%+#010.0e",
1620*2b15cb3dSCy Schubert 		"%#10.1e",
1621*2b15cb3dSCy Schubert 		"%10.5e",
1622*2b15cb3dSCy Schubert 		"% 10.5e",
1623*2b15cb3dSCy Schubert 		"%5.0e",
1624*2b15cb3dSCy Schubert 		"%5.e",
1625*2b15cb3dSCy Schubert 		"%#5.0e",
1626*2b15cb3dSCy Schubert 		"%#5.e",
1627*2b15cb3dSCy Schubert 		"%3.2e",
1628*2b15cb3dSCy Schubert 		"%3.1e",
1629*2b15cb3dSCy Schubert 		"%-1.5e",
1630*2b15cb3dSCy Schubert 		"%1.5e",
1631*2b15cb3dSCy Schubert 		"%01.3e",
1632*2b15cb3dSCy Schubert 		"%1.e",
1633*2b15cb3dSCy Schubert 		"%.1e",
1634*2b15cb3dSCy Schubert 		"%#.0e",
1635*2b15cb3dSCy Schubert 		"%+.0e",
1636*2b15cb3dSCy Schubert 		"% .0e",
1637*2b15cb3dSCy Schubert 		"%.0e",
1638*2b15cb3dSCy Schubert 		"%#.e",
1639*2b15cb3dSCy Schubert 		"%+.e",
1640*2b15cb3dSCy Schubert 		"% .e",
1641*2b15cb3dSCy Schubert 		"%.e",
1642*2b15cb3dSCy Schubert 		"%4e",
1643*2b15cb3dSCy Schubert 		"%e",
1644*2b15cb3dSCy Schubert 		"%E",
1645*2b15cb3dSCy Schubert #endif	/* !OS_LINUX */
1646*2b15cb3dSCy Schubert 		/* "%F" and "%f" formats. */
1647*2b15cb3dSCy Schubert #if !OS_BSD && !OS_IRIX
1648*2b15cb3dSCy Schubert 		"% '022f",
1649*2b15cb3dSCy Schubert 		"%+'022f",
1650*2b15cb3dSCy Schubert 		"%-'22f",
1651*2b15cb3dSCy Schubert 		"%'22f",
1652*2b15cb3dSCy Schubert #if HAVE_LONG_LONG_INT
1653*2b15cb3dSCy Schubert 		"%.16f",
1654*2b15cb3dSCy Schubert 		"%22.16f",
1655*2b15cb3dSCy Schubert 		"%022.16f",
1656*2b15cb3dSCy Schubert 		"%-22.16f",
1657*2b15cb3dSCy Schubert 		"%#+'022.16f",
1658*2b15cb3dSCy Schubert #endif	/* HAVE_LONG_LONG_INT */
1659*2b15cb3dSCy Schubert #endif	/* !OS_BSD && !OS_IRIX */
1660*2b15cb3dSCy Schubert 		"foo|%#+0123.9F|bar",
1661*2b15cb3dSCy Schubert 		"%-123.9f",
1662*2b15cb3dSCy Schubert 		"%123.9f",
1663*2b15cb3dSCy Schubert 		"%+23.9f",
1664*2b15cb3dSCy Schubert 		"%+#010.0f",
1665*2b15cb3dSCy Schubert 		"%#10.1f",
1666*2b15cb3dSCy Schubert 		"%10.5f",
1667*2b15cb3dSCy Schubert 		"% 10.5f",
1668*2b15cb3dSCy Schubert 		"%+05.8f",
1669*2b15cb3dSCy Schubert 		"%-05.8f",
1670*2b15cb3dSCy Schubert 		"%05.8f",
1671*2b15cb3dSCy Schubert 		"%+5.8f",
1672*2b15cb3dSCy Schubert 		"%-5.8f",
1673*2b15cb3dSCy Schubert 		"% 5.8f",
1674*2b15cb3dSCy Schubert 		"%5.8f",
1675*2b15cb3dSCy Schubert 		"%5.0f",
1676*2b15cb3dSCy Schubert 		"%5.f",
1677*2b15cb3dSCy Schubert 		"%#5.0f",
1678*2b15cb3dSCy Schubert 		"%#5.f",
1679*2b15cb3dSCy Schubert 		"%+4.9f",
1680*2b15cb3dSCy Schubert 		"%3.2f",
1681*2b15cb3dSCy Schubert 		"%3.1f",
1682*2b15cb3dSCy Schubert 		"%-1.5f",
1683*2b15cb3dSCy Schubert 		"%1.5f",
1684*2b15cb3dSCy Schubert 		"%01.3f",
1685*2b15cb3dSCy Schubert 		"%1.f",
1686*2b15cb3dSCy Schubert 		"%.1f",
1687*2b15cb3dSCy Schubert 		"%#.0f",
1688*2b15cb3dSCy Schubert 		"%+.0f",
1689*2b15cb3dSCy Schubert 		"% .0f",
1690*2b15cb3dSCy Schubert 		"%.0f",
1691*2b15cb3dSCy Schubert 		"%#.f",
1692*2b15cb3dSCy Schubert 		"%+.f",
1693*2b15cb3dSCy Schubert 		"% .f",
1694*2b15cb3dSCy Schubert 		"%.f",
1695*2b15cb3dSCy Schubert 		"%4f",
1696*2b15cb3dSCy Schubert 		"%f",
1697*2b15cb3dSCy Schubert 		"%F",
1698*2b15cb3dSCy Schubert 		/* "%G" and "%g" formats. */
1699*2b15cb3dSCy Schubert #if !OS_BSD && !OS_IRIX && !OS_LINUX
1700*2b15cb3dSCy Schubert 		"% '022g",
1701*2b15cb3dSCy Schubert 		"%+'022g",
1702*2b15cb3dSCy Schubert 		"%-'22g",
1703*2b15cb3dSCy Schubert 		"%'22g",
1704*2b15cb3dSCy Schubert #if HAVE_LONG_LONG_INT
1705*2b15cb3dSCy Schubert 		"%.16g",
1706*2b15cb3dSCy Schubert 		"%22.16g",
1707*2b15cb3dSCy Schubert 		"%022.16g",
1708*2b15cb3dSCy Schubert 		"%-22.16g",
1709*2b15cb3dSCy Schubert 		"%#+'022.16g",
1710*2b15cb3dSCy Schubert #endif	/* HAVE_LONG_LONG_INT */
1711*2b15cb3dSCy Schubert #endif	/* !OS_BSD && !OS_IRIX && !OS_LINUX */
1712*2b15cb3dSCy Schubert 		"foo|%#+0123.9G|bar",
1713*2b15cb3dSCy Schubert 		"%-123.9g",
1714*2b15cb3dSCy Schubert 		"%123.9g",
1715*2b15cb3dSCy Schubert 		"%+23.9g",
1716*2b15cb3dSCy Schubert 		"%+05.8g",
1717*2b15cb3dSCy Schubert 		"%-05.8g",
1718*2b15cb3dSCy Schubert 		"%05.8g",
1719*2b15cb3dSCy Schubert 		"%+5.8g",
1720*2b15cb3dSCy Schubert 		"%-5.8g",
1721*2b15cb3dSCy Schubert 		"% 5.8g",
1722*2b15cb3dSCy Schubert 		"%5.8g",
1723*2b15cb3dSCy Schubert 		"%+4.9g",
1724*2b15cb3dSCy Schubert #if !OS_LINUX	/* glibc sometimes gets these wrong. */
1725*2b15cb3dSCy Schubert 		"%+#010.0g",
1726*2b15cb3dSCy Schubert 		"%#10.1g",
1727*2b15cb3dSCy Schubert 		"%10.5g",
1728*2b15cb3dSCy Schubert 		"% 10.5g",
1729*2b15cb3dSCy Schubert 		"%5.0g",
1730*2b15cb3dSCy Schubert 		"%5.g",
1731*2b15cb3dSCy Schubert 		"%#5.0g",
1732*2b15cb3dSCy Schubert 		"%#5.g",
1733*2b15cb3dSCy Schubert 		"%3.2g",
1734*2b15cb3dSCy Schubert 		"%3.1g",
1735*2b15cb3dSCy Schubert 		"%-1.5g",
1736*2b15cb3dSCy Schubert 		"%1.5g",
1737*2b15cb3dSCy Schubert 		"%01.3g",
1738*2b15cb3dSCy Schubert 		"%1.g",
1739*2b15cb3dSCy Schubert 		"%.1g",
1740*2b15cb3dSCy Schubert 		"%#.0g",
1741*2b15cb3dSCy Schubert 		"%+.0g",
1742*2b15cb3dSCy Schubert 		"% .0g",
1743*2b15cb3dSCy Schubert 		"%.0g",
1744*2b15cb3dSCy Schubert 		"%#.g",
1745*2b15cb3dSCy Schubert 		"%+.g",
1746*2b15cb3dSCy Schubert 		"% .g",
1747*2b15cb3dSCy Schubert 		"%.g",
1748*2b15cb3dSCy Schubert 		"%4g",
1749*2b15cb3dSCy Schubert 		"%g",
1750*2b15cb3dSCy Schubert 		"%G",
1751*2b15cb3dSCy Schubert #endif	/* !OS_LINUX */
1752*2b15cb3dSCy Schubert 		NULL
1753*2b15cb3dSCy Schubert 	};
1754*2b15cb3dSCy Schubert 	double float_val[] = {
1755*2b15cb3dSCy Schubert 		-4.136,
1756*2b15cb3dSCy Schubert 		-134.52,
1757*2b15cb3dSCy Schubert 		-5.04030201,
1758*2b15cb3dSCy Schubert 		-3410.01234,
1759*2b15cb3dSCy Schubert 		-999999.999999,
1760*2b15cb3dSCy Schubert 		-913450.29876,
1761*2b15cb3dSCy Schubert 		-913450.2,
1762*2b15cb3dSCy Schubert 		-91345.2,
1763*2b15cb3dSCy Schubert 		-9134.2,
1764*2b15cb3dSCy Schubert 		-913.2,
1765*2b15cb3dSCy Schubert 		-91.2,
1766*2b15cb3dSCy Schubert 		-9.2,
1767*2b15cb3dSCy Schubert 		-9.9,
1768*2b15cb3dSCy Schubert 		4.136,
1769*2b15cb3dSCy Schubert 		134.52,
1770*2b15cb3dSCy Schubert 		5.04030201,
1771*2b15cb3dSCy Schubert 		3410.01234,
1772*2b15cb3dSCy Schubert 		999999.999999,
1773*2b15cb3dSCy Schubert 		913450.29876,
1774*2b15cb3dSCy Schubert 		913450.2,
1775*2b15cb3dSCy Schubert 		91345.2,
1776*2b15cb3dSCy Schubert 		9134.2,
1777*2b15cb3dSCy Schubert 		913.2,
1778*2b15cb3dSCy Schubert 		91.2,
1779*2b15cb3dSCy Schubert 		9.2,
1780*2b15cb3dSCy Schubert 		9.9,
1781*2b15cb3dSCy Schubert 		9.96,
1782*2b15cb3dSCy Schubert 		9.996,
1783*2b15cb3dSCy Schubert 		9.9996,
1784*2b15cb3dSCy Schubert 		9.99996,
1785*2b15cb3dSCy Schubert 		9.999996,
1786*2b15cb3dSCy Schubert 		9.9999996,
1787*2b15cb3dSCy Schubert 		9.99999996,
1788*2b15cb3dSCy Schubert 		0.99999996,
1789*2b15cb3dSCy Schubert 		0.99999999,
1790*2b15cb3dSCy Schubert 		0.09999999,
1791*2b15cb3dSCy Schubert 		0.00999999,
1792*2b15cb3dSCy Schubert 		0.00099999,
1793*2b15cb3dSCy Schubert 		0.00009999,
1794*2b15cb3dSCy Schubert 		0.00000999,
1795*2b15cb3dSCy Schubert 		0.00000099,
1796*2b15cb3dSCy Schubert 		0.00000009,
1797*2b15cb3dSCy Schubert 		0.00000001,
1798*2b15cb3dSCy Schubert 		0.0000001,
1799*2b15cb3dSCy Schubert 		0.000001,
1800*2b15cb3dSCy Schubert 		0.00001,
1801*2b15cb3dSCy Schubert 		0.0001,
1802*2b15cb3dSCy Schubert 		0.001,
1803*2b15cb3dSCy Schubert 		0.01,
1804*2b15cb3dSCy Schubert 		0.1,
1805*2b15cb3dSCy Schubert 		1.0,
1806*2b15cb3dSCy Schubert 		1.5,
1807*2b15cb3dSCy Schubert 		-1.5,
1808*2b15cb3dSCy Schubert 		-1.0,
1809*2b15cb3dSCy Schubert 		-0.1,
1810*2b15cb3dSCy Schubert #if !OS_BSD	/* BSD sometimes gets these wrong. */
1811*2b15cb3dSCy Schubert #ifdef INFINITY
1812*2b15cb3dSCy Schubert 		INFINITY,
1813*2b15cb3dSCy Schubert 		-INFINITY,
1814*2b15cb3dSCy Schubert #endif	/* defined(INFINITY) */
1815*2b15cb3dSCy Schubert #ifdef NAN
1816*2b15cb3dSCy Schubert 		NAN,
1817*2b15cb3dSCy Schubert #endif	/* defined(NAN) */
1818*2b15cb3dSCy Schubert #endif	/* !OS_BSD */
1819*2b15cb3dSCy Schubert 		0
1820*2b15cb3dSCy Schubert 	};
1821*2b15cb3dSCy Schubert 	const char *long_fmt[] = {
1822*2b15cb3dSCy Schubert 		"foo|%0123ld|bar",
1823*2b15cb3dSCy Schubert #if !OS_IRIX
1824*2b15cb3dSCy Schubert 		"% '0123ld",
1825*2b15cb3dSCy Schubert 		"%+'0123ld",
1826*2b15cb3dSCy Schubert 		"%-'123ld",
1827*2b15cb3dSCy Schubert 		"%'123ld",
1828*2b15cb3dSCy Schubert #endif	/* !OS_IRiX */
1829*2b15cb3dSCy Schubert 		"%123.9ld",
1830*2b15cb3dSCy Schubert 		"% 123.9ld",
1831*2b15cb3dSCy Schubert 		"%+123.9ld",
1832*2b15cb3dSCy Schubert 		"%-123.9ld",
1833*2b15cb3dSCy Schubert 		"%0123ld",
1834*2b15cb3dSCy Schubert 		"% 0123ld",
1835*2b15cb3dSCy Schubert 		"%+0123ld",
1836*2b15cb3dSCy Schubert 		"%-0123ld",
1837*2b15cb3dSCy Schubert 		"%10.5ld",
1838*2b15cb3dSCy Schubert 		"% 10.5ld",
1839*2b15cb3dSCy Schubert 		"%+10.5ld",
1840*2b15cb3dSCy Schubert 		"%-10.5ld",
1841*2b15cb3dSCy Schubert 		"%010ld",
1842*2b15cb3dSCy Schubert 		"% 010ld",
1843*2b15cb3dSCy Schubert 		"%+010ld",
1844*2b15cb3dSCy Schubert 		"%-010ld",
1845*2b15cb3dSCy Schubert 		"%4.2ld",
1846*2b15cb3dSCy Schubert 		"% 4.2ld",
1847*2b15cb3dSCy Schubert 		"%+4.2ld",
1848*2b15cb3dSCy Schubert 		"%-4.2ld",
1849*2b15cb3dSCy Schubert 		"%04ld",
1850*2b15cb3dSCy Schubert 		"% 04ld",
1851*2b15cb3dSCy Schubert 		"%+04ld",
1852*2b15cb3dSCy Schubert 		"%-04ld",
1853*2b15cb3dSCy Schubert 		"%5.5ld",
1854*2b15cb3dSCy Schubert 		"%+22.33ld",
1855*2b15cb3dSCy Schubert 		"%01.3ld",
1856*2b15cb3dSCy Schubert 		"%1.5ld",
1857*2b15cb3dSCy Schubert 		"%-1.5ld",
1858*2b15cb3dSCy Schubert 		"%44ld",
1859*2b15cb3dSCy Schubert 		"%4ld",
1860*2b15cb3dSCy Schubert 		"%4.0ld",
1861*2b15cb3dSCy Schubert 		"%4.ld",
1862*2b15cb3dSCy Schubert 		"%.44ld",
1863*2b15cb3dSCy Schubert 		"%.4ld",
1864*2b15cb3dSCy Schubert 		"%.0ld",
1865*2b15cb3dSCy Schubert 		"%.ld",
1866*2b15cb3dSCy Schubert 		"%ld",
1867*2b15cb3dSCy Schubert 		NULL
1868*2b15cb3dSCy Schubert 	};
1869*2b15cb3dSCy Schubert 	long int long_val[] = {
1870*2b15cb3dSCy Schubert #ifdef LONG_MAX
1871*2b15cb3dSCy Schubert 		LONG_MAX,
1872*2b15cb3dSCy Schubert #endif	/* LONG_MAX */
1873*2b15cb3dSCy Schubert #ifdef LONG_MIN
1874*2b15cb3dSCy Schubert 		LONG_MIN,
1875*2b15cb3dSCy Schubert #endif	/* LONG_MIN */
1876*2b15cb3dSCy Schubert 		-91340,
1877*2b15cb3dSCy Schubert 		91340,
1878*2b15cb3dSCy Schubert 		341,
1879*2b15cb3dSCy Schubert 		134,
1880*2b15cb3dSCy Schubert 		0203,
1881*2b15cb3dSCy Schubert 		-1,
1882*2b15cb3dSCy Schubert 		1,
1883*2b15cb3dSCy Schubert 		0
1884*2b15cb3dSCy Schubert 	};
1885*2b15cb3dSCy Schubert 	const char *ulong_fmt[] = {
1886*2b15cb3dSCy Schubert 		/* "%u" formats. */
1887*2b15cb3dSCy Schubert 		"foo|%0123lu|bar",
1888*2b15cb3dSCy Schubert #if !OS_IRIX
1889*2b15cb3dSCy Schubert 		"% '0123lu",
1890*2b15cb3dSCy Schubert 		"%+'0123lu",
1891*2b15cb3dSCy Schubert 		"%-'123lu",
1892*2b15cb3dSCy Schubert 		"%'123lu",
1893*2b15cb3dSCy Schubert #endif	/* !OS_IRiX */
1894*2b15cb3dSCy Schubert 		"%123.9lu",
1895*2b15cb3dSCy Schubert 		"% 123.9lu",
1896*2b15cb3dSCy Schubert 		"%+123.9lu",
1897*2b15cb3dSCy Schubert 		"%-123.9lu",
1898*2b15cb3dSCy Schubert 		"%0123lu",
1899*2b15cb3dSCy Schubert 		"% 0123lu",
1900*2b15cb3dSCy Schubert 		"%+0123lu",
1901*2b15cb3dSCy Schubert 		"%-0123lu",
1902*2b15cb3dSCy Schubert 		"%5.5lu",
1903*2b15cb3dSCy Schubert 		"%+22.33lu",
1904*2b15cb3dSCy Schubert 		"%01.3lu",
1905*2b15cb3dSCy Schubert 		"%1.5lu",
1906*2b15cb3dSCy Schubert 		"%-1.5lu",
1907*2b15cb3dSCy Schubert 		"%44lu",
1908*2b15cb3dSCy Schubert 		"%lu",
1909*2b15cb3dSCy Schubert 		/* "%o" formats. */
1910*2b15cb3dSCy Schubert 		"foo|%#0123lo|bar",
1911*2b15cb3dSCy Schubert 		"%#123.9lo",
1912*2b15cb3dSCy Schubert 		"%# 123.9lo",
1913*2b15cb3dSCy Schubert 		"%#+123.9lo",
1914*2b15cb3dSCy Schubert 		"%#-123.9lo",
1915*2b15cb3dSCy Schubert 		"%#0123lo",
1916*2b15cb3dSCy Schubert 		"%# 0123lo",
1917*2b15cb3dSCy Schubert 		"%#+0123lo",
1918*2b15cb3dSCy Schubert 		"%#-0123lo",
1919*2b15cb3dSCy Schubert 		"%#5.5lo",
1920*2b15cb3dSCy Schubert 		"%#+22.33lo",
1921*2b15cb3dSCy Schubert 		"%#01.3lo",
1922*2b15cb3dSCy Schubert 		"%#1.5lo",
1923*2b15cb3dSCy Schubert 		"%#-1.5lo",
1924*2b15cb3dSCy Schubert 		"%#44lo",
1925*2b15cb3dSCy Schubert 		"%#lo",
1926*2b15cb3dSCy Schubert 		"%123.9lo",
1927*2b15cb3dSCy Schubert 		"% 123.9lo",
1928*2b15cb3dSCy Schubert 		"%+123.9lo",
1929*2b15cb3dSCy Schubert 		"%-123.9lo",
1930*2b15cb3dSCy Schubert 		"%0123lo",
1931*2b15cb3dSCy Schubert 		"% 0123lo",
1932*2b15cb3dSCy Schubert 		"%+0123lo",
1933*2b15cb3dSCy Schubert 		"%-0123lo",
1934*2b15cb3dSCy Schubert 		"%5.5lo",
1935*2b15cb3dSCy Schubert 		"%+22.33lo",
1936*2b15cb3dSCy Schubert 		"%01.3lo",
1937*2b15cb3dSCy Schubert 		"%1.5lo",
1938*2b15cb3dSCy Schubert 		"%-1.5lo",
1939*2b15cb3dSCy Schubert 		"%44lo",
1940*2b15cb3dSCy Schubert 		"%lo",
1941*2b15cb3dSCy Schubert 		/* "%X" and "%x" formats. */
1942*2b15cb3dSCy Schubert 		"foo|%#0123lX|bar",
1943*2b15cb3dSCy Schubert 		"%#123.9lx",
1944*2b15cb3dSCy Schubert 		"%# 123.9lx",
1945*2b15cb3dSCy Schubert 		"%#+123.9lx",
1946*2b15cb3dSCy Schubert 		"%#-123.9lx",
1947*2b15cb3dSCy Schubert 		"%#0123lx",
1948*2b15cb3dSCy Schubert 		"%# 0123lx",
1949*2b15cb3dSCy Schubert 		"%#+0123lx",
1950*2b15cb3dSCy Schubert 		"%#-0123lx",
1951*2b15cb3dSCy Schubert 		"%#5.5lx",
1952*2b15cb3dSCy Schubert 		"%#+22.33lx",
1953*2b15cb3dSCy Schubert 		"%#01.3lx",
1954*2b15cb3dSCy Schubert 		"%#1.5lx",
1955*2b15cb3dSCy Schubert 		"%#-1.5lx",
1956*2b15cb3dSCy Schubert 		"%#44lx",
1957*2b15cb3dSCy Schubert 		"%#lx",
1958*2b15cb3dSCy Schubert 		"%#lX",
1959*2b15cb3dSCy Schubert 		"%123.9lx",
1960*2b15cb3dSCy Schubert 		"% 123.9lx",
1961*2b15cb3dSCy Schubert 		"%+123.9lx",
1962*2b15cb3dSCy Schubert 		"%-123.9lx",
1963*2b15cb3dSCy Schubert 		"%0123lx",
1964*2b15cb3dSCy Schubert 		"% 0123lx",
1965*2b15cb3dSCy Schubert 		"%+0123lx",
1966*2b15cb3dSCy Schubert 		"%-0123lx",
1967*2b15cb3dSCy Schubert 		"%5.5lx",
1968*2b15cb3dSCy Schubert 		"%+22.33lx",
1969*2b15cb3dSCy Schubert 		"%01.3lx",
1970*2b15cb3dSCy Schubert 		"%1.5lx",
1971*2b15cb3dSCy Schubert 		"%-1.5lx",
1972*2b15cb3dSCy Schubert 		"%44lx",
1973*2b15cb3dSCy Schubert 		"%lx",
1974*2b15cb3dSCy Schubert 		"%lX",
1975*2b15cb3dSCy Schubert 		NULL
1976*2b15cb3dSCy Schubert 	};
1977*2b15cb3dSCy Schubert 	unsigned long int ulong_val[] = {
1978*2b15cb3dSCy Schubert #ifdef ULONG_MAX
1979*2b15cb3dSCy Schubert 		ULONG_MAX,
1980*2b15cb3dSCy Schubert #endif	/* ULONG_MAX */
1981*2b15cb3dSCy Schubert 		91340,
1982*2b15cb3dSCy Schubert 		341,
1983*2b15cb3dSCy Schubert 		134,
1984*2b15cb3dSCy Schubert 		0203,
1985*2b15cb3dSCy Schubert 		1,
1986*2b15cb3dSCy Schubert 		0
1987*2b15cb3dSCy Schubert 	};
1988*2b15cb3dSCy Schubert 	const char *llong_fmt[] = {
1989*2b15cb3dSCy Schubert 		"foo|%0123lld|bar",
1990*2b15cb3dSCy Schubert 		"%123.9lld",
1991*2b15cb3dSCy Schubert 		"% 123.9lld",
1992*2b15cb3dSCy Schubert 		"%+123.9lld",
1993*2b15cb3dSCy Schubert 		"%-123.9lld",
1994*2b15cb3dSCy Schubert 		"%0123lld",
1995*2b15cb3dSCy Schubert 		"% 0123lld",
1996*2b15cb3dSCy Schubert 		"%+0123lld",
1997*2b15cb3dSCy Schubert 		"%-0123lld",
1998*2b15cb3dSCy Schubert 		"%5.5lld",
1999*2b15cb3dSCy Schubert 		"%+22.33lld",
2000*2b15cb3dSCy Schubert 		"%01.3lld",
2001*2b15cb3dSCy Schubert 		"%1.5lld",
2002*2b15cb3dSCy Schubert 		"%-1.5lld",
2003*2b15cb3dSCy Schubert 		"%44lld",
2004*2b15cb3dSCy Schubert 		"%lld",
2005*2b15cb3dSCy Schubert 		NULL
2006*2b15cb3dSCy Schubert 	};
2007*2b15cb3dSCy Schubert 	LLONG llong_val[] = {
2008*2b15cb3dSCy Schubert #ifdef LLONG_MAX
2009*2b15cb3dSCy Schubert 		LLONG_MAX,
2010*2b15cb3dSCy Schubert #endif	/* LLONG_MAX */
2011*2b15cb3dSCy Schubert #ifdef LLONG_MIN
2012*2b15cb3dSCy Schubert 		LLONG_MIN,
2013*2b15cb3dSCy Schubert #endif	/* LLONG_MIN */
2014*2b15cb3dSCy Schubert 		-91340,
2015*2b15cb3dSCy Schubert 		91340,
2016*2b15cb3dSCy Schubert 		341,
2017*2b15cb3dSCy Schubert 		134,
2018*2b15cb3dSCy Schubert 		0203,
2019*2b15cb3dSCy Schubert 		-1,
2020*2b15cb3dSCy Schubert 		1,
2021*2b15cb3dSCy Schubert 		0
2022*2b15cb3dSCy Schubert 	};
2023*2b15cb3dSCy Schubert 	const char *string_fmt[] = {
2024*2b15cb3dSCy Schubert 		"foo|%10.10s|bar",
2025*2b15cb3dSCy Schubert 		"%-10.10s",
2026*2b15cb3dSCy Schubert 		"%10.10s",
2027*2b15cb3dSCy Schubert 		"%10.5s",
2028*2b15cb3dSCy Schubert 		"%5.10s",
2029*2b15cb3dSCy Schubert 		"%10.1s",
2030*2b15cb3dSCy Schubert 		"%1.10s",
2031*2b15cb3dSCy Schubert 		"%10.0s",
2032*2b15cb3dSCy Schubert 		"%0.10s",
2033*2b15cb3dSCy Schubert 		"%-42.5s",
2034*2b15cb3dSCy Schubert 		"%2.s",
2035*2b15cb3dSCy Schubert 		"%.10s",
2036*2b15cb3dSCy Schubert 		"%.1s",
2037*2b15cb3dSCy Schubert 		"%.0s",
2038*2b15cb3dSCy Schubert 		"%.s",
2039*2b15cb3dSCy Schubert 		"%4s",
2040*2b15cb3dSCy Schubert 		"%s",
2041*2b15cb3dSCy Schubert 		NULL
2042*2b15cb3dSCy Schubert 	};
2043*2b15cb3dSCy Schubert 	const char *string_val[] = {
2044*2b15cb3dSCy Schubert 		"Hello",
2045*2b15cb3dSCy Schubert 		"Hello, world!",
2046*2b15cb3dSCy Schubert 		"Sound check: One, two, three.",
2047*2b15cb3dSCy Schubert 		"This string is a little longer than the other strings.",
2048*2b15cb3dSCy Schubert 		"1",
2049*2b15cb3dSCy Schubert 		"",
2050*2b15cb3dSCy Schubert 		NULL
2051*2b15cb3dSCy Schubert 	};
2052*2b15cb3dSCy Schubert #if !OS_SYSV	/* SysV uses a different format than we do. */
2053*2b15cb3dSCy Schubert 	const char *pointer_fmt[] = {
2054*2b15cb3dSCy Schubert 		"foo|%p|bar",
2055*2b15cb3dSCy Schubert 		"%42p",
2056*2b15cb3dSCy Schubert 		"%p",
2057*2b15cb3dSCy Schubert 		NULL
2058*2b15cb3dSCy Schubert 	};
2059*2b15cb3dSCy Schubert 	const char *pointer_val[] = {
2060*2b15cb3dSCy Schubert 		*pointer_fmt,
2061*2b15cb3dSCy Schubert 		*string_fmt,
2062*2b15cb3dSCy Schubert 		*string_val,
2063*2b15cb3dSCy Schubert 		NULL
2064*2b15cb3dSCy Schubert 	};
2065*2b15cb3dSCy Schubert #endif	/* !OS_SYSV */
2066*2b15cb3dSCy Schubert 	char buf1[1024], buf2[1024];
2067*2b15cb3dSCy Schubert 	double value, digits = 9.123456789012345678901234567890123456789;
2068*2b15cb3dSCy Schubert 	int i, j, r1, r2, failed = 0, num = 0;
2069*2b15cb3dSCy Schubert 
2070*2b15cb3dSCy Schubert /*
2071*2b15cb3dSCy Schubert  * Use -DTEST_NILS in order to also test the conversion of nil values.  Might
2072*2b15cb3dSCy Schubert  * segfault on systems which don't support converting a NULL pointer with "%s"
2073*2b15cb3dSCy Schubert  * and lets some test cases fail against BSD and glibc due to bugs in their
2074*2b15cb3dSCy Schubert  * implementations.
2075*2b15cb3dSCy Schubert  */
2076*2b15cb3dSCy Schubert #ifndef TEST_NILS
2077*2b15cb3dSCy Schubert #define TEST_NILS 0
2078*2b15cb3dSCy Schubert #elif TEST_NILS
2079*2b15cb3dSCy Schubert #undef TEST_NILS
2080*2b15cb3dSCy Schubert #define TEST_NILS 1
2081*2b15cb3dSCy Schubert #endif	/* !defined(TEST_NILS) */
2082*2b15cb3dSCy Schubert #ifdef TEST
2083*2b15cb3dSCy Schubert #undef TEST
2084*2b15cb3dSCy Schubert #endif	/* defined(TEST) */
2085*2b15cb3dSCy Schubert #define TEST(fmt, val)                                                         \
2086*2b15cb3dSCy Schubert do {                                                                           \
2087*2b15cb3dSCy Schubert 	for (i = 0; fmt[i] != NULL; i++)                                       \
2088*2b15cb3dSCy Schubert 		for (j = 0; j == 0 || val[j - TEST_NILS] != 0; j++) {          \
2089*2b15cb3dSCy Schubert 			r1 = sprintf(buf1, fmt[i], val[j]);                    \
2090*2b15cb3dSCy Schubert 			r2 = snprintf(buf2, sizeof(buf2), fmt[i], val[j]);     \
2091*2b15cb3dSCy Schubert 			if (strcmp(buf1, buf2) != 0 || r1 != r2) {             \
2092*2b15cb3dSCy Schubert 				(void)printf("Results don't match, "           \
2093*2b15cb3dSCy Schubert 				    "format string: %s\n"                      \
2094*2b15cb3dSCy Schubert 				    "\t sprintf(3): [%s] (%d)\n"               \
2095*2b15cb3dSCy Schubert 				    "\tsnprintf(3): [%s] (%d)\n",              \
2096*2b15cb3dSCy Schubert 				    fmt[i], buf1, r1, buf2, r2);               \
2097*2b15cb3dSCy Schubert 				failed++;                                      \
2098*2b15cb3dSCy Schubert 			}                                                      \
2099*2b15cb3dSCy Schubert 			num++;                                                 \
2100*2b15cb3dSCy Schubert 		}                                                              \
2101*2b15cb3dSCy Schubert } while (/* CONSTCOND */ 0)
2102*2b15cb3dSCy Schubert 
2103*2b15cb3dSCy Schubert #if HAVE_LOCALE_H
2104*2b15cb3dSCy Schubert 	(void)setlocale(LC_ALL, "");
2105*2b15cb3dSCy Schubert #endif	/* HAVE_LOCALE_H */
2106*2b15cb3dSCy Schubert 
2107*2b15cb3dSCy Schubert 	(void)puts("Testing our snprintf(3) against your system's sprintf(3).");
2108*2b15cb3dSCy Schubert 	TEST(float_fmt, float_val);
2109*2b15cb3dSCy Schubert 	TEST(long_fmt, long_val);
2110*2b15cb3dSCy Schubert 	TEST(ulong_fmt, ulong_val);
2111*2b15cb3dSCy Schubert 	TEST(llong_fmt, llong_val);
2112*2b15cb3dSCy Schubert 	TEST(string_fmt, string_val);
2113*2b15cb3dSCy Schubert #if !OS_SYSV	/* SysV uses a different format than we do. */
2114*2b15cb3dSCy Schubert 	TEST(pointer_fmt, pointer_val);
2115*2b15cb3dSCy Schubert #endif	/* !OS_SYSV */
2116*2b15cb3dSCy Schubert 	(void)printf("Result: %d out of %d tests failed.\n", failed, num);
2117*2b15cb3dSCy Schubert 
2118*2b15cb3dSCy Schubert 	(void)fputs("Checking how many digits we support: ", stdout);
2119*2b15cb3dSCy Schubert 	for (i = 0; i < 100; i++) {
2120*2b15cb3dSCy Schubert 		value = pow(10, i) * digits;
2121*2b15cb3dSCy Schubert 		(void)sprintf(buf1, "%.1f", value);
2122*2b15cb3dSCy Schubert 		(void)snprintf(buf2, sizeof(buf2), "%.1f", value);
2123*2b15cb3dSCy Schubert 		if (strcmp(buf1, buf2) != 0) {
2124*2b15cb3dSCy Schubert 			(void)printf("apparently %d.\n", i);
2125*2b15cb3dSCy Schubert 			break;
2126*2b15cb3dSCy Schubert 		}
2127*2b15cb3dSCy Schubert 	}
2128*2b15cb3dSCy Schubert 	return (failed == 0) ? 0 : 1;
2129*2b15cb3dSCy Schubert }
2130*2b15cb3dSCy Schubert #endif	/* TEST_SNPRINTF */
2131*2b15cb3dSCy Schubert 
2132*2b15cb3dSCy Schubert /* vim: set joinspaces textwidth=80: */
2133