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