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