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