1e2341d08fa4a4e0c22056c410fd34d3f93e06017Elliott Hughes/*	$OpenBSD: vfprintf.c,v 1.66 2014/05/03 12:36:45 deraadt Exp $	*/
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*-
31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (c) 1990 The Regents of the University of California.
41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved.
51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * This code is derived from software contributed to Berkeley by
71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Chris Torek.
81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without
101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions
111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met:
121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    documentation and/or other materials provided with the distribution.
171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 3. Neither the name of the University nor the names of its contributors
181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    may be used to endorse or promote products derived from this software
191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *    without specific prior written permission.
201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE.
321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Actual printf innards.
361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project *
371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * This code is large and complicated...
381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/types.h>
411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/mman.h>
421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h>
440549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#include <langinfo.h>
450549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#include <limits.h>
461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdarg.h>
471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stddef.h>
481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdio.h>
491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdint.h>
501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <stdlib.h>
511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <string.h>
520549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#include <unistd.h>
530549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#include <wchar.h>
541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "local.h"
561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "fvwrite.h"
571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
58edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenkounion arg {
59edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	int			intarg;
60edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	unsigned int		uintarg;
61edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	long			longarg;
62edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	unsigned long		ulongarg;
63edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	long long		longlongarg;
64edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	unsigned long long	ulonglongarg;
65edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	ptrdiff_t		ptrdiffarg;
66edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	size_t			sizearg;
670549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	ssize_t			ssizearg;
68edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	intmax_t		intmaxarg;
69edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	uintmax_t		uintmaxarg;
70edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	void			*pvoidarg;
71edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	char			*pchararg;
72edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	signed char		*pschararg;
73edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	short			*pshortarg;
74edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	int			*pintarg;
75edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	long			*plongarg;
76edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	long long		*plonglongarg;
77edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	ptrdiff_t		*pptrdiffarg;
780549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	ssize_t			*pssizearg;
79edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	intmax_t		*pintmaxarg;
80edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko#ifdef FLOATING_POINT
81edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	double			doublearg;
82edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	long double		longdoublearg;
83edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko#endif
840549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
850549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	wint_t			wintarg;
860549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	wchar_t			*pwchararg;
870549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif
88edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko};
89edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko
90edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenkostatic int __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    size_t *argtablesiz);
921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int __grow_type_table(unsigned char **typetable, int *tablesize);
931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Flush out all the vectors defined by the given uio,
961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * then reset it so that it can be reused.
971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__sprint(FILE *fp, struct __suio *uio)
1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int err;
1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (uio->uio_resid == 0) {
1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		uio->uio_iovcnt = 0;
1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (0);
1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	err = __sfvwrite(fp, uio);
1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uio->uio_resid = 0;
1091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uio->uio_iovcnt = 0;
1101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (err);
1111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Helper function for `fprintf to unbuffered unix file': creates a
1151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * temporary buffer.  We only work on write-only files; this avoids
1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * worries about ungetc buffers and so forth.
1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
1191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__sbprintf(FILE *fp, const char *fmt, va_list ap)
1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int ret;
1221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	FILE fake;
1231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct __sfileext fakeext;
1241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	unsigned char buf[BUFSIZ];
1251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	_FILEEXT_SETUP(&fake, &fakeext);
1271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* copy the important variables */
1281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fake._flags = fp->_flags & ~__SNBF;
1291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fake._file = fp->_file;
1301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fake._cookie = fp->_cookie;
1311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fake._write = fp->_write;
1321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* set up the buffer */
1341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fake._bf._base = fake._p = buf;
1351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fake._bf._size = fake._w = sizeof(buf);
1361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fake._lbfsize = 0;	/* not actually used, but Just In Case */
1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* do the work, then copy any error status */
139f582340a6a48588aa50da17e1620e8f91b146941Kenny Root	ret = __vfprintf(&fake, fmt, ap);
140f582340a6a48588aa50da17e1620e8f91b146941Kenny Root	if (ret >= 0 && __sflush(&fake))
1411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ret = EOF;
1421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (fake._flags & __SERR)
1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fp->_flags |= __SERR;
1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (ret);
1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
1461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
1470549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
1480549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes/*
1490549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes * Convert a wide character string argument for the %ls format to a multibyte
1500549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes * string representation. If not -1, prec specifies the maximum number of
1510549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes * bytes to output, and also means that we can't assume that the wide char
1520549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes * string is null-terminated.
1530549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes */
1540549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughesstatic char *
1550549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes__wcsconv(wchar_t *wcsarg, int prec)
1560549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes{
1570549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	mbstate_t mbs;
1580549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	char buf[MB_LEN_MAX];
1590549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	wchar_t *p;
1600549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	char *convbuf;
1610549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	size_t clen, nbytes;
1620549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
1630549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	/* Allocate space for the maximum number of bytes we could output. */
1640549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if (prec < 0) {
1650549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		memset(&mbs, 0, sizeof(mbs));
1660549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		p = wcsarg;
1670549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
1680549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		if (nbytes == (size_t)-1) {
1690549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			errno = EILSEQ;
1700549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			return (NULL);
1710549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		}
1720549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	} else {
1730549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		/*
1740549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		 * Optimisation: if the output precision is small enough,
1750549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		 * just allocate enough memory for the maximum instead of
1760549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		 * scanning the string.
1770549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		 */
1780549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		if (prec < 128)
1790549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			nbytes = prec;
1800549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		else {
1810549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			nbytes = 0;
1820549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			p = wcsarg;
1830549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			memset(&mbs, 0, sizeof(mbs));
1840549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			for (;;) {
1850549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				clen = wcrtomb(buf, *p++, &mbs);
1860549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (clen == 0 || clen == (size_t)-1 ||
1870549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				    nbytes + clen > (size_t)prec)
1880549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					break;
1890549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				nbytes += clen;
1900549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			}
1910549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (clen == (size_t)-1) {
1920549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				errno = EILSEQ;
1930549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				return (NULL);
1940549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			}
1950549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		}
1960549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	}
1970549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if ((convbuf = malloc(nbytes + 1)) == NULL)
1980549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		return (NULL);
1990549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
2000549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	/* Fill the output buffer. */
2010549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	p = wcsarg;
2020549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	memset(&mbs, 0, sizeof(mbs));
2030549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
2040549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	    nbytes, &mbs)) == (size_t)-1) {
2050549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		free(convbuf);
2060549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		errno = EILSEQ;
2070549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		return (NULL);
2080549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	}
2090549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	convbuf[nbytes] = '\0';
2100549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	return (convbuf);
2110549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes}
2120549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif
2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef FLOATING_POINT
2150549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#include <float.h>
2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <locale.h>
2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <math.h>
2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include "floatio.h"
219f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes#include "gdtoa.h"
2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	DEFPREC		6
2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int exponent(char *, int, int);
2241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* FLOATING_POINT */
2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2260549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes/*
2270549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes * The size of the buffer we use as scratch space for integer
2280549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes * conversions, among other things.  Technically, we would need the
2290549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes * most space for base 10 conversions with thousands' grouping
2300549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes * characters between each pair of digits.  100 bytes is a
2310549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes * conservative overestimate even for a 128-bit uintmax_t.
2320549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes */
2330549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#define BUF	100
2340549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
2351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define STATIC_ARG_TBL_SIZE 8	/* Size of static argument table. */
2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2370549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
2391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Macros for converting digits to letters and vice versa
2401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	to_digit(c)	((c) - '0')
2421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define is_digit(c)	((unsigned)to_digit(c) <= 9)
2431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	to_char(n)	((n) + '0')
2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Flags used during conversion.
2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	ALT		0x0001		/* alternate form */
2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	LADJUST		0x0004		/* left adjustment */
2500549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#define	LONGDBL		0x0008		/* long double */
2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	LONGINT		0x0010		/* long integer */
2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	LLONGINT	0x0020		/* long long integer */
2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	SHORTINT	0x0040		/* short integer */
2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	ZEROPAD		0x0080		/* zero (as opposed to blank) pad */
2551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define FPT		0x0100		/* Floating point number */
2561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define PTRINT		0x0200		/* (unsigned) ptrdiff_t */
2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define SIZEINT		0x0400		/* (signed) size_t */
2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define CHARINT		0x0800		/* 8 bit integer */
2591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define MAXINT		0x1000		/* largest integer size (intmax_t) */
2601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint
2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectvfprintf(FILE *fp, const char *fmt0, __va_list ap)
2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
264f582340a6a48588aa50da17e1620e8f91b146941Kenny Root	int ret;
265f582340a6a48588aa50da17e1620e8f91b146941Kenny Root
266f582340a6a48588aa50da17e1620e8f91b146941Kenny Root	FLOCKFILE(fp);
267f582340a6a48588aa50da17e1620e8f91b146941Kenny Root	ret = __vfprintf(fp, fmt0, ap);
268f582340a6a48588aa50da17e1620e8f91b146941Kenny Root	FUNLOCKFILE(fp);
269f582340a6a48588aa50da17e1620e8f91b146941Kenny Root	return (ret);
270f582340a6a48588aa50da17e1620e8f91b146941Kenny Root}
271f582340a6a48588aa50da17e1620e8f91b146941Kenny Root
272f582340a6a48588aa50da17e1620e8f91b146941Kenny Rootint
273f582340a6a48588aa50da17e1620e8f91b146941Kenny Root__vfprintf(FILE *fp, const char *fmt0, __va_list ap)
274f582340a6a48588aa50da17e1620e8f91b146941Kenny Root{
275edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	char *fmt;		/* format string */
276edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	int ch;			/* character from fmt */
2770549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	int n, n2;		/* handy integers (short term usage) */
278edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	char *cp;		/* handy char pointer (short term usage) */
279edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	struct __siov *iovp;	/* for PRINT macro */
280edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	int flags;		/* flags as above */
2811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int ret;		/* return value accumulator */
2821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int width;		/* width from format (%8d), or 0 */
2830549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	int prec;		/* precision from format; <0 for N/A */
2841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char sign;		/* sign prefix (' ', '+', '-', or \0) */
2851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	wchar_t wc;
2860549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	mbstate_t ps;
2871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef FLOATING_POINT
2880549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	/*
2890549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 * We can decompose the printed representation of floating
2900549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 * point numbers into several parts, some of which may be empty:
2910549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 *
2920549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
2930549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 *    A       B     ---C---      D       E   F
2940549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 *
2950549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 * A:	'sign' holds this value if present; '\0' otherwise
2960549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 * B:	ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
2970549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 * C:	cp points to the string MMMNNN.  Leading and trailing
2980549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 *	zeros are not in the string and must be added.
2990549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 * D:	expchar holds this character; '\0' if no exponent, e.g. %f
3000549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 * F:	at least two digits for decimal, at least one digit for hex
3010549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 */
3020549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	char *decimal_point = NULL;
3030549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	int signflag;		/* true if float is negative */
3040549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	union {			/* floating point arguments %[aAeEfFgG] */
3050549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		double dbl;
3060549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		long double ldbl;
3070549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	} fparg;
3081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int expt;		/* integer value of exponent */
3090549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	char expchar;		/* exponent character: [eEpP\0] */
3100549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	char *dtoaend;		/* pointer to end of converted digits */
3110549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	int expsize;		/* character count for expstr */
3120549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	int lead;		/* sig figs before decimal or group sep */
3130549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	int ndig;		/* actual number of digits returned by dtoa */
3140549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	char expstr[MAXEXPDIG+2];	/* buffer for exponent string: e+ZZZ */
3155eb670462ab9e7d8a6363861e063cad4b5dfe7d1Elliott Hughes	char *dtoaresult = NULL;
3161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
3171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uintmax_t _umax;	/* integer arguments %[diouxX] */
3190549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	enum { OCT, DEC, HEX } base;	/* base for %[diouxX] conversion */
3200549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	int dprec;		/* a copy of prec if %[diouxX], 0 otherwise */
3211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int realsz;		/* field size expanded by dprec */
3221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int size;		/* size of converted field or string */
3230549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	const char *xdigs;	/* digits for %[xX] conversion */
3241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define NIOV 8
3251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct __suio uio;	/* output information: summary */
3261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	struct __siov iov[NIOV];/* ... and individual io vectors */
3270549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	char buf[BUF];		/* buffer with space for digits of uintmax_t */
3280549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	char ox[2];		/* space for 0x; ox[1] is either x, X, or \0 */
329edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	union arg *argtable;	/* args, built due to positional arg */
330edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	union arg statargtable[STATIC_ARG_TBL_SIZE];
3311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	size_t argtablesiz;
3321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int nextarg;		/* 1-based argument index */
3331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_list orgap;		/* original argument pointer */
3340549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
3350549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	char *convbuf;		/* buffer for wide to multi-byte conversion */
3360549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif
3370549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
3381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
3391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
3401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * fields occur frequently, increase PADSIZE and make the initialisers
3411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * below longer.
3421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
3431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	PADSIZE	16		/* pad chunk size */
3440549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	static char blanks[PADSIZE] =
3451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
3460549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	static char zeroes[PADSIZE] =
3471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
3481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3490549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	static const char xdigs_lower[16] = "0123456789abcdef";
3500549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	static const char xdigs_upper[16] = "0123456789ABCDEF";
3510549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
3521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
3531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * BEWARE, these `goto error' on error, and PAD uses `n'.
3541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
3551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	PRINT(ptr, len) do { \
3561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	iovp->iov_base = (ptr); \
3571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	iovp->iov_len = (len); \
3581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uio.uio_resid += (len); \
3591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	iovp++; \
3601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (++uio.uio_iovcnt >= NIOV) { \
3611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (__sprint(fp, &uio)) \
3621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto error; \
3631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		iovp = iov; \
3641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} \
3651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (0)
3661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	PAD(howmany, with) do { \
3671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((n = (howmany)) > 0) { \
3681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		while (n > PADSIZE) { \
3691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			PRINT(with, PADSIZE); \
3701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			n -= PADSIZE; \
3711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} \
3721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		PRINT(with, n); \
3731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} \
3741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (0)
3750549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#define	PRINTANDPAD(p, ep, len, with) do {	\
3760549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	n2 = (ep) - (p);       			\
3770549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if (n2 > (len))				\
3780549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		n2 = (len);			\
3790549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if (n2 > 0)				\
3800549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		PRINT((p), n2);			\
3810549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	PAD((len) - (n2 > 0 ? n2 : 0), (with));	\
3820549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes} while(0)
3831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	FLUSH() do { \
3841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (uio.uio_resid && __sprint(fp, &uio)) \
3851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		goto error; \
3861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uio.uio_iovcnt = 0; \
3871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	iovp = iov; \
3881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} while (0)
3891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
3901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
3911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * To extend shorts properly, we need both signed and unsigned
3921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * argument extraction methods.
3931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
3941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	SARG() \
3951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
3961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&LLONGINT ? GETARG(long long) : \
3971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&LONGINT ? GETARG(long) : \
3981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&PTRINT ? GETARG(ptrdiff_t) : \
3991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&SIZEINT ? GETARG(ssize_t) : \
4001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&SHORTINT ? (short)GETARG(int) : \
401f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes	    flags&CHARINT ? (signed char)GETARG(int) : \
4021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    GETARG(int)))
4031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	UARG() \
4041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
4051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&LLONGINT ? GETARG(unsigned long long) : \
4061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&LONGINT ? GETARG(unsigned long) : \
4071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
4081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&SIZEINT ? GETARG(size_t) : \
4091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&SHORTINT ? (unsigned short)GETARG(int) : \
4101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    flags&CHARINT ? (unsigned char)GETARG(int) : \
4111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    GETARG(unsigned int)))
4121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4130549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	/*
4140549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 * Append a digit to a value and check for overflow.
4150549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	 */
4160549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#define APPEND_DIGIT(val, dig) do { \
4170549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if ((val) > INT_MAX / 10) \
4180549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		goto overflow; \
4190549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	(val) *= 10; \
4200549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if ((val) > INT_MAX - to_digit((dig))) \
4210549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		goto overflow; \
4220549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	(val) += to_digit((dig)); \
4230549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes} while (0)
4240549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
4251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 /*
4261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	  * Get * arguments, including the form *nn$.  Preserve the nextarg
4271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	  * that the argument can be gotten once the type is determined.
4281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	  */
4291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GETASTER(val) \
4301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	n2 = 0; \
4311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = fmt; \
4321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (is_digit(*cp)) { \
4330549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		APPEND_DIGIT(n2, *cp); \
4341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp++; \
4351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} \
4361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (*cp == '$') { \
4371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int hold = nextarg; \
4381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (argtable == NULL) { \
4391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			argtable = statargtable; \
4401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			__find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
4411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} \
4421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		nextarg = n2; \
4431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		val = GETARG(int); \
4441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		nextarg = hold; \
4451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fmt = ++cp; \
4461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else { \
4471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		val = GETARG(int); \
4481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
4511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project* Get the argument indexed by nextarg.   If the argument table is
4521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project* built, use it to get the argument.  If its not, get the next
4531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project* argument (and arguments must be gotten sequentially).
4541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project*/
4551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define GETARG(type) \
456edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
457edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko		(nextarg++, va_arg(ap, type)))
4581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	_SET_ORIENTATION(fp, -1);
4601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
4611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (cantwrite(fp)) {
4621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		errno = EBADF;
4631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (EOF);
4641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
4651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
4671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
4681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    fp->_file >= 0)
4691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		return (__sbprintf(fp, fmt0, ap));
4701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fmt = (char *)fmt0;
4721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	argtable = NULL;
4731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	nextarg = 1;
4741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	va_copy(orgap, ap);
4751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uio.uio_iov = iovp = iov;
4761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uio.uio_resid = 0;
4771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	uio.uio_iovcnt = 0;
4781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	ret = 0;
4790549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
4800549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	convbuf = NULL;
4810549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif
4821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
4831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	memset(&ps, 0, sizeof(ps));
4841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
4851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Scan the format for conversions (`%' character).
4861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
4871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (;;) {
4881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp = fmt;
4891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
4901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			fmt += n;
4911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (wc == '%') {
4921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				fmt--;
4931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				break;
4941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
4951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
4960549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		if (fmt != cp) {
4970549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			ptrdiff_t m = fmt - cp;
4980549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (m < 0 || m > INT_MAX - ret)
4990549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				goto overflow;
5001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			PRINT(cp, m);
5011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ret += m;
5021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
5031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (n <= 0)
5041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto done;
5051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fmt++;		/* skip over '%' */
5061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		flags = 0;
5081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		dprec = 0;
5091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		width = 0;
5101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		prec = -1;
5111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		sign = '\0';
5120549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		ox[1] = '\0';
5131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
5141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectrflag:		ch = *fmt++;
5151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectreswitch:	switch (ch) {
5161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ' ':
5171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
5181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * ``If the space and + flags both appear, the space
5191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * flag will be ignored.''
5201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 *	-- ANSI X3J11
5211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
5221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (!sign)
5231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				sign = ' ';
5241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
5251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '#':
5261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= ALT;
5271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
5280549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case '\'':
5290549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			/* grouping not implemented */
5300549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			goto rflag;
5311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '*':
5321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
5331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * ``A negative field width argument is taken as a
5341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * - flag followed by a positive field width.''
5351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 *	-- ANSI X3J11
5361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * They don't exclude field widths read from args.
5371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
5381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			GETASTER(width);
5391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (width >= 0)
5401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto rflag;
5410549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (width == INT_MIN)
5420549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				goto overflow;
5431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			width = -width;
5441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* FALLTHROUGH */
5451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '-':
5461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LADJUST;
5471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
5481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '+':
5491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			sign = '+';
5501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
5511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '.':
5521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((ch = *fmt++) == '*') {
5531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				GETASTER(n);
5541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				prec = n < 0 ? -1 : n;
5551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto rflag;
5561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
5571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			n = 0;
5581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			while (is_digit(ch)) {
5590549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				APPEND_DIGIT(n, ch);
5601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ch = *fmt++;
5611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
5621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (ch == '$') {
5631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				nextarg = n;
5641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (argtable == NULL) {
5651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					argtable = statargtable;
5661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					__find_arguments(fmt0, orgap,
5671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					    &argtable, &argtablesiz);
5681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
5691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto rflag;
5701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
5710549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			prec = n;
5721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto reswitch;
5731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '0':
5741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
5751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * ``Note that 0 is taken as a flag, not as the
5761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * beginning of a field width.''
5771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 *	-- ANSI X3J11
5781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
5791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= ZEROPAD;
5801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
5811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '1': case '2': case '3': case '4':
5821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '5': case '6': case '7': case '8': case '9':
5831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			n = 0;
5841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			do {
5850549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				APPEND_DIGIT(n, ch);
5861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ch = *fmt++;
5871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} while (is_digit(ch));
5881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (ch == '$') {
5891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				nextarg = n;
5901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				if (argtable == NULL) {
5911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					argtable = statargtable;
5921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					__find_arguments(fmt0, orgap,
5931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					    &argtable, &argtablesiz);
5941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
5951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto rflag;
5961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
5971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			width = n;
5981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto reswitch;
5991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef FLOATING_POINT
6001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'L':
6011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LONGDBL;
6021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
6031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
6041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'h':
6051d13c64d781a87dfa3f01e5c179bfa36748786afElliott Hughes			if (*fmt == 'h') {
6061d13c64d781a87dfa3f01e5c179bfa36748786afElliott Hughes				fmt++;
6071d13c64d781a87dfa3f01e5c179bfa36748786afElliott Hughes				flags |= CHARINT;
6081d13c64d781a87dfa3f01e5c179bfa36748786afElliott Hughes			} else {
6091d13c64d781a87dfa3f01e5c179bfa36748786afElliott Hughes				flags |= SHORTINT;
6101d13c64d781a87dfa3f01e5c179bfa36748786afElliott Hughes			}
6111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
6121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'j':
6131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= MAXINT;
6141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
6151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'l':
6161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (*fmt == 'l') {
6171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				fmt++;
6181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				flags |= LLONGINT;
6191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} else {
6201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				flags |= LONGINT;
6211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
6221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
6231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'q':
6241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LLONGINT;
6251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
6261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 't':
6271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= PTRINT;
6281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
6291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'z':
6301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= SIZEINT;
6311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
6321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'c':
6330549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
6340549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (flags & LONGINT) {
6350549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				mbstate_t mbs;
6360549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				size_t mbseqlen;
6370549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
6380549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				memset(&mbs, 0, sizeof(mbs));
6390549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				mbseqlen = wcrtomb(buf,
6400549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				    (wchar_t)GETARG(wint_t), &mbs);
6410549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (mbseqlen == (size_t)-1) {
6420549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					fp->_flags |= __SERR;
6430549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					errno = EILSEQ;
6440549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					goto error;
6450549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				}
6460549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				cp = buf;
6470549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				size = (int)mbseqlen;
6480549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			} else {
6490549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif
6500549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				*(cp = buf) = GETARG(int);
6510549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				size = 1;
6520549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
6530549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			}
6540549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif
6551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			sign = '\0';
6561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
6571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'D':
6581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LONGINT;
6591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*FALLTHROUGH*/
6601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'd':
6611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'i':
6621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			_umax = SARG();
6631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((intmax_t)_umax < 0) {
6641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				_umax = -_umax;
6651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				sign = '-';
6661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
6671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			base = DEC;
6681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto number;
6691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef FLOATING_POINT
6700549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case 'a':
6710549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case 'A':
6720549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (ch == 'a') {
6730549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				ox[1] = 'x';
6740549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				xdigs = xdigs_lower;
6750549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				expchar = 'p';
6760549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			} else {
6770549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				ox[1] = 'X';
6780549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				xdigs = xdigs_upper;
6790549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				expchar = 'P';
6800549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			}
6810549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (prec >= 0)
6820549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				prec++;
6830549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (dtoaresult)
6840549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				__freedtoa(dtoaresult);
6850549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (flags & LONGDBL) {
6860549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				fparg.ldbl = GETARG(long double);
6870549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				dtoaresult = cp =
6880549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				    __hldtoa(fparg.ldbl, xdigs, prec,
6890549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				    &expt, &signflag, &dtoaend);
6900549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (dtoaresult == NULL) {
6910549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					errno = ENOMEM;
6920549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					goto error;
6930549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				}
6940549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			} else {
6950549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				fparg.dbl = GETARG(double);
6960549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				dtoaresult = cp =
6970549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				    __hdtoa(fparg.dbl, xdigs, prec,
6980549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				    &expt, &signflag, &dtoaend);
6990549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (dtoaresult == NULL) {
7000549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					errno = ENOMEM;
7010549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					goto error;
7020549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				}
7030549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			}
7040549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (prec < 0)
7050549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				prec = dtoaend - cp;
7060549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (expt == INT_MAX)
7070549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				ox[1] = '\0';
7080549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			goto fp_common;
7091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'e':
7101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'E':
7110549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			expchar = ch;
7120549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (prec < 0)	/* account for digit before decpt */
7130549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				prec = DEFPREC + 1;
7140549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			else
7150549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				prec++;
7160549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			goto fp_begin;
7171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'f':
7180549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case 'F':
7190549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			expchar = '\0';
7200549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			goto fp_begin;
7211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'g':
7221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'G':
7230549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			expchar = ch - ('g' - 'e');
7240549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes 			if (prec == 0)
7250549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes 				prec = 1;
7260549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughesfp_begin:
7270549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (prec < 0)
7281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				prec = DEFPREC;
7290549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (dtoaresult)
7300549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				__freedtoa(dtoaresult);
7311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (flags & LONGDBL) {
7320549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				fparg.ldbl = GETARG(long double);
7330549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				dtoaresult = cp =
7340549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				    __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
7350549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				    &expt, &signflag, &dtoaend);
7360549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (dtoaresult == NULL) {
7370549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					errno = ENOMEM;
7380549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					goto error;
7390549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				}
7401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} else {
7410549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				fparg.dbl = GETARG(double);
7420549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				dtoaresult = cp =
7430549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				    __dtoa(fparg.dbl, expchar ? 2 : 3, prec,
7440549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				    &expt, &signflag, &dtoaend);
7450549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (dtoaresult == NULL) {
7460549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					errno = ENOMEM;
7470549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					goto error;
7480549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				}
7490549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (expt == 9999)
7500549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					expt = INT_MAX;
7510549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes 			}
7520549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughesfp_common:
7530549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (signflag)
7540549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				sign = '-';
7550549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (expt == INT_MAX) {	/* inf or nan */
7560549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (*cp == 'N') {
7570549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					cp = (ch >= 'a') ? "nan" : "NAN";
7580549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					sign = '\0';
7590549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				} else
7600549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					cp = (ch >= 'a') ? "inf" : "INF";
7610549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes 				size = 3;
7620549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				flags &= ~ZEROPAD;
7630549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes 				break;
7640549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes 			}
7651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= FPT;
7660549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			ndig = dtoaend - cp;
7670549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes 			if (ch == 'g' || ch == 'G') {
7680549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (expt > -4 && expt <= prec) {
7690549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					/* Make %[gG] smell like %[fF] */
7700549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					expchar = '\0';
7710549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					if (flags & ALT)
7720549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes						prec -= expt;
7730549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					else
7740549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes						prec = ndig - expt;
7750549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					if (prec < 0)
7760549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes						prec = 0;
7770549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				} else {
7780549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					/*
7790549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					 * Make %[gG] smell like %[eE], but
7800549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					 * trim trailing zeroes if no # flag.
7810549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					 */
7820549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					if (!(flags & ALT))
7830549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes						prec = ndig;
784edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko				}
7850549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes 			}
7860549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (expchar) {
7870549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				expsize = exponent(expstr, expt - 1, expchar);
7880549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				size = expsize + prec;
7890549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (prec > 1 || flags & ALT)
7900549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes 					++size;
791edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			} else {
7920549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				/* space for digits before decimal point */
7930549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (expt > 0)
7940549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					size = expt;
7950549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				else	/* "0" */
7960549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					size = 1;
7970549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				/* space for decimal pt and following digits */
7980549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (prec || flags & ALT)
7990549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					size += prec + 1;
8000549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				lead = expt;
801edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			}
8021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
8031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* FLOATING_POINT */
804e2341d08fa4a4e0c22056c410fd34d3f93e06017Elliott Hughes#ifndef NO_PRINTF_PERCENT_N
8051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'n':
8061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (flags & LLONGINT)
8071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*GETARG(long long *) = ret;
8081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & LONGINT)
8091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*GETARG(long *) = ret;
8101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & SHORTINT)
8111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*GETARG(short *) = ret;
8121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & CHARINT)
813f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes				*GETARG(signed char *) = ret;
8141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & PTRINT)
8151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*GETARG(ptrdiff_t *) = ret;
8161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & SIZEINT)
8171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*GETARG(ssize_t *) = ret;
8181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & MAXINT)
8191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*GETARG(intmax_t *) = ret;
8201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else
8211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				*GETARG(int *) = ret;
8221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;	/* no output */
823e2341d08fa4a4e0c22056c410fd34d3f93e06017Elliott Hughes#endif /* NO_PRINTF_PERCENT_N */
8241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'O':
8251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LONGINT;
8261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*FALLTHROUGH*/
8271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'o':
8281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			_umax = UARG();
8291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			base = OCT;
8301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto nosign;
8311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'p':
8321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
8331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * ``The argument shall be a pointer to void.  The
8341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * value of the pointer is converted to a sequence
8351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * of printable characters, in an implementation-
8361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * defined manner.''
8371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 *	-- ANSI X3J11
8381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
8391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* NOSTRICT */
8401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			_umax = (u_long)GETARG(void *);
8411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			base = HEX;
8420549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			xdigs = xdigs_lower;
8430549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			ox[1] = 'x';
8441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto nosign;
8451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 's':
8460549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
8470549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (flags & LONGINT) {
8480549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				wchar_t *wcp;
8490549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
8500549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (convbuf != NULL) {
8510549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					free(convbuf);
8520549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					convbuf = NULL;
8530549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				}
8540549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if ((wcp = GETARG(wchar_t *)) == NULL) {
8550549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					cp = "(null)";
8560549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				} else {
8570549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					convbuf = __wcsconv(wcp, prec);
8580549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					if (convbuf == NULL) {
8590549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes						fp->_flags = __SERR;
8600549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes						goto error;
8610549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					}
8620549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					cp = convbuf;
8630549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				}
8640549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			} else
8650549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif /* PRINTF_WIDE_CHAR */
8661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((cp = GETARG(char *)) == NULL)
8671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				cp = "(null)";
8681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (prec >= 0) {
8691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				/*
8701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * can't use strlen; can only look for the
8711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * NUL in the first `prec' characters, and
8721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * strlen() will go further.
8731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 */
8741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				char *p = memchr(cp, 0, prec);
8751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
8760549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				size = p ? (p - cp) : prec;
877edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			} else {
8780549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				size_t len;
8790549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
8800549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if ((len = strlen(cp)) > INT_MAX)
8810549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					goto overflow;
8820549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				size = (int)len;
883edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			}
8841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			sign = '\0';
8851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
8861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'U':
8871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LONGINT;
8881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*FALLTHROUGH*/
8891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'u':
8901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			_umax = UARG();
8911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			base = DEC;
8921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto nosign;
8931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'X':
8940549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			xdigs = xdigs_upper;
8951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto hex;
8961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'x':
8970549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			xdigs = xdigs_lower;
8981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecthex:			_umax = UARG();
8991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			base = HEX;
9001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* leading 0x/X only if non-zero */
9011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (flags & ALT && _umax != 0)
9020549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				ox[1] = ch;
9031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* unsigned conversions */
9051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectnosign:			sign = '\0';
9061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
9071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * ``... diouXx conversions ... if a precision is
9081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * specified, the 0 flag will be ignored.''
9091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 *	-- ANSI X3J11
9101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
9111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectnumber:			if ((dprec = prec) >= 0)
9121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				flags &= ~ZEROPAD;
9131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*
9151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * ``The result of converting a zero value with an
9161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 * explicit precision of zero is no characters.''
9171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 *	-- ANSI X3J11
9181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			 */
9191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp = buf + BUF;
9201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (_umax != 0 || prec != 0) {
9211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				/*
9221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * Unsigned mod is hard, and unsigned mod
9231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * by a constant is easier than that by
9241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 * a variable; hence this switch.
9251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				 */
9261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				switch (base) {
9271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case OCT:
9281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					do {
9291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						*--cp = to_char(_umax & 7);
9301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						_umax >>= 3;
9311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					} while (_umax);
9321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/* handle octal leading 0 */
9331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					if (flags & ALT && *cp != '0')
9341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						*--cp = '0';
9351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
9361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case DEC:
9381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					/* many numbers are 1 digit */
9391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					while (_umax >= 10) {
9401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						*--cp = to_char(_umax % 10);
9411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						_umax /= 10;
9421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					}
9431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					*--cp = to_char(_umax);
9441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
9451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				case HEX:
9471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					do {
9481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						*--cp = xdigs[_umax & 15];
9491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						_umax >>= 4;
9501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					} while (_umax);
9511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					break;
9521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				default:
9541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					cp = "bug in vfprintf: bad base";
9551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					size = strlen(cp);
9561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					goto skipsize;
9571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
9581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
9591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			size = buf + BUF - cp;
9600549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (size > BUF)	/* should never happen */
9610549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				abort();
9621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		skipsize:
9631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
9641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:	/* "%?" prints ?, unless ? is NUL */
9651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (ch == '\0')
9661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto done;
9671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/* pretend it was %c with argument ch */
9681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			cp = buf;
9691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*cp = ch;
9701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			size = 1;
9711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			sign = '\0';
9721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
9731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
9741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/*
9761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * All reasonable formats wind up here.  At this point, `cp'
9771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * points to a string which (if not flags&LADJUST) should be
9781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * padded out to `width' places.  If flags&ZEROPAD, it should
9791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * first be prefixed by any sign or other prefix; otherwise,
9801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * it should be blank padded before the prefix is emitted.
9811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * After any left-hand padding and prefixing, emit zeroes
9820549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		 * required by a decimal %[diouxX] precision, then print the
9831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * string proper, then emit zeroes required by any leftover
9841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * floating precision; finally, if LADJUST, pad with blanks.
9851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 *
9861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * Compute actual size, so we know how much to pad.
9871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 * size excludes decimal prec; realsz includes it.
9881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		 */
9891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		realsz = dprec > size ? dprec : size;
9901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (sign)
9911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			realsz++;
9920549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		if (ox[1])
9931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			realsz+= 2;
9941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* right-adjusting blank padding */
9961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((flags & (LADJUST|ZEROPAD)) == 0)
9971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			PAD(width - realsz, blanks);
9981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
9991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* prefix */
10000549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		if (sign)
10011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			PRINT(&sign, 1);
10020549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		if (ox[1]) {	/* ox[1] is either x, X, or \0 */
10031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ox[0] = '0';
10041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			PRINT(ox, 2);
10051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
10061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* right-adjusting zero padding */
10081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
10091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			PAD(width - realsz, zeroes);
10101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* leading zeroes from decimal precision */
10121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		PAD(dprec - size, zeroes);
10131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* the string or number proper */
10151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef FLOATING_POINT
10161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if ((flags & FPT) == 0) {
10171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			PRINT(cp, size);
10181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} else {	/* glue together f_p fragments */
10190549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (decimal_point == NULL)
10200549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				decimal_point = nl_langinfo(RADIXCHAR);
10210549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (!expchar) {	/* %[fF] or sufficiently short %[gG] */
10220549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (expt <= 0) {
10230549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					PRINT(zeroes, 1);
10240549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					if (prec || flags & ALT)
10251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project						PRINT(decimal_point, 1);
10261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					PAD(-expt, zeroes);
10270549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					/* already handled initial 0's */
10280549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					prec += expt;
10290549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes 				} else {
10300549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					PRINTANDPAD(cp, dtoaend, lead, zeroes);
10310549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					cp += lead;
10320549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					if (prec || flags & ALT)
10330549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes						PRINT(decimal_point, 1);
10341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				}
10350549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				PRINTANDPAD(cp, dtoaend, prec, zeroes);
10360549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			} else {	/* %[eE] or sufficiently long %[gG] */
10370549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				if (prec > 1 || flags & ALT) {
10380549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					buf[0] = *cp++;
10390549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					buf[1] = *decimal_point;
10400549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					PRINT(buf, 2);
10410549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					PRINT(cp, ndig-1);
10420549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes					PAD(prec - ndig, zeroes);
1043edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko				} else { /* XeYYY */
10441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project					PRINT(cp, 1);
1045edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko				}
10461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				PRINT(expstr, expsize);
10471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
10481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
10491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#else
10501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		PRINT(cp, size);
10511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
10521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* left-adjusting padding (always blank) */
10531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (flags & LADJUST)
10541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			PAD(width - realsz, blanks);
10551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		/* finally, adjust ret */
10570549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		if (width < realsz)
10580549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			width = realsz;
10590549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		if (width > INT_MAX - ret)
10600549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			goto overflow;
10610549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		ret += width;
10621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		FLUSH();	/* copy out the I/O vectors */
10641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
10651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdone:
10661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	FLUSH();
10671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projecterror:
10680549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	va_end(orgap);
10690549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if (__sferror(fp))
10700549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		ret = -1;
10710549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	goto finish;
10720549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
10730549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughesoverflow:
10740549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	errno = ENOMEM;
10750549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	ret = -1;
10760549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
10770549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughesfinish:
10780549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
10790549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if (convbuf)
10800549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		free(convbuf);
10810549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif
10825eb670462ab9e7d8a6363861e063cad4b5dfe7d1Elliott Hughes#ifdef FLOATING_POINT
10830549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if (dtoaresult)
10844bd97cee28dd815fff54fc97560be60d566c1fa5Elliott Hughes		__freedtoa(dtoaresult);
10851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
10861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (argtable != NULL && argtable != statargtable) {
10871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		munmap(argtable, argtablesiz);
10881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		argtable = NULL;
10891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
10900549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	return (ret);
10911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
10921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
10931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
10941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Type ids for argument type table.
10951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
10961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_UNUSED	0
10971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_SHORT		1
10981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_U_SHORT	2
10991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TP_SHORT	3
11001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_INT		4
11011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_U_INT		5
11021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TP_INT		6
11031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_LONG		7
11041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_U_LONG	8
11051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TP_LONG		9
11061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_LLONG		10
11071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_U_LLONG	11
11081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TP_LLONG	12
11091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_DOUBLE	13
11101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_LONG_DOUBLE	14
11111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TP_CHAR		15
11121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TP_VOID		16
11131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_PTRINT	17
11141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TP_PTRINT	18
11151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_SIZEINT	19
11161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_SSIZEINT	20
11171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TP_SSIZEINT	21
11181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_MAXINT	22
11191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define T_MAXUINT	23
11201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define TP_MAXINT	24
11210549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#define T_CHAR		25
11220549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#define T_U_CHAR	26
11230549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#define T_WINT		27
11240549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#define TP_WCHAR	28
11251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
11271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Find all arguments when a positional parameter is encountered.  Returns a
11281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * table, indexed by argument number, of pointers to each arguments.  The
11291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
11301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * It will be replaced with a mmap-ed one if it overflows (malloc cannot be
11311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * used since we are attempting to make snprintf thread safe, and alloca is
11321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * problematic since we have nested functions..)
11331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
1134edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenkostatic int
1135edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko__find_arguments(const char *fmt0, va_list ap, union arg **argtable,
11361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project    size_t *argtablesiz)
11371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
1138edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	char *fmt;		/* format string */
1139edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	int ch;			/* character from fmt */
1140edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	int n, n2;		/* handy integer (short term usage) */
1141edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	char *cp;		/* handy char pointer (short term usage) */
1142edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	int flags;		/* flags as above */
11431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	unsigned char *typetable; /* table of types */
11441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
11451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int tablesize;		/* current size of type table */
11461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int tablemax;		/* largest used index in table */
11471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int nextarg;		/* 1-based argument index */
11480549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	int ret = 0;		/* return value */
11491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	wchar_t wc;
11500549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	mbstate_t ps;
11511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
11531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Add an argument type to the table, expanding if necessary.
11541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
11551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define ADDTYPE(type) \
11561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	((nextarg >= tablesize) ? \
11571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		__grow_type_table(&typetable, &tablesize) : 0, \
11581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	(nextarg > tablemax) ? tablemax = nextarg : 0, \
11591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	typetable[nextarg++] = type)
11601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	ADDSARG() \
11621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
11631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
11641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
11651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
11661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
11670549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	    ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
11680549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	    ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
11691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define	ADDUARG() \
11711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project        ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
11721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
11731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
11741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
11751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	    ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
11760549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	    ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
11770549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	    ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))
11781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
11791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
11801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Add * arguments to the type array.
11811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
11821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#define ADDASTER() \
11831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	n2 = 0; \
11841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	cp = fmt; \
11851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	while (is_digit(*cp)) { \
11860549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		APPEND_DIGIT(n2, *cp); \
11871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp++; \
11881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} \
11891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (*cp == '$') { \
11901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		int hold = nextarg; \
11911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		nextarg = n2; \
11921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ADDTYPE(T_INT); \
11931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		nextarg = hold; \
11941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fmt = ++cp; \
11951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else { \
11961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		ADDTYPE(T_INT); \
11971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
11981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	fmt = (char *)fmt0;
11991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	typetable = stattypetable;
12001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	tablesize = STATIC_ARG_TBL_SIZE;
12011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	tablemax = 0;
12021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	nextarg = 1;
12031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
12041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	memset(&ps, 0, sizeof(ps));
12051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
12071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Scan the format for conversions (`%' character).
12081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
12091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (;;) {
12101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		cp = fmt;
12111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		while ((n = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) > 0) {
12121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			fmt += n;
12131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (wc == '%') {
12141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				fmt--;
12151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				break;
12161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
12171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
12181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		if (n <= 0)
12191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto done;
12201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		fmt++;		/* skip over '%' */
12211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		flags = 0;
12231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
12241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectrflag:		ch = *fmt++;
12251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectreswitch:	switch (ch) {
12261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case ' ':
12271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '#':
12280549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case '\'':
12291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
12301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '*':
12311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ADDASTER();
12321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
12331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '-':
12341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '+':
12351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
12361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '.':
12371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if ((ch = *fmt++) == '*') {
12381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ADDASTER();
12391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto rflag;
12401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
12411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			while (is_digit(ch)) {
12421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ch = *fmt++;
12431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
12441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto reswitch;
12451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '0':
12461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
12471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '1': case '2': case '3': case '4':
12481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case '5': case '6': case '7': case '8': case '9':
12491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			n = 0;
12501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			do {
12510549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				APPEND_DIGIT(n ,ch);
12521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ch = *fmt++;
12531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} while (is_digit(ch));
12541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (ch == '$') {
12551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				nextarg = n;
12561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto rflag;
12571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
12581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto reswitch;
12591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef FLOATING_POINT
12601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'L':
12611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LONGDBL;
12621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
12631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
12641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'h':
12651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (*fmt == 'h') {
12661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				fmt++;
12671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				flags |= CHARINT;
12681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} else {
12691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				flags |= SHORTINT;
12701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
12711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
12720549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case 'j':
12730549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			flags |= MAXINT;
12740549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			goto rflag;
12751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'l':
12761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (*fmt == 'l') {
12771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				fmt++;
12781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				flags |= LLONGINT;
12791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			} else {
12801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				flags |= LONGINT;
12811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			}
12821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
12831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'q':
12841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LLONGINT;
12851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
12861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 't':
12871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= PTRINT;
12881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
12891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'z':
12901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= SIZEINT;
12911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			goto rflag;
12921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'c':
12930549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
12940549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (flags & LONGINT)
12950549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				ADDTYPE(T_WINT);
12960549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			else
12970549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif
12980549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				ADDTYPE(T_INT);
12991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
13001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'D':
13011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LONGINT;
13021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*FALLTHROUGH*/
13031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'd':
13041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'i':
13051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ADDSARG();
13061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
13071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef FLOATING_POINT
13080549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case 'a':
13090549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case 'A':
13101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'e':
13111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'E':
13121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'f':
13130549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case 'F':
13141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'g':
13151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'G':
13161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (flags & LONGDBL)
13171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ADDTYPE(T_LONG_DOUBLE);
13181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else
13191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ADDTYPE(T_DOUBLE);
13201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
13211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* FLOATING_POINT */
1322e2341d08fa4a4e0c22056c410fd34d3f93e06017Elliott Hughes#ifndef NO_PRINTF_PERCENT_N
13231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'n':
13241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (flags & LLONGINT)
13251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ADDTYPE(TP_LLONG);
13261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & LONGINT)
13271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ADDTYPE(TP_LONG);
13281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & SHORTINT)
13291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ADDTYPE(TP_SHORT);
13301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & PTRINT)
13311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ADDTYPE(TP_PTRINT);
13321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & SIZEINT)
13331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ADDTYPE(TP_SSIZEINT);
13341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else if (flags & MAXINT)
13351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ADDTYPE(TP_MAXINT);
13361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			else
13371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				ADDTYPE(TP_INT);
13381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			continue;	/* no output */
1339e2341d08fa4a4e0c22056c410fd34d3f93e06017Elliott Hughes#endif /* NO_PRINTF_PERCENT_N */
13401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'O':
13411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LONGINT;
13421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*FALLTHROUGH*/
13431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'o':
13441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ADDUARG();
13451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
13461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'p':
13471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ADDTYPE(TP_VOID);
13481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
13491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 's':
13500549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
13510549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			if (flags & LONGINT)
13520549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				ADDTYPE(TP_WCHAR);
13530549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			else
13540549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif
13550549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes				ADDTYPE(TP_CHAR);
13561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
13571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'U':
13581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			flags |= LONGINT;
13591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			/*FALLTHROUGH*/
13601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'u':
13611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'X':
13621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case 'x':
13631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			ADDUARG();
13641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
13651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		default:	/* "%?" prints ?, unless ? is NUL */
13661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			if (ch == '\0')
13671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project				goto done;
13681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
13691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
13701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
13711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectdone:
13721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/*
13731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 * Build the argument table.
13741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	 */
13751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (tablemax >= STATIC_ARG_TBL_SIZE) {
1376edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko		*argtablesiz = sizeof(union arg) * (tablemax + 1);
1377edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko		*argtable = mmap(NULL, *argtablesiz,
13781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    PROT_WRITE|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
1379edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko		if (*argtable == MAP_FAILED)
1380edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			return (-1);
13811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
13821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
13831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#if 0
13841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	/* XXX is this required? */
1385edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	(*argtable)[0].intarg = 0;
13861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif
13871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	for (n = 1; n <= tablemax; n++) {
13881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		switch (typetable[n]) {
13891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_UNUSED:
13900549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case T_CHAR:
13910549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case T_U_CHAR:
13921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_SHORT:
13931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_U_SHORT:
13940549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case T_INT:
1395edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].intarg = va_arg(ap, int);
13961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
13971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case TP_SHORT:
1398edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].pshortarg = va_arg(ap, short *);
13991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_U_INT:
1401edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].uintarg = va_arg(ap, unsigned int);
14021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case TP_INT:
1404edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].pintarg = va_arg(ap, int *);
14051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_LONG:
1407edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].longarg = va_arg(ap, long);
14081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_U_LONG:
1410edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].ulongarg = va_arg(ap, unsigned long);
14111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case TP_LONG:
1413edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].plongarg = va_arg(ap, long *);
14141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_LLONG:
1416edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].longlongarg = va_arg(ap, long long);
14171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_U_LLONG:
1419edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long);
14201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case TP_LLONG:
1422edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].plonglongarg = va_arg(ap, long long *);
14231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
1424edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko#ifdef FLOATING_POINT
14251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_DOUBLE:
1426edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].doublearg = va_arg(ap, double);
14271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_LONG_DOUBLE:
1429edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].longdoublearg = va_arg(ap, long double);
14301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
1431edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko#endif
14321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case TP_CHAR:
1433edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].pchararg = va_arg(ap, char *);
14341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case TP_VOID:
1436edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].pvoidarg = va_arg(ap, void *);
14371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_PTRINT:
1439edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t);
14401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case TP_PTRINT:
1442edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *);
14431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_SIZEINT:
1445edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].sizearg = va_arg(ap, size_t);
14461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case T_SSIZEINT:
1448edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].ssizearg = va_arg(ap, ssize_t);
14491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		case TP_SSIZEINT:
1451edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].pssizearg = va_arg(ap, ssize_t *);
14521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14530549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case T_MAXINT:
1454edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			(*argtable)[n].intmaxarg = va_arg(ap, intmax_t);
14551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			break;
14560549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case T_MAXUINT:
14570549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			(*argtable)[n].uintmaxarg = va_arg(ap, uintmax_t);
14580549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			break;
14590549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case TP_MAXINT:
14600549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			(*argtable)[n].pintmaxarg = va_arg(ap, intmax_t *);
14610549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			break;
14620549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#ifdef PRINTF_WIDE_CHAR
14630549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case T_WINT:
14640549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			(*argtable)[n].wintarg = va_arg(ap, wint_t);
14650549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			break;
14660549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		case TP_WCHAR:
14670549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			(*argtable)[n].pwchararg = va_arg(ap, wchar_t *);
14680549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			break;
14690549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes#endif
14701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		}
14711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
14720549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	goto finish;
14730549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
14740549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughesoverflow:
14750549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	errno = ENOMEM;
14760549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	ret = -1;
14771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14780549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughesfinish:
14791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (typetable != NULL && typetable != stattypetable) {
14801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		munmap(typetable, *argtablesiz);
14811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		typetable = NULL;
14821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
14830549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	return (ret);
14841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
14851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/*
14871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Increase the size of the type table.
14881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */
14891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
14901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project__grow_type_table(unsigned char **typetable, int *tablesize)
14911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
14921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	unsigned char *oldtable = *typetable;
14931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	int newsize = *tablesize * 2;
14941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
14950549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	if (newsize < getpagesize())
14960549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		newsize = getpagesize();
14970549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
14981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (*tablesize == STATIC_ARG_TBL_SIZE) {
1499edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko		*typetable = mmap(NULL, newsize, PROT_WRITE|PROT_READ,
15001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    MAP_ANON|MAP_PRIVATE, -1, 0);
1501edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko		if (*typetable == MAP_FAILED)
1502edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			return (-1);
15030549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		bcopy(oldtable, *typetable, *tablesize);
15041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	} else {
1505edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko		unsigned char *new = mmap(NULL, newsize, PROT_WRITE|PROT_READ,
15061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		    MAP_ANON|MAP_PRIVATE, -1, 0);
1507edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko		if (new == MAP_FAILED)
1508edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			return (-1);
15091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		memmove(new, *typetable, *tablesize);
15101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		munmap(*typetable, *tablesize);
15111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*typetable = new;
15121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
15131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));
15141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*tablesize = newsize;
1516edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	return (0);
15171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
15181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15190549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes
15201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#ifdef FLOATING_POINT
15211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int
15221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectexponent(char *p0, int exp, int fmtch)
15231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{
15241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	char *p, *t;
15250549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	char expbuf[MAXEXPDIG];
15261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
15271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	p = p0;
15281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	*p++ = fmtch;
15291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (exp < 0) {
15301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		exp = -exp;
15311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*p++ = '-';
1532edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	} else
15331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*p++ = '+';
15340549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes	t = expbuf + MAXEXPDIG;
15351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	if (exp > 9) {
15361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		do {
15371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project			*--t = to_char(exp % 10);
15381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		} while ((exp /= 10) > 9);
15391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*--t = to_char(exp);
15400549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		for (; t < expbuf + MAXEXPDIG; *p++ = *t++)
1541edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko			/* nothing */;
1542edd7c2ec256548702d275b3023f54bd91b4dcfc4Alexander Ivchenko	} else {
15430549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		/*
15440549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		 * Exponents for decimal floating point conversions
15450549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		 * (%[eEgG]) must be at least two characters long,
15460549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		 * whereas exponents for hexadecimal conversions can
15470549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		 * be only one character long.
15480549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		 */
15490549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes		if (fmtch == 'e' || fmtch == 'E')
15500549371bd74ba7c7a5a16c2a7d6cc17dbe0e6f97Elliott Hughes			*p++ = '0';
15511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project		*p++ = to_char(exp);
15521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	}
15531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project	return (p - p0);
15541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}
15551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#endif /* FLOATING_POINT */
1556