1be8df2e7445968d503a59a0a15c9612a8fb991dfElliott Hughes/* $OpenBSD: vfwprintf.c,v 1.11 2014/06/04 07:45:25 stsp Exp $ */ 294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/*- 394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Copyright (c) 1990 The Regents of the University of California. 494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * All rights reserved. 594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * This code is derived from software contributed to Berkeley by 794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Chris Torek. 894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Redistribution and use in source and binary forms, with or without 1094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * modification, are permitted provided that the following conditions 1194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * are met: 1294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 1. Redistributions of source code must retain the above copyright 1394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * notice, this list of conditions and the following disclaimer. 1494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 2. Redistributions in binary form must reproduce the above copyright 1594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * notice, this list of conditions and the following disclaimer in the 1694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * documentation and/or other materials provided with the distribution. 1794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 3. Neither the name of the University nor the names of its contributors 1894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * may be used to endorse or promote products derived from this software 1994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * without specific prior written permission. 2094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 2194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * SUCH DAMAGE. 3294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 3394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 3494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 3594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Actual wprintf innards. 3694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 3794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * This code is large and complicated... 3894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 3994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 4094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <sys/types.h> 4194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <sys/mman.h> 4294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 4394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <errno.h> 4494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <langinfo.h> 4594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <limits.h> 4694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <stdarg.h> 4794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <stddef.h> 4894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <stdio.h> 4994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <stdint.h> 5094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <stdlib.h> 5194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <string.h> 5294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <unistd.h> 5394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 5494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include "local.h" 5594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include "fvwrite.h" 5694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 5794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesunion arg { 5894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int intarg; 5994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes unsigned int uintarg; 6094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes long longarg; 6194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes unsigned long ulongarg; 6294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes long long longlongarg; 6394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes unsigned long long ulonglongarg; 6494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ptrdiff_t ptrdiffarg; 6594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size_t sizearg; 6694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ssize_t ssizearg; 6794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes intmax_t intmaxarg; 6894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes uintmax_t uintmaxarg; 6994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes void *pvoidarg; 7094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes char *pchararg; 7194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes signed char *pschararg; 7294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes short *pshortarg; 7394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int *pintarg; 7494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes long *plongarg; 7594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes long long *plonglongarg; 7694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ptrdiff_t *pptrdiffarg; 7794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ssize_t *pssizearg; 7894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes intmax_t *pintmaxarg; 7994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 8094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes double doublearg; 8194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes long double longdoublearg; 8294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif 8394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wint_t wintarg; 8494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t *pwchararg; 8594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes}; 8694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 8794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesstatic int __find_arguments(const wchar_t *fmt0, va_list ap, union arg **argtable, 8894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size_t *argtablesiz); 8994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesstatic int __grow_type_table(unsigned char **typetable, int *tablesize); 9094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 9194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 9294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Helper function for `fprintf to unbuffered unix file': creates a 9394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * temporary buffer. We only work on write-only files; this avoids 9494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * worries about ungetc buffers and so forth. 9594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 9694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesstatic int 9794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes__sbprintf(FILE *fp, const wchar_t *fmt, va_list ap) 9894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes{ 9994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int ret; 10094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes FILE fake; 10194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes struct __sfileext fakeext; 10294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes unsigned char buf[BUFSIZ]; 10394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 10494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes _FILEEXT_SETUP(&fake, &fakeext); 10594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* copy the important variables */ 10694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fake._flags = fp->_flags & ~__SNBF; 10794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fake._file = fp->_file; 10894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fake._cookie = fp->_cookie; 10994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fake._write = fp->_write; 11094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 11194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* set up the buffer */ 11294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fake._bf._base = fake._p = buf; 11394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fake._bf._size = fake._w = sizeof(buf); 11494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fake._lbfsize = 0; /* not actually used, but Just In Case */ 11594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 11694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* do the work, then copy any error status */ 11794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ret = __vfwprintf(&fake, fmt, ap); 11894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ret >= 0 && __sflush(&fake)) 11994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ret = EOF; 12094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (fake._flags & __SERR) 12194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fp->_flags |= __SERR; 12294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (ret); 12394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} 12494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 12594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 12694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Like __fputwc_unlock, but handles fake string (__SSTR) files properly. 12794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * File must already be locked. 12894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 12994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesstatic wint_t 13094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes__xfputwc(wchar_t wc, FILE *fp) 13194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes{ 13294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes mbstate_t mbs; 13394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes char buf[MB_LEN_MAX]; 13494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes struct __suio uio; 13594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes struct __siov iov; 13694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size_t len; 13794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 13894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((fp->_flags & __SSTR) == 0) 13994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (__fputwc_unlock(wc, fp)); 14094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 14194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes bzero(&mbs, sizeof(mbs)); 14294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes len = wcrtomb(buf, wc, &mbs); 14394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (len == (size_t)-1) { 14494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fp->_flags |= __SERR; 14594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes errno = EILSEQ; 14694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (WEOF); 14794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 14894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes uio.uio_iov = &iov; 14994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes uio.uio_resid = len; 15094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes uio.uio_iovcnt = 1; 15194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes iov.iov_base = buf; 15294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes iov.iov_len = len; 15394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF); 15494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} 15594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 15694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 15794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Convert a multibyte character string argument for the %s format to a wide 15894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * string representation. ``prec'' specifies the maximum number of bytes 15994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * to output. If ``prec'' is greater than or equal to zero, we can't assume 16094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * that the multibyte character string ends in a null character. 16194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 16294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Returns NULL on failure. 16394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * To find out what happened check errno for ENOMEM, EILSEQ and EINVAL. 16494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 16594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesstatic wchar_t * 16694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes__mbsconv(char *mbsarg, int prec) 16794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes{ 16894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes mbstate_t mbs; 16994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t *convbuf, *wcp; 17094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes const char *p; 17194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size_t insize, nchars, nconv; 17294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 17394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (mbsarg == NULL) 17494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (NULL); 17594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 17694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 17794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Supplied argument is a multibyte string; convert it to wide 17894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * characters first. 17994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 18094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec >= 0) { 18194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 18294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * String is not guaranteed to be NUL-terminated. Find the 18394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * number of characters to print. 18494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 18594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes p = mbsarg; 18694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes insize = nchars = nconv = 0; 18794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes bzero(&mbs, sizeof(mbs)); 18894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes while (nchars != (size_t)prec) { 18994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nconv = mbrlen(p, MB_CUR_MAX, &mbs); 19094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (nconv == (size_t)0 || nconv == (size_t)-1 || 19194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nconv == (size_t)-2) 19294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 19394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes p += nconv; 19494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nchars++; 19594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes insize += nconv; 19694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 19794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (nconv == (size_t)-1 || nconv == (size_t)-2) 19894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (NULL); 19994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else 20094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes insize = strlen(mbsarg); 20194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 20294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 20394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Allocate buffer for the result and perform the conversion, 20494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * converting at most `size' bytes of the input multibyte string to 20594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * wide characters for printing. 20694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 20794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes convbuf = calloc(insize + 1, sizeof(*convbuf)); 20894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (convbuf == NULL) 20994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (NULL); 21094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wcp = convbuf; 21194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes p = mbsarg; 21294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes bzero(&mbs, sizeof(mbs)); 21394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nconv = 0; 21494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes while (insize != 0) { 21594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nconv = mbrtowc(wcp, p, insize, &mbs); 21694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2) 21794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 21894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wcp++; 21994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes p += nconv; 22094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes insize -= nconv; 22194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 22294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (nconv == (size_t)-1 || nconv == (size_t)-2) { 22394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes free(convbuf); 22494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (NULL); 22594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 22694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *wcp = '\0'; 22794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 22894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (convbuf); 22994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} 23094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 23194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 23294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <float.h> 23394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <locale.h> 23494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include <math.h> 23594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#include "floatio.h" 236f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes#include "gdtoa.h" 23794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 23894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define DEFPREC 6 23994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 24094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesstatic int exponent(wchar_t *, int, int); 24194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif /* FLOATING_POINT */ 24294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 24394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 24494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * The size of the buffer we use as scratch space for integer 24594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * conversions, among other things. Technically, we would need the 24694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * most space for base 10 conversions with thousands' grouping 24794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * characters between each pair of digits. 100 bytes is a 24894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * conservative overestimate even for a 128-bit uintmax_t. 24994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 25094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define BUF 100 25194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 25294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ 25394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 25494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 25594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 25694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Macros for converting digits to letters and vice versa 25794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 25894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define to_digit(c) ((c) - '0') 25994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define is_digit(c) ((unsigned)to_digit(c) <= 9) 26094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define to_char(n) ((wchar_t)((n) + '0')) 26194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 26294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 26394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Flags used during conversion. 26494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 26594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define ALT 0x0001 /* alternate form */ 26694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define LADJUST 0x0004 /* left adjustment */ 26794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define LONGDBL 0x0008 /* long double */ 26894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define LONGINT 0x0010 /* long integer */ 26994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define LLONGINT 0x0020 /* long long integer */ 27094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define SHORTINT 0x0040 /* short integer */ 27194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define ZEROPAD 0x0080 /* zero (as opposed to blank) pad */ 27294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define FPT 0x0100 /* Floating point number */ 27394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define PTRINT 0x0200 /* (unsigned) ptrdiff_t */ 27494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define SIZEINT 0x0400 /* (signed) size_t */ 27594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define CHARINT 0x0800 /* 8 bit integer */ 27694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define MAXINT 0x1000 /* largest integer size (intmax_t) */ 27794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 27894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesint 27994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes__vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, __va_list ap) 28094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes{ 28194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t *fmt; /* format string */ 28294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t ch; /* character from fmt */ 28394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int n, n2, n3; /* handy integers (short term usage) */ 28494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t *cp; /* handy char pointer (short term usage) */ 28594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int flags; /* flags as above */ 28694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int ret; /* return value accumulator */ 28794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int width; /* width from format (%8d), or 0 */ 28894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int prec; /* precision from format; <0 for N/A */ 28994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */ 29094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 29194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 29294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * We can decompose the printed representation of floating 29394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * point numbers into several parts, some of which may be empty: 29494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 29594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ 29694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * A B ---C--- D E F 29794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 29894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * A: 'sign' holds this value if present; '\0' otherwise 29994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal 30094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * C: cp points to the string MMMNNN. Leading and trailing 30194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * zeros are not in the string and must be added. 30294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * D: expchar holds this character; '\0' if no exponent, e.g. %f 30394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * F: at least two digits for decimal, at least one digit for hex 30494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 30594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes char *decimal_point = NULL; 30694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int signflag; /* true if float is negative */ 30794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes union { /* floating point arguments %[aAeEfFgG] */ 30894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes double dbl; 30994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes long double ldbl; 31094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } fparg; 31194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int expt; /* integer value of exponent */ 31294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes char expchar; /* exponent character: [eEpP\0] */ 31394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes char *dtoaend; /* pointer to end of converted digits */ 31494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int expsize; /* character count for expstr */ 31594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int lead; /* sig figs before decimal or group sep */ 31694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int ndig; /* actual number of digits returned by dtoa */ 31794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ 31894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes char *dtoaresult = NULL; 31994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif 32094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 32194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes uintmax_t _umax; /* integer arguments %[diouxX] */ 32294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes enum { OCT, DEC, HEX } base; /* base for %[diouxX] conversion */ 32394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int dprec; /* a copy of prec if %[diouxX], 0 otherwise */ 32494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int realsz; /* field size expanded by dprec */ 32594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int size; /* size of converted field or string */ 32694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes const char *xdigs; /* digits for %[xX] conversion */ 32794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */ 32894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */ 32994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes union arg *argtable; /* args, built due to positional arg */ 33094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes union arg statargtable[STATIC_ARG_TBL_SIZE]; 33194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size_t argtablesiz; 33294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int nextarg; /* 1-based argument index */ 33394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes va_list orgap; /* original argument pointer */ 33494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t *convbuf; /* buffer for multibyte to wide conversion */ 33594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 33694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 33794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Choose PADSIZE to trade efficiency vs. size. If larger printf 33894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * fields occur frequently, increase PADSIZE and make the initialisers 33994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * below longer. 34094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 34194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define PADSIZE 16 /* pad chunk size */ 34294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes static wchar_t blanks[PADSIZE] = 34394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 34494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes static wchar_t zeroes[PADSIZE] = 34594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 34694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 34794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes static const char xdigs_lower[16] = "0123456789abcdef"; 34894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes static const char xdigs_upper[16] = "0123456789ABCDEF"; 34994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 35094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 35194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * BEWARE, these `goto error' on error, PRINT uses 'n3', 35294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * PAD uses `n' and 'n3', and PRINTANDPAD uses 'n', 'n2', and 'n3'. 35394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 35494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define PRINT(ptr, len) do { \ 35594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes for (n3 = 0; n3 < (len); n3++) { \ 35694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((__xfputwc((ptr)[n3], fp)) == WEOF) \ 35794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto error; \ 35894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } \ 35994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} while (0) 36094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define PAD(howmany, with) do { \ 36194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((n = (howmany)) > 0) { \ 36294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes while (n > PADSIZE) { \ 36394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(with, PADSIZE); \ 36494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes n -= PADSIZE; \ 36594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } \ 36694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(with, n); \ 36794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } \ 36894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} while (0) 36994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define PRINTANDPAD(p, ep, len, with) do { \ 37094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes n2 = (ep) - (p); \ 37194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (n2 > (len)) \ 37294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes n2 = (len); \ 37394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (n2 > 0) \ 37494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT((p), n2); \ 37594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PAD((len) - (n2 > 0 ? n2 : 0), (with)); \ 37694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} while(0) 37794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 37894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 37994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * To extend shorts properly, we need both signed and unsigned 38094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * argument extraction methods. 38194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 38294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define SARG() \ 38394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \ 38494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&LLONGINT ? GETARG(long long) : \ 38594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&LONGINT ? GETARG(long) : \ 38694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&PTRINT ? GETARG(ptrdiff_t) : \ 38794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&SIZEINT ? GETARG(ssize_t) : \ 38894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&SHORTINT ? (short)GETARG(int) : \ 389f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes flags&CHARINT ? (signed char)GETARG(int) : \ 39094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes GETARG(int))) 39194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define UARG() \ 39294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \ 39394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&LLONGINT ? GETARG(unsigned long long) : \ 39494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&LONGINT ? GETARG(unsigned long) : \ 39594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \ 39694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&SIZEINT ? GETARG(size_t) : \ 39794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&SHORTINT ? (unsigned short)GETARG(int) : \ 39894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags&CHARINT ? (unsigned char)GETARG(int) : \ 39994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes GETARG(unsigned int))) 40094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 40194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 40294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Append a digit to a value and check for overflow. 40394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 40494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define APPEND_DIGIT(val, dig) do { \ 40594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((val) > INT_MAX / 10) \ 40694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto overflow; \ 40794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (val) *= 10; \ 40894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((val) > INT_MAX - to_digit((dig))) \ 40994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto overflow; \ 41094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (val) += to_digit((dig)); \ 41194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} while (0) 41294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 41394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 41494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Get * arguments, including the form *nn$. Preserve the nextarg 41594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * that the argument can be gotten once the type is determined. 41694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 41794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define GETASTER(val) \ 41894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes n2 = 0; \ 41994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = fmt; \ 42094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes while (is_digit(*cp)) { \ 42194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes APPEND_DIGIT(n2, *cp); \ 42294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp++; \ 42394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } \ 42494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (*cp == '$') { \ 42594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int hold = nextarg; \ 42694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (argtable == NULL) { \ 42794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes argtable = statargtable; \ 42894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __find_arguments(fmt0, orgap, &argtable, &argtablesiz); \ 42994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } \ 43094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nextarg = n2; \ 43194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes val = GETARG(int); \ 43294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nextarg = hold; \ 43394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fmt = ++cp; \ 43494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { \ 43594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes val = GETARG(int); \ 43694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 43794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 43894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 43994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes* Get the argument indexed by nextarg. If the argument table is 44094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes* built, use it to get the argument. If its not, get the next 44194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes* argument (and arguments must be gotten sequentially). 44294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes*/ 44394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define GETARG(type) \ 44494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ 44594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (nextarg++, va_arg(ap, type))) 44694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 44794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes _SET_ORIENTATION(fp, 1); 44894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */ 44994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (cantwrite(fp)) { 45094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes errno = EBADF; 45194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (EOF); 45294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 45394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 45494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* optimise fwprintf(stderr) (and other unbuffered Unix files) */ 45594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && 45694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fp->_file >= 0) 45794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (__sbprintf(fp, fmt0, ap)); 45894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 45994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fmt = (wchar_t *)fmt0; 46094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes argtable = NULL; 46194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nextarg = 1; 46294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes va_copy(orgap, ap); 46394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ret = 0; 46494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes convbuf = NULL; 46594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 46694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 46794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Scan the format for conversions (`%' character). 46894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 46994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes for (;;) { 47094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 47194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes continue; 47294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (fmt != cp) { 47394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ptrdiff_t m = fmt - cp; 47494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (m < 0 || m > INT_MAX - ret) 47594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto overflow; 47694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(cp, m); 47794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ret += m; 47894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 47994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ch == '\0') 48094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto done; 48194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fmt++; /* skip over '%' */ 48294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 48394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags = 0; 48494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes dprec = 0; 48594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes width = 0; 48694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec = -1; 48794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes sign = '\0'; 48894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ox[1] = '\0'; 48994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 49094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesrflag: ch = *fmt++; 49194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesreswitch: switch (ch) { 49294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case ' ': 49394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 49494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * ``If the space and + flags both appear, the space 49594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * flag will be ignored.'' 49694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * -- ANSI X3J11 49794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 49894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (!sign) 49994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes sign = ' '; 50094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 50194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '#': 50294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= ALT; 50394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 50494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '\'': 50594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* grouping not implemented */ 50694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 50794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '*': 50894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 50994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * ``A negative field width argument is taken as a 51094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * - flag followed by a positive field width.'' 51194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * -- ANSI X3J11 51294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * They don't exclude field widths read from args. 51394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 51494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes GETASTER(width); 51594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (width >= 0) 51694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 51794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (width == INT_MIN) 51894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto overflow; 51994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes width = -width; 52094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* FALLTHROUGH */ 52194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '-': 52294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LADJUST; 52394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 52494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '+': 52594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes sign = '+'; 52694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 52794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '.': 52894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((ch = *fmt++) == '*') { 52994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes GETASTER(n); 53094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec = n < 0 ? -1 : n; 53194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 53294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 53394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes n = 0; 53494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes while (is_digit(ch)) { 53594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes APPEND_DIGIT(n, ch); 53694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ch = *fmt++; 53794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 53894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ch == '$') { 53994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nextarg = n; 54094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (argtable == NULL) { 54194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes argtable = statargtable; 54294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __find_arguments(fmt0, orgap, 54394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes &argtable, &argtablesiz); 54494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 54594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 54694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 54794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec = n; 54894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto reswitch; 54994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '0': 55094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 55194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * ``Note that 0 is taken as a flag, not as the 55294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * beginning of a field width.'' 55394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * -- ANSI X3J11 55494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 55594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= ZEROPAD; 55694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 55794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '1': case '2': case '3': case '4': 55894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '5': case '6': case '7': case '8': case '9': 55994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes n = 0; 56094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes do { 56194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes APPEND_DIGIT(n, ch); 56294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ch = *fmt++; 56394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } while (is_digit(ch)); 56494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ch == '$') { 56594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nextarg = n; 56694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (argtable == NULL) { 56794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes argtable = statargtable; 56894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __find_arguments(fmt0, orgap, 56994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes &argtable, &argtablesiz); 57094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 57194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 57294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 57394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes width = n; 57494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto reswitch; 57594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 57694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'L': 57794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGDBL; 57894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 57994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif 58094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'h': 58194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (*fmt == 'h') { 58294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fmt++; 58394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= CHARINT; 58494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 58594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= SHORTINT; 58694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 58794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 58894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'j': 58994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= MAXINT; 59094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 59194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'l': 59294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (*fmt == 'l') { 59394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fmt++; 59494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LLONGINT; 59594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 59694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 59794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 59894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 59994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'q': 60094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LLONGINT; 60194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 60294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 't': 60394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= PTRINT; 60494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 60594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'z': 60694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= SIZEINT; 60794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 60894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'C': 60994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 61094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /*FALLTHROUGH*/ 61194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'c': 61294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & LONGINT) 61394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *(cp = buf) = (wchar_t)GETARG(wint_t); 61494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else 61594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *(cp = buf) = (wchar_t)btowc(GETARG(int)); 61694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size = 1; 61794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes sign = '\0'; 61894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 61994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'D': 62094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 62194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /*FALLTHROUGH*/ 62294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'd': 62394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'i': 62494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes _umax = SARG(); 62594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((intmax_t)_umax < 0) { 62694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes _umax = -_umax; 62794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes sign = '-'; 62894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 62994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes base = DEC; 63094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto number; 63194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 63294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'a': 63394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'A': 63494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ch == 'a') { 63594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ox[1] = 'x'; 63694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes xdigs = xdigs_lower; 63794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes expchar = 'p'; 63894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 63994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ox[1] = 'X'; 64094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes xdigs = xdigs_upper; 64194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes expchar = 'P'; 64294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 64394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec >= 0) 64494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec++; 64594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (dtoaresult) 64694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __freedtoa(dtoaresult); 64794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & LONGDBL) { 64894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fparg.ldbl = GETARG(long double); 64994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes dtoaresult = 65094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __hldtoa(fparg.ldbl, xdigs, prec, 65194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes &expt, &signflag, &dtoaend); 65294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (dtoaresult == NULL) { 65394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes errno = ENOMEM; 65494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto error; 65594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 65694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 65794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fparg.dbl = GETARG(double); 65894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes dtoaresult = 65994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __hdtoa(fparg.dbl, xdigs, prec, 66094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes &expt, &signflag, &dtoaend); 66194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (dtoaresult == NULL) { 66294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes errno = ENOMEM; 66394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto error; 66494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 66594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 66694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec < 0) 66794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec = dtoaend - dtoaresult; 66894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (expt == INT_MAX) 66994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ox[1] = '\0'; 67094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (convbuf) { 67194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes free(convbuf); 67294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes convbuf = NULL; 67394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 67494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = convbuf = __mbsconv(dtoaresult, -1); 67594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (cp == NULL) 67694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto error; 67794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ndig = dtoaend - dtoaresult; 67894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto fp_common; 67994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'e': 68094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'E': 68194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes expchar = ch; 68294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec < 0) /* account for digit before decpt */ 68394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec = DEFPREC + 1; 68494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else 68594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec++; 68694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto fp_begin; 68794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'f': 68894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'F': 68994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes expchar = '\0'; 69094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto fp_begin; 69194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'g': 69294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'G': 69394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes expchar = ch - ('g' - 'e'); 69494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec == 0) 69594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec = 1; 69694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesfp_begin: 69794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec < 0) 69894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec = DEFPREC; 69994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (dtoaresult) 70094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __freedtoa(dtoaresult); 70194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & LONGDBL) { 70294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fparg.ldbl = GETARG(long double); 70394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes dtoaresult = 70494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, 70594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes &expt, &signflag, &dtoaend); 70694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (dtoaresult == NULL) { 70794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes errno = ENOMEM; 70894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto error; 70994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 71094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 71194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fparg.dbl = GETARG(double); 71294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes dtoaresult = 71394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __dtoa(fparg.dbl, expchar ? 2 : 3, prec, 71494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes &expt, &signflag, &dtoaend); 71594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (dtoaresult == NULL) { 71694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes errno = ENOMEM; 71794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto error; 71894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 71994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (expt == 9999) 72094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes expt = INT_MAX; 72194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 72294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (convbuf) { 72394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes free(convbuf); 72494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes convbuf = NULL; 72594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 72694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = convbuf = __mbsconv(dtoaresult, -1); 72794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (cp == NULL) 72894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto error; 72994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ndig = dtoaend - dtoaresult; 73094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesfp_common: 73194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (signflag) 73294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes sign = '-'; 73394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (expt == INT_MAX) { /* inf or nan */ 73494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (*cp == 'N') { 73594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = (ch >= 'a') ? L"nan" : L"NAN"; 73694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes sign = '\0'; 73794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else 73894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = (ch >= 'a') ? L"inf" : L"INF"; 73994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size = 3; 74094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags &= ~ZEROPAD; 74194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 74294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 74394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= FPT; 74494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ch == 'g' || ch == 'G') { 74594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (expt > -4 && expt <= prec) { 74694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* Make %[gG] smell like %[fF] */ 74794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes expchar = '\0'; 74894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & ALT) 74994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec -= expt; 75094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else 75194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec = ndig - expt; 75294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec < 0) 75394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec = 0; 75494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 75594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 75694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Make %[gG] smell like %[eE], but 75794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * trim trailing zeroes if no # flag. 75894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 75994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (!(flags & ALT)) 76094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec = ndig; 76194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 76294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 76394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (expchar) { 76494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes expsize = exponent(expstr, expt - 1, expchar); 76594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size = expsize + prec; 76694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec > 1 || flags & ALT) 76794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ++size; 76894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 76994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* space for digits before decimal point */ 77094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (expt > 0) 77194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size = expt; 77294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else /* "0" */ 77394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size = 1; 77494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* space for decimal pt and following digits */ 77594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec || flags & ALT) 77694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size += prec + 1; 77794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes lead = expt; 77894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 77994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 78094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif /* FLOATING_POINT */ 781e2341d08fa4a4e0c22056c410fd34d3f93e06017Elliott Hughes#ifndef NO_PRINTF_PERCENT_N 78294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'n': 78394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & LLONGINT) 78494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *GETARG(long long *) = ret; 78594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & LONGINT) 78694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *GETARG(long *) = ret; 78794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & SHORTINT) 78894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *GETARG(short *) = ret; 78994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & CHARINT) 790f1ada79a83f6ac42f5efd995bf04374005ac532bElliott Hughes *GETARG(signed char *) = ret; 79194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & PTRINT) 79294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *GETARG(ptrdiff_t *) = ret; 79394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & SIZEINT) 79494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *GETARG(ssize_t *) = ret; 79594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & MAXINT) 79694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *GETARG(intmax_t *) = ret; 79794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else 79894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *GETARG(int *) = ret; 79994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes continue; /* no output */ 800e2341d08fa4a4e0c22056c410fd34d3f93e06017Elliott Hughes#endif /* NO_PRINTF_PERCENT_N */ 80194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'O': 80294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 80394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /*FALLTHROUGH*/ 80494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'o': 80594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes _umax = UARG(); 80694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes base = OCT; 80794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto nosign; 80894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'p': 80994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 81094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * ``The argument shall be a pointer to void. The 81194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * value of the pointer is converted to a sequence 81294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * of printable characters, in an implementation- 81394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * defined manner.'' 81494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * -- ANSI X3J11 81594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 81694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* NOSTRICT */ 81794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes _umax = (u_long)GETARG(void *); 81894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes base = HEX; 81994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes xdigs = xdigs_lower; 82094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ox[1] = 'x'; 82194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto nosign; 82294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'S': 82394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 82494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /*FALLTHROUGH*/ 82594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 's': 82694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & LONGINT) { 82794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((cp = GETARG(wchar_t *)) == NULL) 82894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = L"(null)"; 82994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 83094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes char *mbsarg; 83194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((mbsarg = GETARG(char *)) == NULL) 83294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes mbsarg = "(null)"; 83394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (convbuf) { 83494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes free(convbuf); 83594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes convbuf = NULL; 83694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 83794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes convbuf = __mbsconv(mbsarg, prec); 83894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (convbuf == NULL) { 83994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fp->_flags |= __SERR; 84094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto error; 84194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else 84294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = convbuf; 84394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 84494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec >= 0) { 84594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 84694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * can't use wcslen; can only look for the 84794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * NUL in the first `prec' characters, and 84894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * wcslen() will go further. 84994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 85094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t *p = wmemchr(cp, 0, prec); 85194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 85294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size = p ? (p - cp) : prec; 85394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 85494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size_t len; 85594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 85694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((len = wcslen(cp)) > INT_MAX) 85794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto overflow; 85894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size = (int)len; 85994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 86094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes sign = '\0'; 86194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 86294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'U': 86394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 86494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /*FALLTHROUGH*/ 86594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'u': 86694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes _umax = UARG(); 86794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes base = DEC; 86894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto nosign; 86994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'X': 87094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes xdigs = xdigs_upper; 87194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto hex; 87294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'x': 87394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes xdigs = xdigs_lower; 87494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hugheshex: _umax = UARG(); 87594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes base = HEX; 87694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* leading 0x/X only if non-zero */ 87794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & ALT && _umax != 0) 87894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ox[1] = ch; 87994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 88094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* unsigned conversions */ 88194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesnosign: sign = '\0'; 88294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 88394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * ``... diouXx conversions ... if a precision is 88494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * specified, the 0 flag will be ignored.'' 88594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * -- ANSI X3J11 88694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 88794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesnumber: if ((dprec = prec) >= 0) 88894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags &= ~ZEROPAD; 88994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 89094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 89194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * ``The result of converting a zero value with an 89294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * explicit precision of zero is no characters.'' 89394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * -- ANSI X3J11 89494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 89594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = buf + BUF; 89694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (_umax != 0 || prec != 0) { 89794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 89894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Unsigned mod is hard, and unsigned mod 89994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * by a constant is easier than that by 90094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * a variable; hence this switch. 90194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 90294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes switch (base) { 90394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case OCT: 90494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes do { 90594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *--cp = to_char(_umax & 7); 90694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes _umax >>= 3; 90794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } while (_umax); 90894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* handle octal leading 0 */ 90994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & ALT && *cp != '0') 91094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *--cp = '0'; 91194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 91294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 91394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case DEC: 91494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* many numbers are 1 digit */ 91594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes while (_umax >= 10) { 91694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *--cp = to_char(_umax % 10); 91794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes _umax /= 10; 91894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 91994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *--cp = to_char(_umax); 92094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 92194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 92294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case HEX: 92394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes do { 92494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *--cp = xdigs[_umax & 15]; 92594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes _umax >>= 4; 92694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } while (_umax); 92794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 92894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 92994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes default: 93094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = L"bug in vfwprintf: bad base"; 93194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size = wcslen(cp); 93294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto skipsize; 93394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 93494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 93594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size = buf + BUF - cp; 93694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (size > BUF) /* should never happen */ 93794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes abort(); 93894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes skipsize: 93994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 94094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes default: /* "%?" prints ?, unless ? is NUL */ 94194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ch == '\0') 94294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto done; 94394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* pretend it was %c with argument ch */ 94494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = buf; 94594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *cp = ch; 94694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size = 1; 94794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes sign = '\0'; 94894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 94994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 95094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 95194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 95294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * All reasonable formats wind up here. At this point, `cp' 95394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * points to a string which (if not flags&LADJUST) should be 95494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * padded out to `width' places. If flags&ZEROPAD, it should 95594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * first be prefixed by any sign or other prefix; otherwise, 95694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * it should be blank padded before the prefix is emitted. 95794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * After any left-hand padding and prefixing, emit zeroes 95894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * required by a decimal %[diouxX] precision, then print the 95994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * string proper, then emit zeroes required by any leftover 96094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * floating precision; finally, if LADJUST, pad with blanks. 96194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * 96294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Compute actual size, so we know how much to pad. 96394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * size excludes decimal prec; realsz includes it. 96494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 96594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes realsz = dprec > size ? dprec : size; 96694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (sign) 96794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes realsz++; 96894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ox[1]) 96994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes realsz+= 2; 97094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 97194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* right-adjusting blank padding */ 97294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((flags & (LADJUST|ZEROPAD)) == 0) 97394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PAD(width - realsz, blanks); 97494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 97594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* prefix */ 97694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (sign) 97794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(&sign, 1); 97894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ox[1]) { /* ox[1] is either x, X, or \0 */ 97994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ox[0] = '0'; 98094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(ox, 2); 98194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 98294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 98394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* right-adjusting zero padding */ 98494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 98594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PAD(width - realsz, zeroes); 98694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 98794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* leading zeroes from decimal precision */ 98894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PAD(dprec - size, zeroes); 98994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 99094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* the string or number proper */ 99194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 99294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((flags & FPT) == 0) { 99394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(cp, size); 99494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { /* glue together f_p fragments */ 99594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (decimal_point == NULL) 99694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes decimal_point = nl_langinfo(RADIXCHAR); 99794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 99894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (expt <= 0) { 99994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(zeroes, 1); 100094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec || flags & ALT) 100194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(decimal_point, 1); 100294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PAD(-expt, zeroes); 100394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* already handled initial 0's */ 100494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes prec += expt; 100594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 100694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINTANDPAD(cp, convbuf + ndig, 100794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes lead, zeroes); 100894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp += lead; 100994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec || flags & ALT) 101094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(decimal_point, 1); 101194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 101294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINTANDPAD(cp, convbuf + ndig, prec, zeroes); 101394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { /* %[eE] or sufficiently long %[gG] */ 101494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (prec > 1 || flags & ALT) { 101594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes buf[0] = *cp++; 101694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes buf[1] = *decimal_point; 101794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(buf, 2); 101894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(cp, ndig-1); 101994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PAD(prec - ndig, zeroes); 102094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { /* XeYYY */ 102194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(cp, 1); 102294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 102394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(expstr, expsize); 102494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 102594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 102694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#else 102794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PRINT(cp, size); 102894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif 102994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* left-adjusting padding (always blank) */ 103094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & LADJUST) 103194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PAD(width - realsz, blanks); 103294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 103394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* finally, adjust ret */ 103494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (width < realsz) 103594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes width = realsz; 103694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (width > INT_MAX - ret) 103794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto overflow; 103894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ret += width; 103994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 104094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesdone: 104194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hugheserror: 104294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes va_end(orgap); 104394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (__sferror(fp)) 104494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ret = -1; 104594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto finish; 104694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 104794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesoverflow: 104894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes errno = ENOMEM; 104994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ret = -1; 105094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 105194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesfinish: 105294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (convbuf) 105394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes free(convbuf); 105494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 105594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (dtoaresult) 105694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __freedtoa(dtoaresult); 105794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif 105894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (argtable != NULL && argtable != statargtable) { 105994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes munmap(argtable, argtablesiz); 106094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes argtable = NULL; 106194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 106294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (ret); 106394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} 106494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 106594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesint 106694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesvfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, __va_list ap) 106794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes{ 106894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int r; 106994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 107094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes FLOCKFILE(fp); 107194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes r = __vfwprintf(fp, fmt0, ap); 107294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes FUNLOCKFILE(fp); 107394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 107494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (r); 107594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} 107694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 107794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 107894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Type ids for argument type table. 107994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 108094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_UNUSED 0 108194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_SHORT 1 108294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_U_SHORT 2 108394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define TP_SHORT 3 108494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_INT 4 108594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_U_INT 5 108694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define TP_INT 6 108794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_LONG 7 108894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_U_LONG 8 108994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define TP_LONG 9 109094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_LLONG 10 109194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_U_LLONG 11 109294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define TP_LLONG 12 109394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_DOUBLE 13 109494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_LONG_DOUBLE 14 109594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define TP_CHAR 15 109694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define TP_VOID 16 109794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_PTRINT 17 109894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define TP_PTRINT 18 109994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_SIZEINT 19 110094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_SSIZEINT 20 110194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define TP_SSIZEINT 21 110294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_MAXINT 22 110394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_MAXUINT 23 110494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define TP_MAXINT 24 110594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_CHAR 25 110694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_U_CHAR 26 110794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define T_WINT 27 110894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define TP_WCHAR 28 110994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 111094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 111194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Find all arguments when a positional parameter is encountered. Returns a 111294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * table, indexed by argument number, of pointers to each arguments. The 111394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. 111494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * It will be replaced with a mmap-ed one if it overflows (malloc cannot be 111594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * used since we are attempting to make snprintf thread safe, and alloca is 111694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * problematic since we have nested functions..) 111794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 111894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesstatic int 111994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes__find_arguments(const wchar_t *fmt0, va_list ap, union arg **argtable, 112094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes size_t *argtablesiz) 112194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes{ 112294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t *fmt; /* format string */ 112394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int ch; /* character from fmt */ 112494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int n, n2; /* handy integer (short term usage) */ 112594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t *cp; /* handy char pointer (short term usage) */ 112694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int flags; /* flags as above */ 112794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes unsigned char *typetable; /* table of types */ 112894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes unsigned char stattypetable[STATIC_ARG_TBL_SIZE]; 112994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int tablesize; /* current size of type table */ 113094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int tablemax; /* largest used index in table */ 113194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int nextarg; /* 1-based argument index */ 113294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int ret = 0; /* return value */ 113394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 113494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 113594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Add an argument type to the table, expanding if necessary. 113694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 113794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define ADDTYPE(type) \ 113894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((nextarg >= tablesize) ? \ 113994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes __grow_type_table(&typetable, &tablesize) : 0, \ 114094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (nextarg > tablemax) ? tablemax = nextarg : 0, \ 114194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes typetable[nextarg++] = type) 114294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 114394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define ADDSARG() \ 114494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \ 114594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \ 114694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \ 114794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \ 114894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&LONGINT) ? ADDTYPE(T_LONG) : \ 114994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \ 115094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT)))))))) 115194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 115294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define ADDUARG() \ 115394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \ 115494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \ 115594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \ 115694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \ 115794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \ 115894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \ 115994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT)))))))) 116094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 116194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 116294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Add * arguments to the type array. 116394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 116494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#define ADDASTER() \ 116594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes n2 = 0; \ 116694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp = fmt; \ 116794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes while (is_digit(*cp)) { \ 116894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes APPEND_DIGIT(n2, *cp); \ 116994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes cp++; \ 117094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } \ 117194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (*cp == '$') { \ 117294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int hold = nextarg; \ 117394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nextarg = n2; \ 117494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(T_INT); \ 117594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nextarg = hold; \ 117694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fmt = ++cp; \ 117794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { \ 117894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(T_INT); \ 117994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 118094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fmt = (wchar_t *)fmt0; 118194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes typetable = stattypetable; 118294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes tablesize = STATIC_ARG_TBL_SIZE; 118394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes tablemax = 0; 118494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nextarg = 1; 118594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE); 118694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 118794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 118894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Scan the format for conversions (`%' character). 118994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 119094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes for (;;) { 119194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 119294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes continue; 119394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ch == '\0') 119494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto done; 119594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fmt++; /* skip over '%' */ 119694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 119794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags = 0; 119894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 119994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesrflag: ch = *fmt++; 120094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesreswitch: switch (ch) { 120194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case ' ': 120294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '#': 120394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '\'': 120494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 120594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '*': 120694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDASTER(); 120794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 120894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '-': 120994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '+': 121094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 121194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '.': 121294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if ((ch = *fmt++) == '*') { 121394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDASTER(); 121494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 121594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 121694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes while (is_digit(ch)) { 121794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ch = *fmt++; 121894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 121994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto reswitch; 122094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '0': 122194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 122294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '1': case '2': case '3': case '4': 122394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case '5': case '6': case '7': case '8': case '9': 122494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes n = 0; 122594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes do { 122694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes APPEND_DIGIT(n ,ch); 122794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ch = *fmt++; 122894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } while (is_digit(ch)); 122994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ch == '$') { 123094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes nextarg = n; 123194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 123294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 123394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto reswitch; 123494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 123594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'L': 123694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGDBL; 123794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 123894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif 123994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'h': 124094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (*fmt == 'h') { 124194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fmt++; 124294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= CHARINT; 124394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 124494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= SHORTINT; 124594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 124694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 124794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'l': 124894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (*fmt == 'l') { 124994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes fmt++; 125094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LLONGINT; 125194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 125294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 125394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 125494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 125594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'q': 125694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LLONGINT; 125794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 125894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 't': 125994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= PTRINT; 126094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 126194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'z': 126294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= SIZEINT; 126394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto rflag; 126494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'C': 126594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 126694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /*FALLTHROUGH*/ 126794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'c': 126894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & LONGINT) 126994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(T_WINT); 127094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else 127194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(T_INT); 127294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 127394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'D': 127494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 127594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /*FALLTHROUGH*/ 127694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'd': 127794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'i': 127894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDSARG(); 127994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 128094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 128194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'a': 128294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'A': 128394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'e': 128494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'E': 128594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'f': 128694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'F': 128794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'g': 128894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'G': 128994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & LONGDBL) 129094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(T_LONG_DOUBLE); 129194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else 129294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(T_DOUBLE); 129394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 129494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif /* FLOATING_POINT */ 1295e2341d08fa4a4e0c22056c410fd34d3f93e06017Elliott Hughes#ifndef NO_PRINTF_PERCENT_N 129694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'n': 129794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & LLONGINT) 129894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(TP_LLONG); 129994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & LONGINT) 130094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(TP_LONG); 130194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & SHORTINT) 130294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(TP_SHORT); 130394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & PTRINT) 130494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(TP_PTRINT); 130594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & SIZEINT) 130694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(TP_SSIZEINT); 130794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else if (flags & MAXINT) 130894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(TP_MAXINT); 130994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else 131094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(TP_INT); 131194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes continue; /* no output */ 1312e2341d08fa4a4e0c22056c410fd34d3f93e06017Elliott Hughes#endif /* NO_PRINTF_PERCENT_N */ 131394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'O': 131494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 131594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /*FALLTHROUGH*/ 131694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'o': 131794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDUARG(); 131894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 131994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'p': 132094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(TP_VOID); 132194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 132294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'S': 132394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 132494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /*FALLTHROUGH*/ 132594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 's': 132694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (flags & LONGINT) 132794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(TP_CHAR); 132894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes else 132994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDTYPE(TP_WCHAR); 133094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 133194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'U': 133294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes flags |= LONGINT; 133394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /*FALLTHROUGH*/ 133494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'u': 133594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'X': 133694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case 'x': 133794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ADDUARG(); 133894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 133994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes default: /* "%?" prints ?, unless ? is NUL */ 134094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (ch == '\0') 134194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto done; 134294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 134394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 134494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 134594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesdone: 134694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 134794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Build the argument table. 134894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 134994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (tablemax >= STATIC_ARG_TBL_SIZE) { 135094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *argtablesiz = sizeof(union arg) * (tablemax + 1); 135194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *argtable = mmap(NULL, *argtablesiz, 135294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes PROT_WRITE|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0); 135394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (*argtable == MAP_FAILED) 135494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (-1); 135594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 135694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 135794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#if 0 135894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* XXX is this required? */ 135994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[0].intarg = 0; 136094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif 136194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes for (n = 1; n <= tablemax; n++) { 136294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes switch (typetable[n]) { 136394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_UNUSED: 136494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_CHAR: 136594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_U_CHAR: 136694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_SHORT: 136794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_U_SHORT: 136894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_INT: 136994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].intarg = va_arg(ap, int); 137094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 137194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case TP_SHORT: 137294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].pshortarg = va_arg(ap, short *); 137394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 137494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_U_INT: 137594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].uintarg = va_arg(ap, unsigned int); 137694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 137794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case TP_INT: 137894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].pintarg = va_arg(ap, int *); 137994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 138094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_LONG: 138194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].longarg = va_arg(ap, long); 138294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 138394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_U_LONG: 138494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].ulongarg = va_arg(ap, unsigned long); 138594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 138694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case TP_LONG: 138794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].plongarg = va_arg(ap, long *); 138894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 138994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_LLONG: 139094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].longlongarg = va_arg(ap, long long); 139194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 139294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_U_LLONG: 139394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long); 139494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 139594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case TP_LLONG: 139694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].plonglongarg = va_arg(ap, long long *); 139794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 139894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 139994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_DOUBLE: 140094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].doublearg = va_arg(ap, double); 140194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 140294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_LONG_DOUBLE: 140394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].longdoublearg = va_arg(ap, long double); 140494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 140594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif 140694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case TP_CHAR: 140794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].pchararg = va_arg(ap, char *); 140894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 140994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case TP_VOID: 141094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].pvoidarg = va_arg(ap, void *); 141194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 141294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_PTRINT: 141394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t); 141494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 141594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case TP_PTRINT: 141694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *); 141794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 141894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_SIZEINT: 141994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].sizearg = va_arg(ap, size_t); 142094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 142194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_SSIZEINT: 142294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].ssizearg = va_arg(ap, ssize_t); 142394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 142494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case TP_SSIZEINT: 142594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].pssizearg = va_arg(ap, ssize_t *); 142694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 142794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case TP_MAXINT: 142894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].intmaxarg = va_arg(ap, intmax_t); 142994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 143094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case T_WINT: 143194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].wintarg = va_arg(ap, wint_t); 143294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 143394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes case TP_WCHAR: 143494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes (*argtable)[n].pwchararg = va_arg(ap, wchar_t *); 143594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes break; 143694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 143794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 143894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes goto finish; 143994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 144094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesoverflow: 144194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes errno = ENOMEM; 144294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes ret = -1; 144394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 144494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesfinish: 144594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (typetable != NULL && typetable != stattypetable) { 144694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes munmap(typetable, *argtablesiz); 144794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes typetable = NULL; 144894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 144994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (ret); 145094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} 145194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 145294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes/* 145394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Increase the size of the type table. 145494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 145594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesstatic int 145694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes__grow_type_table(unsigned char **typetable, int *tablesize) 145794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes{ 145894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes unsigned char *oldtable = *typetable; 145994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes int newsize = *tablesize * 2; 146094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 146194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (newsize < getpagesize()) 146294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes newsize = getpagesize(); 146394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 146494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (*tablesize == STATIC_ARG_TBL_SIZE) { 146594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *typetable = mmap(NULL, newsize, PROT_WRITE|PROT_READ, 146694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes MAP_ANON|MAP_PRIVATE, -1, 0); 146794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (*typetable == MAP_FAILED) 146894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (-1); 146994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes bcopy(oldtable, *typetable, *tablesize); 147094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 147194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes unsigned char *new = mmap(NULL, newsize, PROT_WRITE|PROT_READ, 147294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes MAP_ANON|MAP_PRIVATE, -1, 0); 147394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (new == MAP_FAILED) 147494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (-1); 147594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes memmove(new, *typetable, *tablesize); 147694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes munmap(*typetable, *tablesize); 147794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *typetable = new; 147894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 147994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize)); 148094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 148194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *tablesize = newsize; 148294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (0); 148394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} 148494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 148594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 148694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#ifdef FLOATING_POINT 148794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesstatic int 148894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughesexponent(wchar_t *p0, int exp, int fmtch) 148994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes{ 149094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t *p, *t; 149194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes wchar_t expbuf[MAXEXPDIG]; 149294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes 149394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes p = p0; 149494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *p++ = fmtch; 149594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (exp < 0) { 149694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes exp = -exp; 149794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *p++ = '-'; 149894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else 149994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *p++ = '+'; 150094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes t = expbuf + MAXEXPDIG; 150194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (exp > 9) { 150294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes do { 150394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *--t = to_char(exp % 10); 150494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } while ((exp /= 10) > 9); 150594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *--t = to_char(exp); 150694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes for (; t < expbuf + MAXEXPDIG; *p++ = *t++) 150794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* nothing */; 150894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } else { 150994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes /* 151094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * Exponents for decimal floating point conversions 151194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * (%[eEgG]) must be at least two characters long, 151294336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * whereas exponents for hexadecimal conversions can 151394336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes * be only one character long. 151494336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes */ 151594336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes if (fmtch == 'e' || fmtch == 'E') 151694336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *p++ = '0'; 151794336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes *p++ = to_char(exp); 151894336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes } 151994336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes return (p - p0); 152094336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes} 152194336d8ecf795cfdde874a1e15977d68cfc7afc1Elliott Hughes#endif /* FLOATING_POINT */ 1522