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