11573Srgrimes/*- 21573Srgrimes * Copyright (c) 1990, 1993 31573Srgrimes * The Regents of the University of California. All rights reserved. 41573Srgrimes * 51573Srgrimes * This code is derived from software contributed to Berkeley by 61573Srgrimes * Chris Torek. 71573Srgrimes * 8227753Stheraven * Copyright (c) 2011 The FreeBSD Foundation 9227753Stheraven * All rights reserved. 10227753Stheraven * Portions of this software were developed by David Chisnall 11227753Stheraven * under sponsorship from the FreeBSD Foundation. 12227753Stheraven * 131573Srgrimes * Redistribution and use in source and binary forms, with or without 141573Srgrimes * modification, are permitted provided that the following conditions 151573Srgrimes * are met: 161573Srgrimes * 1. Redistributions of source code must retain the above copyright 171573Srgrimes * notice, this list of conditions and the following disclaimer. 181573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 191573Srgrimes * notice, this list of conditions and the following disclaimer in the 201573Srgrimes * documentation and/or other materials provided with the distribution. 21249808Semaste * 3. Neither the name of the University nor the names of its contributors 221573Srgrimes * may be used to endorse or promote products derived from this software 231573Srgrimes * without specific prior written permission. 241573Srgrimes * 251573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351573Srgrimes * SUCH DAMAGE. 361573Srgrimes */ 371573Srgrimes 381573Srgrimes#if defined(LIBC_SCCS) && !defined(lint) 391573Srgrimesstatic char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; 401573Srgrimes#endif /* LIBC_SCCS and not lint */ 4192986Sobrien#include <sys/cdefs.h> 4292986Sobrien__FBSDID("$FreeBSD: releng/11.0/lib/libc/stdio/vfprintf.c 268930 2014-07-20 21:24:29Z pfg $"); 431573Srgrimes 441573Srgrimes/* 451573Srgrimes * Actual printf innards. 461573Srgrimes * 471573Srgrimes * This code is large and complicated... 481573Srgrimes */ 491573Srgrimes 5071579Sdeischen#include "namespace.h" 511573Srgrimes#include <sys/types.h> 521573Srgrimes 5387113Sfenner#include <ctype.h> 54234531Sdas#include <errno.h> 551573Srgrimes#include <limits.h> 5687490Sphantom#include <locale.h> 5787113Sfenner#include <stddef.h> 5887113Sfenner#include <stdint.h> 591573Srgrimes#include <stdio.h> 601573Srgrimes#include <stdlib.h> 611573Srgrimes#include <string.h> 62103633Stjr#include <wchar.h> 63153486Sphk#include <printf.h> 641573Srgrimes 651573Srgrimes#include <stdarg.h> 66227753Stheraven#include "xlocale_private.h" 6771579Sdeischen#include "un-namespace.h" 681573Srgrimes 6971579Sdeischen#include "libc_private.h" 701573Srgrimes#include "local.h" 711573Srgrimes#include "fvwrite.h" 72180104Sdas#include "printflocal.h" 731573Srgrimes 74227753Stheravenstatic int __sprint(FILE *, struct __suio *, locale_t); 75227753Stheravenstatic int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0) 76187369Sdas __noinline; 77103633Stjrstatic char *__wcsconv(wchar_t *, int); 7816586Sjraynard 79187277Sdas#define CHAR char 80187277Sdas#include "printfcommon.h" 81187277Sdas 82187582Sdasstruct grouping_state { 83187582Sdas char *thousands_sep; /* locale-specific thousands separator */ 84187582Sdas int thousep_len; /* length of thousands_sep */ 85187582Sdas const char *grouping; /* locale-specific numeric grouping rules */ 86187582Sdas int lead; /* sig figs before decimal or group sep */ 87187582Sdas int nseps; /* number of group separators with ' */ 88187582Sdas int nrepeats; /* number of repeats of the last group */ 89187582Sdas}; 90187582Sdas 911573Srgrimes/* 92187582Sdas * Initialize the thousands' grouping state in preparation to print a 93187582Sdas * number with ndigits digits. This routine returns the total number 94187582Sdas * of bytes that will be needed. 95187582Sdas */ 96187582Sdasstatic int 97227753Stheravengrouping_init(struct grouping_state *gs, int ndigits, locale_t loc) 98187582Sdas{ 99187582Sdas struct lconv *locale; 100187582Sdas 101227753Stheraven locale = localeconv_l(loc); 102187582Sdas gs->grouping = locale->grouping; 103187582Sdas gs->thousands_sep = locale->thousands_sep; 104187582Sdas gs->thousep_len = strlen(gs->thousands_sep); 105187582Sdas 106187582Sdas gs->nseps = gs->nrepeats = 0; 107187582Sdas gs->lead = ndigits; 108187582Sdas while (*gs->grouping != CHAR_MAX) { 109187582Sdas if (gs->lead <= *gs->grouping) 110187582Sdas break; 111187582Sdas gs->lead -= *gs->grouping; 112187582Sdas if (*(gs->grouping+1)) { 113187582Sdas gs->nseps++; 114187582Sdas gs->grouping++; 115187582Sdas } else 116187582Sdas gs->nrepeats++; 117187582Sdas } 118187582Sdas return ((gs->nseps + gs->nrepeats) * gs->thousep_len); 119187582Sdas} 120187582Sdas 121187582Sdas/* 122187582Sdas * Print a number with thousands' separators. 123187582Sdas */ 124187582Sdasstatic int 125187582Sdasgrouping_print(struct grouping_state *gs, struct io_state *iop, 126227753Stheraven const CHAR *cp, const CHAR *ep, locale_t locale) 127187582Sdas{ 128187582Sdas const CHAR *cp0 = cp; 129187582Sdas 130227753Stheraven if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) 131187582Sdas return (-1); 132187582Sdas cp += gs->lead; 133187582Sdas while (gs->nseps > 0 || gs->nrepeats > 0) { 134187582Sdas if (gs->nrepeats > 0) 135187582Sdas gs->nrepeats--; 136187582Sdas else { 137187582Sdas gs->grouping--; 138187582Sdas gs->nseps--; 139187582Sdas } 140227753Stheraven if (io_print(iop, gs->thousands_sep, gs->thousep_len, locale)) 141187582Sdas return (-1); 142227753Stheraven if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) 143187582Sdas return (-1); 144187582Sdas cp += *gs->grouping; 145187582Sdas } 146187582Sdas if (cp > ep) 147187582Sdas cp = ep; 148187582Sdas return (cp - cp0); 149187582Sdas} 150187582Sdas 151187582Sdas/* 1521573Srgrimes * Flush out all the vectors defined by the given uio, 1531573Srgrimes * then reset it so that it can be reused. 1541573Srgrimes */ 1551573Srgrimesstatic int 156227753Stheraven__sprint(FILE *fp, struct __suio *uio, locale_t locale) 1571573Srgrimes{ 15871579Sdeischen int err; 1591573Srgrimes 1601573Srgrimes if (uio->uio_resid == 0) { 1611573Srgrimes uio->uio_iovcnt = 0; 1621573Srgrimes return (0); 1631573Srgrimes } 1641573Srgrimes err = __sfvwrite(fp, uio); 1651573Srgrimes uio->uio_resid = 0; 1661573Srgrimes uio->uio_iovcnt = 0; 1671573Srgrimes return (err); 1681573Srgrimes} 1691573Srgrimes 1701573Srgrimes/* 1711573Srgrimes * Helper function for `fprintf to unbuffered unix file': creates a 1721573Srgrimes * temporary buffer. We only work on write-only files; this avoids 1731573Srgrimes * worries about ungetc buffers and so forth. 1741573Srgrimes */ 1751573Srgrimesstatic int 176227753Stheraven__sbprintf(FILE *fp, locale_t locale, const char *fmt, va_list ap) 1771573Srgrimes{ 1781573Srgrimes int ret; 179205021Sjhb FILE fake = FAKE_FILE; 1801573Srgrimes unsigned char buf[BUFSIZ]; 1811573Srgrimes 182187369Sdas /* XXX This is probably not needed. */ 183187369Sdas if (prepwrite(fp) != 0) 184187369Sdas return (EOF); 185187369Sdas 1861573Srgrimes /* copy the important variables */ 1871573Srgrimes fake._flags = fp->_flags & ~__SNBF; 1881573Srgrimes fake._file = fp->_file; 1891573Srgrimes fake._cookie = fp->_cookie; 1901573Srgrimes fake._write = fp->_write; 191178287Sjhb fake._orientation = fp->_orientation; 192178287Sjhb fake._mbstate = fp->_mbstate; 1931573Srgrimes 1941573Srgrimes /* set up the buffer */ 1951573Srgrimes fake._bf._base = fake._p = buf; 1961573Srgrimes fake._bf._size = fake._w = sizeof(buf); 1971573Srgrimes fake._lbfsize = 0; /* not actually used, but Just In Case */ 1981573Srgrimes 1991573Srgrimes /* do the work, then copy any error status */ 200227753Stheraven ret = __vfprintf(&fake, locale, fmt, ap); 20171579Sdeischen if (ret >= 0 && __fflush(&fake)) 2021573Srgrimes ret = EOF; 2031573Srgrimes if (fake._flags & __SERR) 2041573Srgrimes fp->_flags |= __SERR; 2051573Srgrimes return (ret); 2061573Srgrimes} 2071573Srgrimes 2081573Srgrimes/* 209103633Stjr * Convert a wide character string argument for the %ls format to a multibyte 210148363Stjr * string representation. If not -1, prec specifies the maximum number of 211148363Stjr * bytes to output, and also means that we can't assume that the wide char. 212148363Stjr * string ends is null-terminated. 213103633Stjr */ 214103633Stjrstatic char * 215103633Stjr__wcsconv(wchar_t *wcsarg, int prec) 216103633Stjr{ 217128002Stjr static const mbstate_t initial; 218128002Stjr mbstate_t mbs; 219103633Stjr char buf[MB_LEN_MAX]; 220103633Stjr wchar_t *p; 221148363Stjr char *convbuf; 222103633Stjr size_t clen, nbytes; 223103633Stjr 224148363Stjr /* Allocate space for the maximum number of bytes we could output. */ 225148363Stjr if (prec < 0) { 226103633Stjr p = wcsarg; 227128002Stjr mbs = initial; 228128002Stjr nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs); 229103633Stjr if (nbytes == (size_t)-1) 230103633Stjr return (NULL); 231148363Stjr } else { 232148363Stjr /* 233148363Stjr * Optimisation: if the output precision is small enough, 234148363Stjr * just allocate enough memory for the maximum instead of 235148363Stjr * scanning the string. 236148363Stjr */ 237148363Stjr if (prec < 128) 238148363Stjr nbytes = prec; 239148363Stjr else { 240148363Stjr nbytes = 0; 241148363Stjr p = wcsarg; 242148363Stjr mbs = initial; 243148363Stjr for (;;) { 244148363Stjr clen = wcrtomb(buf, *p++, &mbs); 245148363Stjr if (clen == 0 || clen == (size_t)-1 || 246148363Stjr nbytes + clen > prec) 247148363Stjr break; 248148363Stjr nbytes += clen; 249148363Stjr } 250148363Stjr } 251103633Stjr } 252103633Stjr if ((convbuf = malloc(nbytes + 1)) == NULL) 253103633Stjr return (NULL); 254103633Stjr 255148363Stjr /* Fill the output buffer. */ 256103633Stjr p = wcsarg; 257128002Stjr mbs = initial; 258148363Stjr if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p, 259148363Stjr nbytes, &mbs)) == (size_t)-1) { 260113196Sache free(convbuf); 261113196Sache return (NULL); 262113196Sache } 263148363Stjr convbuf[nbytes] = '\0'; 264103633Stjr return (convbuf); 265103633Stjr} 266103633Stjr 267103633Stjr/* 26871579Sdeischen * MT-safe version 26971579Sdeischen */ 27071579Sdeischenint 271227753Stheravenvfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0, 272227753Stheraven va_list ap) 27371579Sdeischen{ 27471579Sdeischen int ret; 275227753Stheraven FIX_LOCALE(locale); 27671579Sdeischen 27771579Sdeischen FLOCKFILE(fp); 278187369Sdas /* optimise fprintf(stderr) (and other unbuffered Unix files) */ 279187369Sdas if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && 280187369Sdas fp->_file >= 0) 281227753Stheraven ret = __sbprintf(fp, locale, fmt0, ap); 282187369Sdas else 283227753Stheraven ret = __vfprintf(fp, locale, fmt0, ap); 28471579Sdeischen FUNLOCKFILE(fp); 28571579Sdeischen return (ret); 28671579Sdeischen} 287227753Stheravenint 288227753Stheravenvfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) 289227753Stheraven{ 290227753Stheraven return vfprintf_l(fp, __get_locale(), fmt0, ap); 291227753Stheraven} 29271579Sdeischen 293113142Sdas/* 294113142Sdas * The size of the buffer we use as scratch space for integer 295187582Sdas * conversions, among other things. We need enough space to 296187582Sdas * write a uintmax_t in octal (plus one byte). 297113142Sdas */ 298187582Sdas#if UINTMAX_MAX <= UINT64_MAX 299187582Sdas#define BUF 32 300187582Sdas#else 301187582Sdas#error "BUF must be large enough to format a uintmax_t" 302187582Sdas#endif 3031573Srgrimes 3041573Srgrimes/* 30571579Sdeischen * Non-MT-safe version 30671579Sdeischen */ 3071573Srgrimesint 308227753Stheraven__vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) 3091573Srgrimes{ 31071579Sdeischen char *fmt; /* format string */ 31171579Sdeischen int ch; /* character from fmt */ 31271579Sdeischen int n, n2; /* handy integer (short term usage) */ 31371579Sdeischen char *cp; /* handy char pointer (short term usage) */ 31471579Sdeischen int flags; /* flags as above */ 3151573Srgrimes int ret; /* return value accumulator */ 3161573Srgrimes int width; /* width from format (%8d), or 0 */ 317113146Sdas int prec; /* precision from format; <0 for N/A */ 3181573Srgrimes char sign; /* sign prefix (' ', '+', '-', or \0) */ 319187582Sdas struct grouping_state gs; /* thousands' grouping info */ 320187277Sdas 321128819Sdas#ifndef NO_FLOATING_POINT 322113146Sdas /* 323113146Sdas * We can decompose the printed representation of floating 324113146Sdas * point numbers into several parts, some of which may be empty: 325113146Sdas * 326113146Sdas * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ 327113146Sdas * A B ---C--- D E F 328113146Sdas * 329113146Sdas * A: 'sign' holds this value if present; '\0' otherwise 330113146Sdas * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal 331113146Sdas * C: cp points to the string MMMNNN. Leading and trailing 332113146Sdas * zeros are not in the string and must be added. 333113146Sdas * D: expchar holds this character; '\0' if no exponent, e.g. %f 334113146Sdas * F: at least two digits for decimal, at least one digit for hex 335113146Sdas */ 33687490Sphantom char *decimal_point; /* locale specific decimal point */ 337187421Sdas int decpt_len; /* length of decimal_point */ 338113146Sdas int signflag; /* true if float is negative */ 339113146Sdas union { /* floating point arguments %[aAeEfFgG] */ 340113146Sdas double dbl; 341113146Sdas long double ldbl; 342113146Sdas } fparg; 3431573Srgrimes int expt; /* integer value of exponent */ 344113146Sdas char expchar; /* exponent character: [eEpP\0] */ 345113146Sdas char *dtoaend; /* pointer to end of converted digits */ 3461573Srgrimes int expsize; /* character count for expstr */ 347113146Sdas int ndig; /* actual number of digits returned by dtoa */ 348113146Sdas char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ 34972523Stegge char *dtoaresult; /* buffer allocated by dtoa */ 3501573Srgrimes#endif 3511573Srgrimes u_long ulval; /* integer arguments %[diouxX] */ 35287113Sfenner uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */ 3531573Srgrimes int base; /* base for [diouxX] conversion */ 3541573Srgrimes int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 35514727Sfenner int realsz; /* field size expanded by dprec, sign, etc */ 3561573Srgrimes int size; /* size of converted field or string */ 35731983Sache int prsize; /* max size of printed field */ 358113146Sdas const char *xdigs; /* digits for %[xX] conversion */ 359187277Sdas struct io_state io; /* I/O buffering state */ 360113142Sdas char buf[BUF]; /* buffer with space for digits of uintmax_t */ 361113146Sdas char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */ 362103399Stjr union arg *argtable; /* args, built due to positional arg */ 363103399Stjr union arg statargtable [STATIC_ARG_TBL_SIZE]; 364103399Stjr int nextarg; /* 1-based argument index */ 365103399Stjr va_list orgap; /* original argument pointer */ 366103633Stjr char *convbuf; /* wide to multibyte conversion result */ 3671573Srgrimes 368165742Sdas static const char xdigs_lower[16] = "0123456789abcdef"; 369165742Sdas static const char xdigs_upper[16] = "0123456789ABCDEF"; 370113146Sdas 371187277Sdas /* BEWARE, these `goto error' on error. */ 3721573Srgrimes#define PRINT(ptr, len) { \ 373227753Stheraven if (io_print(&io, (ptr), (len), locale)) \ 374187277Sdas goto error; \ 3751573Srgrimes} 3761573Srgrimes#define PAD(howmany, with) { \ 377227753Stheraven if (io_pad(&io, (howmany), (with), locale)) \ 378187277Sdas goto error; \ 3791573Srgrimes} 380187277Sdas#define PRINTANDPAD(p, ep, len, with) { \ 381227753Stheraven if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ 382187277Sdas goto error; \ 383187277Sdas} 3841573Srgrimes#define FLUSH() { \ 385227753Stheraven if (io_flush(&io, locale)) \ 3861573Srgrimes goto error; \ 3871573Srgrimes} 3881573Srgrimes 389103399Stjr /* 390103399Stjr * Get the argument indexed by nextarg. If the argument table is 391103399Stjr * built, use it to get the argument. If its not, get the next 392103399Stjr * argument (and arguments must be gotten sequentially). 393103399Stjr */ 39421674Sjkh#define GETARG(type) \ 395103399Stjr ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ 396103399Stjr (nextarg++, va_arg(ap, type))) 39721674Sjkh 3981573Srgrimes /* 3991573Srgrimes * To extend shorts properly, we need both signed and unsigned 4001573Srgrimes * argument extraction methods. 4011573Srgrimes */ 4021573Srgrimes#define SARG() \ 40321674Sjkh (flags&LONGINT ? GETARG(long) : \ 40421674Sjkh flags&SHORTINT ? (long)(short)GETARG(int) : \ 40587113Sfenner flags&CHARINT ? (long)(signed char)GETARG(int) : \ 40621674Sjkh (long)GETARG(int)) 4071573Srgrimes#define UARG() \ 40821674Sjkh (flags&LONGINT ? GETARG(u_long) : \ 40921674Sjkh flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \ 41087113Sfenner flags&CHARINT ? (u_long)(u_char)GETARG(int) : \ 41121674Sjkh (u_long)GETARG(u_int)) 41287113Sfenner#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT) 41387113Sfenner#define SJARG() \ 41487113Sfenner (flags&INTMAXT ? GETARG(intmax_t) : \ 415189131Sdas flags&SIZET ? (intmax_t)GETARG(ssize_t) : \ 41687113Sfenner flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \ 41787113Sfenner (intmax_t)GETARG(long long)) 41887113Sfenner#define UJARG() \ 41987113Sfenner (flags&INTMAXT ? GETARG(uintmax_t) : \ 42087113Sfenner flags&SIZET ? (uintmax_t)GETARG(size_t) : \ 42187113Sfenner flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \ 42287113Sfenner (uintmax_t)GETARG(unsigned long long)) 4231573Srgrimes 424103399Stjr /* 425103399Stjr * Get * arguments, including the form *nn$. Preserve the nextarg 426103399Stjr * that the argument can be gotten once the type is determined. 427103399Stjr */ 42821674Sjkh#define GETASTER(val) \ 429103399Stjr n2 = 0; \ 430103399Stjr cp = fmt; \ 431103399Stjr while (is_digit(*cp)) { \ 432103399Stjr n2 = 10 * n2 + to_digit(*cp); \ 433103399Stjr cp++; \ 434103399Stjr } \ 435103399Stjr if (*cp == '$') { \ 436103399Stjr int hold = nextarg; \ 437103399Stjr if (argtable == NULL) { \ 438103399Stjr argtable = statargtable; \ 439180106Sdas if (__find_arguments (fmt0, orgap, &argtable)) { \ 440180106Sdas ret = EOF; \ 441180106Sdas goto error; \ 442180106Sdas } \ 443103399Stjr } \ 444103399Stjr nextarg = n2; \ 44521674Sjkh val = GETARG (int); \ 446103399Stjr nextarg = hold; \ 447103399Stjr fmt = ++cp; \ 448103399Stjr } else { \ 449103399Stjr val = GETARG (int); \ 450103399Stjr } 45187815Sphantom 452185825Sdas if (__use_xprintf == 0 && getenv("USE_XPRINTF")) 453185825Sdas __use_xprintf = 1; 454185825Sdas if (__use_xprintf > 0) 455185825Sdas return (__xvprintf(fp, fmt0, ap)); 45688057Sphantom 4571573Srgrimes /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ 458268930Spfg if (prepwrite(fp) != 0) { 459268930Spfg errno = EBADF; 4601573Srgrimes return (EOF); 461268930Spfg } 4621573Srgrimes 463185904Sdas convbuf = NULL; 4641573Srgrimes fmt = (char *)fmt0; 465103399Stjr argtable = NULL; 466103399Stjr nextarg = 1; 467103876Stjr va_copy(orgap, ap); 468187277Sdas io_init(&io, fp); 4691573Srgrimes ret = 0; 470185904Sdas#ifndef NO_FLOATING_POINT 471185904Sdas dtoaresult = NULL; 472227753Stheraven decimal_point = localeconv_l(locale)->decimal_point; 473187421Sdas /* The overwhelmingly common case is decpt_len == 1. */ 474187421Sdas decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point)); 475185904Sdas#endif 4761573Srgrimes 4771573Srgrimes /* 4781573Srgrimes * Scan the format for conversions (`%' character). 4791573Srgrimes */ 4801573Srgrimes for (;;) { 4811573Srgrimes for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 4821573Srgrimes /* void */; 4831573Srgrimes if ((n = fmt - cp) != 0) { 48432253Sache if ((unsigned)ret + n > INT_MAX) { 48531983Sache ret = EOF; 486234531Sdas errno = EOVERFLOW; 48731983Sache goto error; 48831983Sache } 4891573Srgrimes PRINT(cp, n); 4901573Srgrimes ret += n; 4911573Srgrimes } 4921573Srgrimes if (ch == '\0') 4931573Srgrimes goto done; 4941573Srgrimes fmt++; /* skip over '%' */ 4951573Srgrimes 4961573Srgrimes flags = 0; 4971573Srgrimes dprec = 0; 4981573Srgrimes width = 0; 4991573Srgrimes prec = -1; 500187582Sdas gs.grouping = NULL; 5011573Srgrimes sign = '\0'; 502113146Sdas ox[1] = '\0'; 5031573Srgrimes 5041573Srgrimesrflag: ch = *fmt++; 5051573Srgrimesreswitch: switch (ch) { 5061573Srgrimes case ' ': 50788057Sphantom /*- 5081573Srgrimes * ``If the space and + flags both appear, the space 5091573Srgrimes * flag will be ignored.'' 5101573Srgrimes * -- ANSI X3J11 5111573Srgrimes */ 5121573Srgrimes if (!sign) 5131573Srgrimes sign = ' '; 5141573Srgrimes goto rflag; 5151573Srgrimes case '#': 5161573Srgrimes flags |= ALT; 5171573Srgrimes goto rflag; 5181573Srgrimes case '*': 51988057Sphantom /*- 5201573Srgrimes * ``A negative field width argument is taken as a 5211573Srgrimes * - flag followed by a positive field width.'' 5221573Srgrimes * -- ANSI X3J11 5231573Srgrimes * They don't exclude field widths read from args. 5241573Srgrimes */ 52521674Sjkh GETASTER (width); 52621674Sjkh if (width >= 0) 5271573Srgrimes goto rflag; 5281573Srgrimes width = -width; 5291573Srgrimes /* FALLTHROUGH */ 5301573Srgrimes case '-': 5311573Srgrimes flags |= LADJUST; 5321573Srgrimes goto rflag; 5331573Srgrimes case '+': 5341573Srgrimes sign = '+'; 5351573Srgrimes goto rflag; 53687113Sfenner case '\'': 53787815Sphantom flags |= GROUPING; 53887113Sfenner goto rflag; 5391573Srgrimes case '.': 5401573Srgrimes if ((ch = *fmt++) == '*') { 541113191Sdas GETASTER (prec); 5421573Srgrimes goto rflag; 5431573Srgrimes } 544113191Sdas prec = 0; 5451573Srgrimes while (is_digit(ch)) { 546113191Sdas prec = 10 * prec + to_digit(ch); 5471573Srgrimes ch = *fmt++; 5481573Srgrimes } 5491573Srgrimes goto reswitch; 5501573Srgrimes case '0': 55188057Sphantom /*- 5521573Srgrimes * ``Note that 0 is taken as a flag, not as the 5531573Srgrimes * beginning of a field width.'' 5541573Srgrimes * -- ANSI X3J11 5551573Srgrimes */ 5561573Srgrimes flags |= ZEROPAD; 5571573Srgrimes goto rflag; 5581573Srgrimes case '1': case '2': case '3': case '4': 5591573Srgrimes case '5': case '6': case '7': case '8': case '9': 5601573Srgrimes n = 0; 5611573Srgrimes do { 5621573Srgrimes n = 10 * n + to_digit(ch); 5631573Srgrimes ch = *fmt++; 5641573Srgrimes } while (is_digit(ch)); 56521674Sjkh if (ch == '$') { 56621674Sjkh nextarg = n; 567103399Stjr if (argtable == NULL) { 568103399Stjr argtable = statargtable; 569180106Sdas if (__find_arguments (fmt0, orgap, 570180106Sdas &argtable)) { 571180106Sdas ret = EOF; 572180106Sdas goto error; 573180106Sdas } 57421674Sjkh } 57521674Sjkh goto rflag; 576103399Stjr } 5771573Srgrimes width = n; 5781573Srgrimes goto reswitch; 579128819Sdas#ifndef NO_FLOATING_POINT 5801573Srgrimes case 'L': 5811573Srgrimes flags |= LONGDBL; 5821573Srgrimes goto rflag; 5831573Srgrimes#endif 5841573Srgrimes case 'h': 58587113Sfenner if (flags & SHORTINT) { 58687113Sfenner flags &= ~SHORTINT; 58787113Sfenner flags |= CHARINT; 58887113Sfenner } else 58987113Sfenner flags |= SHORTINT; 5901573Srgrimes goto rflag; 59187113Sfenner case 'j': 59287113Sfenner flags |= INTMAXT; 59387113Sfenner goto rflag; 5941573Srgrimes case 'l': 59587113Sfenner if (flags & LONGINT) { 59687113Sfenner flags &= ~LONGINT; 59787113Sfenner flags |= LLONGINT; 59887113Sfenner } else 59944674Sdfr flags |= LONGINT; 6001573Srgrimes goto rflag; 6011573Srgrimes case 'q': 60287113Sfenner flags |= LLONGINT; /* not necessarily */ 6031573Srgrimes goto rflag; 60487113Sfenner case 't': 60587113Sfenner flags |= PTRDIFFT; 60687113Sfenner goto rflag; 60787113Sfenner case 'z': 60887113Sfenner flags |= SIZET; 60987113Sfenner goto rflag; 610105204Stjr case 'C': 611105204Stjr flags |= LONGINT; 612105204Stjr /*FALLTHROUGH*/ 6131573Srgrimes case 'c': 614103633Stjr if (flags & LONGINT) { 615128002Stjr static const mbstate_t initial; 616128002Stjr mbstate_t mbs; 617103633Stjr size_t mbseqlen; 618103633Stjr 619128002Stjr mbs = initial; 620103633Stjr mbseqlen = wcrtomb(cp = buf, 621128002Stjr (wchar_t)GETARG(wint_t), &mbs); 622105234Stjr if (mbseqlen == (size_t)-1) { 623105234Stjr fp->_flags |= __SERR; 624103633Stjr goto error; 625105234Stjr } 626103633Stjr size = (int)mbseqlen; 627103633Stjr } else { 628103633Stjr *(cp = buf) = GETARG(int); 629103633Stjr size = 1; 630103633Stjr } 6311573Srgrimes sign = '\0'; 6321573Srgrimes break; 6331573Srgrimes case 'D': 6341573Srgrimes flags |= LONGINT; 6351573Srgrimes /*FALLTHROUGH*/ 6361573Srgrimes case 'd': 6371573Srgrimes case 'i': 63887113Sfenner if (flags & INTMAX_SIZE) { 63987113Sfenner ujval = SJARG(); 64087113Sfenner if ((intmax_t)ujval < 0) { 64187113Sfenner ujval = -ujval; 6421573Srgrimes sign = '-'; 6431573Srgrimes } 6441573Srgrimes } else { 6451573Srgrimes ulval = SARG(); 6461573Srgrimes if ((long)ulval < 0) { 6471573Srgrimes ulval = -ulval; 6481573Srgrimes sign = '-'; 6491573Srgrimes } 6501573Srgrimes } 6511573Srgrimes base = 10; 6521573Srgrimes goto number; 653128819Sdas#ifndef NO_FLOATING_POINT 65487113Sfenner case 'a': 65587113Sfenner case 'A': 656113146Sdas if (ch == 'a') { 657113146Sdas ox[1] = 'x'; 658113146Sdas xdigs = xdigs_lower; 659113146Sdas expchar = 'p'; 660113146Sdas } else { 661113146Sdas ox[1] = 'X'; 662113146Sdas xdigs = xdigs_upper; 663113146Sdas expchar = 'P'; 664113146Sdas } 665124657Sdas if (prec >= 0) 666124657Sdas prec++; 667124657Sdas if (dtoaresult != NULL) 668124657Sdas freedtoa(dtoaresult); 669113146Sdas if (flags & LONGDBL) { 670124657Sdas fparg.ldbl = GETARG(long double); 671113146Sdas dtoaresult = cp = 672113146Sdas __hldtoa(fparg.ldbl, xdigs, prec, 673113146Sdas &expt, &signflag, &dtoaend); 674113146Sdas } else { 675113146Sdas fparg.dbl = GETARG(double); 676113146Sdas dtoaresult = cp = 677113146Sdas __hdtoa(fparg.dbl, xdigs, prec, 678113146Sdas &expt, &signflag, &dtoaend); 679113146Sdas } 680124657Sdas if (prec < 0) 681124657Sdas prec = dtoaend - cp; 682124657Sdas if (expt == INT_MAX) 683124657Sdas ox[1] = '\0'; 684124657Sdas goto fp_common; 6857033Sbde case 'e': 6861573Srgrimes case 'E': 687113146Sdas expchar = ch; 688113146Sdas if (prec < 0) /* account for digit before decpt */ 689113146Sdas prec = DEFPREC + 1; 690113146Sdas else 691113146Sdas prec++; 692113146Sdas goto fp_begin; 6937033Sbde case 'f': 69487113Sfenner case 'F': 695113146Sdas expchar = '\0'; 6967033Sbde goto fp_begin; 6971573Srgrimes case 'g': 6981573Srgrimes case 'G': 699113146Sdas expchar = ch - ('g' - 'e'); 7007033Sbde if (prec == 0) 7017033Sbde prec = 1; 702113146Sdasfp_begin: 703113146Sdas if (prec < 0) 7041573Srgrimes prec = DEFPREC; 705113146Sdas if (dtoaresult != NULL) 706113146Sdas freedtoa(dtoaresult); 707113146Sdas if (flags & LONGDBL) { 708113146Sdas fparg.ldbl = GETARG(long double); 709113146Sdas dtoaresult = cp = 710113146Sdas __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, 711113146Sdas &expt, &signflag, &dtoaend); 712113146Sdas } else { 713113146Sdas fparg.dbl = GETARG(double); 714113146Sdas dtoaresult = cp = 715113146Sdas dtoa(fparg.dbl, expchar ? 2 : 3, prec, 716113146Sdas &expt, &signflag, &dtoaend); 717113146Sdas if (expt == 9999) 718113146Sdas expt = INT_MAX; 7191573Srgrimes } 720124657Sdasfp_common: 721113146Sdas if (signflag) 722113146Sdas sign = '-'; 723113146Sdas if (expt == INT_MAX) { /* inf or nan */ 724113146Sdas if (*cp == 'N') { 725113146Sdas cp = (ch >= 'a') ? "nan" : "NAN"; 726113146Sdas sign = '\0'; 727113146Sdas } else 728113146Sdas cp = (ch >= 'a') ? "inf" : "INF"; 7291573Srgrimes size = 3; 730169355Sdas flags &= ~ZEROPAD; 7311573Srgrimes break; 7321573Srgrimes } 7331573Srgrimes flags |= FPT; 734113146Sdas ndig = dtoaend - cp; 7351573Srgrimes if (ch == 'g' || ch == 'G') { 736113146Sdas if (expt > -4 && expt <= prec) { 737113146Sdas /* Make %[gG] smell like %[fF] */ 738113146Sdas expchar = '\0'; 739113146Sdas if (flags & ALT) 740113146Sdas prec -= expt; 741113146Sdas else 742113146Sdas prec = ndig - expt; 743113146Sdas if (prec < 0) 744113146Sdas prec = 0; 745113723Sdas } else { 746113723Sdas /* 747113723Sdas * Make %[gG] smell like %[eE], but 748113723Sdas * trim trailing zeroes if no # flag. 749113723Sdas */ 750113723Sdas if (!(flags & ALT)) 751113723Sdas prec = ndig; 752113146Sdas } 7538870Srgrimes } 754113146Sdas if (expchar) { 755113146Sdas expsize = exponent(expstr, expt - 1, expchar); 756113146Sdas size = expsize + prec; 757113191Sdas if (prec > 1 || flags & ALT) 758187421Sdas size += decpt_len; 759113146Sdas } else { 760113468Sdas /* space for digits before decimal point */ 761113468Sdas if (expt > 0) 7621573Srgrimes size = expt; 763113468Sdas else /* "0" */ 764113468Sdas size = 1; 765113468Sdas /* space for decimal pt and following digits */ 766113468Sdas if (prec || flags & ALT) 767187421Sdas size += prec + decpt_len; 768187582Sdas if ((flags & GROUPING) && expt > 0) 769227753Stheraven size += grouping_init(&gs, expt, locale); 770113146Sdas } 7711573Srgrimes break; 772128819Sdas#endif /* !NO_FLOATING_POINT */ 7731573Srgrimes case 'n': 77487113Sfenner /* 77587113Sfenner * Assignment-like behavior is specified if the 77687113Sfenner * value overflows or is otherwise unrepresentable. 77787113Sfenner * C99 says to use `signed char' for %hhn conversions. 77887113Sfenner */ 77987113Sfenner if (flags & LLONGINT) 78087113Sfenner *GETARG(long long *) = ret; 78187113Sfenner else if (flags & SIZET) 78287113Sfenner *GETARG(ssize_t *) = (ssize_t)ret; 78387113Sfenner else if (flags & PTRDIFFT) 78487113Sfenner *GETARG(ptrdiff_t *) = ret; 78587113Sfenner else if (flags & INTMAXT) 78687113Sfenner *GETARG(intmax_t *) = ret; 7871573Srgrimes else if (flags & LONGINT) 78831980Sache *GETARG(long *) = ret; 7891573Srgrimes else if (flags & SHORTINT) 79031980Sache *GETARG(short *) = ret; 79187113Sfenner else if (flags & CHARINT) 79287113Sfenner *GETARG(signed char *) = ret; 7931573Srgrimes else 79431980Sache *GETARG(int *) = ret; 7951573Srgrimes continue; /* no output */ 7961573Srgrimes case 'O': 7971573Srgrimes flags |= LONGINT; 7981573Srgrimes /*FALLTHROUGH*/ 7991573Srgrimes case 'o': 80087113Sfenner if (flags & INTMAX_SIZE) 80187113Sfenner ujval = UJARG(); 8021573Srgrimes else 8031573Srgrimes ulval = UARG(); 8041573Srgrimes base = 8; 8051573Srgrimes goto nosign; 8061573Srgrimes case 'p': 80788057Sphantom /*- 8081573Srgrimes * ``The argument shall be a pointer to void. The 8091573Srgrimes * value of the pointer is converted to a sequence 8101573Srgrimes * of printable characters, in an implementation- 8111573Srgrimes * defined manner.'' 8121573Srgrimes * -- ANSI X3J11 8131573Srgrimes */ 81487113Sfenner ujval = (uintmax_t)(uintptr_t)GETARG(void *); 8151573Srgrimes base = 16; 816113146Sdas xdigs = xdigs_lower; 817113146Sdas flags = flags | INTMAXT; 818113146Sdas ox[1] = 'x'; 8191573Srgrimes goto nosign; 820105204Stjr case 'S': 821105204Stjr flags |= LONGINT; 822105204Stjr /*FALLTHROUGH*/ 8231573Srgrimes case 's': 824103633Stjr if (flags & LONGINT) { 825103633Stjr wchar_t *wcp; 826103633Stjr 827103633Stjr if (convbuf != NULL) 828103633Stjr free(convbuf); 829103633Stjr if ((wcp = GETARG(wchar_t *)) == NULL) 830103633Stjr cp = "(null)"; 831103633Stjr else { 832103633Stjr convbuf = __wcsconv(wcp, prec); 833105234Stjr if (convbuf == NULL) { 834105234Stjr fp->_flags |= __SERR; 835103633Stjr goto error; 836105234Stjr } 837103633Stjr cp = convbuf; 838103633Stjr } 839103633Stjr } else if ((cp = GETARG(char *)) == NULL) 8401573Srgrimes cp = "(null)"; 841189138Sdas size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp); 8421573Srgrimes sign = '\0'; 8431573Srgrimes break; 8441573Srgrimes case 'U': 8451573Srgrimes flags |= LONGINT; 8461573Srgrimes /*FALLTHROUGH*/ 8471573Srgrimes case 'u': 84887113Sfenner if (flags & INTMAX_SIZE) 84987113Sfenner ujval = UJARG(); 8501573Srgrimes else 8511573Srgrimes ulval = UARG(); 8521573Srgrimes base = 10; 8531573Srgrimes goto nosign; 8541573Srgrimes case 'X': 855113146Sdas xdigs = xdigs_upper; 8561573Srgrimes goto hex; 8571573Srgrimes case 'x': 858113146Sdas xdigs = xdigs_lower; 85987113Sfennerhex: 86087113Sfenner if (flags & INTMAX_SIZE) 86187113Sfenner ujval = UJARG(); 8621573Srgrimes else 8631573Srgrimes ulval = UARG(); 8641573Srgrimes base = 16; 8651573Srgrimes /* leading 0x/X only if non-zero */ 8661573Srgrimes if (flags & ALT && 86787113Sfenner (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) 868113146Sdas ox[1] = ch; 8691573Srgrimes 87087815Sphantom flags &= ~GROUPING; 8711573Srgrimes /* unsigned conversions */ 8721573Srgrimesnosign: sign = '\0'; 87388057Sphantom /*- 8741573Srgrimes * ``... diouXx conversions ... if a precision is 8751573Srgrimes * specified, the 0 flag will be ignored.'' 8761573Srgrimes * -- ANSI X3J11 8771573Srgrimes */ 8781573Srgrimesnumber: if ((dprec = prec) >= 0) 8791573Srgrimes flags &= ~ZEROPAD; 8801573Srgrimes 88188057Sphantom /*- 8821573Srgrimes * ``The result of converting a zero value with an 8831573Srgrimes * explicit precision of zero is no characters.'' 8841573Srgrimes * -- ANSI X3J11 885145172Sdas * 886145172Sdas * ``The C Standard is clear enough as is. The call 887145172Sdas * printf("%#.0o", 0) should print 0.'' 888145172Sdas * -- Defect Report #151 8891573Srgrimes */ 8901573Srgrimes cp = buf + BUF; 89187113Sfenner if (flags & INTMAX_SIZE) { 892145172Sdas if (ujval != 0 || prec != 0 || 893145172Sdas (flags & ALT && base == 8)) 89487113Sfenner cp = __ujtoa(ujval, cp, base, 895187582Sdas flags & ALT, xdigs); 8961573Srgrimes } else { 897145172Sdas if (ulval != 0 || prec != 0 || 898145172Sdas (flags & ALT && base == 8)) 8991573Srgrimes cp = __ultoa(ulval, cp, base, 900187582Sdas flags & ALT, xdigs); 9011573Srgrimes } 9021573Srgrimes size = buf + BUF - cp; 903113142Sdas if (size > BUF) /* should never happen */ 904113142Sdas abort(); 905187582Sdas if ((flags & GROUPING) && size != 0) 906227753Stheraven size += grouping_init(&gs, size, locale); 9071573Srgrimes break; 9081573Srgrimes default: /* "%?" prints ?, unless ? is NUL */ 9091573Srgrimes if (ch == '\0') 9101573Srgrimes goto done; 9111573Srgrimes /* pretend it was %c with argument ch */ 9121573Srgrimes cp = buf; 9131573Srgrimes *cp = ch; 9141573Srgrimes size = 1; 9151573Srgrimes sign = '\0'; 9161573Srgrimes break; 9171573Srgrimes } 9181573Srgrimes 9191573Srgrimes /* 9201573Srgrimes * All reasonable formats wind up here. At this point, `cp' 9211573Srgrimes * points to a string which (if not flags&LADJUST) should be 9221573Srgrimes * padded out to `width' places. If flags&ZEROPAD, it should 9231573Srgrimes * first be prefixed by any sign or other prefix; otherwise, 9241573Srgrimes * it should be blank padded before the prefix is emitted. 9251573Srgrimes * After any left-hand padding and prefixing, emit zeroes 9261573Srgrimes * required by a decimal [diouxX] precision, then print the 9271573Srgrimes * string proper, then emit zeroes required by any leftover 9281573Srgrimes * floating precision; finally, if LADJUST, pad with blanks. 9291573Srgrimes * 9301573Srgrimes * Compute actual size, so we know how much to pad. 93114727Sfenner * size excludes decimal prec; realsz includes it. 9321573Srgrimes */ 93314727Sfenner realsz = dprec > size ? dprec : size; 9341573Srgrimes if (sign) 93514727Sfenner realsz++; 936124657Sdas if (ox[1]) 93714727Sfenner realsz += 2; 9381573Srgrimes 93931983Sache prsize = width > realsz ? width : realsz; 94032253Sache if ((unsigned)ret + prsize > INT_MAX) { 94131983Sache ret = EOF; 942234531Sdas errno = EOVERFLOW; 94331983Sache goto error; 94431983Sache } 94531983Sache 9461573Srgrimes /* right-adjusting blank padding */ 9471573Srgrimes if ((flags & (LADJUST|ZEROPAD)) == 0) 9481573Srgrimes PAD(width - realsz, blanks); 9491573Srgrimes 9501573Srgrimes /* prefix */ 951124657Sdas if (sign) 9521573Srgrimes PRINT(&sign, 1); 953124657Sdas 954124657Sdas if (ox[1]) { /* ox[1] is either x, X, or \0 */ 9551573Srgrimes ox[0] = '0'; 9561573Srgrimes PRINT(ox, 2); 9571573Srgrimes } 9581573Srgrimes 9591573Srgrimes /* right-adjusting zero padding */ 9601573Srgrimes if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 9611573Srgrimes PAD(width - realsz, zeroes); 9621573Srgrimes 9631573Srgrimes /* the string or number proper */ 964128819Sdas#ifndef NO_FLOATING_POINT 9651573Srgrimes if ((flags & FPT) == 0) { 966187582Sdas#endif 967187582Sdas /* leading zeroes from decimal precision */ 968187582Sdas PAD(dprec - size, zeroes); 969187582Sdas if (gs.grouping) { 970227753Stheraven if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) 971187582Sdas goto error; 972187582Sdas } else { 973187582Sdas PRINT(cp, size); 974187582Sdas } 975187582Sdas#ifndef NO_FLOATING_POINT 9761573Srgrimes } else { /* glue together f_p fragments */ 977113146Sdas if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 978113146Sdas if (expt <= 0) { 979113468Sdas PRINT(zeroes, 1); 980113468Sdas if (prec || flags & ALT) 981187421Sdas PRINT(decimal_point,decpt_len); 9821573Srgrimes PAD(-expt, zeroes); 983113191Sdas /* already handled initial 0's */ 984113191Sdas prec += expt; 9851573Srgrimes } else { 986187582Sdas if (gs.grouping) { 987187582Sdas n = grouping_print(&gs, &io, 988227753Stheraven cp, dtoaend, locale); 989187582Sdas if (n < 0) 990187582Sdas goto error; 991187582Sdas cp += n; 992187582Sdas } else { 993187582Sdas PRINTANDPAD(cp, dtoaend, 994187582Sdas expt, zeroes); 995187582Sdas cp += expt; 996113146Sdas } 997113146Sdas if (prec || flags & ALT) 998187421Sdas PRINT(decimal_point,decpt_len); 9991573Srgrimes } 1000113191Sdas PRINTANDPAD(cp, dtoaend, prec, zeroes); 1001113146Sdas } else { /* %[eE] or sufficiently long %[gG] */ 1002113191Sdas if (prec > 1 || flags & ALT) { 1003187421Sdas PRINT(cp++, 1); 1004187421Sdas PRINT(decimal_point, decpt_len); 1005113146Sdas PRINT(cp, ndig-1); 1006113146Sdas PAD(prec - ndig, zeroes); 10071573Srgrimes } else /* XeYYY */ 10081573Srgrimes PRINT(cp, 1); 10091573Srgrimes PRINT(expstr, expsize); 10101573Srgrimes } 10111573Srgrimes } 10121573Srgrimes#endif 10131573Srgrimes /* left-adjusting padding (always blank) */ 10141573Srgrimes if (flags & LADJUST) 10151573Srgrimes PAD(width - realsz, blanks); 10161573Srgrimes 10171573Srgrimes /* finally, adjust ret */ 101831983Sache ret += prsize; 10191573Srgrimes 10201573Srgrimes FLUSH(); /* copy out the I/O vectors */ 10211573Srgrimes } 10221573Srgrimesdone: 10231573Srgrimes FLUSH(); 10241573Srgrimeserror: 1025134332Sdes va_end(orgap); 1026128819Sdas#ifndef NO_FLOATING_POINT 102772523Stegge if (dtoaresult != NULL) 1028113146Sdas freedtoa(dtoaresult); 102972523Stegge#endif 1030103633Stjr if (convbuf != NULL) 1031103633Stjr free(convbuf); 103213545Sjulian if (__sferror(fp)) 103313545Sjulian ret = EOF; 1034103399Stjr if ((argtable != NULL) && (argtable != statargtable)) 1035103399Stjr free (argtable); 103613545Sjulian return (ret); 10371573Srgrimes /* NOTREACHED */ 10381573Srgrimes} 10391573Srgrimes 1040