vfprintf.c revision 187369
1219182Sglebius/*- 2219182Sglebius * Copyright (c) 1990, 1993 3219182Sglebius * The Regents of the University of California. All rights reserved. 4219182Sglebius * 5219182Sglebius * This code is derived from software contributed to Berkeley by 6219182Sglebius * Chris Torek. 7219182Sglebius * 8219182Sglebius * Redistribution and use in source and binary forms, with or without 9219182Sglebius * modification, are permitted provided that the following conditions 10219182Sglebius * are met: 11219182Sglebius * 1. Redistributions of source code must retain the above copyright 12219182Sglebius * notice, this list of conditions and the following disclaimer. 13219182Sglebius * 2. Redistributions in binary form must reproduce the above copyright 14219182Sglebius * notice, this list of conditions and the following disclaimer in the 15219182Sglebius * documentation and/or other materials provided with the distribution. 16219182Sglebius * 4. Neither the name of the University nor the names of its contributors 17219182Sglebius * may be used to endorse or promote products derived from this software 18219182Sglebius * without specific prior written permission. 19219182Sglebius * 20219182Sglebius * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21219182Sglebius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22219182Sglebius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23219182Sglebius * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24219182Sglebius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25219182Sglebius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26219182Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27219182Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28219182Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29219182Sglebius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30219182Sglebius * SUCH DAMAGE. 31219182Sglebius */ 32219182Sglebius 33219182Sglebius#if defined(LIBC_SCCS) && !defined(lint) 34219182Sglebiusstatic char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; 35219182Sglebius#endif /* LIBC_SCCS and not lint */ 36219182Sglebius#include <sys/cdefs.h> 37219182Sglebius__FBSDID("$FreeBSD: head/lib/libc/stdio/vfprintf.c 187369 2009-01-17 18:57:12Z das $"); 38219182Sglebius 39219182Sglebius/* 40219182Sglebius * Actual printf innards. 41219182Sglebius * 42219182Sglebius * This code is large and complicated... 43219182Sglebius */ 44219182Sglebius 45219182Sglebius#include "namespace.h" 46219182Sglebius#include <sys/types.h> 47219182Sglebius 48219182Sglebius#include <ctype.h> 49219182Sglebius#include <limits.h> 50219182Sglebius#include <locale.h> 51219182Sglebius#include <stddef.h> 52219182Sglebius#include <stdint.h> 53219182Sglebius#include <stdio.h> 54219182Sglebius#include <stdlib.h> 55219182Sglebius#include <string.h> 56219182Sglebius#include <wchar.h> 57219182Sglebius#include <printf.h> 58219182Sglebius 59219182Sglebius#include <stdarg.h> 60219182Sglebius#include "un-namespace.h" 61219182Sglebius 62219182Sglebius#include "libc_private.h" 63219182Sglebius#include "local.h" 64219182Sglebius#include "fvwrite.h" 65219182Sglebius#include "printflocal.h" 66219182Sglebius 67219182Sglebiusstatic int __sprint(FILE *, struct __suio *); 68219182Sglebiusstatic int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0) 69219182Sglebius __noinline; 70219182Sglebiusstatic char *__wcsconv(wchar_t *, int); 71219182Sglebius 72219182Sglebius#define CHAR char 73219182Sglebius#include "printfcommon.h" 74219182Sglebius 75219182Sglebius/* 76219182Sglebius * Flush out all the vectors defined by the given uio, 77219182Sglebius * then reset it so that it can be reused. 78219182Sglebius */ 79219182Sglebiusstatic int 80219182Sglebius__sprint(FILE *fp, struct __suio *uio) 81219182Sglebius{ 82219182Sglebius int err; 83219182Sglebius 84219182Sglebius if (uio->uio_resid == 0) { 85219182Sglebius uio->uio_iovcnt = 0; 86219182Sglebius return (0); 87219182Sglebius } 88219182Sglebius err = __sfvwrite(fp, uio); 89219182Sglebius uio->uio_resid = 0; 90219182Sglebius uio->uio_iovcnt = 0; 91219182Sglebius return (err); 92219182Sglebius} 93219182Sglebius 94219182Sglebius/* 95219182Sglebius * Helper function for `fprintf to unbuffered unix file': creates a 96219182Sglebius * temporary buffer. We only work on write-only files; this avoids 97219182Sglebius * worries about ungetc buffers and so forth. 98219182Sglebius */ 99219182Sglebiusstatic int 100219182Sglebius__sbprintf(FILE *fp, const char *fmt, va_list ap) 101219182Sglebius{ 102219182Sglebius int ret; 103219182Sglebius FILE fake; 104219182Sglebius unsigned char buf[BUFSIZ]; 105219182Sglebius 106219182Sglebius /* XXX This is probably not needed. */ 107219182Sglebius if (prepwrite(fp) != 0) 108219182Sglebius return (EOF); 109219182Sglebius 110219182Sglebius /* copy the important variables */ 111219182Sglebius fake._flags = fp->_flags & ~__SNBF; 112219182Sglebius fake._file = fp->_file; 113219182Sglebius fake._cookie = fp->_cookie; 114219182Sglebius fake._write = fp->_write; 115219182Sglebius fake._orientation = fp->_orientation; 116219182Sglebius fake._mbstate = fp->_mbstate; 117219182Sglebius 118219182Sglebius /* set up the buffer */ 119219182Sglebius fake._bf._base = fake._p = buf; 120219182Sglebius fake._bf._size = fake._w = sizeof(buf); 121219182Sglebius fake._lbfsize = 0; /* not actually used, but Just In Case */ 122219182Sglebius 123219182Sglebius /* do the work, then copy any error status */ 124219182Sglebius ret = __vfprintf(&fake, fmt, ap); 125219182Sglebius if (ret >= 0 && __fflush(&fake)) 126219182Sglebius ret = EOF; 127219182Sglebius if (fake._flags & __SERR) 128219182Sglebius fp->_flags |= __SERR; 129219182Sglebius return (ret); 130219182Sglebius} 131219182Sglebius 132219182Sglebius/* 133219182Sglebius * Convert a wide character string argument for the %ls format to a multibyte 134219182Sglebius * string representation. If not -1, prec specifies the maximum number of 135219182Sglebius * bytes to output, and also means that we can't assume that the wide char. 136219182Sglebius * string ends is null-terminated. 137219182Sglebius */ 138219182Sglebiusstatic char * 139219182Sglebius__wcsconv(wchar_t *wcsarg, int prec) 140219182Sglebius{ 141219182Sglebius static const mbstate_t initial; 142219182Sglebius mbstate_t mbs; 143219182Sglebius char buf[MB_LEN_MAX]; 144219182Sglebius wchar_t *p; 145219182Sglebius char *convbuf; 146219182Sglebius size_t clen, nbytes; 147219182Sglebius 148219182Sglebius /* Allocate space for the maximum number of bytes we could output. */ 149219182Sglebius if (prec < 0) { 150219182Sglebius p = wcsarg; 151219182Sglebius mbs = initial; 152219182Sglebius nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs); 153219182Sglebius if (nbytes == (size_t)-1) 154219182Sglebius return (NULL); 155219182Sglebius } else { 156219182Sglebius /* 157219182Sglebius * Optimisation: if the output precision is small enough, 158219182Sglebius * just allocate enough memory for the maximum instead of 159219182Sglebius * scanning the string. 160219182Sglebius */ 161219182Sglebius if (prec < 128) 162219182Sglebius nbytes = prec; 163219182Sglebius else { 164219182Sglebius nbytes = 0; 165219182Sglebius p = wcsarg; 166219182Sglebius mbs = initial; 167219182Sglebius for (;;) { 168219182Sglebius clen = wcrtomb(buf, *p++, &mbs); 169219182Sglebius if (clen == 0 || clen == (size_t)-1 || 170219182Sglebius nbytes + clen > prec) 171219182Sglebius break; 172219182Sglebius nbytes += clen; 173219182Sglebius } 174219182Sglebius } 175219182Sglebius } 176219182Sglebius if ((convbuf = malloc(nbytes + 1)) == NULL) 177219182Sglebius return (NULL); 178219182Sglebius 179219182Sglebius /* Fill the output buffer. */ 180219182Sglebius p = wcsarg; 181219182Sglebius mbs = initial; 182219182Sglebius if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p, 183219182Sglebius nbytes, &mbs)) == (size_t)-1) { 184219182Sglebius free(convbuf); 185219182Sglebius return (NULL); 186219182Sglebius } 187219182Sglebius convbuf[nbytes] = '\0'; 188219182Sglebius return (convbuf); 189219182Sglebius} 190219182Sglebius 191219182Sglebius/* 192219182Sglebius * MT-safe version 193219182Sglebius */ 194219182Sglebiusint 195219182Sglebiusvfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) 196219182Sglebius 197219182Sglebius{ 198219182Sglebius int ret; 199219182Sglebius 200219182Sglebius FLOCKFILE(fp); 201219182Sglebius /* optimise fprintf(stderr) (and other unbuffered Unix files) */ 202219182Sglebius if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && 203219182Sglebius fp->_file >= 0) 204219182Sglebius ret = __sbprintf(fp, fmt0, ap); 205219182Sglebius else 206219182Sglebius ret = __vfprintf(fp, fmt0, ap); 207219182Sglebius FUNLOCKFILE(fp); 208219182Sglebius return (ret); 209219182Sglebius} 210219182Sglebius 211219182Sglebius/* 212219182Sglebius * The size of the buffer we use as scratch space for integer 213219182Sglebius * conversions, among other things. Technically, we would need the 214219182Sglebius * most space for base 10 conversions with thousands' grouping 215219182Sglebius * characters between each pair of digits. 100 bytes is a 216219182Sglebius * conservative overestimate even for a 128-bit uintmax_t. 217219182Sglebius */ 218219182Sglebius#define BUF 100 219219182Sglebius 220219182Sglebius/* 221219182Sglebius * Non-MT-safe version 222219182Sglebius */ 223219182Sglebiusint 224219182Sglebius__vfprintf(FILE *fp, const char *fmt0, va_list ap) 225238295Smelifaro{ 226219182Sglebius char *fmt; /* format string */ 227219182Sglebius int ch; /* character from fmt */ 228219182Sglebius int n, n2; /* handy integer (short term usage) */ 229219182Sglebius char *cp; /* handy char pointer (short term usage) */ 230219182Sglebius int flags; /* flags as above */ 231219182Sglebius int ret; /* return value accumulator */ 232219182Sglebius int width; /* width from format (%8d), or 0 */ 233219182Sglebius int prec; /* precision from format; <0 for N/A */ 234219182Sglebius char sign; /* sign prefix (' ', '+', '-', or \0) */ 235219182Sglebius char thousands_sep; /* locale specific thousands separator */ 236219182Sglebius const char *grouping; /* locale specific numeric grouping rules */ 237219182Sglebius 238219182Sglebius#ifndef NO_FLOATING_POINT 239219182Sglebius /* 240219182Sglebius * We can decompose the printed representation of floating 241219182Sglebius * point numbers into several parts, some of which may be empty: 242219182Sglebius * 243219182Sglebius * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ 244219182Sglebius * A B ---C--- D E F 245219182Sglebius * 246219182Sglebius * A: 'sign' holds this value if present; '\0' otherwise 247219182Sglebius * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal 248219182Sglebius * C: cp points to the string MMMNNN. Leading and trailing 249219182Sglebius * zeros are not in the string and must be added. 250219182Sglebius * D: expchar holds this character; '\0' if no exponent, e.g. %f 251219182Sglebius * F: at least two digits for decimal, at least one digit for hex 252219182Sglebius */ 253219182Sglebius char *decimal_point; /* locale specific decimal point */ 254219182Sglebius int signflag; /* true if float is negative */ 255219182Sglebius union { /* floating point arguments %[aAeEfFgG] */ 256219182Sglebius double dbl; 257219182Sglebius long double ldbl; 258219182Sglebius } fparg; 259219229Sbz int expt; /* integer value of exponent */ 260219182Sglebius char expchar; /* exponent character: [eEpP\0] */ 261219229Sbz char *dtoaend; /* pointer to end of converted digits */ 262219182Sglebius int expsize; /* character count for expstr */ 263219182Sglebius int lead; /* sig figs before decimal or group sep */ 264219182Sglebius int ndig; /* actual number of digits returned by dtoa */ 265219182Sglebius char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ 266219182Sglebius char *dtoaresult; /* buffer allocated by dtoa */ 267219182Sglebius int nseps; /* number of group separators with ' */ 268219182Sglebius int nrepeats; /* number of repeats of the last group */ 269219182Sglebius#endif 270219182Sglebius u_long ulval; /* integer arguments %[diouxX] */ 271219182Sglebius uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */ 272219182Sglebius int base; /* base for [diouxX] conversion */ 273219182Sglebius int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 274219182Sglebius int realsz; /* field size expanded by dprec, sign, etc */ 275219182Sglebius int size; /* size of converted field or string */ 276219182Sglebius int prsize; /* max size of printed field */ 277219182Sglebius const char *xdigs; /* digits for %[xX] conversion */ 278219182Sglebius struct io_state io; /* I/O buffering state */ 279219182Sglebius char buf[BUF]; /* buffer with space for digits of uintmax_t */ 280219182Sglebius char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */ 281219182Sglebius union arg *argtable; /* args, built due to positional arg */ 282219182Sglebius union arg statargtable [STATIC_ARG_TBL_SIZE]; 283219182Sglebius int nextarg; /* 1-based argument index */ 284219182Sglebius va_list orgap; /* original argument pointer */ 285219182Sglebius char *convbuf; /* wide to multibyte conversion result */ 286219182Sglebius 287219182Sglebius static const char xdigs_lower[16] = "0123456789abcdef"; 288219182Sglebius static const char xdigs_upper[16] = "0123456789ABCDEF"; 289219182Sglebius 290219182Sglebius /* BEWARE, these `goto error' on error. */ 291219182Sglebius#define PRINT(ptr, len) { \ 292219182Sglebius if (io_print(&io, (ptr), (len))) \ 293219182Sglebius goto error; \ 294219182Sglebius} 295219182Sglebius#define PAD(howmany, with) { \ 296219182Sglebius if (io_pad(&io, (howmany), (with))) \ 297219182Sglebius goto error; \ 298219182Sglebius} 299219182Sglebius#define PRINTANDPAD(p, ep, len, with) { \ 300219182Sglebius if (io_printandpad(&io, (p), (ep), (len), (with))) \ 301219182Sglebius goto error; \ 302219182Sglebius} 303219182Sglebius#define FLUSH() { \ 304219182Sglebius if (io_flush(&io)) \ 305219182Sglebius goto error; \ 306219182Sglebius} 307219182Sglebius 308219182Sglebius /* 309219182Sglebius * Get the argument indexed by nextarg. If the argument table is 310219182Sglebius * built, use it to get the argument. If its not, get the next 311219182Sglebius * argument (and arguments must be gotten sequentially). 312219182Sglebius */ 313219182Sglebius#define GETARG(type) \ 314219182Sglebius ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ 315219182Sglebius (nextarg++, va_arg(ap, type))) 316219182Sglebius 317219182Sglebius /* 318219182Sglebius * To extend shorts properly, we need both signed and unsigned 319219182Sglebius * argument extraction methods. 320219182Sglebius */ 321219182Sglebius#define SARG() \ 322219182Sglebius (flags&LONGINT ? GETARG(long) : \ 323219182Sglebius flags&SHORTINT ? (long)(short)GETARG(int) : \ 324219182Sglebius flags&CHARINT ? (long)(signed char)GETARG(int) : \ 325219182Sglebius (long)GETARG(int)) 326219182Sglebius#define UARG() \ 327219182Sglebius (flags&LONGINT ? GETARG(u_long) : \ 328219182Sglebius flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \ 329219182Sglebius flags&CHARINT ? (u_long)(u_char)GETARG(int) : \ 330219182Sglebius (u_long)GETARG(u_int)) 331219182Sglebius#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT) 332219182Sglebius#define SJARG() \ 333219182Sglebius (flags&INTMAXT ? GETARG(intmax_t) : \ 334219182Sglebius flags&SIZET ? (intmax_t)GETARG(size_t) : \ 335219182Sglebius flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \ 336219182Sglebius (intmax_t)GETARG(long long)) 337219182Sglebius#define UJARG() \ 338219182Sglebius (flags&INTMAXT ? GETARG(uintmax_t) : \ 339219182Sglebius flags&SIZET ? (uintmax_t)GETARG(size_t) : \ 340219182Sglebius flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \ 341219182Sglebius (uintmax_t)GETARG(unsigned long long)) 342219182Sglebius 343219182Sglebius /* 344219182Sglebius * Get * arguments, including the form *nn$. Preserve the nextarg 345219182Sglebius * that the argument can be gotten once the type is determined. 346219182Sglebius */ 347219182Sglebius#define GETASTER(val) \ 348219182Sglebius n2 = 0; \ 349219182Sglebius cp = fmt; \ 350219182Sglebius while (is_digit(*cp)) { \ 351219182Sglebius n2 = 10 * n2 + to_digit(*cp); \ 352219182Sglebius cp++; \ 353219182Sglebius } \ 354219182Sglebius if (*cp == '$') { \ 355219182Sglebius int hold = nextarg; \ 356219182Sglebius if (argtable == NULL) { \ 357219182Sglebius argtable = statargtable; \ 358219182Sglebius if (__find_arguments (fmt0, orgap, &argtable)) { \ 359219182Sglebius ret = EOF; \ 360219182Sglebius goto error; \ 361219182Sglebius } \ 362219182Sglebius } \ 363219182Sglebius nextarg = n2; \ 364219182Sglebius val = GETARG (int); \ 365219182Sglebius nextarg = hold; \ 366219182Sglebius fmt = ++cp; \ 367219182Sglebius } else { \ 368219182Sglebius val = GETARG (int); \ 369219182Sglebius } 370219182Sglebius 371219182Sglebius if (__use_xprintf == 0 && getenv("USE_XPRINTF")) 372219182Sglebius __use_xprintf = 1; 373219182Sglebius if (__use_xprintf > 0) 374219182Sglebius return (__xvprintf(fp, fmt0, ap)); 375219182Sglebius 376219182Sglebius /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ 377219182Sglebius if (prepwrite(fp) != 0) 378219182Sglebius return (EOF); 379219182Sglebius 380219182Sglebius thousands_sep = '\0'; 381219182Sglebius grouping = NULL; 382219182Sglebius convbuf = NULL; 383219182Sglebius fmt = (char *)fmt0; 384219182Sglebius argtable = NULL; 385219182Sglebius nextarg = 1; 386219182Sglebius va_copy(orgap, ap); 387219182Sglebius io_init(&io, fp); 388219182Sglebius ret = 0; 389219182Sglebius#ifndef NO_FLOATING_POINT 390219182Sglebius dtoaresult = NULL; 391219182Sglebius decimal_point = localeconv()->decimal_point; 392219182Sglebius#endif 393219182Sglebius 394219182Sglebius /* 395219182Sglebius * Scan the format for conversions (`%' character). 396219182Sglebius */ 397219182Sglebius for (;;) { 398219182Sglebius for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 399219182Sglebius /* void */; 400219182Sglebius if ((n = fmt - cp) != 0) { 401219182Sglebius if ((unsigned)ret + n > INT_MAX) { 402219182Sglebius ret = EOF; 403219182Sglebius goto error; 404219182Sglebius } 405219182Sglebius PRINT(cp, n); 406219182Sglebius ret += n; 407219182Sglebius } 408219182Sglebius if (ch == '\0') 409219182Sglebius goto done; 410219182Sglebius fmt++; /* skip over '%' */ 411219182Sglebius 412219182Sglebius flags = 0; 413219182Sglebius dprec = 0; 414219182Sglebius width = 0; 415219182Sglebius prec = -1; 416219182Sglebius sign = '\0'; 417219182Sglebius ox[1] = '\0'; 418219182Sglebius 419219182Sglebiusrflag: ch = *fmt++; 420219182Sglebiusreswitch: switch (ch) { 421238295Smelifaro case ' ': 422219182Sglebius /*- 423219182Sglebius * ``If the space and + flags both appear, the space 424238295Smelifaro * flag will be ignored.'' 425238295Smelifaro * -- ANSI X3J11 426238295Smelifaro */ 427219182Sglebius if (!sign) 428219182Sglebius sign = ' '; 429219182Sglebius goto rflag; 430219182Sglebius case '#': 431219182Sglebius flags |= ALT; 432219182Sglebius goto rflag; 433219182Sglebius case '*': 434219182Sglebius /*- 435219182Sglebius * ``A negative field width argument is taken as a 436219182Sglebius * - flag followed by a positive field width.'' 437219182Sglebius * -- ANSI X3J11 438219182Sglebius * They don't exclude field widths read from args. 439219182Sglebius */ 440219182Sglebius GETASTER (width); 441219182Sglebius if (width >= 0) 442219182Sglebius goto rflag; 443219182Sglebius width = -width; 444219182Sglebius /* FALLTHROUGH */ 445219182Sglebius case '-': 446219182Sglebius flags |= LADJUST; 447219182Sglebius goto rflag; 448219182Sglebius case '+': 449219182Sglebius sign = '+'; 450219182Sglebius goto rflag; 451219182Sglebius case '\'': 452219182Sglebius flags |= GROUPING; 453219182Sglebius thousands_sep = *(localeconv()->thousands_sep); 454219182Sglebius grouping = localeconv()->grouping; 455219182Sglebius goto rflag; 456219182Sglebius case '.': 457219182Sglebius if ((ch = *fmt++) == '*') { 458219182Sglebius GETASTER (prec); 459219182Sglebius goto rflag; 460219182Sglebius } 461219182Sglebius prec = 0; 462219182Sglebius while (is_digit(ch)) { 463219182Sglebius prec = 10 * prec + to_digit(ch); 464219182Sglebius ch = *fmt++; 465219182Sglebius } 466219182Sglebius goto reswitch; 467219182Sglebius case '0': 468219182Sglebius /*- 469219182Sglebius * ``Note that 0 is taken as a flag, not as the 470219182Sglebius * beginning of a field width.'' 471219182Sglebius * -- ANSI X3J11 472219182Sglebius */ 473219182Sglebius flags |= ZEROPAD; 474219182Sglebius goto rflag; 475219182Sglebius case '1': case '2': case '3': case '4': 476219182Sglebius case '5': case '6': case '7': case '8': case '9': 477219182Sglebius n = 0; 478219182Sglebius do { 479219182Sglebius n = 10 * n + to_digit(ch); 480219182Sglebius ch = *fmt++; 481219182Sglebius } while (is_digit(ch)); 482219182Sglebius if (ch == '$') { 483 nextarg = n; 484 if (argtable == NULL) { 485 argtable = statargtable; 486 if (__find_arguments (fmt0, orgap, 487 &argtable)) { 488 ret = EOF; 489 goto error; 490 } 491 } 492 goto rflag; 493 } 494 width = n; 495 goto reswitch; 496#ifndef NO_FLOATING_POINT 497 case 'L': 498 flags |= LONGDBL; 499 goto rflag; 500#endif 501 case 'h': 502 if (flags & SHORTINT) { 503 flags &= ~SHORTINT; 504 flags |= CHARINT; 505 } else 506 flags |= SHORTINT; 507 goto rflag; 508 case 'j': 509 flags |= INTMAXT; 510 goto rflag; 511 case 'l': 512 if (flags & LONGINT) { 513 flags &= ~LONGINT; 514 flags |= LLONGINT; 515 } else 516 flags |= LONGINT; 517 goto rflag; 518 case 'q': 519 flags |= LLONGINT; /* not necessarily */ 520 goto rflag; 521 case 't': 522 flags |= PTRDIFFT; 523 goto rflag; 524 case 'z': 525 flags |= SIZET; 526 goto rflag; 527 case 'C': 528 flags |= LONGINT; 529 /*FALLTHROUGH*/ 530 case 'c': 531 if (flags & LONGINT) { 532 static const mbstate_t initial; 533 mbstate_t mbs; 534 size_t mbseqlen; 535 536 mbs = initial; 537 mbseqlen = wcrtomb(cp = buf, 538 (wchar_t)GETARG(wint_t), &mbs); 539 if (mbseqlen == (size_t)-1) { 540 fp->_flags |= __SERR; 541 goto error; 542 } 543 size = (int)mbseqlen; 544 } else { 545 *(cp = buf) = GETARG(int); 546 size = 1; 547 } 548 sign = '\0'; 549 break; 550 case 'D': 551 flags |= LONGINT; 552 /*FALLTHROUGH*/ 553 case 'd': 554 case 'i': 555 if (flags & INTMAX_SIZE) { 556 ujval = SJARG(); 557 if ((intmax_t)ujval < 0) { 558 ujval = -ujval; 559 sign = '-'; 560 } 561 } else { 562 ulval = SARG(); 563 if ((long)ulval < 0) { 564 ulval = -ulval; 565 sign = '-'; 566 } 567 } 568 base = 10; 569 goto number; 570#ifndef NO_FLOATING_POINT 571 case 'a': 572 case 'A': 573 if (ch == 'a') { 574 ox[1] = 'x'; 575 xdigs = xdigs_lower; 576 expchar = 'p'; 577 } else { 578 ox[1] = 'X'; 579 xdigs = xdigs_upper; 580 expchar = 'P'; 581 } 582 if (prec >= 0) 583 prec++; 584 if (dtoaresult != NULL) 585 freedtoa(dtoaresult); 586 if (flags & LONGDBL) { 587 fparg.ldbl = GETARG(long double); 588 dtoaresult = cp = 589 __hldtoa(fparg.ldbl, xdigs, prec, 590 &expt, &signflag, &dtoaend); 591 } else { 592 fparg.dbl = GETARG(double); 593 dtoaresult = cp = 594 __hdtoa(fparg.dbl, xdigs, prec, 595 &expt, &signflag, &dtoaend); 596 } 597 if (prec < 0) 598 prec = dtoaend - cp; 599 if (expt == INT_MAX) 600 ox[1] = '\0'; 601 goto fp_common; 602 case 'e': 603 case 'E': 604 expchar = ch; 605 if (prec < 0) /* account for digit before decpt */ 606 prec = DEFPREC + 1; 607 else 608 prec++; 609 goto fp_begin; 610 case 'f': 611 case 'F': 612 expchar = '\0'; 613 goto fp_begin; 614 case 'g': 615 case 'G': 616 expchar = ch - ('g' - 'e'); 617 if (prec == 0) 618 prec = 1; 619fp_begin: 620 if (prec < 0) 621 prec = DEFPREC; 622 if (dtoaresult != NULL) 623 freedtoa(dtoaresult); 624 if (flags & LONGDBL) { 625 fparg.ldbl = GETARG(long double); 626 dtoaresult = cp = 627 __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, 628 &expt, &signflag, &dtoaend); 629 } else { 630 fparg.dbl = GETARG(double); 631 dtoaresult = cp = 632 dtoa(fparg.dbl, expchar ? 2 : 3, prec, 633 &expt, &signflag, &dtoaend); 634 if (expt == 9999) 635 expt = INT_MAX; 636 } 637fp_common: 638 if (signflag) 639 sign = '-'; 640 if (expt == INT_MAX) { /* inf or nan */ 641 if (*cp == 'N') { 642 cp = (ch >= 'a') ? "nan" : "NAN"; 643 sign = '\0'; 644 } else 645 cp = (ch >= 'a') ? "inf" : "INF"; 646 size = 3; 647 flags &= ~ZEROPAD; 648 break; 649 } 650 flags |= FPT; 651 ndig = dtoaend - cp; 652 if (ch == 'g' || ch == 'G') { 653 if (expt > -4 && expt <= prec) { 654 /* Make %[gG] smell like %[fF] */ 655 expchar = '\0'; 656 if (flags & ALT) 657 prec -= expt; 658 else 659 prec = ndig - expt; 660 if (prec < 0) 661 prec = 0; 662 } else { 663 /* 664 * Make %[gG] smell like %[eE], but 665 * trim trailing zeroes if no # flag. 666 */ 667 if (!(flags & ALT)) 668 prec = ndig; 669 } 670 } 671 if (expchar) { 672 expsize = exponent(expstr, expt - 1, expchar); 673 size = expsize + prec; 674 if (prec > 1 || flags & ALT) 675 ++size; 676 } else { 677 /* space for digits before decimal point */ 678 if (expt > 0) 679 size = expt; 680 else /* "0" */ 681 size = 1; 682 /* space for decimal pt and following digits */ 683 if (prec || flags & ALT) 684 size += prec + 1; 685 if (grouping && expt > 0) { 686 /* space for thousands' grouping */ 687 nseps = nrepeats = 0; 688 lead = expt; 689 while (*grouping != CHAR_MAX) { 690 if (lead <= *grouping) 691 break; 692 lead -= *grouping; 693 if (*(grouping+1)) { 694 nseps++; 695 grouping++; 696 } else 697 nrepeats++; 698 } 699 size += nseps + nrepeats; 700 } else 701 lead = expt; 702 } 703 break; 704#endif /* !NO_FLOATING_POINT */ 705 case 'n': 706 /* 707 * Assignment-like behavior is specified if the 708 * value overflows or is otherwise unrepresentable. 709 * C99 says to use `signed char' for %hhn conversions. 710 */ 711 if (flags & LLONGINT) 712 *GETARG(long long *) = ret; 713 else if (flags & SIZET) 714 *GETARG(ssize_t *) = (ssize_t)ret; 715 else if (flags & PTRDIFFT) 716 *GETARG(ptrdiff_t *) = ret; 717 else if (flags & INTMAXT) 718 *GETARG(intmax_t *) = ret; 719 else if (flags & LONGINT) 720 *GETARG(long *) = ret; 721 else if (flags & SHORTINT) 722 *GETARG(short *) = ret; 723 else if (flags & CHARINT) 724 *GETARG(signed char *) = ret; 725 else 726 *GETARG(int *) = ret; 727 continue; /* no output */ 728 case 'O': 729 flags |= LONGINT; 730 /*FALLTHROUGH*/ 731 case 'o': 732 if (flags & INTMAX_SIZE) 733 ujval = UJARG(); 734 else 735 ulval = UARG(); 736 base = 8; 737 goto nosign; 738 case 'p': 739 /*- 740 * ``The argument shall be a pointer to void. The 741 * value of the pointer is converted to a sequence 742 * of printable characters, in an implementation- 743 * defined manner.'' 744 * -- ANSI X3J11 745 */ 746 ujval = (uintmax_t)(uintptr_t)GETARG(void *); 747 base = 16; 748 xdigs = xdigs_lower; 749 flags = flags | INTMAXT; 750 ox[1] = 'x'; 751 goto nosign; 752 case 'S': 753 flags |= LONGINT; 754 /*FALLTHROUGH*/ 755 case 's': 756 if (flags & LONGINT) { 757 wchar_t *wcp; 758 759 if (convbuf != NULL) 760 free(convbuf); 761 if ((wcp = GETARG(wchar_t *)) == NULL) 762 cp = "(null)"; 763 else { 764 convbuf = __wcsconv(wcp, prec); 765 if (convbuf == NULL) { 766 fp->_flags |= __SERR; 767 goto error; 768 } 769 cp = convbuf; 770 } 771 } else if ((cp = GETARG(char *)) == NULL) 772 cp = "(null)"; 773 if (prec >= 0) { 774 /* 775 * can't use strlen; can only look for the 776 * NUL in the first `prec' characters, and 777 * strlen() will go further. 778 */ 779 char *p = memchr(cp, 0, (size_t)prec); 780 781 if (p != NULL) { 782 size = p - cp; 783 if (size > prec) 784 size = prec; 785 } else 786 size = prec; 787 } else 788 size = strlen(cp); 789 sign = '\0'; 790 break; 791 case 'U': 792 flags |= LONGINT; 793 /*FALLTHROUGH*/ 794 case 'u': 795 if (flags & INTMAX_SIZE) 796 ujval = UJARG(); 797 else 798 ulval = UARG(); 799 base = 10; 800 goto nosign; 801 case 'X': 802 xdigs = xdigs_upper; 803 goto hex; 804 case 'x': 805 xdigs = xdigs_lower; 806hex: 807 if (flags & INTMAX_SIZE) 808 ujval = UJARG(); 809 else 810 ulval = UARG(); 811 base = 16; 812 /* leading 0x/X only if non-zero */ 813 if (flags & ALT && 814 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) 815 ox[1] = ch; 816 817 flags &= ~GROUPING; 818 /* unsigned conversions */ 819nosign: sign = '\0'; 820 /*- 821 * ``... diouXx conversions ... if a precision is 822 * specified, the 0 flag will be ignored.'' 823 * -- ANSI X3J11 824 */ 825number: if ((dprec = prec) >= 0) 826 flags &= ~ZEROPAD; 827 828 /*- 829 * ``The result of converting a zero value with an 830 * explicit precision of zero is no characters.'' 831 * -- ANSI X3J11 832 * 833 * ``The C Standard is clear enough as is. The call 834 * printf("%#.0o", 0) should print 0.'' 835 * -- Defect Report #151 836 */ 837 cp = buf + BUF; 838 if (flags & INTMAX_SIZE) { 839 if (ujval != 0 || prec != 0 || 840 (flags & ALT && base == 8)) 841 cp = __ujtoa(ujval, cp, base, 842 flags & ALT, xdigs, 843 flags & GROUPING, thousands_sep, 844 grouping); 845 } else { 846 if (ulval != 0 || prec != 0 || 847 (flags & ALT && base == 8)) 848 cp = __ultoa(ulval, cp, base, 849 flags & ALT, xdigs, 850 flags & GROUPING, thousands_sep, 851 grouping); 852 } 853 size = buf + BUF - cp; 854 if (size > BUF) /* should never happen */ 855 abort(); 856 break; 857 default: /* "%?" prints ?, unless ? is NUL */ 858 if (ch == '\0') 859 goto done; 860 /* pretend it was %c with argument ch */ 861 cp = buf; 862 *cp = ch; 863 size = 1; 864 sign = '\0'; 865 break; 866 } 867 868 /* 869 * All reasonable formats wind up here. At this point, `cp' 870 * points to a string which (if not flags&LADJUST) should be 871 * padded out to `width' places. If flags&ZEROPAD, it should 872 * first be prefixed by any sign or other prefix; otherwise, 873 * it should be blank padded before the prefix is emitted. 874 * After any left-hand padding and prefixing, emit zeroes 875 * required by a decimal [diouxX] precision, then print the 876 * string proper, then emit zeroes required by any leftover 877 * floating precision; finally, if LADJUST, pad with blanks. 878 * 879 * Compute actual size, so we know how much to pad. 880 * size excludes decimal prec; realsz includes it. 881 */ 882 realsz = dprec > size ? dprec : size; 883 if (sign) 884 realsz++; 885 if (ox[1]) 886 realsz += 2; 887 888 prsize = width > realsz ? width : realsz; 889 if ((unsigned)ret + prsize > INT_MAX) { 890 ret = EOF; 891 goto error; 892 } 893 894 /* right-adjusting blank padding */ 895 if ((flags & (LADJUST|ZEROPAD)) == 0) 896 PAD(width - realsz, blanks); 897 898 /* prefix */ 899 if (sign) 900 PRINT(&sign, 1); 901 902 if (ox[1]) { /* ox[1] is either x, X, or \0 */ 903 ox[0] = '0'; 904 PRINT(ox, 2); 905 } 906 907 /* right-adjusting zero padding */ 908 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 909 PAD(width - realsz, zeroes); 910 911 /* leading zeroes from decimal precision */ 912 PAD(dprec - size, zeroes); 913 914 /* the string or number proper */ 915#ifndef NO_FLOATING_POINT 916 if ((flags & FPT) == 0) { 917 PRINT(cp, size); 918 } else { /* glue together f_p fragments */ 919 if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 920 if (expt <= 0) { 921 PRINT(zeroes, 1); 922 if (prec || flags & ALT) 923 PRINT(decimal_point, 1); 924 PAD(-expt, zeroes); 925 /* already handled initial 0's */ 926 prec += expt; 927 } else { 928 PRINTANDPAD(cp, dtoaend, lead, zeroes); 929 cp += lead; 930 if (grouping) { 931 while (nseps>0 || nrepeats>0) { 932 if (nrepeats > 0) 933 nrepeats--; 934 else { 935 grouping--; 936 nseps--; 937 } 938 PRINT(&thousands_sep, 939 1); 940 PRINTANDPAD(cp,dtoaend, 941 *grouping, zeroes); 942 cp += *grouping; 943 } 944 if (cp > dtoaend) 945 cp = dtoaend; 946 } 947 if (prec || flags & ALT) 948 PRINT(decimal_point,1); 949 } 950 PRINTANDPAD(cp, dtoaend, prec, zeroes); 951 } else { /* %[eE] or sufficiently long %[gG] */ 952 if (prec > 1 || flags & ALT) { 953 buf[0] = *cp++; 954 buf[1] = *decimal_point; 955 PRINT(buf, 2); 956 PRINT(cp, ndig-1); 957 PAD(prec - ndig, zeroes); 958 } else /* XeYYY */ 959 PRINT(cp, 1); 960 PRINT(expstr, expsize); 961 } 962 } 963#else 964 PRINT(cp, size); 965#endif 966 /* left-adjusting padding (always blank) */ 967 if (flags & LADJUST) 968 PAD(width - realsz, blanks); 969 970 /* finally, adjust ret */ 971 ret += prsize; 972 973 FLUSH(); /* copy out the I/O vectors */ 974 } 975done: 976 FLUSH(); 977error: 978 va_end(orgap); 979#ifndef NO_FLOATING_POINT 980 if (dtoaresult != NULL) 981 freedtoa(dtoaresult); 982#endif 983 if (convbuf != NULL) 984 free(convbuf); 985 if (__sferror(fp)) 986 ret = EOF; 987 if ((argtable != NULL) && (argtable != statargtable)) 988 free (argtable); 989 return (ret); 990 /* NOTREACHED */ 991} 992 993