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) 35 static 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$"); 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 68 union arg { 69 int intarg; 70 u_int uintarg; 71 long longarg; 72 u_long ulongarg; 73 long long longlongarg; 74 unsigned long long ulonglongarg; 75 ptrdiff_t ptrdiffarg; 76 size_t sizearg; 77 intmax_t intmaxarg; 78 uintmax_t uintmaxarg; 79 void *pvoidarg; 80 char *pchararg; 81 signed char *pschararg; 82 short *pshortarg; 83 int *pintarg; 84 long *plongarg; 85 long long *plonglongarg; 86 ptrdiff_t *pptrdiffarg; 87 size_t *psizearg; 88 intmax_t *pintmaxarg; 89 #ifndef NO_FLOATING_POINT 90 double doublearg; 91 long double longdoublearg; 92 #endif 93 wint_t wintarg; 94 wchar_t *pwchararg; 95 }; 96 97 /* 98 * Type ids for argument type table. 99 */ 100 enum typeid { 101 T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT, 102 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG, 103 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET, 104 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR, 105 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR 106 }; 107 108 static int __sbprintf(FILE *, const wchar_t *, va_list); 109 static wint_t __xfputwc(wchar_t, FILE *); 110 static wchar_t *__ujtoa(uintmax_t, wchar_t *, int, int, const char *, int, 111 char, const char *); 112 static wchar_t *__ultoa(u_long, wchar_t *, int, int, const char *, int, 113 char, const char *); 114 static wchar_t *__mbsconv(char *, int); 115 static void __find_arguments(const wchar_t *, va_list, union arg **); 116 static void __grow_type_table(int, enum typeid **, int *); 117 118 /* 119 * Helper function for `fprintf to unbuffered unix file': creates a 120 * temporary buffer. We only work on write-only files; this avoids 121 * worries about ungetc buffers and so forth. 122 */ 123 static int 124 __sbprintf(FILE *fp, const wchar_t *fmt, va_list ap) 125 { 126 int ret; 127 FILE fake; 128 unsigned char buf[BUFSIZ]; 129 130 /* copy the important variables */ 131 fake._flags = fp->_flags & ~__SNBF; 132 fake._file = fp->_file; 133 fake._cookie = fp->_cookie; 134 fake._write = fp->_write; 135 fake._extra = fp->_extra; 136 137 /* set up the buffer */ 138 fake._bf._base = fake._p = buf; 139 fake._bf._size = fake._w = sizeof(buf); 140 fake._lbfsize = 0; /* not actually used, but Just In Case */ 141 142 /* do the work, then copy any error status */ 143 ret = __vfwprintf(&fake, fmt, ap); 144 if (ret >= 0 && __fflush(&fake)) 145 ret = WEOF; 146 if (fake._flags & __SERR) 147 fp->_flags |= __SERR; 148 return (ret); 149 } 150 151 /* 152 * Like __fputwc, but handles fake string (__SSTR) files properly. 153 * File must already be locked. 154 */ 155 static wint_t 156 __xfputwc(wchar_t wc, FILE *fp) 157 { 158 static const mbstate_t initial; 159 mbstate_t mbs; 160 char buf[MB_LEN_MAX]; 161 struct __suio uio; 162 struct __siov iov; 163 size_t len; 164 165 if ((fp->_flags & __SSTR) == 0) 166 return (__fputwc(wc, fp)); 167 168 mbs = initial; 169 if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) { 170 fp->_flags |= __SERR; 171 return (WEOF); 172 } 173 uio.uio_iov = &iov; 174 uio.uio_resid = len; 175 uio.uio_iovcnt = 1; 176 iov.iov_base = buf; 177 iov.iov_len = len; 178 return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF); 179 } 180 181 /* 182 * Macros for converting digits to letters and vice versa 183 */ 184 #define to_digit(c) ((c) - '0') 185 #define is_digit(c) ((unsigned)to_digit(c) <= 9) 186 #define to_char(n) ((n) + '0') 187 188 /* 189 * Convert an unsigned long to ASCII for printf purposes, returning 190 * a pointer to the first character of the string representation. 191 * Octal numbers can be forced to have a leading zero; hex numbers 192 * use the given digits. 193 */ 194 static wchar_t * 195 __ultoa(u_long val, wchar_t *endp, int base, int octzero, const char *xdigs, 196 int needgrp, char thousep, const char *grp) 197 { 198 wchar_t *cp = endp; 199 long sval; 200 int ndig; 201 202 /* 203 * Handle the three cases separately, in the hope of getting 204 * better/faster code. 205 */ 206 switch (base) { 207 case 10: 208 if (val < 10) { /* many numbers are 1 digit */ 209 *--cp = to_char(val); 210 return (cp); 211 } 212 ndig = 0; 213 /* 214 * On many machines, unsigned arithmetic is harder than 215 * signed arithmetic, so we do at most one unsigned mod and 216 * divide; this is sufficient to reduce the range of 217 * the incoming value to where signed arithmetic works. 218 */ 219 if (val > LONG_MAX) { 220 *--cp = to_char(val % 10); 221 ndig++; 222 sval = val / 10; 223 } else 224 sval = val; 225 do { 226 *--cp = to_char(sval % 10); 227 ndig++; 228 /* 229 * If (*grp == CHAR_MAX) then no more grouping 230 * should be performed. 231 */ 232 if (needgrp && ndig == *grp && *grp != CHAR_MAX 233 && sval > 9) { 234 *--cp = thousep; 235 ndig = 0; 236 /* 237 * If (*(grp+1) == '\0') then we have to 238 * use *grp character (last grouping rule) 239 * for all next cases 240 */ 241 if (*(grp+1) != '\0') 242 grp++; 243 } 244 sval /= 10; 245 } while (sval != 0); 246 break; 247 248 case 8: 249 do { 250 *--cp = to_char(val & 7); 251 val >>= 3; 252 } while (val); 253 if (octzero && *cp != '0') 254 *--cp = '0'; 255 break; 256 257 case 16: 258 do { 259 *--cp = xdigs[val & 15]; 260 val >>= 4; 261 } while (val); 262 break; 263 264 default: /* oops */ 265 abort(); 266 } 267 return (cp); 268 } 269 270 /* Identical to __ultoa, but for intmax_t. */ 271 static wchar_t * 272 __ujtoa(uintmax_t val, wchar_t *endp, int base, int octzero, 273 const char *xdigs, int needgrp, char thousep, const char *grp) 274 { 275 wchar_t *cp = endp; 276 intmax_t sval; 277 int ndig; 278 279 /* quick test for small values; __ultoa is typically much faster */ 280 /* (perhaps instead we should run until small, then call __ultoa?) */ 281 if (val <= ULONG_MAX) 282 return (__ultoa((u_long)val, endp, base, octzero, xdigs, 283 needgrp, thousep, grp)); 284 switch (base) { 285 case 10: 286 if (val < 10) { 287 *--cp = to_char(val % 10); 288 return (cp); 289 } 290 ndig = 0; 291 if (val > INTMAX_MAX) { 292 *--cp = to_char(val % 10); 293 ndig++; 294 sval = val / 10; 295 } else 296 sval = val; 297 do { 298 *--cp = to_char(sval % 10); 299 ndig++; 300 /* 301 * If (*grp == CHAR_MAX) then no more grouping 302 * should be performed. 303 */ 304 if (needgrp && *grp != CHAR_MAX && ndig == *grp 305 && sval > 9) { 306 *--cp = thousep; 307 ndig = 0; 308 /* 309 * If (*(grp+1) == '\0') then we have to 310 * use *grp character (last grouping rule) 311 * for all next cases 312 */ 313 if (*(grp+1) != '\0') 314 grp++; 315 } 316 sval /= 10; 317 } while (sval != 0); 318 break; 319 320 case 8: 321 do { 322 *--cp = to_char(val & 7); 323 val >>= 3; 324 } while (val); 325 if (octzero && *cp != '0') 326 *--cp = '0'; 327 break; 328 329 case 16: 330 do { 331 *--cp = xdigs[val & 15]; 332 val >>= 4; 333 } while (val); 334 break; 335 336 default: 337 abort(); 338 } 339 return (cp); 340 } 341 342 /* 343 * Convert a multibyte character string argument for the %s format to a wide 344 * string representation. ``prec'' specifies the maximum number of bytes 345 * to output. If ``prec'' is greater than or equal to zero, we can't assume 346 * that the multibyte char. string ends in a null character. 347 */ 348 static wchar_t * 349 __mbsconv(char *mbsarg, int prec) 350 { 351 static const mbstate_t initial; 352 mbstate_t mbs; 353 wchar_t *convbuf, *wcp; 354 const char *p; 355 size_t insize, nchars, nconv; 356 357 if (mbsarg == NULL) 358 return (NULL); 359 360 /* 361 * Supplied argument is a multibyte string; convert it to wide 362 * characters first. 363 */ 364 if (prec >= 0) { 365 /* 366 * String is not guaranteed to be NUL-terminated. Find the 367 * number of characters to print. 368 */ 369 p = mbsarg; 370 insize = nchars = 0; 371 mbs = initial; 372 while (nchars != (size_t)prec) { 373 nconv = mbrlen(p, MB_CUR_MAX, &mbs); 374 if (nconv == 0 || nconv == (size_t)-1 || 375 nconv == (size_t)-2) 376 break; 377 p += nconv; 378 nchars++; 379 insize += nconv; 380 } 381 if (nconv == (size_t)-1 || nconv == (size_t)-2) 382 return (NULL); 383 } else 384 insize = strlen(mbsarg); 385 386 /* 387 * Allocate buffer for the result and perform the conversion, 388 * converting at most `size' bytes of the input multibyte string to 389 * wide characters for printing. 390 */ 391 convbuf = malloc((insize + 1) * sizeof(*convbuf)); 392 if (convbuf == NULL) 393 return (NULL); 394 wcp = convbuf; 395 p = mbsarg; 396 mbs = initial; 397 while (insize != 0) { 398 nconv = mbrtowc(wcp, p, insize, &mbs); 399 if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2) 400 break; 401 wcp++; 402 p += nconv; 403 insize -= nconv; 404 } 405 if (nconv == (size_t)-1 || nconv == (size_t)-2) { 406 free(convbuf); 407 return (NULL); 408 } 409 *wcp = L'\0'; 410 411 return (convbuf); 412 } 413 414 /* 415 * MT-safe version 416 */ 417 int 418 vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap) 419 420 { 421 int ret; 422 423 FLOCKFILE(fp); 424 ret = __vfwprintf(fp, fmt0, ap); 425 FUNLOCKFILE(fp); 426 return (ret); 427 } 428 429 #ifndef NO_FLOATING_POINT 430 431 #define dtoa __dtoa 432 #define freedtoa __freedtoa 433 434 #include <float.h> 435 #include <math.h> 436 #include "floatio.h" 437 #include "gdtoa.h" 438 439 #define DEFPREC 6 440 441 static int exponent(wchar_t *, int, wchar_t); 442 443 #endif /* !NO_FLOATING_POINT */ 444 445 /* 446 * The size of the buffer we use as scratch space for integer 447 * conversions, among other things. Technically, we would need the 448 * most space for base 10 conversions with thousands' grouping 449 * characters between each pair of digits. 100 bytes is a 450 * conservative overestimate even for a 128-bit uintmax_t. 451 */ 452 #define BUF 100 453 454 #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ 455 456 /* 457 * Flags used during conversion. 458 */ 459 #define ALT 0x001 /* alternate form */ 460 #define LADJUST 0x004 /* left adjustment */ 461 #define LONGDBL 0x008 /* long double */ 462 #define LONGINT 0x010 /* long integer */ 463 #define LLONGINT 0x020 /* long long integer */ 464 #define SHORTINT 0x040 /* short integer */ 465 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ 466 #define FPT 0x100 /* Floating point number */ 467 #define GROUPING 0x200 /* use grouping ("'" flag) */ 468 /* C99 additional size modifiers: */ 469 #define SIZET 0x400 /* size_t */ 470 #define PTRDIFFT 0x800 /* ptrdiff_t */ 471 #define INTMAXT 0x1000 /* intmax_t */ 472 #define CHARINT 0x2000 /* print char using int format */ 473 474 /* 475 * Non-MT-safe version 476 */ 477 int 478 __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) 479 { 480 wchar_t *fmt; /* format string */ 481 wchar_t ch; /* character from fmt */ 482 int n, n2, n3; /* handy integer (short term usage) */ 483 wchar_t *cp; /* handy char pointer (short term usage) */ 484 int flags; /* flags as above */ 485 int ret; /* return value accumulator */ 486 int width; /* width from format (%8d), or 0 */ 487 int prec; /* precision from format; <0 for N/A */ 488 wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */ 489 char thousands_sep; /* locale specific thousands separator */ 490 const char *grouping; /* locale specific numeric grouping rules */ 491 #ifndef NO_FLOATING_POINT 492 /* 493 * We can decompose the printed representation of floating 494 * point numbers into several parts, some of which may be empty: 495 * 496 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ 497 * A B ---C--- D E F 498 * 499 * A: 'sign' holds this value if present; '\0' otherwise 500 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal 501 * C: cp points to the string MMMNNN. Leading and trailing 502 * zeros are not in the string and must be added. 503 * D: expchar holds this character; '\0' if no exponent, e.g. %f 504 * F: at least two digits for decimal, at least one digit for hex 505 */ 506 char *decimal_point; /* locale specific decimal point */ 507 int signflag; /* true if float is negative */ 508 union { /* floating point arguments %[aAeEfFgG] */ 509 double dbl; 510 long double ldbl; 511 } fparg; 512 int expt; /* integer value of exponent */ 513 char expchar; /* exponent character: [eEpP\0] */ 514 char *dtoaend; /* pointer to end of converted digits */ 515 int expsize; /* character count for expstr */ 516 int lead; /* sig figs before decimal or group sep */ 517 int ndig; /* actual number of digits returned by dtoa */ 518 wchar_t expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ 519 char *dtoaresult; /* buffer allocated by dtoa */ 520 int nseps; /* number of group separators with ' */ 521 int nrepeats; /* number of repeats of the last group */ 522 #endif 523 u_long ulval; /* integer arguments %[diouxX] */ 524 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */ 525 int base; /* base for [diouxX] conversion */ 526 int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 527 int realsz; /* field size expanded by dprec, sign, etc */ 528 int size; /* size of converted field or string */ 529 int prsize; /* max size of printed field */ 530 const char *xdigs; /* digits for [xX] conversion */ 531 wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */ 532 wchar_t ox[2]; /* space for 0x hex-prefix */ 533 union arg *argtable; /* args, built due to positional arg */ 534 union arg statargtable [STATIC_ARG_TBL_SIZE]; 535 int nextarg; /* 1-based argument index */ 536 va_list orgap; /* original argument pointer */ 537 wchar_t *convbuf; /* multibyte to wide conversion result */ 538 539 /* 540 * Choose PADSIZE to trade efficiency vs. size. If larger printf 541 * fields occur frequently, increase PADSIZE and make the initialisers 542 * below longer. 543 */ 544 #define PADSIZE 16 /* pad chunk size */ 545 static wchar_t blanks[PADSIZE] = 546 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 547 static wchar_t zeroes[PADSIZE] = 548 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 549 550 static const char xdigs_lower[16] = "0123456789abcdef"; 551 static const char xdigs_upper[16] = "0123456789ABCDEF"; 552 553 /* 554 * BEWARE, these `goto error' on error, PRINT uses `n2' and 555 * PAD uses `n'. 556 */ 557 #define PRINT(ptr, len) do { \ 558 for (n3 = 0; n3 < (len); n3++) \ 559 __xfputwc((ptr)[n3], fp); \ 560 } while (0) 561 #define PAD(howmany, with) do { \ 562 if ((n = (howmany)) > 0) { \ 563 while (n > PADSIZE) { \ 564 PRINT(with, PADSIZE); \ 565 n -= PADSIZE; \ 566 } \ 567 PRINT(with, n); \ 568 } \ 569 } while (0) 570 #define PRINTANDPAD(p, ep, len, with) do { \ 571 n2 = (ep) - (p); \ 572 if (n2 > (len)) \ 573 n2 = (len); \ 574 if (n2 > 0) \ 575 PRINT((p), n2); \ 576 PAD((len) - (n2 > 0 ? n2 : 0), (with)); \ 577 } while(0) 578 579 /* 580 * Get the argument indexed by nextarg. If the argument table is 581 * built, use it to get the argument. If its not, get the next 582 * argument (and arguments must be gotten sequentially). 583 */ 584 #define GETARG(type) \ 585 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ 586 (nextarg++, va_arg(ap, type))) 587 588 /* 589 * To extend shorts properly, we need both signed and unsigned 590 * argument extraction methods. 591 */ 592 #define SARG() \ 593 (flags&LONGINT ? GETARG(long) : \ 594 flags&SHORTINT ? (long)(short)GETARG(int) : \ 595 flags&CHARINT ? (long)(signed char)GETARG(int) : \ 596 (long)GETARG(int)) 597 #define UARG() \ 598 (flags&LONGINT ? GETARG(u_long) : \ 599 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \ 600 flags&CHARINT ? (u_long)(u_char)GETARG(int) : \ 601 (u_long)GETARG(u_int)) 602 #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT) 603 #define SJARG() \ 604 (flags&INTMAXT ? GETARG(intmax_t) : \ 605 flags&SIZET ? (intmax_t)GETARG(size_t) : \ 606 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \ 607 (intmax_t)GETARG(long long)) 608 #define UJARG() \ 609 (flags&INTMAXT ? GETARG(uintmax_t) : \ 610 flags&SIZET ? (uintmax_t)GETARG(size_t) : \ 611 flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \ 612 (uintmax_t)GETARG(unsigned long long)) 613 614 /* 615 * Get * arguments, including the form *nn$. Preserve the nextarg 616 * that the argument can be gotten once the type is determined. 617 */ 618 #define GETASTER(val) \ 619 n2 = 0; \ 620 cp = fmt; \ 621 while (is_digit(*cp)) { \ 622 n2 = 10 * n2 + to_digit(*cp); \ 623 cp++; \ 624 } \ 625 if (*cp == '$') { \ 626 int hold = nextarg; \ 627 if (argtable == NULL) { \ 628 argtable = statargtable; \ 629 __find_arguments (fmt0, orgap, &argtable); \ 630 } \ 631 nextarg = n2; \ 632 val = GETARG (int); \ 633 nextarg = hold; \ 634 fmt = ++cp; \ 635 } else { \ 636 val = GETARG (int); \ 637 } 638 639 640 thousands_sep = '\0'; 641 grouping = NULL; 642 #ifndef NO_FLOATING_POINT 643 decimal_point = localeconv()->decimal_point; 644 #endif 645 convbuf = NULL; 646 /* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */ 647 if (prepwrite(fp) != 0) 648 return (EOF); 649 650 /* optimise fprintf(stderr) (and other unbuffered Unix files) */ 651 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && 652 fp->_file >= 0) 653 return (__sbprintf(fp, fmt0, ap)); 654 655 fmt = (wchar_t *)fmt0; 656 argtable = NULL; 657 nextarg = 1; 658 va_copy(orgap, ap); 659 ret = 0; 660 661 /* 662 * Scan the format for conversions (`%' character). 663 */ 664 for (;;) { 665 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 666 /* void */; 667 if ((n = fmt - cp) != 0) { 668 if ((unsigned)ret + n > INT_MAX) { 669 ret = EOF; 670 goto error; 671 } 672 PRINT(cp, n); 673 ret += n; 674 } 675 if (ch == '\0') 676 goto done; 677 fmt++; /* skip over '%' */ 678 679 flags = 0; 680 dprec = 0; 681 width = 0; 682 prec = -1; 683 sign = '\0'; 684 ox[1] = '\0'; 685 686 rflag: ch = *fmt++; 687 reswitch: switch (ch) { 688 case ' ': 689 /*- 690 * ``If the space and + flags both appear, the space 691 * flag will be ignored.'' 692 * -- ANSI X3J11 693 */ 694 if (!sign) 695 sign = ' '; 696 goto rflag; 697 case '#': 698 flags |= ALT; 699 goto rflag; 700 case '*': 701 /*- 702 * ``A negative field width argument is taken as a 703 * - flag followed by a positive field width.'' 704 * -- ANSI X3J11 705 * They don't exclude field widths read from args. 706 */ 707 GETASTER (width); 708 if (width >= 0) 709 goto rflag; 710 width = -width; 711 /* FALLTHROUGH */ 712 case '-': 713 flags |= LADJUST; 714 goto rflag; 715 case '+': 716 sign = '+'; 717 goto rflag; 718 case '\'': 719 flags |= GROUPING; 720 thousands_sep = *(localeconv()->thousands_sep); 721 grouping = localeconv()->grouping; 722 goto rflag; 723 case '.': 724 if ((ch = *fmt++) == '*') { 725 GETASTER (prec); 726 goto rflag; 727 } 728 prec = 0; 729 while (is_digit(ch)) { 730 prec = 10 * prec + to_digit(ch); 731 ch = *fmt++; 732 } 733 goto reswitch; 734 case '0': 735 /*- 736 * ``Note that 0 is taken as a flag, not as the 737 * beginning of a field width.'' 738 * -- ANSI X3J11 739 */ 740 flags |= ZEROPAD; 741 goto rflag; 742 case '1': case '2': case '3': case '4': 743 case '5': case '6': case '7': case '8': case '9': 744 n = 0; 745 do { 746 n = 10 * n + to_digit(ch); 747 ch = *fmt++; 748 } while (is_digit(ch)); 749 if (ch == '$') { 750 nextarg = n; 751 if (argtable == NULL) { 752 argtable = statargtable; 753 __find_arguments (fmt0, orgap, 754 &argtable); 755 } 756 goto rflag; 757 } 758 width = n; 759 goto reswitch; 760 #ifndef NO_FLOATING_POINT 761 case 'L': 762 flags |= LONGDBL; 763 goto rflag; 764 #endif 765 case 'h': 766 if (flags & SHORTINT) { 767 flags &= ~SHORTINT; 768 flags |= CHARINT; 769 } else 770 flags |= SHORTINT; 771 goto rflag; 772 case 'j': 773 flags |= INTMAXT; 774 goto rflag; 775 case 'l': 776 if (flags & LONGINT) { 777 flags &= ~LONGINT; 778 flags |= LLONGINT; 779 } else 780 flags |= LONGINT; 781 goto rflag; 782 case 'q': 783 flags |= LLONGINT; /* not necessarily */ 784 goto rflag; 785 case 't': 786 flags |= PTRDIFFT; 787 goto rflag; 788 case 'z': 789 flags |= SIZET; 790 goto rflag; 791 case 'C': 792 flags |= LONGINT; 793 /*FALLTHROUGH*/ 794 case 'c': 795 if (flags & LONGINT) 796 *(cp = buf) = (wchar_t)GETARG(wint_t); 797 else 798 *(cp = buf) = (wchar_t)btowc(GETARG(int)); 799 size = 1; 800 sign = '\0'; 801 break; 802 case 'D': 803 flags |= LONGINT; 804 /*FALLTHROUGH*/ 805 case 'd': 806 case 'i': 807 if (flags & INTMAX_SIZE) { 808 ujval = SJARG(); 809 if ((intmax_t)ujval < 0) { 810 ujval = -ujval; 811 sign = '-'; 812 } 813 } else { 814 ulval = SARG(); 815 if ((long)ulval < 0) { 816 ulval = -ulval; 817 sign = '-'; 818 } 819 } 820 base = 10; 821 goto number; 822 #ifndef NO_FLOATING_POINT 823 case 'a': 824 case 'A': 825 if (ch == 'a') { 826 ox[1] = 'x'; 827 xdigs = xdigs_lower; 828 expchar = 'p'; 829 } else { 830 ox[1] = 'X'; 831 xdigs = xdigs_upper; 832 expchar = 'P'; 833 } 834 if (prec >= 0) 835 prec++; 836 if (flags & LONGDBL) { 837 fparg.ldbl = GETARG(long double); 838 dtoaresult = 839 __hldtoa(fparg.ldbl, xdigs, prec, 840 &expt, &signflag, &dtoaend); 841 } else { 842 fparg.dbl = GETARG(double); 843 dtoaresult = 844 __hdtoa(fparg.dbl, xdigs, prec, 845 &expt, &signflag, &dtoaend); 846 } 847 if (prec < 0) 848 prec = dtoaend - dtoaresult; 849 if (expt == INT_MAX) 850 ox[1] = '\0'; 851 if (convbuf != NULL) 852 free(convbuf); 853 ndig = dtoaend - dtoaresult; 854 cp = convbuf = __mbsconv(dtoaresult, -1); 855 freedtoa(dtoaresult); 856 goto fp_common; 857 case 'e': 858 case 'E': 859 expchar = ch; 860 if (prec < 0) /* account for digit before decpt */ 861 prec = DEFPREC + 1; 862 else 863 prec++; 864 goto fp_begin; 865 case 'f': 866 case 'F': 867 expchar = '\0'; 868 goto fp_begin; 869 case 'g': 870 case 'G': 871 expchar = ch - ('g' - 'e'); 872 if (prec == 0) 873 prec = 1; 874 fp_begin: 875 if (prec < 0) 876 prec = DEFPREC; 877 if (convbuf != NULL) 878 free(convbuf); 879 if (flags & LONGDBL) { 880 fparg.ldbl = GETARG(long double); 881 dtoaresult = 882 __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, 883 &expt, &signflag, &dtoaend); 884 } else { 885 fparg.dbl = GETARG(double); 886 dtoaresult = 887 dtoa(fparg.dbl, expchar ? 2 : 3, prec, 888 &expt, &signflag, &dtoaend); 889 if (expt == 9999) 890 expt = INT_MAX; 891 } 892 ndig = dtoaend - dtoaresult; 893 cp = convbuf = __mbsconv(dtoaresult, -1); 894 freedtoa(dtoaresult); 895 fp_common: 896 if (signflag) 897 sign = '-'; 898 if (expt == INT_MAX) { /* inf or nan */ 899 if (*cp == 'N') { 900 cp = (ch >= 'a') ? L"nan" : L"NAN"; 901 sign = '\0'; 902 } else 903 cp = (ch >= 'a') ? L"inf" : L"INF"; 904 size = 3; 905 flags &= ~ZEROPAD; 906 break; 907 } 908 flags |= FPT; 909 if (ch == 'g' || ch == 'G') { 910 if (expt > -4 && expt <= prec) { 911 /* Make %[gG] smell like %[fF] */ 912 expchar = '\0'; 913 if (flags & ALT) 914 prec -= expt; 915 else 916 prec = ndig - expt; 917 if (prec < 0) 918 prec = 0; 919 } else { 920 /* 921 * Make %[gG] smell like %[eE], but 922 * trim trailing zeroes if no # flag. 923 */ 924 if (!(flags & ALT)) 925 prec = ndig; 926 } 927 } 928 if (expchar) { 929 expsize = exponent(expstr, expt - 1, expchar); 930 size = expsize + prec; 931 if (prec > 1 || flags & ALT) 932 ++size; 933 } else { 934 /* space for digits before decimal point */ 935 if (expt > 0) 936 size = expt; 937 else /* "0" */ 938 size = 1; 939 /* space for decimal pt and following digits */ 940 if (prec || flags & ALT) 941 size += prec + 1; 942 if (grouping && expt > 0) { 943 /* space for thousands' grouping */ 944 nseps = nrepeats = 0; 945 lead = expt; 946 while (*grouping != CHAR_MAX) { 947 if (lead <= *grouping) 948 break; 949 lead -= *grouping; 950 if (*(grouping+1)) { 951 nseps++; 952 grouping++; 953 } else 954 nrepeats++; 955 } 956 size += nseps + nrepeats; 957 } else 958 lead = expt; 959 } 960 break; 961 #endif /* !NO_FLOATING_POINT */ 962 case 'n': 963 /* 964 * Assignment-like behavior is specified if the 965 * value overflows or is otherwise unrepresentable. 966 * C99 says to use `signed char' for %hhn conversions. 967 */ 968 if (flags & LLONGINT) 969 *GETARG(long long *) = ret; 970 else if (flags & SIZET) 971 *GETARG(ssize_t *) = (ssize_t)ret; 972 else if (flags & PTRDIFFT) 973 *GETARG(ptrdiff_t *) = ret; 974 else if (flags & INTMAXT) 975 *GETARG(intmax_t *) = ret; 976 else if (flags & LONGINT) 977 *GETARG(long *) = ret; 978 else if (flags & SHORTINT) 979 *GETARG(short *) = ret; 980 else if (flags & CHARINT) 981 *GETARG(signed char *) = ret; 982 else 983 *GETARG(int *) = ret; 984 continue; /* no output */ 985 case 'O': 986 flags |= LONGINT; 987 /*FALLTHROUGH*/ 988 case 'o': 989 if (flags & INTMAX_SIZE) 990 ujval = UJARG(); 991 else 992 ulval = UARG(); 993 base = 8; 994 goto nosign; 995 case 'p': 996 /*- 997 * ``The argument shall be a pointer to void. The 998 * value of the pointer is converted to a sequence 999 * of printable characters, in an implementation- 1000 * defined manner.'' 1001 * -- ANSI X3J11 1002 */ 1003 ujval = (uintmax_t)(uintptr_t)GETARG(void *); 1004 base = 16; 1005 xdigs = xdigs_lower; 1006 flags = flags | INTMAXT; 1007 ox[1] = 'x'; 1008 goto nosign; 1009 case 'S': 1010 flags |= LONGINT; 1011 /*FALLTHROUGH*/ 1012 case 's': 1013 if (flags & LONGINT) { 1014 if ((cp = GETARG(wchar_t *)) == NULL) 1015 cp = L"(null)"; 1016 } else { 1017 char *mbp; 1018 1019 if (convbuf != NULL) 1020 free(convbuf); 1021 if ((mbp = GETARG(char *)) == NULL) 1022 cp = L"(null)"; 1023 else { 1024 convbuf = __mbsconv(mbp, prec); 1025 if (convbuf == NULL) { 1026 fp->_flags |= __SERR; 1027 goto error; 1028 } 1029 cp = convbuf; 1030 } 1031 } 1032 1033 if (prec >= 0) { 1034 /* 1035 * can't use wcslen; can only look for the 1036 * NUL in the first `prec' characters, and 1037 * wcslen() will go further. 1038 */ 1039 wchar_t *p = wmemchr(cp, 0, (size_t)prec); 1040 1041 if (p != NULL) { 1042 size = p - cp; 1043 if (size > prec) 1044 size = prec; 1045 } else 1046 size = prec; 1047 } else 1048 size = wcslen(cp); 1049 sign = '\0'; 1050 break; 1051 case 'U': 1052 flags |= LONGINT; 1053 /*FALLTHROUGH*/ 1054 case 'u': 1055 if (flags & INTMAX_SIZE) 1056 ujval = UJARG(); 1057 else 1058 ulval = UARG(); 1059 base = 10; 1060 goto nosign; 1061 case 'X': 1062 xdigs = xdigs_upper; 1063 goto hex; 1064 case 'x': 1065 xdigs = xdigs_lower; 1066 hex: 1067 if (flags & INTMAX_SIZE) 1068 ujval = UJARG(); 1069 else 1070 ulval = UARG(); 1071 base = 16; 1072 /* leading 0x/X only if non-zero */ 1073 if (flags & ALT && 1074 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) 1075 ox[1] = ch; 1076 1077 flags &= ~GROUPING; 1078 /* unsigned conversions */ 1079 nosign: sign = '\0'; 1080 /*- 1081 * ``... diouXx conversions ... if a precision is 1082 * specified, the 0 flag will be ignored.'' 1083 * -- ANSI X3J11 1084 */ 1085 number: if ((dprec = prec) >= 0) 1086 flags &= ~ZEROPAD; 1087 1088 /*- 1089 * ``The result of converting a zero value with an 1090 * explicit precision of zero is no characters.'' 1091 * -- ANSI X3J11 1092 * 1093 * ``The C Standard is clear enough as is. The call 1094 * printf("%#.0o", 0) should print 0.'' 1095 * -- Defect Report #151 1096 */ 1097 cp = buf + BUF; 1098 if (flags & INTMAX_SIZE) { 1099 if (ujval != 0 || prec != 0 || 1100 (flags & ALT && base == 8)) 1101 cp = __ujtoa(ujval, cp, base, 1102 flags & ALT, xdigs, 1103 flags & GROUPING, thousands_sep, 1104 grouping); 1105 } else { 1106 if (ulval != 0 || prec != 0 || 1107 (flags & ALT && base == 8)) 1108 cp = __ultoa(ulval, cp, base, 1109 flags & ALT, xdigs, 1110 flags & GROUPING, thousands_sep, 1111 grouping); 1112 } 1113 size = buf + BUF - cp; 1114 if (size > BUF) /* should never happen */ 1115 abort(); 1116 break; 1117 default: /* "%?" prints ?, unless ? is NUL */ 1118 if (ch == '\0') 1119 goto done; 1120 /* pretend it was %c with argument ch */ 1121 cp = buf; 1122 *cp = ch; 1123 size = 1; 1124 sign = '\0'; 1125 break; 1126 } 1127 1128 /* 1129 * All reasonable formats wind up here. At this point, `cp' 1130 * points to a string which (if not flags&LADJUST) should be 1131 * padded out to `width' places. If flags&ZEROPAD, it should 1132 * first be prefixed by any sign or other prefix; otherwise, 1133 * it should be blank padded before the prefix is emitted. 1134 * After any left-hand padding and prefixing, emit zeroes 1135 * required by a decimal [diouxX] precision, then print the 1136 * string proper, then emit zeroes required by any leftover 1137 * floating precision; finally, if LADJUST, pad with blanks. 1138 * 1139 * Compute actual size, so we know how much to pad. 1140 * size excludes decimal prec; realsz includes it. 1141 */ 1142 realsz = dprec > size ? dprec : size; 1143 if (sign) 1144 realsz++; 1145 if (ox[1]) 1146 realsz += 2; 1147 1148 prsize = width > realsz ? width : realsz; 1149 if ((unsigned)ret + prsize > INT_MAX) { 1150 ret = EOF; 1151 goto error; 1152 } 1153 1154 /* right-adjusting blank padding */ 1155 if ((flags & (LADJUST|ZEROPAD)) == 0) 1156 PAD(width - realsz, blanks); 1157 1158 /* prefix */ 1159 if (sign) 1160 PRINT(&sign, 1); 1161 1162 if (ox[1]) { /* ox[1] is either x, X, or \0 */ 1163 ox[0] = '0'; 1164 PRINT(ox, 2); 1165 } 1166 1167 /* right-adjusting zero padding */ 1168 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 1169 PAD(width - realsz, zeroes); 1170 1171 /* leading zeroes from decimal precision */ 1172 PAD(dprec - size, zeroes); 1173 1174 /* the string or number proper */ 1175 #ifndef NO_FLOATING_POINT 1176 if ((flags & FPT) == 0) { 1177 PRINT(cp, size); 1178 } else { /* glue together f_p fragments */ 1179 if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 1180 if (expt <= 0) { 1181 PRINT(zeroes, 1); 1182 if (prec || flags & ALT) 1183 PRINT(decimal_point, 1); 1184 PAD(-expt, zeroes); 1185 /* already handled initial 0's */ 1186 prec += expt; 1187 } else { 1188 PRINTANDPAD(cp, convbuf + ndig, lead, zeroes); 1189 cp += lead; 1190 if (grouping) { 1191 while (nseps>0 || nrepeats>0) { 1192 if (nrepeats > 0) 1193 nrepeats--; 1194 else { 1195 grouping--; 1196 nseps--; 1197 } 1198 PRINT(&thousands_sep, 1199 1); 1200 PRINTANDPAD(cp, 1201 convbuf + ndig, 1202 *grouping, zeroes); 1203 cp += *grouping; 1204 } 1205 if (cp > convbuf + ndig) 1206 cp = convbuf + ndig; 1207 } 1208 if (prec || flags & ALT) { 1209 buf[0] = *decimal_point; 1210 PRINT(buf, 1); 1211 } 1212 } 1213 PRINTANDPAD(cp, convbuf + ndig, prec, zeroes); 1214 } else { /* %[eE] or sufficiently long %[gG] */ 1215 if (prec > 1 || flags & ALT) { 1216 buf[0] = *cp++; 1217 buf[1] = *decimal_point; 1218 PRINT(buf, 2); 1219 PRINT(cp, ndig-1); 1220 PAD(prec - ndig, zeroes); 1221 } else /* XeYYY */ 1222 PRINT(cp, 1); 1223 PRINT(expstr, expsize); 1224 } 1225 } 1226 #else 1227 PRINT(cp, size); 1228 #endif 1229 /* left-adjusting padding (always blank) */ 1230 if (flags & LADJUST) 1231 PAD(width - realsz, blanks); 1232 1233 /* finally, adjust ret */ 1234 ret += prsize; 1235 } 1236 done: 1237 error: 1238 va_end(orgap); 1239 if (convbuf != NULL) 1240 free(convbuf); 1241 if (__sferror(fp)) 1242 ret = EOF; 1243 if ((argtable != NULL) && (argtable != statargtable)) 1244 free (argtable); 1245 return (ret); 1246 /* NOTREACHED */ 1247 } 1248 1249 /* 1250 * Find all arguments when a positional parameter is encountered. Returns a 1251 * table, indexed by argument number, of pointers to each arguments. The 1252 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. 1253 * It will be replaces with a malloc-ed one if it overflows. 1254 */ 1255 static void 1256 __find_arguments (const wchar_t *fmt0, va_list ap, union arg **argtable) 1257 { 1258 wchar_t *fmt; /* format string */ 1259 wchar_t ch; /* character from fmt */ 1260 int n, n2; /* handy integer (short term usage) */ 1261 wchar_t *cp; /* handy char pointer (short term usage) */ 1262 int flags; /* flags as above */ 1263 int width; /* width from format (%8d), or 0 */ 1264 enum typeid *typetable; /* table of types */ 1265 enum typeid stattypetable [STATIC_ARG_TBL_SIZE]; 1266 int tablesize; /* current size of type table */ 1267 int tablemax; /* largest used index in table */ 1268 int nextarg; /* 1-based argument index */ 1269 1270 /* 1271 * Add an argument type to the table, expanding if necessary. 1272 */ 1273 #define ADDTYPE(type) \ 1274 ((nextarg >= tablesize) ? \ 1275 __grow_type_table(nextarg, &typetable, &tablesize) : (void)0, \ 1276 (nextarg > tablemax) ? tablemax = nextarg : 0, \ 1277 typetable[nextarg++] = type) 1278 1279 #define ADDSARG() \ 1280 ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \ 1281 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \ 1282 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \ 1283 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \ 1284 ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT)))))) 1285 1286 #define ADDUARG() \ 1287 ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \ 1288 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \ 1289 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \ 1290 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \ 1291 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT)))))) 1292 1293 /* 1294 * Add * arguments to the type array. 1295 */ 1296 #define ADDASTER() \ 1297 n2 = 0; \ 1298 cp = fmt; \ 1299 while (is_digit(*cp)) { \ 1300 n2 = 10 * n2 + to_digit(*cp); \ 1301 cp++; \ 1302 } \ 1303 if (*cp == '$') { \ 1304 int hold = nextarg; \ 1305 nextarg = n2; \ 1306 ADDTYPE (T_INT); \ 1307 nextarg = hold; \ 1308 fmt = ++cp; \ 1309 } else { \ 1310 ADDTYPE (T_INT); \ 1311 } 1312 fmt = (wchar_t *)fmt0; 1313 typetable = stattypetable; 1314 tablesize = STATIC_ARG_TBL_SIZE; 1315 tablemax = 0; 1316 nextarg = 1; 1317 for (n = 0; n < STATIC_ARG_TBL_SIZE; n++) 1318 typetable[n] = T_UNUSED; 1319 1320 /* 1321 * Scan the format for conversions (`%' character). 1322 */ 1323 for (;;) { 1324 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 1325 /* void */; 1326 if (ch == '\0') 1327 goto done; 1328 fmt++; /* skip over '%' */ 1329 1330 flags = 0; 1331 width = 0; 1332 1333 rflag: ch = *fmt++; 1334 reswitch: switch (ch) { 1335 case ' ': 1336 case '#': 1337 goto rflag; 1338 case '*': 1339 ADDASTER (); 1340 goto rflag; 1341 case '-': 1342 case '+': 1343 case '\'': 1344 goto rflag; 1345 case '.': 1346 if ((ch = *fmt++) == '*') { 1347 ADDASTER (); 1348 goto rflag; 1349 } 1350 while (is_digit(ch)) { 1351 ch = *fmt++; 1352 } 1353 goto reswitch; 1354 case '0': 1355 goto rflag; 1356 case '1': case '2': case '3': case '4': 1357 case '5': case '6': case '7': case '8': case '9': 1358 n = 0; 1359 do { 1360 n = 10 * n + to_digit(ch); 1361 ch = *fmt++; 1362 } while (is_digit(ch)); 1363 if (ch == '$') { 1364 nextarg = n; 1365 goto rflag; 1366 } 1367 width = n; 1368 goto reswitch; 1369 #ifndef NO_FLOATING_POINT 1370 case 'L': 1371 flags |= LONGDBL; 1372 goto rflag; 1373 #endif 1374 case 'h': 1375 if (flags & SHORTINT) { 1376 flags &= ~SHORTINT; 1377 flags |= CHARINT; 1378 } else 1379 flags |= SHORTINT; 1380 goto rflag; 1381 case 'j': 1382 flags |= INTMAXT; 1383 goto rflag; 1384 case 'l': 1385 if (flags & LONGINT) { 1386 flags &= ~LONGINT; 1387 flags |= LLONGINT; 1388 } else 1389 flags |= LONGINT; 1390 goto rflag; 1391 case 'q': 1392 flags |= LLONGINT; /* not necessarily */ 1393 goto rflag; 1394 case 't': 1395 flags |= PTRDIFFT; 1396 goto rflag; 1397 case 'z': 1398 flags |= SIZET; 1399 goto rflag; 1400 case 'C': 1401 flags |= LONGINT; 1402 /*FALLTHROUGH*/ 1403 case 'c': 1404 if (flags & LONGINT) 1405 ADDTYPE(T_WINT); 1406 else 1407 ADDTYPE(T_INT); 1408 break; 1409 case 'D': 1410 flags |= LONGINT; 1411 /*FALLTHROUGH*/ 1412 case 'd': 1413 case 'i': 1414 ADDSARG(); 1415 break; 1416 #ifndef NO_FLOATING_POINT 1417 case 'a': 1418 case 'A': 1419 case 'e': 1420 case 'E': 1421 case 'f': 1422 case 'g': 1423 case 'G': 1424 if (flags & LONGDBL) 1425 ADDTYPE(T_LONG_DOUBLE); 1426 else 1427 ADDTYPE(T_DOUBLE); 1428 break; 1429 #endif /* !NO_FLOATING_POINT */ 1430 case 'n': 1431 if (flags & INTMAXT) 1432 ADDTYPE(TP_INTMAXT); 1433 else if (flags & PTRDIFFT) 1434 ADDTYPE(TP_PTRDIFFT); 1435 else if (flags & SIZET) 1436 ADDTYPE(TP_SIZET); 1437 else if (flags & LLONGINT) 1438 ADDTYPE(TP_LLONG); 1439 else if (flags & LONGINT) 1440 ADDTYPE(TP_LONG); 1441 else if (flags & SHORTINT) 1442 ADDTYPE(TP_SHORT); 1443 else if (flags & CHARINT) 1444 ADDTYPE(TP_SCHAR); 1445 else 1446 ADDTYPE(TP_INT); 1447 continue; /* no output */ 1448 case 'O': 1449 flags |= LONGINT; 1450 /*FALLTHROUGH*/ 1451 case 'o': 1452 ADDUARG(); 1453 break; 1454 case 'p': 1455 ADDTYPE(TP_VOID); 1456 break; 1457 case 'S': 1458 flags |= LONGINT; 1459 /*FALLTHROUGH*/ 1460 case 's': 1461 if (flags & LONGINT) 1462 ADDTYPE(TP_WCHAR); 1463 else 1464 ADDTYPE(TP_CHAR); 1465 break; 1466 case 'U': 1467 flags |= LONGINT; 1468 /*FALLTHROUGH*/ 1469 case 'u': 1470 case 'X': 1471 case 'x': 1472 ADDUARG(); 1473 break; 1474 default: /* "%?" prints ?, unless ? is NUL */ 1475 if (ch == '\0') 1476 goto done; 1477 break; 1478 } 1479 } 1480 done: 1481 /* 1482 * Build the argument table. 1483 */ 1484 if (tablemax >= STATIC_ARG_TBL_SIZE) { 1485 *argtable = (union arg *) 1486 malloc (sizeof (union arg) * (tablemax + 1)); 1487 } 1488 1489 (*argtable) [0].intarg = 0; 1490 for (n = 1; n <= tablemax; n++) { 1491 switch (typetable [n]) { 1492 case T_UNUSED: /* whoops! */ 1493 (*argtable) [n].intarg = va_arg (ap, int); 1494 break; 1495 case TP_SCHAR: 1496 (*argtable) [n].pschararg = va_arg (ap, signed char *); 1497 break; 1498 case TP_SHORT: 1499 (*argtable) [n].pshortarg = va_arg (ap, short *); 1500 break; 1501 case T_INT: 1502 (*argtable) [n].intarg = va_arg (ap, int); 1503 break; 1504 case T_U_INT: 1505 (*argtable) [n].uintarg = va_arg (ap, unsigned int); 1506 break; 1507 case TP_INT: 1508 (*argtable) [n].pintarg = va_arg (ap, int *); 1509 break; 1510 case T_LONG: 1511 (*argtable) [n].longarg = va_arg (ap, long); 1512 break; 1513 case T_U_LONG: 1514 (*argtable) [n].ulongarg = va_arg (ap, unsigned long); 1515 break; 1516 case TP_LONG: 1517 (*argtable) [n].plongarg = va_arg (ap, long *); 1518 break; 1519 case T_LLONG: 1520 (*argtable) [n].longlongarg = va_arg (ap, long long); 1521 break; 1522 case T_U_LLONG: 1523 (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long); 1524 break; 1525 case TP_LLONG: 1526 (*argtable) [n].plonglongarg = va_arg (ap, long long *); 1527 break; 1528 case T_PTRDIFFT: 1529 (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t); 1530 break; 1531 case TP_PTRDIFFT: 1532 (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *); 1533 break; 1534 case T_SIZET: 1535 (*argtable) [n].sizearg = va_arg (ap, size_t); 1536 break; 1537 case TP_SIZET: 1538 (*argtable) [n].psizearg = va_arg (ap, size_t *); 1539 break; 1540 case T_INTMAXT: 1541 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t); 1542 break; 1543 case T_UINTMAXT: 1544 (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t); 1545 break; 1546 case TP_INTMAXT: 1547 (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *); 1548 break; 1549 case T_DOUBLE: 1550 #ifndef NO_FLOATING_POINT 1551 (*argtable) [n].doublearg = va_arg (ap, double); 1552 #endif 1553 break; 1554 case T_LONG_DOUBLE: 1555 #ifndef NO_FLOATING_POINT 1556 (*argtable) [n].longdoublearg = va_arg (ap, long double); 1557 #endif 1558 break; 1559 case TP_CHAR: 1560 (*argtable) [n].pchararg = va_arg (ap, char *); 1561 break; 1562 case TP_VOID: 1563 (*argtable) [n].pvoidarg = va_arg (ap, void *); 1564 break; 1565 case T_WINT: 1566 (*argtable) [n].wintarg = va_arg (ap, wint_t); 1567 break; 1568 case TP_WCHAR: 1569 (*argtable) [n].pwchararg = va_arg (ap, wchar_t *); 1570 break; 1571 } 1572 } 1573 1574 if ((typetable != NULL) && (typetable != stattypetable)) 1575 free (typetable); 1576 } 1577 1578 /* 1579 * Increase the size of the type table. 1580 */ 1581 static void 1582 __grow_type_table (int nextarg, enum typeid **typetable, int *tablesize) 1583 { 1584 enum typeid *const oldtable = *typetable; 1585 const int oldsize = *tablesize; 1586 enum typeid *newtable; 1587 int n, newsize = oldsize * 2; 1588 1589 if (newsize < nextarg + 1) 1590 newsize = nextarg + 1; 1591 if (oldsize == STATIC_ARG_TBL_SIZE) { 1592 if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL) 1593 abort(); /* XXX handle better */ 1594 bcopy(oldtable, newtable, oldsize * sizeof(enum typeid)); 1595 } else { 1596 newtable = reallocf(oldtable, newsize * sizeof(enum typeid)); 1597 if (newtable == NULL) 1598 abort(); /* XXX handle better */ 1599 } 1600 for (n = oldsize; n < newsize; n++) 1601 newtable[n] = T_UNUSED; 1602 1603 *typetable = newtable; 1604 *tablesize = newsize; 1605 } 1606 1607 1608 #ifndef NO_FLOATING_POINT 1609 1610 static int 1611 exponent(wchar_t *p0, int exp, wchar_t fmtch) 1612 { 1613 wchar_t *p, *t; 1614 wchar_t expbuf[MAXEXPDIG]; 1615 1616 p = p0; 1617 *p++ = fmtch; 1618 if (exp < 0) { 1619 exp = -exp; 1620 *p++ = '-'; 1621 } 1622 else 1623 *p++ = '+'; 1624 t = expbuf + MAXEXPDIG; 1625 if (exp > 9) { 1626 do { 1627 *--t = to_char(exp % 10); 1628 } while ((exp /= 10) > 9); 1629 *--t = to_char(exp); 1630 for (; t < expbuf + MAXEXPDIG; *p++ = *t++); 1631 } 1632 else { 1633 /* 1634 * Exponents for decimal floating point conversions 1635 * (%[eEgG]) must be at least two characters long, 1636 * whereas exponents for hexadecimal conversions can 1637 * be only one character long. 1638 */ 1639 if (fmtch == 'e' || fmtch == 'E') 1640 *p++ = '0'; 1641 *p++ = to_char(exp); 1642 } 1643 return (p - p0); 1644 } 1645 #endif /* !NO_FLOATING_POINT */ 1646