1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Chris Torek. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#if defined(LIBC_SCCS) && !defined(lint) 34static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; 35#endif /* LIBC_SCCS and not lint */ 36#include <sys/cdefs.h> 37__FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.90 2009/02/28 06:06:57 das Exp $"); 38 39#include "xlocale_private.h" 40 41/* 42 * Actual printf innards. 43 * 44 * This code is large and complicated... 45 */ 46 47#include "namespace.h" 48#include <sys/types.h> 49 50#include <ctype.h> 51#include <limits.h> 52#include <locale.h> 53#include <stddef.h> 54#include <stdint.h> 55#include <stdio.h> 56#include <stdlib.h> 57#include <string.h> 58#include <wchar.h> 59#if 0 // xprintf pending API review 60#include <printf.h> 61#endif 62#include <errno.h> 63 64#include <stdarg.h> 65#include "un-namespace.h" 66 67#include "libc_private.h" 68#include "local.h" 69#include "fvwrite.h" 70#include "printflocal.h" 71 72static int __sprint(FILE *, locale_t, struct __suio *); 73#if 0 74static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0); 75#endif 76static char *__wcsconv(wchar_t *, int, locale_t); 77 78__private_extern__ const char *__fix_nogrouping(const char *); 79 80#define CHAR char 81#include "printfcommon.h" 82 83struct grouping_state { 84 char *thousands_sep; /* locale-specific thousands separator */ 85 int thousep_len; /* length of thousands_sep */ 86 const char *grouping; /* locale-specific numeric grouping rules */ 87 int lead; /* sig figs before decimal or group sep */ 88 int nseps; /* number of group separators with ' */ 89 int nrepeats; /* number of repeats of the last group */ 90}; 91 92/* 93 * Initialize the thousands' grouping state in preparation to print a 94 * number with ndigits digits. This routine returns the total number 95 * of bytes that will be needed. 96 */ 97static int 98grouping_init(struct grouping_state *gs, int ndigits, locale_t loc) 99{ 100 struct lconv *locale; 101 102 locale = localeconv_l(loc); 103 gs->grouping = __fix_nogrouping(locale->grouping); 104 gs->thousands_sep = locale->thousands_sep; 105 gs->thousep_len = strlen(gs->thousands_sep); 106 107 gs->nseps = gs->nrepeats = 0; 108 gs->lead = ndigits; 109 while (*gs->grouping != CHAR_MAX) { 110 if (gs->lead <= *gs->grouping) 111 break; 112 gs->lead -= *gs->grouping; 113 if (*(gs->grouping+1)) { 114 gs->nseps++; 115 gs->grouping++; 116 } else 117 gs->nrepeats++; 118 } 119 return ((gs->nseps + gs->nrepeats) * gs->thousep_len); 120} 121 122/* 123 * Print a number with thousands' separators. 124 */ 125static int 126grouping_print(struct grouping_state *gs, struct io_state *iop, 127 const CHAR *cp, const CHAR *ep, locale_t loc) 128{ 129 const CHAR *cp0 = cp; 130 131 if (io_printandpad(iop, cp, ep, gs->lead, zeroes, loc)) 132 return (-1); 133 cp += gs->lead; 134 while (gs->nseps > 0 || gs->nrepeats > 0) { 135 if (gs->nrepeats > 0) 136 gs->nrepeats--; 137 else { 138 gs->grouping--; 139 gs->nseps--; 140 } 141 if (io_print(iop, gs->thousands_sep, gs->thousep_len, loc)) 142 return (-1); 143 if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, loc)) 144 return (-1); 145 cp += *gs->grouping; 146 } 147 if (cp > ep) 148 cp = ep; 149 return (cp - cp0); 150} 151 152/* 153 * Flush out all the vectors defined by the given uio, 154 * then reset it so that it can be reused. 155 */ 156static int 157__sprint(FILE *fp, locale_t loc __unused, struct __suio *uio) 158{ 159 int err; 160 161 if (uio->uio_resid == 0) { 162 uio->uio_iovcnt = 0; 163 return (0); 164 } 165 err = __sfvwrite(fp, uio); 166 uio->uio_resid = 0; 167 uio->uio_iovcnt = 0; 168 return (err); 169} 170 171#if 0 172/* 173 * Helper function for `fprintf to unbuffered unix file': creates a 174 * temporary buffer. We only work on write-only files; this avoids 175 * worries about ungetc buffers and so forth. 176 */ 177static int 178__sbprintf(FILE *fp, locale_t loc, const char *fmt, va_list ap) 179{ 180 int ret; 181 FILE fake; 182 unsigned char buf[BUFSIZ]; 183 struct __sFILEX ext; 184 fake._extra = &ext; 185 INITEXTRA(&fake); 186 187 /* XXX This is probably not needed. */ 188 if (prepwrite(fp) != 0) 189 return (EOF); 190 191 /* copy the important variables */ 192 fake._flags = fp->_flags & ~__SNBF; 193 fake._file = fp->_file; 194 fake._cookie = fp->_cookie; 195 fake._write = fp->_write; 196 fake._orientation = fp->_orientation; 197 fake._mbstate = fp->_mbstate; 198 199 /* set up the buffer */ 200 fake._bf._base = fake._p = buf; 201 fake._bf._size = fake._w = sizeof(buf); 202 fake._lbfsize = 0; /* not actually used, but Just In Case */ 203 204 /* do the work, then copy any error status */ 205 ret = __vfprintf(&fake, loc, fmt, ap); 206 if (ret >= 0 && __fflush(&fake)) 207 ret = EOF; 208 if (fake._flags & __SERR) 209 fp->_flags |= __SERR; 210 return (ret); 211} 212#endif 213 214/* 215 * Convert a wide character string argument for the %ls format to a multibyte 216 * string representation. If not -1, prec specifies the maximum number of 217 * bytes to output, and also means that we can't assume that the wide char. 218 * string ends is null-terminated. 219 */ 220static char * 221__wcsconv(wchar_t *wcsarg, int prec, locale_t loc) 222{ 223 static const mbstate_t initial; 224 mbstate_t mbs; 225 char buf[MB_LEN_MAX]; 226 wchar_t *p; 227 char *convbuf; 228 size_t clen, nbytes; 229 230 /* Allocate space for the maximum number of bytes we could output. */ 231 if (prec < 0) { 232 p = wcsarg; 233 mbs = initial; 234 nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc); 235 if (nbytes == (size_t)-1) 236 return (NULL); 237 } else { 238 /* 239 * Optimisation: if the output precision is small enough, 240 * just allocate enough memory for the maximum instead of 241 * scanning the string. 242 */ 243 if (prec < 128) 244 nbytes = prec; 245 else { 246 nbytes = 0; 247 p = wcsarg; 248 mbs = initial; 249 for (;;) { 250 clen = wcrtomb_l(buf, *p++, &mbs, loc); 251 if (clen == 0 || clen == (size_t)-1 || 252 nbytes + clen > prec) 253 break; 254 nbytes += clen; 255 } 256 } 257 } 258 if ((convbuf = malloc(nbytes + 1)) == NULL) 259 return (NULL); 260 261 /* Fill the output buffer. */ 262 p = wcsarg; 263 mbs = initial; 264 if ((nbytes = wcsrtombs_l(convbuf, (const wchar_t **)&p, 265 nbytes, &mbs, loc)) == (size_t)-1) { 266 free(convbuf); 267 return (NULL); 268 } 269 convbuf[nbytes] = '\0'; 270 return (convbuf); 271} 272 273/* 274 * MT-safe version 275 */ 276int 277vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, va_list ap) 278 279{ 280 int ret; 281 282 FLOCKFILE(fp); 283 ret = __xvprintf(XPRINTF_PLAIN, NULL, fp, loc, fmt0, ap); 284 FUNLOCKFILE(fp); 285 return (ret); 286} 287 288int 289vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) 290 291{ 292 int ret; 293 294 FLOCKFILE(fp); 295 ret = __xvprintf(XPRINTF_PLAIN, NULL, fp, __current_locale(), fmt0, ap); 296 FUNLOCKFILE(fp); 297 return ret; 298} 299 300/* 301 * The size of the buffer we use as scratch space for integer 302 * conversions, among other things. We need enough space to 303 * write a uintmax_t in octal (plus one byte). 304 */ 305#if UINTMAX_MAX <= UINT64_MAX 306#define BUF 32 307#else 308#error "BUF must be large enough to format a uintmax_t" 309#endif 310 311/* 312 * Non-MT-safe version 313 */ 314__private_extern__ int 315__vfprintf(FILE *fp, locale_t loc, const char *fmt0, va_list ap) 316{ 317 char *fmt; /* format string */ 318 int ch; /* character from fmt */ 319 int n, n2; /* handy integer (short term usage) */ 320 char *cp; /* handy char pointer (short term usage) */ 321 int flags; /* flags as above */ 322 int ret; /* return value accumulator */ 323 int width; /* width from format (%8d), or 0 */ 324 int prec; /* precision from format; <0 for N/A */ 325 char sign; /* sign prefix (' ', '+', '-', or \0) */ 326 struct grouping_state gs; /* thousands' grouping info */ 327 328#ifndef NO_FLOATING_POINT 329 /* 330 * We can decompose the printed representation of floating 331 * point numbers into several parts, some of which may be empty: 332 * 333 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ 334 * A B ---C--- D E F 335 * 336 * A: 'sign' holds this value if present; '\0' otherwise 337 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal 338 * C: cp points to the string MMMNNN. Leading and trailing 339 * zeros are not in the string and must be added. 340 * D: expchar holds this character; '\0' if no exponent, e.g. %f 341 * F: at least two digits for decimal, at least one digit for hex 342 */ 343 char *decimal_point; /* locale specific decimal point */ 344 int decpt_len; /* length of decimal_point */ 345 int signflag; /* true if float is negative */ 346 union { /* floating point arguments %[aAeEfFgG] */ 347 double dbl; 348 long double ldbl; 349 } fparg; 350 int expt; /* integer value of exponent */ 351 char expchar; /* exponent character: [eEpP\0] */ 352 char *dtoaend; /* pointer to end of converted digits */ 353 int expsize; /* character count for expstr */ 354 int ndig; /* actual number of digits returned by dtoa */ 355 char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ 356 char *dtoaresult; /* buffer allocated by dtoa */ 357#endif 358#ifdef VECTORS 359 union arg vval; /* Vector argument. */ 360 char *pct; /* Pointer to '%' at beginning of specifier. */ 361 char vsep; /* Vector separator character. */ 362#endif 363 u_long ulval; /* integer arguments %[diouxX] */ 364 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */ 365 int base; /* base for [diouxX] conversion */ 366 int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 367 int realsz; /* field size expanded by dprec, sign, etc */ 368 int size; /* size of converted field or string */ 369 int prsize; /* max size of printed field */ 370 const char *xdigs; /* digits for %[xX] conversion */ 371 struct io_state io; /* I/O buffering state */ 372 char buf[BUF]; /* buffer with space for digits of uintmax_t */ 373 char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */ 374 union arg *argtable; /* args, built due to positional arg */ 375 union arg statargtable [STATIC_ARG_TBL_SIZE]; 376 int nextarg; /* 1-based argument index */ 377 va_list orgap; /* original argument pointer */ 378 char *convbuf; /* wide to multibyte conversion result */ 379 380 static const char xdigs_lower[16] = "0123456789abcdef"; 381 static const char xdigs_upper[16] = "0123456789ABCDEF"; 382 383 /* BEWARE, these `goto error' on error. */ 384#define PRINT(ptr, len) { \ 385 if (io_print(&io, (ptr), (len), loc)) \ 386 goto error; \ 387} 388#define PAD(howmany, with) { \ 389 if (io_pad(&io, (howmany), (with), loc)) \ 390 goto error; \ 391} 392#define PRINTANDPAD(p, ep, len, with) { \ 393 if (io_printandpad(&io, (p), (ep), (len), (with), loc)) \ 394 goto error; \ 395} 396#define FLUSH() { \ 397 if (io_flush(&io, loc)) \ 398 goto error; \ 399} 400 401 /* 402 * Get the argument indexed by nextarg. If the argument table is 403 * built, use it to get the argument. If its not, get the next 404 * argument (and arguments must be gotten sequentially). 405 */ 406#define GETARG(type) \ 407 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ 408 (nextarg++, va_arg(ap, type))) 409 410 /* 411 * To extend shorts properly, we need both signed and unsigned 412 * argument extraction methods. 413 */ 414#define SARG() \ 415 (flags&LONGINT ? GETARG(long) : \ 416 flags&SHORTINT ? (long)(short)GETARG(int) : \ 417 flags&CHARINT ? (long)(signed char)GETARG(int) : \ 418 (long)GETARG(int)) 419#define UARG() \ 420 (flags&LONGINT ? GETARG(u_long) : \ 421 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \ 422 flags&CHARINT ? (u_long)(u_char)GETARG(int) : \ 423 (u_long)GETARG(u_int)) 424#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT) 425#define SJARG() \ 426 (flags&INTMAXT ? GETARG(intmax_t) : \ 427 flags&SIZET ? (intmax_t)GETARG(ssize_t) : \ 428 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \ 429 (intmax_t)GETARG(long long)) 430#define UJARG() \ 431 (flags&INTMAXT ? GETARG(uintmax_t) : \ 432 flags&SIZET ? (uintmax_t)GETARG(size_t) : \ 433 flags&PTRDIFFT ? (uintmax_t)(unsigned long)GETARG(ptrdiff_t) : \ 434 (uintmax_t)GETARG(unsigned long long)) 435 436 /* 437 * Get * arguments, including the form *nn$. Preserve the nextarg 438 * that the argument can be gotten once the type is determined. 439 */ 440#define GETASTER(val) \ 441 n2 = 0; \ 442 cp = fmt; \ 443 while (is_digit(*cp)) { \ 444 n2 = 10 * n2 + to_digit(*cp); \ 445 cp++; \ 446 } \ 447 if (*cp == '$') { \ 448 int hold = nextarg; \ 449 if (argtable == NULL) { \ 450 argtable = statargtable; \ 451 if (__find_arguments (fmt0, orgap, &argtable)) { \ 452 ret = EOF; \ 453 goto error; \ 454 } \ 455 } \ 456 nextarg = n2; \ 457 val = GETARG (int); \ 458 nextarg = hold; \ 459 fmt = ++cp; \ 460 } else { \ 461 val = GETARG (int); \ 462 } 463 464 /* The following has been moved to __v2printf() */ 465#if 0 466 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ 467 if (prepwrite(fp) != 0) { 468 errno = EBADF; 469 return (EOF); 470 } 471 ORIENT(fp, -1); 472#endif 473 474 convbuf = NULL; 475 fmt = (char *)fmt0; 476 argtable = NULL; 477 nextarg = 1; 478 va_copy(orgap, ap); 479 io_init(&io, fp); 480 ret = 0; 481#ifndef NO_FLOATING_POINT 482 dtoaresult = NULL; 483 decimal_point = localeconv_l(loc)->decimal_point; 484 /* The overwhelmingly common case is decpt_len == 1. */ 485 decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point)); 486#endif 487 488 /* 489 * Scan the format for conversions (`%' character). 490 */ 491 for (;;) { 492 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 493 /* void */; 494 if ((n = fmt - cp) != 0) { 495 if ((unsigned)ret + n > INT_MAX) { 496 ret = EOF; 497 goto error; 498 } 499 PRINT(cp, n); 500 ret += n; 501 } 502 if (ch == '\0') 503 goto done; 504#ifdef VECTORS 505 pct = fmt; 506#endif /* VECTORS */ 507 fmt++; /* skip over '%' */ 508 509 flags = 0; 510 dprec = 0; 511 width = 0; 512 prec = -1; 513 gs.grouping = NULL; 514 sign = '\0'; 515 ox[1] = '\0'; 516#ifdef VECTORS 517 vsep = 'X'; /* Illegal value, changed to defaults later. */ 518#endif /* VECTORS */ 519 520rflag: ch = *fmt++; 521reswitch: switch (ch) { 522 case ' ': 523 /*- 524 * ``If the space and + flags both appear, the space 525 * flag will be ignored.'' 526 * -- ANSI X3J11 527 */ 528 if (!sign) 529 sign = ' '; 530 goto rflag; 531 case '#': 532 flags |= ALT; 533 goto rflag; 534#ifdef VECTORS 535 case ',': case ';': case ':': case '_': 536 vsep = ch; 537 goto rflag; 538#endif /* VECTORS */ 539 case '*': 540 /*- 541 * ``A negative field width argument is taken as a 542 * - flag followed by a positive field width.'' 543 * -- ANSI X3J11 544 * They don't exclude field widths read from args. 545 */ 546 GETASTER (width); 547 if (width >= 0) 548 goto rflag; 549 width = -width; 550 /* FALLTHROUGH */ 551 case '-': 552 flags |= LADJUST; 553 goto rflag; 554 case '+': 555 sign = '+'; 556 goto rflag; 557 case '\'': 558 flags |= GROUPING; 559 goto rflag; 560 case '.': 561 if ((ch = *fmt++) == '*') { 562 GETASTER (prec); 563 goto rflag; 564 } 565 prec = 0; 566 while (is_digit(ch)) { 567 prec = 10 * prec + to_digit(ch); 568 ch = *fmt++; 569 } 570 goto reswitch; 571 case '0': 572 /*- 573 * ``Note that 0 is taken as a flag, not as the 574 * beginning of a field width.'' 575 * -- ANSI X3J11 576 */ 577 flags |= ZEROPAD; 578 goto rflag; 579 case '1': case '2': case '3': case '4': 580 case '5': case '6': case '7': case '8': case '9': 581 n = 0; 582 do { 583 n = 10 * n + to_digit(ch); 584 ch = *fmt++; 585 } while (is_digit(ch)); 586 if (ch == '$') { 587 nextarg = n; 588 if (argtable == NULL) { 589 argtable = statargtable; 590 if (__find_arguments (fmt0, orgap, 591 &argtable)) { 592 ret = EOF; 593 goto error; 594 } 595 } 596 goto rflag; 597 } 598 width = n; 599 goto reswitch; 600#ifndef NO_FLOATING_POINT 601 case 'L': 602 flags |= LONGDBL; 603 goto rflag; 604#endif 605 case 'h': 606 if (flags & SHORTINT) { 607 flags &= ~SHORTINT; 608 flags |= CHARINT; 609 } else 610 flags |= SHORTINT; 611 goto rflag; 612 case 'j': 613 flags |= INTMAXT; 614 goto rflag; 615 case 'l': 616 if (flags & LONGINT) { 617 flags &= ~LONGINT; 618 flags |= LLONGINT; 619 } else 620 flags |= LONGINT; 621 goto rflag; 622 case 'q': 623 flags |= LLONGINT; /* not necessarily */ 624 goto rflag; 625 case 't': 626 flags |= PTRDIFFT; 627 goto rflag; 628 case 'z': 629 flags |= SIZET; 630 goto rflag; 631 case 'C': 632 flags |= LONGINT; 633 /*FALLTHROUGH*/ 634 case 'c': 635#ifdef VECTORS 636 if (flags & VECTOR) 637 break; 638#endif /* VECTORS */ 639 if (flags & LONGINT) { 640 static const mbstate_t initial; 641 mbstate_t mbs; 642 size_t mbseqlen; 643 644 mbs = initial; 645 mbseqlen = wcrtomb_l(cp = buf, 646 (wchar_t)GETARG(wint_t), &mbs, loc); 647 if (mbseqlen == (size_t)-1) { 648 fp->_flags |= __SERR; 649 goto error; 650 } 651 size = (int)mbseqlen; 652 } else { 653 *(cp = buf) = GETARG(int); 654 size = 1; 655 } 656 sign = '\0'; 657 break; 658 case 'D': 659 flags |= LONGINT; 660 /*FALLTHROUGH*/ 661 case 'd': 662 case 'i': 663#ifdef VECTORS 664 if (flags & VECTOR) 665 break; 666#endif /* VECTORS */ 667 if (flags & INTMAX_SIZE) { 668 ujval = SJARG(); 669 if ((intmax_t)ujval < 0) { 670 ujval = -ujval; 671 sign = '-'; 672 } 673 } else { 674 ulval = SARG(); 675 if ((long)ulval < 0) { 676 ulval = -ulval; 677 sign = '-'; 678 } 679 } 680 base = 10; 681 goto number; 682#ifndef NO_FLOATING_POINT 683 case 'a': 684 case 'A': 685#ifdef VECTORS 686 if (flags & VECTOR) { 687 flags |= FPT; 688 break; 689 } 690#endif /* VECTORS */ 691 if (ch == 'a') { 692 ox[1] = 'x'; 693 xdigs = xdigs_lower; 694 expchar = 'p'; 695 } else { 696 ox[1] = 'X'; 697 xdigs = xdigs_upper; 698 expchar = 'P'; 699 } 700 if (prec >= 0) 701 prec++; 702 if (dtoaresult != NULL) 703 freedtoa(dtoaresult); 704 if (flags & LONGDBL) { 705 fparg.ldbl = GETARG(long double); 706 dtoaresult = cp = 707 __hldtoa(fparg.ldbl, xdigs, prec, 708 &expt, &signflag, &dtoaend); 709 } else { 710 fparg.dbl = GETARG(double); 711 dtoaresult = cp = 712 __hdtoa(fparg.dbl, xdigs, prec, 713 &expt, &signflag, &dtoaend); 714 } 715 if (prec < 0) 716 prec = dtoaend - cp; 717 if (expt == INT_MAX) 718 ox[1] = '\0'; 719 goto fp_common; 720 case 'e': 721 case 'E': 722#ifdef VECTORS 723 if (flags & VECTOR) { 724 flags |= FPT; 725 break; 726 } 727#endif /* VECTORS */ 728 expchar = ch; 729 if (prec < 0) /* account for digit before decpt */ 730 prec = DEFPREC + 1; 731 else 732 prec++; 733 goto fp_begin; 734 case 'f': 735 case 'F': 736#ifdef VECTORS 737 if (flags & VECTOR) { 738 flags |= FPT; 739 break; 740 } 741#endif /* VECTORS */ 742 expchar = '\0'; 743 goto fp_begin; 744 case 'g': 745 case 'G': 746#ifdef VECTORS 747 if (flags & VECTOR) { 748 flags |= FPT; 749 break; 750 } 751#endif /* VECTORS */ 752 expchar = ch - ('g' - 'e'); 753 if (prec == 0) 754 prec = 1; 755fp_begin: 756 if (prec < 0) 757 prec = DEFPREC; 758 if (dtoaresult != NULL) 759 freedtoa(dtoaresult); 760 if (flags & LONGDBL) { 761 fparg.ldbl = GETARG(long double); 762 dtoaresult = cp = 763 __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, 764 &expt, &signflag, &dtoaend); 765 } else { 766 fparg.dbl = GETARG(double); 767 dtoaresult = cp = 768 dtoa(fparg.dbl, expchar ? 2 : 3, prec, 769 &expt, &signflag, &dtoaend); 770 if (expt == 9999) 771 expt = INT_MAX; 772 } 773fp_common: 774 if (signflag) 775 sign = '-'; 776 if (expt == INT_MAX) { /* inf or nan */ 777 if (*cp == 'N') { 778 cp = (ch >= 'a') ? "nan" : "NAN"; 779 sign = '\0'; 780 } else 781 cp = (ch >= 'a') ? "inf" : "INF"; 782 size = 3; 783 flags &= ~ZEROPAD; 784 break; 785 } 786 flags |= FPT; 787 ndig = dtoaend - cp; 788 if (ch == 'g' || ch == 'G') { 789 if (expt > -4 && expt <= prec) { 790 /* Make %[gG] smell like %[fF] */ 791 expchar = '\0'; 792 if (flags & ALT) 793 prec -= expt; 794 else 795 prec = ndig - expt; 796 if (prec < 0) 797 prec = 0; 798 } else { 799 /* 800 * Make %[gG] smell like %[eE], but 801 * trim trailing zeroes if no # flag. 802 */ 803 if (!(flags & ALT)) 804 prec = ndig; 805 } 806 } 807 if (expchar) { 808 expsize = exponent(expstr, expt - 1, expchar); 809 size = expsize + prec; 810 if (prec > 1 || flags & ALT) 811 size += decpt_len; 812 } else { 813 /* space for digits before decimal point */ 814 if (expt > 0) 815 size = expt; 816 else /* "0" */ 817 size = 1; 818 /* space for decimal pt and following digits */ 819 if (prec || flags & ALT) 820 size += prec + decpt_len; 821 if ((flags & GROUPING) && expt > 0) 822 size += grouping_init(&gs, expt, loc); 823 } 824 break; 825#endif /* !NO_FLOATING_POINT */ 826 case 'n': 827 { 828 /* 829 * Assignment-like behavior is specified if the 830 * value overflows or is otherwise unrepresentable. 831 * C99 says to use `signed char' for %hhn conversions. 832 */ 833 void *ptr = GETARG(void *); 834 if (ptr == NULL) 835 continue; 836 else if (flags & LLONGINT) 837 *(long long *)ptr = ret; 838 else if (flags & SIZET) 839 *(ssize_t *)ptr = (ssize_t)ret; 840 else if (flags & PTRDIFFT) 841 *(ptrdiff_t *)ptr = ret; 842 else if (flags & INTMAXT) 843 *(intmax_t *)ptr = ret; 844 else if (flags & LONGINT) 845 *(long *)ptr = ret; 846 else if (flags & SHORTINT) 847 *(short *)ptr = ret; 848 else if (flags & CHARINT) 849 *(signed char *)ptr = ret; 850 else 851 *(int *)ptr = ret; 852 continue; /* no output */ 853 } 854 case 'O': 855 flags |= LONGINT; 856 /*FALLTHROUGH*/ 857 case 'o': 858#ifdef VECTORS 859 if (flags & VECTOR) 860 break; 861#endif /* VECTORS */ 862 if (flags & INTMAX_SIZE) 863 ujval = UJARG(); 864 else 865 ulval = UARG(); 866 base = 8; 867 goto nosign; 868 case 'p': 869 /*- 870 * ``The argument shall be a pointer to void. The 871 * value of the pointer is converted to a sequence 872 * of printable characters, in an implementation- 873 * defined manner.'' 874 * -- ANSI X3J11 875 */ 876#ifdef VECTORS 877 if (flags & VECTOR) 878 break; 879#endif /* VECTORS */ 880 ujval = (uintmax_t)(uintptr_t)GETARG(void *); 881 base = 16; 882 xdigs = xdigs_lower; 883 flags = flags | INTMAXT; 884 ox[1] = 'x'; 885 goto nosign; 886 case 'S': 887 flags |= LONGINT; 888 /*FALLTHROUGH*/ 889 case 's': 890 if (flags & LONGINT) { 891 wchar_t *wcp; 892 893 if (convbuf != NULL) 894 free(convbuf); 895 if ((wcp = GETARG(wchar_t *)) == NULL) 896 cp = "(null)"; 897 else { 898 convbuf = __wcsconv(wcp, prec, loc); 899 if (convbuf == NULL) { 900 fp->_flags |= __SERR; 901 goto error; 902 } 903 cp = convbuf; 904 } 905 } else if ((cp = GETARG(char *)) == NULL) 906 cp = "(null)"; 907 size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp); 908 sign = '\0'; 909 break; 910 case 'U': 911 flags |= LONGINT; 912 /*FALLTHROUGH*/ 913 case 'u': 914#ifdef VECTORS 915 if (flags & VECTOR) 916 break; 917#endif /* VECTORS */ 918 if (flags & INTMAX_SIZE) 919 ujval = UJARG(); 920 else 921 ulval = UARG(); 922 base = 10; 923 goto nosign; 924 case 'X': 925 xdigs = xdigs_upper; 926 goto hex; 927 case 'x': 928 xdigs = xdigs_lower; 929hex: 930#ifdef VECTORS 931 if (flags & VECTOR) 932 break; 933#endif /* VECTORS */ 934 if (flags & INTMAX_SIZE) 935 ujval = UJARG(); 936 else 937 ulval = UARG(); 938 base = 16; 939 /* leading 0x/X only if non-zero */ 940 if (flags & ALT && 941 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) 942 ox[1] = ch; 943 944 flags &= ~GROUPING; 945 /* unsigned conversions */ 946nosign: sign = '\0'; 947 /*- 948 * ``... diouXx conversions ... if a precision is 949 * specified, the 0 flag will be ignored.'' 950 * -- ANSI X3J11 951 * except for %#.0o and zero value 952 */ 953number: if ((dprec = prec) >= 0) 954 flags &= ~ZEROPAD; 955 956 /*- 957 * ``The result of converting a zero value with an 958 * explicit precision of zero is no characters.'' 959 * -- ANSI X3J11 960 * 961 * ``The C Standard is clear enough as is. The call 962 * printf("%#.0o", 0) should print 0.'' 963 * -- Defect Report #151 964 */ 965 cp = buf + BUF; 966 if (flags & INTMAX_SIZE) { 967 if (ujval != 0 || prec != 0 || 968 (flags & ALT && base == 8)) 969 cp = __ujtoa(ujval, cp, base, 970 flags & ALT, xdigs); 971 } else { 972 if (ulval != 0 || prec != 0 || 973 (flags & ALT && base == 8)) 974 cp = __ultoa(ulval, cp, base, 975 flags & ALT, xdigs); 976 } 977 size = buf + BUF - cp; 978 if (size > BUF) /* should never happen */ 979 LIBC_ABORT("size (%d) > BUF (%d)", size, BUF); 980 if ((flags & GROUPING) && size != 0) 981 size += grouping_init(&gs, size, loc); 982 break; 983#ifdef VECTORS 984 case 'v': 985 flags |= VECTOR; 986 goto rflag; 987#endif /* VECTORS */ 988 default: /* "%?" prints ?, unless ? is NUL */ 989 if (ch == '\0') 990 goto done; 991 /* pretend it was %c with argument ch */ 992 cp = buf; 993 *cp = ch; 994 size = 1; 995 sign = '\0'; 996 break; 997 } 998 999#ifdef VECTORS 1000 if (flags & VECTOR) { 1001 /* 1002 * Do the minimum amount of work necessary to construct 1003 * a format specifier that can be used to recursively 1004 * call vfprintf() for each element in the vector. 1005 */ 1006 int i, j; /* Counter. */ 1007 int vcnt; /* Number of elements in vector. */ 1008 char *vfmt; /* Pointer to format specifier. */ 1009#define EXTRAHH 2 1010 char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */ 1011 int vwidth = 0; /* Width specified via '*'. */ 1012 int vprec = 0; /* Precision specified via '*'. */ 1013 char *vstr; /* Used for asprintf(). */ 1014 int vlen; /* Length returned by asprintf(). */ 1015 enum { 1016 V_CHAR, V_SHORT, V_INT, 1017 V_PCHAR, V_PSHORT, V_PINT, 1018 V_FLOAT, 1019#ifdef V64TYPE 1020 V_LONGLONG, V_PLONGLONG, 1021 V_DOUBLE, 1022#endif /* V64TYPE */ 1023 } vtype; 1024 1025 vval.vectorarg = GETARG(VECTORTYPE); 1026 /* 1027 * Set vfmt. If vfmt_buf may not be big enough, 1028 * malloc() space, taking care to free it later. 1029 * (EXTRAHH is for possible extra "hh") 1030 */ 1031 if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf)) 1032 vfmt = vfmt_buf; 1033 else 1034 vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1); 1035 1036 /* Set the separator character, if not specified. */ 1037 if (vsep == 'X') { 1038 if (ch == 'c') 1039 vsep = '\0'; 1040 else 1041 vsep = ' '; 1042 } 1043 1044 /* Create the format specifier. */ 1045 for (i = j = 0; i < &fmt[-1] - pct; i++) { 1046 switch (pct[i]) { 1047 case ',': case ';': case ':': case '_': 1048 case 'v': case 'h': case 'l': 1049 /* Ignore. */ 1050 break; 1051 case '*': 1052 if (pct[i - 1] != '.') 1053 vwidth = 1; 1054 else 1055 vprec = 1; 1056 /* FALLTHROUGH */ 1057 default: 1058 vfmt[j++] = pct[i]; 1059 } 1060 } 1061 1062 /* 1063 * Determine the number of elements in the vector and 1064 * finish up the format specifier. 1065 */ 1066 if (flags & SHORTINT) { 1067 switch (ch) { 1068 case 'c': 1069 vtype = V_SHORT; 1070 break; 1071 case 'p': 1072 vtype = V_PSHORT; 1073 break; 1074 default: 1075 vfmt[j++] = 'h'; 1076 vtype = V_SHORT; 1077 break; 1078 } 1079 vcnt = 8; 1080 } else if (flags & LONGINT) { 1081 vcnt = 4; 1082 vtype = (ch == 'p') ? V_PINT : V_INT; 1083#ifdef V64TYPE 1084 } else if (flags & LLONGINT) { 1085 switch (ch) { 1086 case 'a': 1087 case 'A': 1088 case 'e': 1089 case 'E': 1090 case 'f': 1091 case 'g': 1092 case 'G': 1093 vcnt = 2; 1094 vtype = V_DOUBLE; 1095 break; 1096 case 'd': 1097 case 'i': 1098 case 'u': 1099 case 'o': 1100 case 'p': 1101 case 'x': 1102 case 'X': 1103 vfmt[j++] = 'l'; 1104 vfmt[j++] = 'l'; 1105 vcnt = 2; 1106 vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG; 1107 break; 1108 default: 1109 /* 1110 * The default case should never 1111 * happen. 1112 */ 1113 case 'c': 1114 vcnt = 16; 1115 vtype = V_CHAR; 1116 } 1117#endif /* V64TYPE */ 1118 } else { 1119 switch (ch) { 1120 case 'a': 1121 case 'A': 1122 case 'e': 1123 case 'E': 1124 case 'f': 1125 case 'g': 1126 case 'G': 1127 vcnt = 4; 1128 vtype = V_FLOAT; 1129 break; 1130 default: 1131 /* 1132 * The default case should never 1133 * happen. 1134 */ 1135 case 'd': 1136 case 'i': 1137 case 'u': 1138 case 'o': 1139 case 'x': 1140 case 'X': 1141 vfmt[j++] = 'h'; 1142 vfmt[j++] = 'h'; 1143 /* drop through */ 1144 case 'p': 1145 case 'c': 1146 vcnt = 16; 1147 vtype = (ch == 'p') ? V_PCHAR : V_CHAR; 1148 } 1149 } 1150 vfmt[j++] = ch; 1151 vfmt[j++] = '\0'; 1152 1153/* Get a vector element. */ 1154#ifdef V64TYPE 1155#define VPRINT(type, ind, args...) do { \ 1156 switch (type) { \ 1157 case V_CHAR: \ 1158 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \ 1159 break; \ 1160 case V_PCHAR: \ 1161 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \ 1162 break; \ 1163 case V_SHORT: \ 1164 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \ 1165 break; \ 1166 case V_PSHORT: \ 1167 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \ 1168 break; \ 1169 case V_INT: \ 1170 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \ 1171 break; \ 1172 case V_PINT: \ 1173 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \ 1174 break; \ 1175 case V_LONGLONG: \ 1176 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \ 1177 break; \ 1178 case V_PLONGLONG: \ 1179 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \ 1180 break; \ 1181 case V_FLOAT: \ 1182 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \ 1183 break; \ 1184 case V_DOUBLE: \ 1185 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \ 1186 break; \ 1187 } \ 1188 ret += vlen; \ 1189 PRINT(vstr, vlen); \ 1190 FLUSH(); \ 1191 free(vstr); \ 1192} while (0) 1193#else /* !V64TYPE */ 1194#define VPRINT(type, ind, args...) do { \ 1195 switch (type) { \ 1196 case V_CHAR: \ 1197 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \ 1198 break; \ 1199 case V_PCHAR: \ 1200 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \ 1201 break; \ 1202 case V_SHORT: \ 1203 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \ 1204 break; \ 1205 case V_PSHORT: \ 1206 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \ 1207 break; \ 1208 case V_INT: \ 1209 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \ 1210 break; \ 1211 case V_PINT: \ 1212 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \ 1213 break; \ 1214 case V_FLOAT: \ 1215 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \ 1216 break; \ 1217 } \ 1218 ret += vlen; \ 1219 PRINT(vstr, vlen); \ 1220 FLUSH(); \ 1221 free(vstr); \ 1222} while (0) 1223#endif /* V64TYPE */ 1224 1225 /* Actually print. */ 1226 if (vwidth == 0) { 1227 if (vprec == 0) { 1228 /* First element. */ 1229 VPRINT(vtype, 0); 1230 for (i = 1; i < vcnt; i++) { 1231 /* Separator. */ 1232 if(vsep) 1233 PRINT(&vsep, 1); 1234 1235 /* Element. */ 1236 VPRINT(vtype, i); 1237 } 1238 } else { 1239 /* First element. */ 1240 VPRINT(vtype, 0, prec); 1241 for (i = 1; i < vcnt; i++) { 1242 /* Separator. */ 1243 if(vsep) 1244 PRINT(&vsep, 1); 1245 1246 /* Element. */ 1247 VPRINT(vtype, i, prec); 1248 } 1249 } 1250 } else { 1251 if (vprec == 0) { 1252 /* First element. */ 1253 VPRINT(vtype, 0, width); 1254 for (i = 1; i < vcnt; i++) { 1255 /* Separator. */ 1256 if(vsep) 1257 PRINT(&vsep, 1); 1258 1259 /* Element. */ 1260 VPRINT(vtype, i, width); 1261 } 1262 } else { 1263 /* First element. */ 1264 VPRINT(vtype, 0, width, prec); 1265 for (i = 1; i < vcnt; i++) { 1266 /* Separator. */ 1267 if(vsep) 1268 PRINT(&vsep, 1); 1269 1270 /* Element. */ 1271 VPRINT(vtype, i, width, prec); 1272 } 1273 } 1274 } 1275#undef VPRINT 1276 1277 if (vfmt != vfmt_buf) 1278 free(vfmt); 1279 1280 continue; 1281 } 1282#endif /* VECTORS */ 1283 /* 1284 * All reasonable formats wind up here. At this point, `cp' 1285 * points to a string which (if not flags&LADJUST) should be 1286 * padded out to `width' places. If flags&ZEROPAD, it should 1287 * first be prefixed by any sign or other prefix; otherwise, 1288 * it should be blank padded before the prefix is emitted. 1289 * After any left-hand padding and prefixing, emit zeroes 1290 * required by a decimal [diouxX] precision, then print the 1291 * string proper, then emit zeroes required by any leftover 1292 * floating precision; finally, if LADJUST, pad with blanks. 1293 * 1294 * Compute actual size, so we know how much to pad. 1295 * size excludes decimal prec; realsz includes it. 1296 */ 1297 realsz = dprec > size ? dprec : size; 1298 if (sign) 1299 realsz++; 1300 if (ox[1]) 1301 realsz += 2; 1302 1303 prsize = width > realsz ? width : realsz; 1304 if ((unsigned)ret + prsize > INT_MAX) { 1305 ret = EOF; 1306 goto error; 1307 } 1308 1309 /* right-adjusting blank padding */ 1310 if ((flags & (LADJUST|ZEROPAD)) == 0) 1311 PAD(width - realsz, blanks); 1312 1313 /* prefix */ 1314 if (sign) 1315 PRINT(&sign, 1); 1316 1317 if (ox[1]) { /* ox[1] is either x, X, or \0 */ 1318 ox[0] = '0'; 1319 PRINT(ox, 2); 1320 } 1321 1322 /* right-adjusting zero padding */ 1323 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 1324 PAD(width - realsz, zeroes); 1325 1326 /* the string or number proper */ 1327#ifndef NO_FLOATING_POINT 1328 if ((flags & FPT) == 0) { 1329#endif 1330 /* leading zeroes from decimal precision */ 1331 PAD(dprec - size, zeroes); 1332 if (gs.grouping) { 1333 if (grouping_print(&gs, &io, cp, buf+BUF, loc) < 0) 1334 goto error; 1335 } else { 1336 PRINT(cp, size); 1337 } 1338#ifndef NO_FLOATING_POINT 1339 } else { /* glue together f_p fragments */ 1340 if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 1341 if (expt <= 0) { 1342 PRINT(zeroes, 1); 1343 if (prec || flags & ALT) 1344 PRINT(decimal_point,decpt_len); 1345 PAD(-expt, zeroes); 1346 /* already handled initial 0's */ 1347 prec += expt; 1348 } else { 1349 if (gs.grouping) { 1350 n = grouping_print(&gs, &io, 1351 cp, dtoaend, loc); 1352 if (n < 0) 1353 goto error; 1354 cp += n; 1355 } else { 1356 PRINTANDPAD(cp, dtoaend, 1357 expt, zeroes); 1358 cp += expt; 1359 } 1360 if (prec || flags & ALT) 1361 PRINT(decimal_point,decpt_len); 1362 } 1363 PRINTANDPAD(cp, dtoaend, prec, zeroes); 1364 } else { /* %[eE] or sufficiently long %[gG] */ 1365 if (prec > 1 || flags & ALT) { 1366 PRINT(cp++, 1); 1367 PRINT(decimal_point, decpt_len); 1368 PRINT(cp, ndig-1); 1369 PAD(prec - ndig, zeroes); 1370 } else /* XeYYY */ 1371 PRINT(cp, 1); 1372 PRINT(expstr, expsize); 1373 } 1374 } 1375#endif 1376 /* left-adjusting padding (always blank) */ 1377 if (flags & LADJUST) 1378 PAD(width - realsz, blanks); 1379 1380 /* finally, adjust ret */ 1381 ret += prsize; 1382 1383 FLUSH(); /* copy out the I/O vectors */ 1384 } 1385done: 1386 FLUSH(); 1387error: 1388 va_end(orgap); 1389#ifndef NO_FLOATING_POINT 1390 if (dtoaresult != NULL) 1391 freedtoa(dtoaresult); 1392#endif 1393 if (convbuf != NULL) 1394 free(convbuf); 1395 if (__sferror(fp)) 1396 ret = EOF; 1397 if ((argtable != NULL) && (argtable != statargtable)) 1398 free (argtable); 1399 return (ret); 1400 /* NOTREACHED */ 1401} 1402 1403