1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (c) 1995 Patrick Powell.
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This code is based on code written by Patrick Powell <papowell@astart.com>.
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * It may be used for any purpose as long as this notice remains intact on all
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * source code distributions.
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (c) 2008 Holger Weiss.
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * My changes to the code may freely be used, modified and/or redistributed for
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * any purpose.  It would be nice if additions and fixes to this file (including
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * trivial code cleanups) would be sent back in order to let me include them in
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the version available at <http://www.jhweiss.de/software/snprintf.html>.
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * However, this is not a requirement for using or redistributing (possibly
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * modified) versions of this file, nor is leaving this notice intact mandatory.
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * History
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	Fixed the detection of infinite floating point values on IRIX (and
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	possibly other systems) and applied another few minor cleanups.
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	Added a lot of new features, fixed many bugs, and incorporated various
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	<rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	<djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	projects.  The additions include: support the "e", "E", "g", "G", and
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	"F" conversion specifiers (and use conversion style "f" or "F" for the
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	"t", and "z" length modifiers; support the "#" flag and the (non-C99)
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	"'" flag; use localeconv(3) (if available) to get both the current
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	locale's decimal point character and the separator between groups of
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	digits; fix the handling of various corner cases of field width and
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	precision specifications; fix various floating point conversion bugs;
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	handle infinite and NaN floating point values; don't attempt to write to
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	the output buffer (which may be NULL) if a size of zero was specified;
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	check for integer overflow of the field width, precision, and return
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	values and during the floating point conversion; use the OUTCHAR() macro
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	instead of a function for better performance; provide asprintf(3) and
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	vasprintf(3) functions; add new test cases.  The replacement functions
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	have been renamed to use an "rpl_" prefix, the function calls in the
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	main project (and in this file) must be redefined accordingly for each
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	replacement function which is needed (by using Autoconf or other means).
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	Various other minor improvements have been applied and the coding style
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	was cleaned up for consistency.
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	C99 compliant snprintf(3) and vsnprintf(3) functions return the number
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	of characters that would have been written to a sufficiently sized
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	buffer (excluding the '\0').  The original code simply returned the
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	length of the resulting output string, so that's been fixed.
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	The original code assumed that both snprintf(3) and vsnprintf(3) were
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	missing.  Some systems only have snprintf(3) but not vsnprintf(3), so
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	The PGP code was using unsigned hexadecimal formats.  Unfortunately,
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	unsigned formats simply didn't work.
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	Ok, added some minimal floating point support, which means this probably
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	requires libm on most operating systems.  Don't yet support the exponent
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	(e,E) and sigfig (g,G).  Also, fmtint() was pretty badly broken, it just
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	wasn't being exercised in ways which showed it, so that's been fixed.
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	Also, formatted the code to Mutt conventions, and removed dead code left
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	over from the original.  Also, there is now a builtin-test, run with:
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	This was ugly.  It is still ugly.  I opted out of floating point
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	numbers, but the formatter understands just about everything from the
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	normal C string format, at least as far as I can tell from the Solaris
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 	2.5 printf(3S) man page.
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ToDo
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Add wide character support.
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Add support for "%a" and "%A" conversions.
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * - Create test routines which predefine the expected results.  Our test cases
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   usually expose bugs in system implementations rather than in ours :-)
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Usage
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1) The following preprocessor macros should be defined to 1 if the feature or
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    file in question is available on the target system (by using Autoconf or
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    other means), though basic functionality should be available as long as
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_VSNPRINTF
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_SNPRINTF
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_VASPRINTF
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_ASPRINTF
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_STDARG_H
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_STDDEF_H
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_STDINT_H
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_STDLIB_H
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_INTTYPES_H
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_LOCALE_H
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_LOCALECONV
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_LCONV_DECIMAL_POINT
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_LCONV_THOUSANDS_SEP
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_LONG_DOUBLE
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_LONG_LONG_INT
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_UNSIGNED_LONG_LONG_INT
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_INTMAX_T
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_UINTMAX_T
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_UINTPTR_T
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_PTRDIFF_T
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE_VA_COPY
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	HAVE___VA_COPY
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2) The calls to the functions which should be replaced must be redefined
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    throughout the project files (by using Autoconf or other means):
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#define vsnprintf rpl_vsnprintf
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#define snprintf rpl_snprintf
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#define vasprintf rpl_vasprintf
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#define asprintf rpl_asprintf
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 3) The required replacement functions should be declared in some header file
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    included throughout the project files:
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#if HAVE_CONFIG_H
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#include <config.h>
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#endif
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#if HAVE_STDARG_H
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#include <stdarg.h>
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#if !HAVE_VSNPRINTF
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	int rpl_vsnprintf(char *, size_t, const char *, va_list);
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#endif
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#if !HAVE_SNPRINTF
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	int rpl_snprintf(char *, size_t, const char *, ...);
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#endif
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#if !HAVE_VASPRINTF
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	int rpl_vasprintf(char **, const char *, va_list);
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#endif
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#if !HAVE_ASPRINTF
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	int rpl_asprintf(char **, const char *, ...);
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#endif
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *    	#endif
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Autoconf macros for handling step 1 and step 2 are available at
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * <http://www.jhweiss.de/software/snprintf.html>.
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_config.h"
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_CONFIG_H
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <config.h>
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef WIN32
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define vsnprintf util_vsnprintf
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define snprintf util_snprintf
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_VSNPRINTF 0
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_SNPRINTF 0
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_VASPRINTF 1 /* not needed */
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_ASPRINTF 1 /* not needed */
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_STDARG_H 1
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_STDDEF_H 1
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_STDINT_H 0
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_STDLIB_H 1
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_INTTYPES_H 0
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_LOCALE_H 0
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_LOCALECONV 0
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_LCONV_DECIMAL_POINT 0
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_LCONV_THOUSANDS_SEP 0
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_LONG_DOUBLE 0
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_LONG_LONG_INT 1
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_UNSIGNED_LONG_LONG_INT 1
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_INTMAX_T 0
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_UINTMAX_T 0
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_UINTPTR_T 1
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_PTRDIFF_T 1
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_VA_COPY 0
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE___VA_COPY 0
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_VSNPRINTF 1
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_SNPRINTF 1
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_VASPRINTF 1
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define HAVE_ASPRINTF 1
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_CONFIG_H */
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdio.h>	/* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef VA_START
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef VA_START
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(VA_START) */
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef VA_SHIFT
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef VA_SHIFT
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(VA_SHIFT) */
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_STDARG_H
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdarg.h>
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VA_START(ap, last) va_start(ap, last)
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else	/* Assume <varargs.h> is available. */
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <varargs.h>
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VA_START(ap, last) va_start(ap)	/* "last" is ignored. */
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_STDARG_H */
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if !HAVE_VASPRINTF
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_STDLIB_H
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdlib.h>	/* For malloc(3). */
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_STDLIB_H */
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef VA_COPY
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef VA_COPY
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(VA_COPY) */
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef VA_END_COPY
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef VA_END_COPY
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(VA_END_COPY) */
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_VA_COPY
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VA_COPY(dest, src) va_copy(dest, src)
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VA_END_COPY(ap) va_end(ap)
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#elif HAVE___VA_COPY
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VA_COPY(dest, src) __va_copy(dest, src)
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VA_END_COPY(ap) va_end(ap)
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list))
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define VA_END_COPY(ap) /* No-op. */
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define NEED_MYMEMCPY 1
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void *mymemcpy(void *, void *, size_t);
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_VA_COPY */
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !HAVE_VASPRINTF */
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if !HAVE_VSNPRINTF
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <limits.h>	/* For *_MAX. */
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_INTTYPES_H
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <inttypes.h>	/* For intmax_t (if not defined in <stdint.h>). */
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_INTTYPES_H */
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_LOCALE_H
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <locale.h>	/* For localeconv(3). */
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_LOCALE_H */
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_STDDEF_H
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stddef.h>	/* For ptrdiff_t. */
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_STDDEF_H */
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_STDINT_H
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <stdint.h>	/* For intmax_t. */
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_STDINT_H */
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Support for unsigned long long int.  We may also need ULLONG_MAX. */
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef ULONG_MAX	/* We may need ULONG_MAX as a fallback. */
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef UINT_MAX
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define ULONG_MAX UINT_MAX
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define ULONG_MAX INT_MAX
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(UINT_MAX) */
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(ULONG_MAX) */
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef ULLONG
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef ULLONG
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(ULLONG) */
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_UNSIGNED_LONG_LONG_INT
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define ULLONG unsigned long long int
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef ULLONG_MAX
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define ULLONG_MAX ULONG_MAX
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(ULLONG_MAX) */
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define ULLONG unsigned long int
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef ULLONG_MAX
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef ULLONG_MAX
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(ULLONG_MAX) */
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define ULLONG_MAX ULONG_MAX
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_LONG_LONG_INT */
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Support for uintmax_t.  We also need UINTMAX_MAX. */
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef UINTMAX_T
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef UINTMAX_T
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(UINTMAX_T) */
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_UINTMAX_T || defined(uintmax_t)
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define UINTMAX_T uintmax_t
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef UINTMAX_MAX
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define UINTMAX_MAX ULLONG_MAX
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(UINTMAX_MAX) */
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define UINTMAX_T ULLONG
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef UINTMAX_MAX
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef UINTMAX_MAX
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(UINTMAX_MAX) */
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define UINTMAX_MAX ULLONG_MAX
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_UINTMAX_T || defined(uintmax_t) */
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Support for long double. */
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef LDOUBLE
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_LONG_DOUBLE
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define LDOUBLE long double
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define LDOUBLE double
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_LONG_DOUBLE */
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(LDOUBLE) */
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Support for long long int. */
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef LLONG
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_LONG_LONG_INT
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define LLONG long long int
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define LLONG long int
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_LONG_LONG_INT */
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(LLONG) */
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Support for intmax_t. */
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef INTMAX_T
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_INTMAX_T || defined(intmax_t)
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define INTMAX_T intmax_t
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define INTMAX_T LLONG
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_INTMAX_T || defined(intmax_t) */
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(INTMAX_T) */
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Support for uintptr_t. */
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef UINTPTR_T
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_UINTPTR_T || defined(uintptr_t)
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define UINTPTR_T uintptr_t
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define UINTPTR_T unsigned long int
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_UINTPTR_T || defined(uintptr_t) */
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(UINTPTR_T) */
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* WinCE5.0 does not have uintptr_t defined */
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if (_WIN32_WCE < 600)
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef UINTPTR_T
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef UINTPTR_T
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define UINTPTR_T unsigned long int
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Support for ptrdiff_t. */
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef PTRDIFF_T
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_PTRDIFF_T || defined(ptrdiff_t)
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PTRDIFF_T ptrdiff_t
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PTRDIFF_T long int
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(PTRDIFF_T) */
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 7.19.6.1, 7).  However, we'll simply use PTRDIFF_T and convert it to an
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * unsigned type if necessary.  This should work just fine in practice.
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef UPTRDIFF_T
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define UPTRDIFF_T PTRDIFF_T
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(UPTRDIFF_T) */
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * However, we'll simply use size_t and convert it to a signed type if
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * necessary.  This should work just fine in practice.
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef SSIZE_T
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define SSIZE_T size_t
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(SSIZE_T) */
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Either ERANGE or E2BIG should be available everywhere. */
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef ERANGE
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define ERANGE E2BIG
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(ERANGE) */
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef EOVERFLOW
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define EOVERFLOW ERANGE
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(EOVERFLOW) */
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Buffer size to hold the octal string representation of UINT128_MAX without
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * nul-termination ("3777777777777777777777777777777777777777777").
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef MAX_CONVERT_LENGTH
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef MAX_CONVERT_LENGTH
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(MAX_CONVERT_LENGTH) */
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define MAX_CONVERT_LENGTH      43
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Format read states. */
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_S_DEFAULT         0
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_S_FLAGS           1
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_S_WIDTH           2
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_S_DOT             3
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_S_PRECISION       4
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_S_MOD             5
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_S_CONV            6
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Format flags. */
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_F_MINUS           (1 << 0)
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_F_PLUS            (1 << 1)
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_F_SPACE           (1 << 2)
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_F_NUM             (1 << 3)
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_F_ZERO            (1 << 4)
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_F_QUOTE           (1 << 5)
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_F_UP              (1 << 6)
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_F_UNSIGNED        (1 << 7)
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_F_TYPE_G          (1 << 8)
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_F_TYPE_E          (1 << 9)
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Conversion flags. */
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_C_CHAR            1
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_C_SHORT           2
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_C_LONG            3
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_C_LLONG           4
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_C_LDOUBLE         5
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_C_SIZE            6
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_C_PTRDIFF         7
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define PRINT_C_INTMAX          8
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef MAX
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define MAX(x, y) ((x >= y) ? x : y)
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(MAX) */
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef CHARTOINT
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define CHARTOINT(ch) (ch - '0')
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(CHARTOINT) */
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef ISDIGIT
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(ISDIGIT) */
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef ISNAN
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define ISNAN(x) (x != x)
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(ISNAN) */
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifndef ISINF
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define ISINF(x) (x != 0.0 && x + x == x)
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !defined(ISINF) */
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef OUTCHAR
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#undef OUTCHAR
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* defined(OUTCHAR) */
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#define OUTCHAR(str, len, size, ch)                                          \
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdo {                                                                         \
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (len + 1 < size)                                                  \
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		str[len] = ch;                                               \
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	(len)++;                                                             \
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} while (/* CONSTCOND */ 0)
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void printsep(char *, size_t *, size_t);
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int getnumsep(int);
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int getexponent(LDOUBLE);
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int convert(UINTMAX_T, char *, size_t, int, int);
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic UINTMAX_T cast(LDOUBLE);
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic UINTMAX_T myround(LDOUBLE);
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic LDOUBLE mypow10(int);
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgutil_vsnprintf(char *str, size_t size, const char *format, va_list args)
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	LDOUBLE fvalue;
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	INTMAX_T value;
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	unsigned char cvalue;
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char *strvalue;
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	INTMAX_T *intmaxptr;
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	PTRDIFF_T *ptrdiffptr;
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	SSIZE_T *sizeptr;
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	LLONG *llongptr;
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	long int *longptr;
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int *intptr;
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	short int *shortptr;
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	signed char *charptr;
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	size_t len = 0;
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int overflow = 0;
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int base = 0;
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int cflags = 0;
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int flags = 0;
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int width = 0;
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int precision = -1;
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int state = PRINT_S_DEFAULT;
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char ch = *format++;
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * pointer." (7.19.6.5, 2)  We're forgiving and allow a NULL pointer
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * even if a size larger than zero was specified.  At least NetBSD's
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * snprintf(3) does the same, as well as other versions of this file.
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * (Though some of these versions will write to a non-NULL buffer even
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * if a size of zero was specified, which violates the standard.)
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (str == NULL && size != 0)
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		size = 0;
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (ch != '\0')
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		switch (state) {
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case PRINT_S_DEFAULT:
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (ch == '%')
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				state = PRINT_S_FLAGS;
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			else
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				OUTCHAR(str, len, size, ch);
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			ch = *format++;
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case PRINT_S_FLAGS:
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			switch (ch) {
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case '-':
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_MINUS;
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case '+':
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_PLUS;
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case ' ':
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_SPACE;
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case '#':
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_NUM;
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case '0':
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_ZERO;
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case '\'':	/* SUSv2 flag (not in C99). */
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_QUOTE;
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			default:
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				state = PRINT_S_WIDTH;
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case PRINT_S_WIDTH:
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (ISDIGIT(ch)) {
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = CHARTOINT(ch);
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (width > (INT_MAX - ch) / 10) {
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					overflow = 1;
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					goto out;
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				width = 10 * width + ch;
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			} else if (ch == '*') {
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/*
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * C99 says: "A negative field width argument is
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * taken as a `-' flag followed by a positive
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * field width." (7.19.6.1, 5)
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 */
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if ((width = va_arg(args, int)) < 0) {
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					flags |= PRINT_F_MINUS;
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					width = -width;
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				state = PRINT_S_DOT;
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			} else
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				state = PRINT_S_DOT;
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case PRINT_S_DOT:
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (ch == '.') {
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				state = PRINT_S_PRECISION;
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			} else
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				state = PRINT_S_MOD;
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case PRINT_S_PRECISION:
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (precision == -1)
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				precision = 0;
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (ISDIGIT(ch)) {
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = CHARTOINT(ch);
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (precision > (INT_MAX - ch) / 10) {
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					overflow = 1;
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					goto out;
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				precision = 10 * precision + ch;
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			} else if (ch == '*') {
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/*
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * C99 says: "A negative precision argument is
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * taken as if the precision were omitted."
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * (7.19.6.1, 5)
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 */
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if ((precision = va_arg(args, int)) < 0)
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					precision = -1;
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				state = PRINT_S_MOD;
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			} else
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				state = PRINT_S_MOD;
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case PRINT_S_MOD:
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			switch (ch) {
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'h':
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (ch == 'h') {	/* It's a char. */
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					ch = *format++;
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					cflags = PRINT_C_CHAR;
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				} else
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					cflags = PRINT_C_SHORT;
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'l':
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (ch == 'l') {	/* It's a long long. */
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					ch = *format++;
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					cflags = PRINT_C_LLONG;
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				} else
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					cflags = PRINT_C_LONG;
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'L':
608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				cflags = PRINT_C_LDOUBLE;
609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'j':
612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				cflags = PRINT_C_INTMAX;
613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 't':
616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				cflags = PRINT_C_PTRDIFF;
617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'z':
620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				cflags = PRINT_C_SIZE;
621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				ch = *format++;
622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			state = PRINT_S_CONV;
625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case PRINT_S_CONV:
627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			switch (ch) {
628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'd':
629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* FALLTHROUGH */
630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'i':
631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				switch (cflags) {
632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_CHAR:
633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = (signed char)va_arg(args, int);
634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_SHORT:
636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = (short int)va_arg(args, int);
637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_LONG:
639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, long int);
640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_LLONG:
642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, LLONG);
643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_SIZE:
645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, SSIZE_T);
646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_INTMAX:
648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, INTMAX_T);
649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_PTRDIFF:
651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, PTRDIFF_T);
652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				default:
654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, int);
655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fmtint(str, &len, size, value, 10, width,
658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    precision, flags);
659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'X':
661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_UP;
662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* FALLTHROUGH */
663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'x':
664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				base = 16;
665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* FALLTHROUGH */
666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'o':
667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (base == 0)
668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					base = 8;
669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* FALLTHROUGH */
670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'u':
671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (base == 0)
672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					base = 10;
673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_UNSIGNED;
674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				switch (cflags) {
675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_CHAR:
676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = (unsigned char)va_arg(args,
677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					    unsigned int);
678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_SHORT:
680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = (unsigned short int)va_arg(args,
681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					    unsigned int);
682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_LONG:
684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, unsigned long int);
685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_LLONG:
687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, ULLONG);
688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_SIZE:
690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, size_t);
691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_INTMAX:
693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, UINTMAX_T);
694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_PTRDIFF:
696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, UPTRDIFF_T);
697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				default:
699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					value = va_arg(args, unsigned int);
700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fmtint(str, &len, size, value, base, width,
703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    precision, flags);
704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'A':
706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* Not yet supported, we'll use "%F". */
707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* FALLTHROUGH */
708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'F':
709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_UP;
710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'a':
711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* Not yet supported, we'll use "%f". */
712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* FALLTHROUGH */
713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'f':
714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (cflags == PRINT_C_LDOUBLE)
715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fvalue = va_arg(args, LDOUBLE);
716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				else
717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fvalue = va_arg(args, double);
718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fmtflt(str, &len, size, fvalue, width,
719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    precision, flags, &overflow);
720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (overflow)
721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					goto out;
722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'E':
724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_UP;
725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* FALLTHROUGH */
726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'e':
727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_TYPE_E;
728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (cflags == PRINT_C_LDOUBLE)
729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fvalue = va_arg(args, LDOUBLE);
730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				else
731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fvalue = va_arg(args, double);
732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fmtflt(str, &len, size, fvalue, width,
733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    precision, flags, &overflow);
734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (overflow)
735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					goto out;
736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'G':
738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_UP;
739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/* FALLTHROUGH */
740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'g':
741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				flags |= PRINT_F_TYPE_G;
742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (cflags == PRINT_C_LDOUBLE)
743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fvalue = va_arg(args, LDOUBLE);
744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				else
745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fvalue = va_arg(args, double);
746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/*
747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * If the precision is zero, it is treated as
748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * one (cf. C99: 7.19.6.1, 8).
749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 */
750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (precision == 0)
751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					precision = 1;
752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fmtflt(str, &len, size, fvalue, width,
753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    precision, flags, &overflow);
754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if (overflow)
755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					goto out;
756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'c':
758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				cvalue = (unsigned char)va_arg(args, int);
759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				OUTCHAR(str, len, size, cvalue);
760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 's':
762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				strvalue = va_arg(args, char *);
763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				fmtstr(str, &len, size, strvalue, width,
764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    precision, flags);
765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'p':
767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				/*
768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * C99 says: "The value of the pointer is
769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * converted to a sequence of printing
770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * characters, in an implementation-defined
771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 * manner." (C99: 7.19.6.1, 8)
772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 */
773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				if ((strvalue = va_arg(args, void *)) == NULL)
774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					/*
775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 * We use the glibc format.  BSD prints
776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 * "0x0", SysV "0".
777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 */
778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fmtstr(str, &len, size, "(nil)", width,
779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					    -1, flags);
780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				else {
781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					/*
782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 * We use the BSD/glibc format.  SysV
783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 * omits the "0x" prefix (which we emit
784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 * using the PRINT_F_NUM flag).
785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 */
786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					flags |= PRINT_F_NUM;
787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					flags |= PRINT_F_UNSIGNED;
788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					fmtint(str, &len, size,
789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					    (UINTPTR_T)strvalue, 16, width,
790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					    precision, flags);
791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case 'n':
794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				switch (cflags) {
795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_CHAR:
796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					charptr = va_arg(args, signed char *);
797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					*charptr = (signed char)len;
798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_SHORT:
800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					shortptr = va_arg(args, short int *);
801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					*shortptr = (short int)len;
802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_LONG:
804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					longptr = va_arg(args, long int *);
805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					*longptr = (long int)len;
806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_LLONG:
808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					llongptr = va_arg(args, LLONG *);
809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					*llongptr = (LLONG)len;
810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_SIZE:
812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					/*
813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 * C99 says that with the "z" length
814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 * modifier, "a following `n' conversion
815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 * specifier applies to a pointer to a
816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 * signed integer type corresponding to
817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 * size_t argument." (7.19.6.1, 7)
818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					 */
819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					sizeptr = va_arg(args, SSIZE_T *);
820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					*sizeptr = len;
821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_INTMAX:
823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					intmaxptr = va_arg(args, INTMAX_T *);
824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					*intmaxptr = len;
825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				case PRINT_C_PTRDIFF:
827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					ptrdiffptr = va_arg(args, PTRDIFF_T *);
828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					*ptrdiffptr = len;
829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				default:
831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					intptr = va_arg(args, int *);
832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					*intptr = (int)len;
833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					break;
834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				}
835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			case '%':	/* Print a "%" character verbatim. */
837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				OUTCHAR(str, len, size, ch);
838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			default:	/* Skip other characters. */
840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				break;
841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			}
842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			ch = *format++;
843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			state = PRINT_S_DEFAULT;
844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			base = cflags = flags = width = 0;
845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			precision = -1;
846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgout:
849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (len < size)
850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		str[len] = '\0';
851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	else if (size > 0)
852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		str[size - 1] = '\0';
853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (overflow || len >= INT_MAX) {
855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return -1;
856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return (int)len;
858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfmtstr(char *str, size_t *len, size_t size, const char *value, int width,
862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       int precision, int flags)
863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int padlen, strln;	/* Amount to pad. */
865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int noprecision = (precision == -1);
866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (value == NULL)	/* We're forgiving. */
868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		value = "(null)";
869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* If a precision was specified, don't read the string past it. */
871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	for (strln = 0; value[strln] != '\0' &&
872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    (noprecision || strln < precision); strln++)
873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		continue;
874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if ((padlen = width - strln) < 0)
876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		padlen = 0;
877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (flags & PRINT_F_MINUS)	/* Left justify. */
878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		padlen = -padlen;
879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (padlen > 0) {	/* Leading spaces. */
881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, ' ');
882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		padlen--;
883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (*value != '\0' && (noprecision || precision-- > 0)) {
885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, *value);
886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		value++;
887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (padlen < 0) {	/* Trailing spaces. */
889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, ' ');
890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		padlen++;
891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       int precision, int flags)
897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	UINTMAX_T uvalue;
899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char iconvert[MAX_CONVERT_LENGTH];
900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char sign = 0;
901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char hexprefix = 0;
902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int spadlen = 0;	/* Amount to space pad. */
903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int zpadlen = 0;	/* Amount to zero pad. */
904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int pos;
905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int separators = (flags & PRINT_F_QUOTE);
906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int noprecision = (precision == -1);
907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (flags & PRINT_F_UNSIGNED)
909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		uvalue = value;
910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	else {
911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		uvalue = (value >= 0) ? value : -value;
912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (value < 0)
913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			sign = '-';
914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else if (flags & PRINT_F_PLUS)	/* Do a sign. */
915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			sign = '+';
916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else if (flags & PRINT_F_SPACE)
917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			sign = ' ';
918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	pos = convert(uvalue, iconvert, sizeof(iconvert), base,
921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    flags & PRINT_F_UP);
922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (flags & PRINT_F_NUM && uvalue != 0) {
924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/*
925f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * C99 says: "The result is converted to an `alternative form'.
926f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * For `o' conversion, it increases the precision, if and only
927f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * if necessary, to force the first digit of the result to be a
928f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * zero (if the value and precision are both 0, a single 0 is
929f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * printed).  For `x' (or `X') conversion, a nonzero result has
930f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
931f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 */
932f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		switch (base) {
933f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case 8:
934f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (precision <= pos)
935f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				precision = pos + 1;
936f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
937f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		case 16:
938f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
939f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			break;
940f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
941f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
942f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
943f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (separators)	/* Get the number of group separators we'll print. */
944f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		separators = getnumsep(pos);
945f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
946f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	zpadlen = precision - pos - separators;
947f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	spadlen = width                         /* Minimum field width. */
948f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    - separators                        /* Number of separators. */
949f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    - MAX(precision, pos)               /* Number of integer digits. */
950f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    - ((sign != 0) ? 1 : 0)             /* Will we print a sign? */
951f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    - ((hexprefix != 0) ? 2 : 0);       /* Will we print a prefix? */
952f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
953f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (zpadlen < 0)
954f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		zpadlen = 0;
955f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (spadlen < 0)
956f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		spadlen = 0;
957f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
958f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
959f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
960f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * ignored.  For `d', `i', `o', `u', `x', and `X' conversions, if a
961f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
962f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
963f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (flags & PRINT_F_MINUS)	/* Left justify. */
964f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		spadlen = -spadlen;
965f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	else if (flags & PRINT_F_ZERO && noprecision) {
966f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		zpadlen += spadlen;
967f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		spadlen = 0;
968f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
969f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (spadlen > 0) {	/* Leading spaces. */
970f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, ' ');
971f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		spadlen--;
972f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
973f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (sign != 0)	/* Sign. */
974f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, sign);
975f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (hexprefix != 0) {	/* A "0x" or "0X" prefix. */
976f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, '0');
977f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, hexprefix);
978f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
979f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (zpadlen > 0) {	/* Leading zeros. */
980f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, '0');
981f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		zpadlen--;
982f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
983f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (pos > 0) {	/* The actual digits. */
984f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		pos--;
985f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, iconvert[pos]);
986f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (separators > 0 && pos > 0 && pos % 3 == 0)
987f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			printsep(str, len, size);
988f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
989f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (spadlen < 0) {	/* Trailing spaces. */
990f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, ' ');
991f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		spadlen++;
992f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
993f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
994f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
995f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
996f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
997f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       int precision, int flags, int *overflow)
998f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
999f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	LDOUBLE ufvalue;
1000f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	UINTMAX_T intpart;
1001f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	UINTMAX_T fracpart;
1002f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	UINTMAX_T mask;
1003f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char *infnan = NULL;
1004f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char iconvert[MAX_CONVERT_LENGTH];
1005f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char fconvert[MAX_CONVERT_LENGTH];
1006f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char econvert[4];	/* "e-12" (without nul-termination). */
1007f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char esign = 0;
1008f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char sign = 0;
1009f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int leadfraczeros = 0;
1010f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int exponent = 0;
1011f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int emitpoint = 0;
1012f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int omitzeros = 0;
1013f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int omitcount = 0;
1014f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int padlen = 0;
1015f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int epos = 0;
1016f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int fpos = 0;
1017f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int ipos = 0;
1018f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int separators = (flags & PRINT_F_QUOTE);
1019f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int estyle = (flags & PRINT_F_TYPE_E);
1020f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
1021f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct lconv *lc = localeconv();
1022f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
1023f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1024f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
1025f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * AIX' man page says the default is 0, but C99 and at least Solaris'
1026f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
1027f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * defaults to 6.
1028f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
1029f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (precision == -1)
1030f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		precision = 6;
1031f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1032f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (fvalue < 0.0)
1033f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		sign = '-';
1034f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	else if (flags & PRINT_F_PLUS)	/* Do a sign. */
1035f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		sign = '+';
1036f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	else if (flags & PRINT_F_SPACE)
1037f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		sign = ' ';
1038f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1039f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (ISNAN(fvalue))
1040f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
1041f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	else if (ISINF(fvalue))
1042f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
1043f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1044f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (infnan != NULL) {
1045f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (sign != 0)
1046f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			iconvert[ipos++] = sign;
1047f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		while (*infnan != '\0')
1048f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			iconvert[ipos++] = *infnan++;
1049f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fmtstr(str, len, size, iconvert, width, ipos, flags);
1050f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
1051f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1052f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1053f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* "%e" (or "%E") or "%g" (or "%G") conversion. */
1054f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
1055f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (flags & PRINT_F_TYPE_G) {
1056f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/*
1057f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * For "%g" (and "%G") conversions, the precision
1058f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * specifies the number of significant digits, which
1059f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * includes the digits in the integer part.  The
1060f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * conversion will or will not be using "e-style" (like
1061f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * "%e" or "%E" conversions) depending on the precision
1062f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * and on the exponent.  However, the exponent can be
1063f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * affected by rounding the converted value, so we'll
1064f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * leave this decision for later.  Until then, we'll
1065f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * assume that we're going to do an "e-style" conversion
1066f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * (in order to get the exponent calculated).  For
1067f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * "e-style", the precision must be decremented by one.
1068f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 */
1069f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			precision--;
1070f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/*
1071f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * For "%g" (and "%G") conversions, trailing zeros are
1072f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * removed from the fractional portion of the result
1073f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * unless the "#" flag was specified.
1074f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 */
1075f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			if (!(flags & PRINT_F_NUM))
1076f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				omitzeros = 1;
1077f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
1078f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		exponent = getexponent(fvalue);
1079f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		estyle = 1;
1080f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1081f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1082f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgagain:
1083f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
1084f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * Sorry, we only support 9, 19, or 38 digits (that is, the number of
1085f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
1086f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * minus one) past the decimal point due to our conversion method.
1087f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
1088f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	switch (sizeof(UINTMAX_T)) {
1089f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	case 16:
1090f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (precision > 38)
1091f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			precision = 38;
1092f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		break;
1093f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	case 8:
1094f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (precision > 19)
1095f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			precision = 19;
1096f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		break;
1097f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	default:
1098f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (precision > 9)
1099f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			precision = 9;
1100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		break;
1101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
1104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (estyle)	/* We want exactly one integer digit. */
1105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		ufvalue /= mypow10(exponent);
1106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
1108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		*overflow = 1;
1109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return;
1110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
1113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * Factor of ten with the number of digits needed for the fractional
1114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * part.  For example, if the precision is 3, the mask will be 1000.
1115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
1116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	mask = (UINTMAX_T)mypow10(precision);
1117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
1118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * We "cheat" by converting the fractional part to integer by
1119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * multiplying by a factor of ten.
1120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
1121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
1122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/*
1123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
1124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * (because precision = 3).  Now, myround(1000 * 0.99962) will
1125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * return 1000.  So, the integer part must be incremented by one
1126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * and the fractional part must be set to zero.
1127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 */
1128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		intpart++;
1129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fracpart = 0;
1130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (estyle && intpart == 10) {
1131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			/*
1132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * The value was rounded up to ten, but we only want one
1133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * integer digit if using "e-style".  So, the integer
1134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * part must be set to one and the exponent must be
1135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 * incremented by one.
1136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 */
1137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			intpart = 1;
1138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			exponent++;
1139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
1140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
1143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * Now that we know the real exponent, we can check whether or not to
1144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * use "e-style" for "%g" (and "%G") conversions.  If we don't need
1145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * "e-style", the precision must be adjusted and the integer and
1146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * fractional parts must be recalculated from the original value.
1147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 *
1148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * C99 says: "Let P equal the precision if nonzero, 6 if the precision
1149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * is omitted, or 1 if the precision is zero.  Then, if a conversion
1150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * with style `E' would have an exponent of X:
1151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 *
1152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * - if P > X >= -4, the conversion is with style `f' (or `F') and
1153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 *   precision P - (X + 1).
1154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 *
1155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * - otherwise, the conversion is with style `e' (or `E') and precision
1156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 *   P - 1." (7.19.6.1, 8)
1157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 *
1158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * Note that we had decremented the precision by one.
1159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
1160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (flags & PRINT_F_TYPE_G && estyle &&
1161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    precision + 1 > exponent && exponent >= -4) {
1162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		precision -= exponent;
1163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		estyle = 0;
1164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		goto again;
1165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (estyle) {
1168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (exponent < 0) {
1169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			exponent = -exponent;
1170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			esign = '-';
1171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		} else
1172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			esign = '+';
1173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/*
1175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * Convert the exponent.  The sizeof(econvert) is 4.  So, the
1176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * econvert buffer can hold e.g. "e+99" and "e-99".  We don't
1177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * support an exponent which contains more than two digits.
1178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * Therefore, the following stores are safe.
1179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 */
1180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		epos = convert(exponent, econvert, 2, 10, 0);
1181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		/*
1182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * C99 says: "The exponent always contains at least two digits,
1183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * and only as many more digits as necessary to represent the
1184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 * exponent." (7.19.6.1, 8)
1185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		 */
1186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (epos == 1)
1187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			econvert[epos++] = '0';
1188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		econvert[epos++] = esign;
1189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
1190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* Convert the integer part and the fractional part. */
1193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
1194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (fracpart != 0)	/* convert() would return 1 if fracpart == 0. */
1195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
1196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	leadfraczeros = precision - fpos;
1198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (omitzeros) {
1200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (fpos > 0)	/* Omit trailing fractional part zeros. */
1201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			while (omitcount < fpos && fconvert[omitcount] == '0')
1202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				omitcount++;
1203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else {	/* The fractional part is zero, omit it completely. */
1204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			omitcount = precision;
1205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			leadfraczeros = 0;
1206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
1207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		precision -= omitcount;
1208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
1211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * Print a decimal point if either the fractional part is non-zero
1212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * and/or the "#" flag was specified.
1213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
1214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (precision > 0 || flags & PRINT_F_NUM)
1215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		emitpoint = 1;
1216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (separators)	/* Get the number of group separators we'll print. */
1217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		separators = getnumsep(ipos);
1218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	padlen = width                  /* Minimum field width. */
1220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    - ipos                      /* Number of integer digits. */
1221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    - epos                      /* Number of exponent characters. */
1222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    - precision                 /* Number of fractional digits. */
1223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    - separators                /* Number of group separators. */
1224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    - (emitpoint ? 1 : 0)       /* Will we print a decimal point? */
1225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    - ((sign != 0) ? 1 : 0);    /* Will we print a sign character? */
1226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (padlen < 0)
1228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		padlen = 0;
1229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
1231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
1232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * ignored." (7.19.6.1, 6)
1233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
1234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (flags & PRINT_F_MINUS)	/* Left justifty. */
1235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		padlen = -padlen;
1236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	else if (flags & PRINT_F_ZERO && padlen > 0) {
1237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (sign != 0) {	/* Sign. */
1238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			OUTCHAR(str, *len, size, sign);
1239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			sign = 0;
1240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
1241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		while (padlen > 0) {	/* Leading zeros. */
1242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			OUTCHAR(str, *len, size, '0');
1243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			padlen--;
1244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		}
1245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (padlen > 0) {	/* Leading spaces. */
1247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, ' ');
1248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		padlen--;
1249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (sign != 0)	/* Sign. */
1251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, sign);
1252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (ipos > 0) {	/* Integer part. */
1253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		ipos--;
1254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, iconvert[ipos]);
1255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (separators > 0 && ipos > 0 && ipos % 3 == 0)
1256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			printsep(str, len, size);
1257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (emitpoint) {	/* Decimal point. */
1259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
1260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
1261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			OUTCHAR(str, *len, size, *lc->decimal_point);
1262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		else	/* We'll always print some decimal point character. */
1263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
1264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			OUTCHAR(str, *len, size, '.');
1265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (leadfraczeros > 0) {	/* Leading fractional part zeros. */
1267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, '0');
1268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		leadfraczeros--;
1269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (fpos > omitcount) {	/* The remaining fractional part. */
1271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		fpos--;
1272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, fconvert[fpos]);
1273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (epos > 0) {	/* Exponent. */
1275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		epos--;
1276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, econvert[epos]);
1277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (padlen < 0) {	/* Trailing spaces. */
1279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, ' ');
1280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		padlen++;
1281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
1285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprintsep(char *str, size_t *len, size_t size)
1286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
1288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct lconv *lc = localeconv();
1289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int i;
1290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (lc->thousands_sep != NULL)
1292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for (i = 0; lc->thousands_sep[i] != '\0'; i++)
1293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			OUTCHAR(str, *len, size, lc->thousands_sep[i]);
1294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	else
1295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
1296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		OUTCHAR(str, *len, size, ',');
1297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int
1300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orggetnumsep(int digits)
1301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
1303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
1304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int strln;
1305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	struct lconv *lc = localeconv();
1306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* We support an arbitrary separator length (including zero). */
1308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (lc->thousands_sep != NULL) {
1309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
1310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			continue;
1311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		separators *= strln;
1312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
1314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return separators;
1315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int
1318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orggetexponent(LDOUBLE value)
1319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	LDOUBLE tmp = (value >= 0.0) ? value : -value;
1321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int exponent = 0;
1322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
1324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * We check for 99 > exponent > -99 in order to work around possible
1325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * endless loops which could happen (at least) in the second loop (at
1326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * least) if we're called with an infinite value.  However, we checked
1327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * for infinity before calling this function using our ISINF() macro, so
1328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * this might be somewhat paranoid.
1329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
1330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
1331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		tmp *= 10;
1332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (tmp >= 10.0 && ++exponent < 99)
1333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		tmp /= 10;
1334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return exponent;
1336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic int
1339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgconvert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
1340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
1342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	size_t pos = 0;
1343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* We return an unterminated buffer with the digits in reverse order. */
1345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	do {
1346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		buf[pos++] = digits[value % base];
1347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		value /= base;
1348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	} while (value != 0 && pos < size);
1349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return (int)pos;
1351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic UINTMAX_T
1354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcast(LDOUBLE value)
1355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	UINTMAX_T result;
1357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
1359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
1360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
1361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * it may be increased to the nearest higher representable value for the
1362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * comparison (cf. C99: 6.3.1.4, 2).  It might then equal the LDOUBLE
1363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * value although converting the latter to UINTMAX_T would overflow.
1364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
1365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (value >= UINTMAX_MAX)
1366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return UINTMAX_MAX;
1367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	result = (UINTMAX_T)value;
1369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/*
1370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
1371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
1372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 * the standard).  Sigh.
1373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 */
1374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return (result <= value) ? result : result - 1;
1375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic UINTMAX_T
1378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmyround(LDOUBLE value)
1379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	UINTMAX_T intpart = cast(value);
1381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
1383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic LDOUBLE
1386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmypow10(int exponent)
1387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	LDOUBLE result = 1;
1389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (exponent > 0) {
1391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		result *= 10;
1392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		exponent--;
1393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (exponent < 0) {
1395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		result /= 10;
1396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		exponent++;
1397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	}
1398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return result;
1399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !HAVE_VSNPRINTF */
1401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if !HAVE_VASPRINTF
1403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if NEED_MYMEMCPY
1404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid *
1405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmymemcpy(void *dst, void *src, size_t len)
1406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	const char *from = src;
1408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char *to = dst;
1409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	/* No need for optimization, we use this only to replace va_copy(3). */
1411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	while (len-- > 0)
1412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		*to++ = *from++;
1413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return dst;
1414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* NEED_MYMEMCPY */
1416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
1418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgutil_vasprintf(char **ret, const char *format, va_list ap)
1419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	size_t size;
1421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int len;
1422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	va_list aq;
1423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	VA_COPY(aq, ap);
1425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	len = vsnprintf(NULL, 0, format, aq);
1426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	VA_END_COPY(aq);
1427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
1428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		return -1;
1429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return vsnprintf(*ret, size, format, ap);
1430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !HAVE_VASPRINTF */
1432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if !HAVE_SNPRINTF
1434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_STDARG_H
1435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
1436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgutil_snprintf(char *str, size_t size, const char *format, ...)
1437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
1438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
1439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgutil_snprintf(va_alist) va_dcl
1440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_STDARG_H */
1441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if !HAVE_STDARG_H
1443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char *str;
1444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	size_t size;
1445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char *format;
1446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_STDARG_H */
1447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	va_list ap;
1448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int len;
1449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	VA_START(ap, format);
1451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	VA_SHIFT(ap, str, char *);
1452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	VA_SHIFT(ap, size, size_t);
1453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	VA_SHIFT(ap, format, const char *);
1454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	len = vsnprintf(str, size, format, ap);
1455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	va_end(ap);
1456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return len;
1457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !HAVE_SNPRINTF */
1459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if !HAVE_ASPRINTF
1461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if HAVE_STDARG_H
1462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
1463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgutil_asprintf(char **ret, const char *format, ...)
1464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else
1465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
1466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgutil_asprintf(va_alist) va_dcl
1467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_STDARG_H */
1468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if !HAVE_STDARG_H
1470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char **ret;
1471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	char *format;
1472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* HAVE_STDARG_H */
1473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	va_list ap;
1474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	int len;
1475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	VA_START(ap, format);
1477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	VA_SHIFT(ap, ret, char **);
1478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	VA_SHIFT(ap, format, const char *);
1479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	len = vasprintf(ret, format, ap);
1480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	va_end(ap);
1481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	return len;
1482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !HAVE_ASPRINTF */
1484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#else	/* Dummy declaration to avoid empty translation unit warnings. */
1485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint main(void);
1486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif	/* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */
1487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* vim: set joinspaces textwidth=80: */
1490