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 * Copyright (c) 2011 The FreeBSD Foundation 9 * All rights reserved. 10 * Portions of this software were developed by David Chisnall 11 * under sponsorship from the FreeBSD Foundation. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 38 #if 0 39 #if defined(LIBC_SCCS) && !defined(lint) 40 static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; 41 #endif /* LIBC_SCCS and not lint */ 42 #endif 43 #include <sys/cdefs.h> 44 __FBSDID("$FreeBSD$"); 45 46 /* 47 * Actual wprintf innards. 48 * 49 * Avoid making gratuitous changes to this source file; it should be kept 50 * as close as possible to vfprintf.c for ease of maintenance. 51 */ 52 53 #include "namespace.h" 54 #include <sys/types.h> 55 56 #include <ctype.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(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(fp); 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 447 static const char xdigs_lower[16] = "0123456789abcdef"; 448 static const char xdigs_upper[16] = "0123456789ABCDEF"; 449 450 /* BEWARE, these `goto error' on error. */ 451 #define PRINT(ptr, len) do { \ 452 if (io_print(&io, (ptr), (len), locale)) \ 453 goto error; \ 454 } while (0) 455 #define PAD(howmany, with) { \ 456 if (io_pad(&io, (howmany), (with), locale)) \ 457 goto error; \ 458 } 459 #define PRINTANDPAD(p, ep, len, with) { \ 460 if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ 461 goto error; \ 462 } 463 #define FLUSH() { \ 464 if (io_flush(&io, locale)) \ 465 goto error; \ 466 } 467 468 /* 469 * Get the argument indexed by nextarg. If the argument table is 470 * built, use it to get the argument. If its not, get the next 471 * argument (and arguments must be gotten sequentially). 472 */ 473 #define GETARG(type) \ 474 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ 475 (nextarg++, va_arg(ap, type))) 476 477 /* 478 * To extend shorts properly, we need both signed and unsigned 479 * argument extraction methods. 480 */ 481 #define SARG() \ 482 (flags&LONGINT ? GETARG(long) : \ 483 flags&SHORTINT ? (long)(short)GETARG(int) : \ 484 flags&CHARINT ? (long)(signed char)GETARG(int) : \ 485 (long)GETARG(int)) 486 #define UARG() \ 487 (flags&LONGINT ? GETARG(u_long) : \ 488 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \ 489 flags&CHARINT ? (u_long)(u_char)GETARG(int) : \ 490 (u_long)GETARG(u_int)) 491 #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT) 492 #define SJARG() \ 493 (flags&INTMAXT ? GETARG(intmax_t) : \ 494 flags&SIZET ? (intmax_t)GETARG(ssize_t) : \ 495 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \ 496 (intmax_t)GETARG(long long)) 497 #define UJARG() \ 498 (flags&INTMAXT ? GETARG(uintmax_t) : \ 499 flags&SIZET ? (uintmax_t)GETARG(size_t) : \ 500 flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \ 501 (uintmax_t)GETARG(unsigned long long)) 502 503 /* 504 * Get * arguments, including the form *nn$. Preserve the nextarg 505 * that the argument can be gotten once the type is determined. 506 */ 507 #define GETASTER(val) \ 508 n2 = 0; \ 509 cp = fmt; \ 510 while (is_digit(*cp)) { \ 511 n2 = 10 * n2 + to_digit(*cp); \ 512 cp++; \ 513 } \ 514 if (*cp == '$') { \ 515 int hold = nextarg; \ 516 if (argtable == NULL) { \ 517 argtable = statargtable; \ 518 if (__find_warguments (fmt0, orgap, &argtable)) { \ 519 ret = EOF; \ 520 goto error; \ 521 } \ 522 } \ 523 nextarg = n2; \ 524 val = GETARG (int); \ 525 nextarg = hold; \ 526 fmt = ++cp; \ 527 } else { \ 528 val = GETARG (int); \ 529 } 530 531 532 /* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */ 533 if (prepwrite(fp) != 0) 534 return (EOF); 535 536 convbuf = NULL; 537 fmt = (wchar_t *)fmt0; 538 argtable = NULL; 539 nextarg = 1; 540 va_copy(orgap, ap); 541 io_init(&io, fp); 542 ret = 0; 543 #ifndef NO_FLOATING_POINT 544 decimal_point = get_decpt(locale); 545 #endif 546 547 /* 548 * Scan the format for conversions (`%' character). 549 */ 550 for (;;) { 551 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 552 /* void */; 553 if ((n = fmt - cp) != 0) { 554 if ((unsigned)ret + n > INT_MAX) { 555 ret = EOF; 556 goto error; 557 } 558 PRINT(cp, n); 559 ret += n; 560 } 561 if (ch == '\0') 562 goto done; 563 fmt++; /* skip over '%' */ 564 565 flags = 0; 566 dprec = 0; 567 width = 0; 568 prec = -1; 569 gs.grouping = NULL; 570 sign = '\0'; 571 ox[1] = '\0'; 572 573 rflag: ch = *fmt++; 574 reswitch: switch (ch) { 575 case ' ': 576 /*- 577 * ``If the space and + flags both appear, the space 578 * flag will be ignored.'' 579 * -- ANSI X3J11 580 */ 581 if (!sign) 582 sign = ' '; 583 goto rflag; 584 case '#': 585 flags |= ALT; 586 goto rflag; 587 case '*': 588 /*- 589 * ``A negative field width argument is taken as a 590 * - flag followed by a positive field width.'' 591 * -- ANSI X3J11 592 * They don't exclude field widths read from args. 593 */ 594 GETASTER (width); 595 if (width >= 0) 596 goto rflag; 597 width = -width; 598 /* FALLTHROUGH */ 599 case '-': 600 flags |= LADJUST; 601 goto rflag; 602 case '+': 603 sign = '+'; 604 goto rflag; 605 case '\'': 606 flags |= GROUPING; 607 goto rflag; 608 case '.': 609 if ((ch = *fmt++) == '*') { 610 GETASTER (prec); 611 goto rflag; 612 } 613 prec = 0; 614 while (is_digit(ch)) { 615 prec = 10 * prec + to_digit(ch); 616 ch = *fmt++; 617 } 618 goto reswitch; 619 case '0': 620 /*- 621 * ``Note that 0 is taken as a flag, not as the 622 * beginning of a field width.'' 623 * -- ANSI X3J11 624 */ 625 flags |= ZEROPAD; 626 goto rflag; 627 case '1': case '2': case '3': case '4': 628 case '5': case '6': case '7': case '8': case '9': 629 n = 0; 630 do { 631 n = 10 * n + to_digit(ch); 632 ch = *fmt++; 633 } while (is_digit(ch)); 634 if (ch == '$') { 635 nextarg = n; 636 if (argtable == NULL) { 637 argtable = statargtable; 638 if (__find_warguments (fmt0, orgap, 639 &argtable)) { 640 ret = EOF; 641 goto error; 642 } 643 } 644 goto rflag; 645 } 646 width = n; 647 goto reswitch; 648 #ifndef NO_FLOATING_POINT 649 case 'L': 650 flags |= LONGDBL; 651 goto rflag; 652 #endif 653 case 'h': 654 if (flags & SHORTINT) { 655 flags &= ~SHORTINT; 656 flags |= CHARINT; 657 } else 658 flags |= SHORTINT; 659 goto rflag; 660 case 'j': 661 flags |= INTMAXT; 662 goto rflag; 663 case 'l': 664 if (flags & LONGINT) { 665 flags &= ~LONGINT; 666 flags |= LLONGINT; 667 } else 668 flags |= LONGINT; 669 goto rflag; 670 case 'q': 671 flags |= LLONGINT; /* not necessarily */ 672 goto rflag; 673 case 't': 674 flags |= PTRDIFFT; 675 goto rflag; 676 case 'z': 677 flags |= SIZET; 678 goto rflag; 679 case 'C': 680 flags |= LONGINT; 681 /*FALLTHROUGH*/ 682 case 'c': 683 if (flags & LONGINT) 684 *(cp = buf) = (wchar_t)GETARG(wint_t); 685 else 686 *(cp = buf) = (wchar_t)btowc(GETARG(int)); 687 size = 1; 688 sign = '\0'; 689 break; 690 case 'D': 691 flags |= LONGINT; 692 /*FALLTHROUGH*/ 693 case 'd': 694 case 'i': 695 if (flags & INTMAX_SIZE) { 696 ujval = SJARG(); 697 if ((intmax_t)ujval < 0) { 698 ujval = -ujval; 699 sign = '-'; 700 } 701 } else { 702 ulval = SARG(); 703 if ((long)ulval < 0) { 704 ulval = -ulval; 705 sign = '-'; 706 } 707 } 708 base = 10; 709 goto number; 710 #ifndef NO_FLOATING_POINT 711 case 'a': 712 case 'A': 713 if (ch == 'a') { 714 ox[1] = 'x'; 715 xdigs = xdigs_lower; 716 expchar = 'p'; 717 } else { 718 ox[1] = 'X'; 719 xdigs = xdigs_upper; 720 expchar = 'P'; 721 } 722 if (prec >= 0) 723 prec++; 724 if (flags & LONGDBL) { 725 fparg.ldbl = GETARG(long double); 726 dtoaresult = 727 __hldtoa(fparg.ldbl, xdigs, prec, 728 &expt, &signflag, &dtoaend); 729 } else { 730 fparg.dbl = GETARG(double); 731 dtoaresult = 732 __hdtoa(fparg.dbl, xdigs, prec, 733 &expt, &signflag, &dtoaend); 734 } 735 if (prec < 0) 736 prec = dtoaend - dtoaresult; 737 if (expt == INT_MAX) 738 ox[1] = '\0'; 739 if (convbuf != NULL) 740 free(convbuf); 741 ndig = dtoaend - dtoaresult; 742 cp = convbuf = __mbsconv(dtoaresult, -1); 743 freedtoa(dtoaresult); 744 goto fp_common; 745 case 'e': 746 case 'E': 747 expchar = ch; 748 if (prec < 0) /* account for digit before decpt */ 749 prec = DEFPREC + 1; 750 else 751 prec++; 752 goto fp_begin; 753 case 'f': 754 case 'F': 755 expchar = '\0'; 756 goto fp_begin; 757 case 'g': 758 case 'G': 759 expchar = ch - ('g' - 'e'); 760 if (prec == 0) 761 prec = 1; 762 fp_begin: 763 if (prec < 0) 764 prec = DEFPREC; 765 if (convbuf != NULL) 766 free(convbuf); 767 if (flags & LONGDBL) { 768 fparg.ldbl = GETARG(long double); 769 dtoaresult = 770 __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, 771 &expt, &signflag, &dtoaend); 772 } else { 773 fparg.dbl = GETARG(double); 774 dtoaresult = 775 dtoa(fparg.dbl, expchar ? 2 : 3, prec, 776 &expt, &signflag, &dtoaend); 777 if (expt == 9999) 778 expt = INT_MAX; 779 } 780 ndig = dtoaend - dtoaresult; 781 cp = convbuf = __mbsconv(dtoaresult, -1); 782 freedtoa(dtoaresult); 783 fp_common: 784 if (signflag) 785 sign = '-'; 786 if (expt == INT_MAX) { /* inf or nan */ 787 if (*cp == 'N') { 788 cp = (ch >= 'a') ? L"nan" : L"NAN"; 789 sign = '\0'; 790 } else 791 cp = (ch >= 'a') ? L"inf" : L"INF"; 792 size = 3; 793 flags &= ~ZEROPAD; 794 break; 795 } 796 flags |= FPT; 797 if (ch == 'g' || ch == 'G') { 798 if (expt > -4 && expt <= prec) { 799 /* Make %[gG] smell like %[fF] */ 800 expchar = '\0'; 801 if (flags & ALT) 802 prec -= expt; 803 else 804 prec = ndig - expt; 805 if (prec < 0) 806 prec = 0; 807 } else { 808 /* 809 * Make %[gG] smell like %[eE], but 810 * trim trailing zeroes if no # flag. 811 */ 812 if (!(flags & ALT)) 813 prec = ndig; 814 } 815 } 816 if (expchar) { 817 expsize = exponent(expstr, expt - 1, expchar); 818 size = expsize + prec; 819 if (prec > 1 || flags & ALT) 820 ++size; 821 } else { 822 /* space for digits before decimal point */ 823 if (expt > 0) 824 size = expt; 825 else /* "0" */ 826 size = 1; 827 /* space for decimal pt and following digits */ 828 if (prec || flags & ALT) 829 size += prec + 1; 830 if ((flags & GROUPING) && expt > 0) 831 size += grouping_init(&gs, expt, locale); 832 } 833 break; 834 #endif /* !NO_FLOATING_POINT */ 835 case 'n': 836 /* 837 * Assignment-like behavior is specified if the 838 * value overflows or is otherwise unrepresentable. 839 * C99 says to use `signed char' for %hhn conversions. 840 */ 841 if (flags & LLONGINT) 842 *GETARG(long long *) = ret; 843 else if (flags & SIZET) 844 *GETARG(ssize_t *) = (ssize_t)ret; 845 else if (flags & PTRDIFFT) 846 *GETARG(ptrdiff_t *) = ret; 847 else if (flags & INTMAXT) 848 *GETARG(intmax_t *) = ret; 849 else if (flags & LONGINT) 850 *GETARG(long *) = ret; 851 else if (flags & SHORTINT) 852 *GETARG(short *) = ret; 853 else if (flags & CHARINT) 854 *GETARG(signed char *) = ret; 855 else 856 *GETARG(int *) = ret; 857 continue; /* no output */ 858 case 'O': 859 flags |= LONGINT; 860 /*FALLTHROUGH*/ 861 case 'o': 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 ujval = (uintmax_t)(uintptr_t)GETARG(void *); 877 base = 16; 878 xdigs = xdigs_lower; 879 flags = flags | INTMAXT; 880 ox[1] = 'x'; 881 goto nosign; 882 case 'S': 883 flags |= LONGINT; 884 /*FALLTHROUGH*/ 885 case 's': 886 if (flags & LONGINT) { 887 if ((cp = GETARG(wchar_t *)) == NULL) 888 cp = L"(null)"; 889 } else { 890 char *mbp; 891 892 if (convbuf != NULL) 893 free(convbuf); 894 if ((mbp = GETARG(char *)) == NULL) 895 cp = L"(null)"; 896 else { 897 convbuf = __mbsconv(mbp, prec); 898 if (convbuf == NULL) { 899 fp->_flags |= __SERR; 900 goto error; 901 } 902 cp = convbuf; 903 } 904 } 905 size = (prec >= 0) ? wcsnlen(cp, prec) : wcslen(cp); 906 sign = '\0'; 907 break; 908 case 'U': 909 flags |= LONGINT; 910 /*FALLTHROUGH*/ 911 case 'u': 912 if (flags & INTMAX_SIZE) 913 ujval = UJARG(); 914 else 915 ulval = UARG(); 916 base = 10; 917 goto nosign; 918 case 'X': 919 xdigs = xdigs_upper; 920 goto hex; 921 case 'x': 922 xdigs = xdigs_lower; 923 hex: 924 if (flags & INTMAX_SIZE) 925 ujval = UJARG(); 926 else 927 ulval = UARG(); 928 base = 16; 929 /* leading 0x/X only if non-zero */ 930 if (flags & ALT && 931 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) 932 ox[1] = ch; 933 934 flags &= ~GROUPING; 935 /* unsigned conversions */ 936 nosign: sign = '\0'; 937 /*- 938 * ``... diouXx conversions ... if a precision is 939 * specified, the 0 flag will be ignored.'' 940 * -- ANSI X3J11 941 */ 942 number: if ((dprec = prec) >= 0) 943 flags &= ~ZEROPAD; 944 945 /*- 946 * ``The result of converting a zero value with an 947 * explicit precision of zero is no characters.'' 948 * -- ANSI X3J11 949 * 950 * ``The C Standard is clear enough as is. The call 951 * printf("%#.0o", 0) should print 0.'' 952 * -- Defect Report #151 953 */ 954 cp = buf + BUF; 955 if (flags & INTMAX_SIZE) { 956 if (ujval != 0 || prec != 0 || 957 (flags & ALT && base == 8)) 958 cp = __ujtoa(ujval, cp, base, 959 flags & ALT, xdigs); 960 } else { 961 if (ulval != 0 || prec != 0 || 962 (flags & ALT && base == 8)) 963 cp = __ultoa(ulval, cp, base, 964 flags & ALT, xdigs); 965 } 966 size = buf + BUF - cp; 967 if (size > BUF) /* should never happen */ 968 abort(); 969 if ((flags & GROUPING) && size != 0) 970 size += grouping_init(&gs, size, locale); 971 break; 972 default: /* "%?" prints ?, unless ? is NUL */ 973 if (ch == '\0') 974 goto done; 975 /* pretend it was %c with argument ch */ 976 cp = buf; 977 *cp = ch; 978 size = 1; 979 sign = '\0'; 980 break; 981 } 982 983 /* 984 * All reasonable formats wind up here. At this point, `cp' 985 * points to a string which (if not flags&LADJUST) should be 986 * padded out to `width' places. If flags&ZEROPAD, it should 987 * first be prefixed by any sign or other prefix; otherwise, 988 * it should be blank padded before the prefix is emitted. 989 * After any left-hand padding and prefixing, emit zeroes 990 * required by a decimal [diouxX] precision, then print the 991 * string proper, then emit zeroes required by any leftover 992 * floating precision; finally, if LADJUST, pad with blanks. 993 * 994 * Compute actual size, so we know how much to pad. 995 * size excludes decimal prec; realsz includes it. 996 */ 997 realsz = dprec > size ? dprec : size; 998 if (sign) 999 realsz++; 1000 if (ox[1]) 1001 realsz += 2; 1002 1003 prsize = width > realsz ? width : realsz; 1004 if ((unsigned)ret + prsize > INT_MAX) { 1005 ret = EOF; 1006 goto error; 1007 } 1008 1009 /* right-adjusting blank padding */ 1010 if ((flags & (LADJUST|ZEROPAD)) == 0) 1011 PAD(width - realsz, blanks); 1012 1013 /* prefix */ 1014 if (sign) 1015 PRINT(&sign, 1); 1016 1017 if (ox[1]) { /* ox[1] is either x, X, or \0 */ 1018 ox[0] = '0'; 1019 PRINT(ox, 2); 1020 } 1021 1022 /* right-adjusting zero padding */ 1023 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 1024 PAD(width - realsz, zeroes); 1025 1026 /* the string or number proper */ 1027 #ifndef NO_FLOATING_POINT 1028 if ((flags & FPT) == 0) { 1029 #endif 1030 /* leading zeroes from decimal precision */ 1031 PAD(dprec - size, zeroes); 1032 if (gs.grouping) { 1033 if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) 1034 goto error; 1035 } else { 1036 PRINT(cp, size); 1037 } 1038 #ifndef NO_FLOATING_POINT 1039 } else { /* glue together f_p fragments */ 1040 if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 1041 if (expt <= 0) { 1042 PRINT(zeroes, 1); 1043 if (prec || flags & ALT) 1044 PRINT(&decimal_point, 1); 1045 PAD(-expt, zeroes); 1046 /* already handled initial 0's */ 1047 prec += expt; 1048 } else { 1049 if (gs.grouping) { 1050 n = grouping_print(&gs, &io, 1051 cp, convbuf + ndig, locale); 1052 if (n < 0) 1053 goto error; 1054 cp += n; 1055 } else { 1056 PRINTANDPAD(cp, convbuf + ndig, 1057 expt, zeroes); 1058 cp += expt; 1059 } 1060 if (prec || flags & ALT) 1061 PRINT(&decimal_point, 1); 1062 } 1063 PRINTANDPAD(cp, convbuf + ndig, prec, zeroes); 1064 } else { /* %[eE] or sufficiently long %[gG] */ 1065 if (prec > 1 || flags & ALT) { 1066 buf[0] = *cp++; 1067 buf[1] = decimal_point; 1068 PRINT(buf, 2); 1069 PRINT(cp, ndig-1); 1070 PAD(prec - ndig, zeroes); 1071 } else /* XeYYY */ 1072 PRINT(cp, 1); 1073 PRINT(expstr, expsize); 1074 } 1075 } 1076 #endif 1077 /* left-adjusting padding (always blank) */ 1078 if (flags & LADJUST) 1079 PAD(width - realsz, blanks); 1080 1081 /* finally, adjust ret */ 1082 ret += prsize; 1083 1084 FLUSH(); /* copy out the I/O vectors */ 1085 } 1086 done: 1087 FLUSH(); 1088 error: 1089 va_end(orgap); 1090 if (convbuf != NULL) 1091 free(convbuf); 1092 if (__sferror(fp)) 1093 ret = EOF; 1094 if ((argtable != NULL) && (argtable != statargtable)) 1095 free (argtable); 1096 return (ret); 1097 /* NOTREACHED */ 1098 } 1099