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