1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Chris Torek. 9 * 10 * Copyright (c) 2011 The FreeBSD Foundation 11 * 12 * Portions of this software were developed by David Chisnall 13 * under sponsorship from the FreeBSD Foundation. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 */ 39 40 #if 0 41 #if defined(LIBC_SCCS) && !defined(lint) 42 static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; 43 #endif /* LIBC_SCCS and not lint */ 44 #endif 45 /* 46 * Actual wprintf innards. 47 * 48 * Avoid making gratuitous changes to this source file; it should be kept 49 * as close as possible to vfprintf.c for ease of maintenance. 50 */ 51 52 #include "namespace.h" 53 #include <sys/types.h> 54 55 #include <ctype.h> 56 #include <errno.h> 57 #include <limits.h> 58 #include <locale.h> 59 #include <stdarg.h> 60 #include <stddef.h> 61 #include <stdint.h> 62 #include <stdio.h> 63 #include <stdlib.h> 64 #include <string.h> 65 #include <wchar.h> 66 #include <wctype.h> 67 #include "un-namespace.h" 68 69 #include "libc_private.h" 70 #include "local.h" 71 #include "fvwrite.h" 72 #include "printflocal.h" 73 #include "xlocale_private.h" 74 75 static int __sprint(FILE *, struct __suio *, locale_t); 76 static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list) __noinline; 77 static wint_t __xfputwc(wchar_t, FILE *, locale_t); 78 static wchar_t *__mbsconv(char *, int); 79 80 #define CHAR wchar_t 81 #include "printfcommon.h" 82 83 struct grouping_state { 84 wchar_t thousands_sep; /* locale-specific thousands separator */ 85 const char *grouping; /* locale-specific numeric grouping rules */ 86 int lead; /* sig figs before decimal or group sep */ 87 int nseps; /* number of group separators with ' */ 88 int nrepeats; /* number of repeats of the last group */ 89 }; 90 91 static const mbstate_t initial_mbs; 92 93 static inline wchar_t 94 get_decpt(locale_t locale) 95 { 96 mbstate_t mbs; 97 wchar_t decpt; 98 int nconv; 99 100 mbs = initial_mbs; 101 nconv = mbrtowc(&decpt, localeconv_l(locale)->decimal_point, MB_CUR_MAX, &mbs); 102 if (nconv == (size_t)-1 || nconv == (size_t)-2) 103 decpt = '.'; /* failsafe */ 104 return (decpt); 105 } 106 107 static inline wchar_t 108 get_thousep(locale_t locale) 109 { 110 mbstate_t mbs; 111 wchar_t thousep; 112 int nconv; 113 114 mbs = initial_mbs; 115 nconv = mbrtowc(&thousep, localeconv_l(locale)->thousands_sep, 116 MB_CUR_MAX, &mbs); 117 if (nconv == (size_t)-1 || nconv == (size_t)-2) 118 thousep = '\0'; /* failsafe */ 119 return (thousep); 120 } 121 122 /* 123 * Initialize the thousands' grouping state in preparation to print a 124 * number with ndigits digits. This routine returns the total number 125 * of wide characters that will be printed. 126 */ 127 static int 128 grouping_init(struct grouping_state *gs, int ndigits, locale_t locale) 129 { 130 131 gs->grouping = localeconv_l(locale)->grouping; 132 gs->thousands_sep = get_thousep(locale); 133 134 gs->nseps = gs->nrepeats = 0; 135 gs->lead = ndigits; 136 while (*gs->grouping != CHAR_MAX) { 137 if (gs->lead <= *gs->grouping) 138 break; 139 gs->lead -= *gs->grouping; 140 if (*(gs->grouping+1)) { 141 gs->nseps++; 142 gs->grouping++; 143 } else 144 gs->nrepeats++; 145 } 146 return (gs->nseps + gs->nrepeats); 147 } 148 149 /* 150 * Print a number with thousands' separators. 151 */ 152 static int 153 grouping_print(struct grouping_state *gs, struct io_state *iop, 154 const CHAR *cp, const CHAR *ep, locale_t locale) 155 { 156 const CHAR *cp0 = cp; 157 158 if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) 159 return (-1); 160 cp += gs->lead; 161 while (gs->nseps > 0 || gs->nrepeats > 0) { 162 if (gs->nrepeats > 0) 163 gs->nrepeats--; 164 else { 165 gs->grouping--; 166 gs->nseps--; 167 } 168 if (io_print(iop, &gs->thousands_sep, 1, locale)) 169 return (-1); 170 if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) 171 return (-1); 172 cp += *gs->grouping; 173 } 174 if (cp > ep) 175 cp = ep; 176 return (cp - cp0); 177 } 178 179 180 /* 181 * Flush out all the vectors defined by the given uio, 182 * then reset it so that it can be reused. 183 * 184 * XXX The fact that we do this a character at a time and convert to a 185 * multibyte character sequence even if the destination is a wide 186 * string eclipses the benefits of buffering. 187 */ 188 static int 189 __sprint(FILE *fp, struct __suio *uio, locale_t locale) 190 { 191 struct __siov *iov; 192 wchar_t *p; 193 int i, len; 194 195 iov = uio->uio_iov; 196 for (; uio->uio_resid != 0; uio->uio_resid -= len, iov++) { 197 p = (wchar_t *)iov->iov_base; 198 len = iov->iov_len; 199 for (i = 0; i < len; i++) { 200 if (__xfputwc(p[i], fp, locale) == WEOF) 201 return (-1); 202 } 203 } 204 uio->uio_iovcnt = 0; 205 return (0); 206 } 207 208 /* 209 * Helper function for `fprintf to unbuffered unix file': creates a 210 * temporary buffer. We only work on write-only files; this avoids 211 * worries about ungetc buffers and so forth. 212 */ 213 static int 214 __sbprintf(FILE *fp, locale_t locale, const wchar_t *fmt, va_list ap) 215 { 216 int ret; 217 FILE fake; 218 unsigned char buf[BUFSIZ]; 219 220 /* XXX This is probably not needed. */ 221 if (prepwrite(fp) != 0) 222 return (EOF); 223 224 /* copy the important variables */ 225 fake._flags = fp->_flags & ~__SNBF; 226 fake._file = fp->_file; 227 fake._cookie = fp->_cookie; 228 fake._write = fp->_write; 229 fake._orientation = fp->_orientation; 230 fake._mbstate = fp->_mbstate; 231 232 /* set up the buffer */ 233 fake._bf._base = fake._p = buf; 234 fake._bf._size = fake._w = sizeof(buf); 235 fake._lbfsize = 0; /* not actually used, but Just In Case */ 236 237 /* do the work, then copy any error status */ 238 ret = __vfwprintf(&fake, locale, fmt, ap); 239 if (ret >= 0 && __fflush(&fake)) 240 ret = WEOF; 241 if (fake._flags & __SERR) 242 fp->_flags |= __SERR; 243 return (ret); 244 } 245 246 /* 247 * Like __fputwc, but handles fake string (__SSTR) files properly. 248 * File must already be locked. 249 */ 250 static wint_t 251 __xfputwc(wchar_t wc, FILE *fp, locale_t locale) 252 { 253 mbstate_t mbs; 254 char buf[MB_LEN_MAX]; 255 struct __suio uio; 256 struct __siov iov; 257 size_t len; 258 259 if ((fp->_flags & __SSTR) == 0) 260 return (__fputwc(wc, fp, locale)); 261 262 mbs = initial_mbs; 263 if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) { 264 fp->_flags |= __SERR; 265 return (WEOF); 266 } 267 uio.uio_iov = &iov; 268 uio.uio_resid = len; 269 uio.uio_iovcnt = 1; 270 iov.iov_base = buf; 271 iov.iov_len = len; 272 return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF); 273 } 274 275 /* 276 * Convert a multibyte character string argument for the %s format to a wide 277 * string representation. ``prec'' specifies the maximum number of bytes 278 * to output. If ``prec'' is greater than or equal to zero, we can't assume 279 * that the multibyte char. string ends in a null character. 280 */ 281 static wchar_t * 282 __mbsconv(char *mbsarg, int prec) 283 { 284 mbstate_t mbs; 285 wchar_t *convbuf, *wcp; 286 const char *p; 287 size_t insize, nchars, nconv; 288 289 if (mbsarg == NULL) 290 return (NULL); 291 292 /* 293 * Supplied argument is a multibyte string; convert it to wide 294 * characters first. 295 */ 296 if (prec >= 0) { 297 /* 298 * String is not guaranteed to be NUL-terminated. Find the 299 * number of characters to print. 300 */ 301 p = mbsarg; 302 insize = nchars = nconv = 0; 303 mbs = initial_mbs; 304 while (nchars != (size_t)prec) { 305 nconv = mbrlen(p, MB_CUR_MAX, &mbs); 306 if (nconv == 0 || nconv == (size_t)-1 || 307 nconv == (size_t)-2) 308 break; 309 p += nconv; 310 nchars++; 311 insize += nconv; 312 } 313 if (nconv == (size_t)-1 || nconv == (size_t)-2) 314 return (NULL); 315 } else { 316 insize = strlen(mbsarg); 317 nconv = 0; 318 } 319 320 /* 321 * Allocate buffer for the result and perform the conversion, 322 * converting at most `size' bytes of the input multibyte string to 323 * wide characters for printing. 324 */ 325 convbuf = malloc((insize + 1) * sizeof(*convbuf)); 326 if (convbuf == NULL) 327 return (NULL); 328 wcp = convbuf; 329 p = mbsarg; 330 mbs = initial_mbs; 331 while (insize != 0) { 332 nconv = mbrtowc(wcp, p, insize, &mbs); 333 if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2) 334 break; 335 wcp++; 336 p += nconv; 337 insize -= nconv; 338 } 339 if (nconv == (size_t)-1 || nconv == (size_t)-2) { 340 free(convbuf); 341 return (NULL); 342 } 343 *wcp = L'\0'; 344 345 return (convbuf); 346 } 347 348 /* 349 * MT-safe version 350 */ 351 int 352 vfwprintf_l(FILE * __restrict fp, locale_t locale, 353 const wchar_t * __restrict fmt0, va_list ap) 354 355 { 356 int ret; 357 FIX_LOCALE(locale); 358 FLOCKFILE_CANCELSAFE(fp); 359 /* optimise fprintf(stderr) (and other unbuffered Unix files) */ 360 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && 361 fp->_file >= 0) 362 ret = __sbprintf(fp, locale, fmt0, ap); 363 else 364 ret = __vfwprintf(fp, locale, fmt0, ap); 365 FUNLOCKFILE_CANCELSAFE(); 366 return (ret); 367 } 368 int 369 vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) 370 { 371 return vfwprintf_l(fp, __get_locale(), fmt0, ap); 372 } 373 374 /* 375 * The size of the buffer we use as scratch space for integer 376 * conversions, among other things. We need enough space to 377 * write a uintmax_t in octal (plus one byte). 378 */ 379 #if UINTMAX_MAX <= UINT64_MAX 380 #define BUF 32 381 #else 382 #error "BUF must be large enough to format a uintmax_t" 383 #endif 384 385 /* 386 * Non-MT-safe version 387 */ 388 int 389 __vfwprintf(FILE *fp, locale_t locale, const wchar_t *fmt0, va_list ap) 390 { 391 wchar_t *fmt; /* format string */ 392 wchar_t ch; /* character from fmt */ 393 int n, n2; /* handy integer (short term usage) */ 394 wchar_t *cp; /* handy char pointer (short term usage) */ 395 int flags; /* flags as above */ 396 int ret; /* return value accumulator */ 397 int width; /* width from format (%8d), or 0 */ 398 int prec; /* precision from format; <0 for N/A */ 399 wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */ 400 struct grouping_state gs; /* thousands' grouping info */ 401 #ifndef NO_FLOATING_POINT 402 /* 403 * We can decompose the printed representation of floating 404 * point numbers into several parts, some of which may be empty: 405 * 406 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ 407 * A B ---C--- D E F 408 * 409 * A: 'sign' holds this value if present; '\0' otherwise 410 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal 411 * C: cp points to the string MMMNNN. Leading and trailing 412 * zeros are not in the string and must be added. 413 * D: expchar holds this character; '\0' if no exponent, e.g. %f 414 * F: at least two digits for decimal, at least one digit for hex 415 */ 416 wchar_t decimal_point; /* locale specific decimal point */ 417 int signflag; /* true if float is negative */ 418 union { /* floating point arguments %[aAeEfFgG] */ 419 double dbl; 420 long double ldbl; 421 } fparg; 422 int expt; /* integer value of exponent */ 423 char expchar; /* exponent character: [eEpP\0] */ 424 char *dtoaend; /* pointer to end of converted digits */ 425 int expsize; /* character count for expstr */ 426 int ndig; /* actual number of digits returned by dtoa */ 427 wchar_t expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ 428 char *dtoaresult; /* buffer allocated by dtoa */ 429 #endif 430 u_long ulval; /* integer arguments %[diouxX] */ 431 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */ 432 int base; /* base for [diouxX] conversion */ 433 int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 434 int realsz; /* field size expanded by dprec, sign, etc */ 435 int size; /* size of converted field or string */ 436 int prsize; /* max size of printed field */ 437 const char *xdigs; /* digits for [xX] conversion */ 438 struct io_state io; /* I/O buffering state */ 439 wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */ 440 wchar_t ox[2]; /* space for 0x hex-prefix */ 441 union arg *argtable; /* args, built due to positional arg */ 442 union arg statargtable [STATIC_ARG_TBL_SIZE]; 443 int nextarg; /* 1-based argument index */ 444 va_list orgap; /* original argument pointer */ 445 wchar_t *convbuf; /* multibyte to wide conversion result */ 446 int savserr; 447 448 static const char xdigs_lower[16] = "0123456789abcdef"; 449 static const char xdigs_upper[16] = "0123456789ABCDEF"; 450 451 /* BEWARE, these `goto error' on error. */ 452 #define PRINT(ptr, len) do { \ 453 if (io_print(&io, (ptr), (len), locale)) \ 454 goto error; \ 455 } while (0) 456 #define PAD(howmany, with) { \ 457 if (io_pad(&io, (howmany), (with), locale)) \ 458 goto error; \ 459 } 460 #define PRINTANDPAD(p, ep, len, with) { \ 461 if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ 462 goto error; \ 463 } 464 #define FLUSH() { \ 465 if (io_flush(&io, locale)) \ 466 goto error; \ 467 } 468 469 /* 470 * Get the argument indexed by nextarg. If the argument table is 471 * built, use it to get the argument. If its not, get the next 472 * argument (and arguments must be gotten sequentially). 473 */ 474 #define GETARG(type) \ 475 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ 476 (nextarg++, va_arg(ap, type))) 477 478 /* 479 * To extend shorts properly, we need both signed and unsigned 480 * argument extraction methods. 481 */ 482 #define SARG() \ 483 (flags&LONGINT ? GETARG(long) : \ 484 flags&SHORTINT ? (long)(short)GETARG(int) : \ 485 flags&CHARINT ? (long)(signed char)GETARG(int) : \ 486 (long)GETARG(int)) 487 #define UARG() \ 488 (flags&LONGINT ? GETARG(u_long) : \ 489 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \ 490 flags&CHARINT ? (u_long)(u_char)GETARG(int) : \ 491 (u_long)GETARG(u_int)) 492 #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT) 493 #define SJARG() \ 494 (flags&INTMAXT ? GETARG(intmax_t) : \ 495 flags&SIZET ? (intmax_t)GETARG(ssize_t) : \ 496 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \ 497 (intmax_t)GETARG(long long)) 498 #define UJARG() \ 499 (flags&INTMAXT ? GETARG(uintmax_t) : \ 500 flags&SIZET ? (uintmax_t)GETARG(size_t) : \ 501 flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \ 502 (uintmax_t)GETARG(unsigned long long)) 503 504 /* 505 * Get * arguments, including the form *nn$. Preserve the nextarg 506 * that the argument can be gotten once the type is determined. 507 */ 508 #define GETASTER(val) \ 509 n2 = 0; \ 510 cp = fmt; \ 511 while (is_digit(*cp)) { \ 512 n2 = 10 * n2 + to_digit(*cp); \ 513 cp++; \ 514 } \ 515 if (*cp == '$') { \ 516 int hold = nextarg; \ 517 if (argtable == NULL) { \ 518 argtable = statargtable; \ 519 if (__find_warguments (fmt0, orgap, &argtable)) { \ 520 ret = EOF; \ 521 goto error; \ 522 } \ 523 } \ 524 nextarg = n2; \ 525 val = GETARG (int); \ 526 nextarg = hold; \ 527 fmt = ++cp; \ 528 } else { \ 529 val = GETARG (int); \ 530 } 531 532 533 /* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */ 534 if (prepwrite(fp) != 0) { 535 errno = EBADF; 536 return (EOF); 537 } 538 539 savserr = fp->_flags & __SERR; 540 fp->_flags &= ~__SERR; 541 542 convbuf = NULL; 543 fmt = (wchar_t *)fmt0; 544 argtable = NULL; 545 nextarg = 1; 546 va_copy(orgap, ap); 547 io_init(&io, fp); 548 ret = 0; 549 #ifndef NO_FLOATING_POINT 550 decimal_point = get_decpt(locale); 551 #endif 552 553 /* 554 * Scan the format for conversions (`%' character). 555 */ 556 for (;;) { 557 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 558 /* void */; 559 if ((n = fmt - cp) != 0) { 560 if ((unsigned)ret + n > INT_MAX) { 561 ret = EOF; 562 errno = EOVERFLOW; 563 goto error; 564 } 565 PRINT(cp, n); 566 ret += n; 567 } 568 if (ch == '\0') 569 goto done; 570 fmt++; /* skip over '%' */ 571 572 flags = 0; 573 dprec = 0; 574 width = 0; 575 prec = -1; 576 gs.grouping = NULL; 577 sign = '\0'; 578 ox[1] = '\0'; 579 580 rflag: ch = *fmt++; 581 reswitch: switch (ch) { 582 case ' ': 583 /*- 584 * ``If the space and + flags both appear, the space 585 * flag will be ignored.'' 586 * -- ANSI X3J11 587 */ 588 if (!sign) 589 sign = ' '; 590 goto rflag; 591 case '#': 592 flags |= ALT; 593 goto rflag; 594 case '*': 595 /*- 596 * ``A negative field width argument is taken as a 597 * - flag followed by a positive field width.'' 598 * -- ANSI X3J11 599 * They don't exclude field widths read from args. 600 */ 601 GETASTER (width); 602 if (width >= 0) 603 goto rflag; 604 width = -width; 605 /* FALLTHROUGH */ 606 case '-': 607 flags |= LADJUST; 608 goto rflag; 609 case '+': 610 sign = '+'; 611 goto rflag; 612 case '\'': 613 flags |= GROUPING; 614 goto rflag; 615 case '.': 616 if ((ch = *fmt++) == '*') { 617 GETASTER (prec); 618 goto rflag; 619 } 620 prec = 0; 621 while (is_digit(ch)) { 622 prec = 10 * prec + to_digit(ch); 623 ch = *fmt++; 624 } 625 goto reswitch; 626 case '0': 627 /*- 628 * ``Note that 0 is taken as a flag, not as the 629 * beginning of a field width.'' 630 * -- ANSI X3J11 631 */ 632 flags |= ZEROPAD; 633 goto rflag; 634 case '1': case '2': case '3': case '4': 635 case '5': case '6': case '7': case '8': case '9': 636 n = 0; 637 do { 638 n = 10 * n + to_digit(ch); 639 ch = *fmt++; 640 } while (is_digit(ch)); 641 if (ch == '$') { 642 nextarg = n; 643 if (argtable == NULL) { 644 argtable = statargtable; 645 if (__find_warguments (fmt0, orgap, 646 &argtable)) { 647 ret = EOF; 648 goto error; 649 } 650 } 651 goto rflag; 652 } 653 width = n; 654 goto reswitch; 655 #ifndef NO_FLOATING_POINT 656 case 'L': 657 flags |= LONGDBL; 658 goto rflag; 659 #endif 660 case 'h': 661 if (flags & SHORTINT) { 662 flags &= ~SHORTINT; 663 flags |= CHARINT; 664 } else 665 flags |= SHORTINT; 666 goto rflag; 667 case 'j': 668 flags |= INTMAXT; 669 goto rflag; 670 case 'l': 671 if (flags & LONGINT) { 672 flags &= ~LONGINT; 673 flags |= LLONGINT; 674 } else 675 flags |= LONGINT; 676 goto rflag; 677 case 'q': 678 flags |= LLONGINT; /* not necessarily */ 679 goto rflag; 680 case 't': 681 flags |= PTRDIFFT; 682 goto rflag; 683 case 'w': 684 /* 685 * Fixed-width integer types. On all platforms we 686 * support, int8_t is equivalent to char, int16_t 687 * is equivalent to short, int32_t is equivalent 688 * to int, int64_t is equivalent to long long int. 689 * Furthermore, int_fast8_t, int_fast16_t and 690 * int_fast32_t are equivalent to int, and 691 * int_fast64_t is equivalent to long long int. 692 */ 693 flags &= ~(CHARINT|SHORTINT|LONGINT|LLONGINT|INTMAXT); 694 if (fmt[0] == 'f') { 695 flags |= FASTINT; 696 fmt++; 697 } else { 698 flags &= ~FASTINT; 699 } 700 if (fmt[0] == '8') { 701 if (!(flags & FASTINT)) 702 flags |= CHARINT; 703 else 704 /* no flag set = 32 */ ; 705 fmt += 1; 706 } else if (fmt[0] == '1' && fmt[1] == '6') { 707 if (!(flags & FASTINT)) 708 flags |= SHORTINT; 709 else 710 /* no flag set = 32 */ ; 711 fmt += 2; 712 } else if (fmt[0] == '3' && fmt[1] == '2') { 713 /* no flag set = 32 */ ; 714 fmt += 2; 715 } else if (fmt[0] == '6' && fmt[1] == '4') { 716 flags |= LLONGINT; 717 fmt += 2; 718 } else { 719 if (flags & FASTINT) { 720 flags &= ~FASTINT; 721 fmt--; 722 } 723 goto invalid; 724 } 725 goto rflag; 726 case 'z': 727 flags |= SIZET; 728 goto rflag; 729 case 'B': 730 case 'b': 731 if (flags & INTMAX_SIZE) 732 ujval = UJARG(); 733 else 734 ulval = UARG(); 735 base = 2; 736 /* leading 0b/B only if non-zero */ 737 if (flags & ALT && 738 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) 739 ox[1] = ch; 740 goto nosign; 741 break; 742 case 'C': 743 flags |= LONGINT; 744 /*FALLTHROUGH*/ 745 case 'c': 746 if (flags & LONGINT) 747 *(cp = buf) = (wchar_t)GETARG(wint_t); 748 else 749 *(cp = buf) = (wchar_t)btowc(GETARG(int)); 750 size = 1; 751 sign = '\0'; 752 break; 753 case 'D': 754 flags |= LONGINT; 755 /*FALLTHROUGH*/ 756 case 'd': 757 case 'i': 758 if (flags & INTMAX_SIZE) { 759 ujval = SJARG(); 760 if ((intmax_t)ujval < 0) { 761 ujval = -ujval; 762 sign = '-'; 763 } 764 } else { 765 ulval = SARG(); 766 if ((long)ulval < 0) { 767 ulval = -ulval; 768 sign = '-'; 769 } 770 } 771 base = 10; 772 goto number; 773 #ifndef NO_FLOATING_POINT 774 case 'a': 775 case 'A': 776 if (ch == 'a') { 777 ox[1] = 'x'; 778 xdigs = xdigs_lower; 779 expchar = 'p'; 780 } else { 781 ox[1] = 'X'; 782 xdigs = xdigs_upper; 783 expchar = 'P'; 784 } 785 if (prec >= 0) 786 prec++; 787 if (flags & LONGDBL) { 788 fparg.ldbl = GETARG(long double); 789 dtoaresult = 790 __hldtoa(fparg.ldbl, xdigs, prec, 791 &expt, &signflag, &dtoaend); 792 } else { 793 fparg.dbl = GETARG(double); 794 dtoaresult = 795 __hdtoa(fparg.dbl, xdigs, prec, 796 &expt, &signflag, &dtoaend); 797 } 798 if (prec < 0) 799 prec = dtoaend - dtoaresult; 800 if (expt == INT_MAX) 801 ox[1] = '\0'; 802 if (convbuf != NULL) 803 free(convbuf); 804 ndig = dtoaend - dtoaresult; 805 cp = convbuf = __mbsconv(dtoaresult, -1); 806 freedtoa(dtoaresult); 807 goto fp_common; 808 case 'e': 809 case 'E': 810 expchar = ch; 811 if (prec < 0) /* account for digit before decpt */ 812 prec = DEFPREC + 1; 813 else 814 prec++; 815 goto fp_begin; 816 case 'f': 817 case 'F': 818 expchar = '\0'; 819 goto fp_begin; 820 case 'g': 821 case 'G': 822 expchar = ch - ('g' - 'e'); 823 if (prec == 0) 824 prec = 1; 825 fp_begin: 826 if (prec < 0) 827 prec = DEFPREC; 828 if (convbuf != NULL) 829 free(convbuf); 830 if (flags & LONGDBL) { 831 fparg.ldbl = GETARG(long double); 832 dtoaresult = 833 __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, 834 &expt, &signflag, &dtoaend); 835 } else { 836 fparg.dbl = GETARG(double); 837 dtoaresult = 838 dtoa(fparg.dbl, expchar ? 2 : 3, prec, 839 &expt, &signflag, &dtoaend); 840 if (expt == 9999) 841 expt = INT_MAX; 842 } 843 ndig = dtoaend - dtoaresult; 844 cp = convbuf = __mbsconv(dtoaresult, -1); 845 freedtoa(dtoaresult); 846 fp_common: 847 if (signflag) 848 sign = '-'; 849 if (expt == INT_MAX) { /* inf or nan */ 850 if (*cp == 'N') { 851 cp = (ch >= 'a') ? L"nan" : L"NAN"; 852 sign = '\0'; 853 } else 854 cp = (ch >= 'a') ? L"inf" : L"INF"; 855 size = 3; 856 flags &= ~ZEROPAD; 857 break; 858 } 859 flags |= FPT; 860 if (ch == 'g' || ch == 'G') { 861 if (expt > -4 && expt <= prec) { 862 /* Make %[gG] smell like %[fF] */ 863 expchar = '\0'; 864 if (flags & ALT) 865 prec -= expt; 866 else 867 prec = ndig - expt; 868 if (prec < 0) 869 prec = 0; 870 } else { 871 /* 872 * Make %[gG] smell like %[eE], but 873 * trim trailing zeroes if no # flag. 874 */ 875 if (!(flags & ALT)) 876 prec = ndig; 877 } 878 } 879 if (expchar) { 880 expsize = exponent(expstr, expt - 1, expchar); 881 size = expsize + prec; 882 if (prec > 1 || flags & ALT) 883 ++size; 884 } else { 885 /* space for digits before decimal point */ 886 if (expt > 0) 887 size = expt; 888 else /* "0" */ 889 size = 1; 890 /* space for decimal pt and following digits */ 891 if (prec || flags & ALT) 892 size += prec + 1; 893 if ((flags & GROUPING) && expt > 0) 894 size += grouping_init(&gs, expt, locale); 895 } 896 break; 897 #endif /* !NO_FLOATING_POINT */ 898 case 'n': 899 /* 900 * Assignment-like behavior is specified if the 901 * value overflows or is otherwise unrepresentable. 902 * C99 says to use `signed char' for %hhn conversions. 903 */ 904 if (flags & LLONGINT) 905 *GETARG(long long *) = ret; 906 else if (flags & SIZET) 907 *GETARG(ssize_t *) = (ssize_t)ret; 908 else if (flags & PTRDIFFT) 909 *GETARG(ptrdiff_t *) = ret; 910 else if (flags & INTMAXT) 911 *GETARG(intmax_t *) = ret; 912 else if (flags & LONGINT) 913 *GETARG(long *) = ret; 914 else if (flags & SHORTINT) 915 *GETARG(short *) = ret; 916 else if (flags & CHARINT) 917 *GETARG(signed char *) = ret; 918 else 919 *GETARG(int *) = ret; 920 continue; /* no output */ 921 case 'O': 922 flags |= LONGINT; 923 /*FALLTHROUGH*/ 924 case 'o': 925 if (flags & INTMAX_SIZE) 926 ujval = UJARG(); 927 else 928 ulval = UARG(); 929 base = 8; 930 goto nosign; 931 case 'p': 932 /*- 933 * ``The argument shall be a pointer to void. The 934 * value of the pointer is converted to a sequence 935 * of printable characters, in an implementation- 936 * defined manner.'' 937 * -- ANSI X3J11 938 */ 939 ujval = (uintmax_t)(uintptr_t)GETARG(void *); 940 base = 16; 941 xdigs = xdigs_lower; 942 flags = flags | INTMAXT; 943 ox[1] = 'x'; 944 goto nosign; 945 case 'S': 946 flags |= LONGINT; 947 /*FALLTHROUGH*/ 948 case 's': 949 if (flags & LONGINT) { 950 if ((cp = GETARG(wchar_t *)) == NULL) 951 cp = L"(null)"; 952 } else { 953 char *mbp; 954 955 if (convbuf != NULL) 956 free(convbuf); 957 if ((mbp = GETARG(char *)) == NULL) 958 cp = L"(null)"; 959 else { 960 convbuf = __mbsconv(mbp, prec); 961 if (convbuf == NULL) { 962 fp->_flags |= __SERR; 963 goto error; 964 } 965 cp = convbuf; 966 } 967 } 968 size = (prec >= 0) ? wcsnlen(cp, prec) : wcslen(cp); 969 sign = '\0'; 970 break; 971 case 'U': 972 flags |= LONGINT; 973 /*FALLTHROUGH*/ 974 case 'u': 975 if (flags & INTMAX_SIZE) 976 ujval = UJARG(); 977 else 978 ulval = UARG(); 979 base = 10; 980 goto nosign; 981 case 'X': 982 xdigs = xdigs_upper; 983 goto hex; 984 case 'x': 985 xdigs = xdigs_lower; 986 hex: 987 if (flags & INTMAX_SIZE) 988 ujval = UJARG(); 989 else 990 ulval = UARG(); 991 base = 16; 992 /* leading 0x/X only if non-zero */ 993 if (flags & ALT && 994 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) 995 ox[1] = ch; 996 997 flags &= ~GROUPING; 998 /* unsigned conversions */ 999 nosign: sign = '\0'; 1000 /*- 1001 * ``... diouXx conversions ... if a precision is 1002 * specified, the 0 flag will be ignored.'' 1003 * -- ANSI X3J11 1004 */ 1005 number: if ((dprec = prec) >= 0) 1006 flags &= ~ZEROPAD; 1007 1008 /*- 1009 * ``The result of converting a zero value with an 1010 * explicit precision of zero is no characters.'' 1011 * -- ANSI X3J11 1012 * 1013 * ``The C Standard is clear enough as is. The call 1014 * printf("%#.0o", 0) should print 0.'' 1015 * -- Defect Report #151 1016 */ 1017 cp = buf + BUF; 1018 if (flags & INTMAX_SIZE) { 1019 if (ujval != 0 || prec != 0 || 1020 (flags & ALT && base == 8)) 1021 cp = __ujtoa(ujval, cp, base, 1022 flags & ALT, xdigs); 1023 } else { 1024 if (ulval != 0 || prec != 0 || 1025 (flags & ALT && base == 8)) 1026 cp = __ultoa(ulval, cp, base, 1027 flags & ALT, xdigs); 1028 } 1029 size = buf + BUF - cp; 1030 if (size > BUF) /* should never happen */ 1031 abort(); 1032 if ((flags & GROUPING) && size != 0) 1033 size += grouping_init(&gs, size, locale); 1034 break; 1035 default: /* "%?" prints ?, unless ? is NUL */ 1036 if (ch == '\0') 1037 goto done; 1038 invalid: 1039 /* pretend it was %c with argument ch */ 1040 cp = buf; 1041 *cp = ch; 1042 size = 1; 1043 sign = '\0'; 1044 break; 1045 } 1046 1047 /* 1048 * All reasonable formats wind up here. At this point, `cp' 1049 * points to a string which (if not flags&LADJUST) should be 1050 * padded out to `width' places. If flags&ZEROPAD, it should 1051 * first be prefixed by any sign or other prefix; otherwise, 1052 * it should be blank padded before the prefix is emitted. 1053 * After any left-hand padding and prefixing, emit zeroes 1054 * required by a decimal [diouxX] precision, then print the 1055 * string proper, then emit zeroes required by any leftover 1056 * floating precision; finally, if LADJUST, pad with blanks. 1057 * 1058 * Compute actual size, so we know how much to pad. 1059 * size excludes decimal prec; realsz includes it. 1060 */ 1061 realsz = dprec > size ? dprec : size; 1062 if (sign) 1063 realsz++; 1064 if (ox[1]) 1065 realsz += 2; 1066 1067 prsize = width > realsz ? width : realsz; 1068 if ((unsigned)ret + prsize > INT_MAX) { 1069 ret = EOF; 1070 errno = EOVERFLOW; 1071 goto error; 1072 } 1073 1074 /* right-adjusting blank padding */ 1075 if ((flags & (LADJUST|ZEROPAD)) == 0) 1076 PAD(width - realsz, blanks); 1077 1078 /* prefix */ 1079 if (sign) 1080 PRINT(&sign, 1); 1081 1082 if (ox[1]) { /* ox[1] is either x, X, or \0 */ 1083 ox[0] = '0'; 1084 PRINT(ox, 2); 1085 } 1086 1087 /* right-adjusting zero padding */ 1088 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 1089 PAD(width - realsz, zeroes); 1090 1091 /* the string or number proper */ 1092 #ifndef NO_FLOATING_POINT 1093 if ((flags & FPT) == 0) { 1094 #endif 1095 /* leading zeroes from decimal precision */ 1096 PAD(dprec - size, zeroes); 1097 if (gs.grouping) { 1098 if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) 1099 goto error; 1100 } else { 1101 PRINT(cp, size); 1102 } 1103 #ifndef NO_FLOATING_POINT 1104 } else { /* glue together f_p fragments */ 1105 if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 1106 if (expt <= 0) { 1107 PRINT(zeroes, 1); 1108 if (prec || flags & ALT) 1109 PRINT(&decimal_point, 1); 1110 PAD(-expt, zeroes); 1111 /* already handled initial 0's */ 1112 prec += expt; 1113 } else { 1114 if (gs.grouping) { 1115 n = grouping_print(&gs, &io, 1116 cp, convbuf + ndig, locale); 1117 if (n < 0) 1118 goto error; 1119 cp += n; 1120 } else { 1121 PRINTANDPAD(cp, convbuf + ndig, 1122 expt, zeroes); 1123 cp += expt; 1124 } 1125 if (prec || flags & ALT) 1126 PRINT(&decimal_point, 1); 1127 } 1128 PRINTANDPAD(cp, convbuf + ndig, prec, zeroes); 1129 } else { /* %[eE] or sufficiently long %[gG] */ 1130 if (prec > 1 || flags & ALT) { 1131 buf[0] = *cp++; 1132 buf[1] = decimal_point; 1133 PRINT(buf, 2); 1134 PRINT(cp, ndig-1); 1135 PAD(prec - ndig, zeroes); 1136 } else /* XeYYY */ 1137 PRINT(cp, 1); 1138 PRINT(expstr, expsize); 1139 } 1140 } 1141 #endif 1142 /* left-adjusting padding (always blank) */ 1143 if (flags & LADJUST) 1144 PAD(width - realsz, blanks); 1145 1146 /* finally, adjust ret */ 1147 ret += prsize; 1148 1149 FLUSH(); /* copy out the I/O vectors */ 1150 } 1151 done: 1152 FLUSH(); 1153 error: 1154 va_end(orgap); 1155 if (convbuf != NULL) 1156 free(convbuf); 1157 if (__sferror(fp)) 1158 ret = EOF; 1159 else 1160 fp->_flags |= savserr; 1161 if ((argtable != NULL) && (argtable != statargtable)) 1162 free (argtable); 1163 return (ret); 1164 /* NOTREACHED */ 1165 } 1166