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 break; 906 } 907 flags |= FPT; 908 if (ch == 'g' || ch == 'G') { 909 if (expt > -4 && expt <= prec) { 910 /* Make %[gG] smell like %[fF] */ 911 expchar = '\0'; 912 if (flags & ALT) 913 prec -= expt; 914 else 915 prec = ndig - expt; 916 if (prec < 0) 917 prec = 0; 918 } else { 919 /* 920 * Make %[gG] smell like %[eE], but 921 * trim trailing zeroes if no # flag. 922 */ 923 if (!(flags & ALT)) 924 prec = ndig; 925 } 926 } 927 if (expchar) { 928 expsize = exponent(expstr, expt - 1, expchar); 929 size = expsize + prec; 930 if (prec > 1 || flags & ALT) 931 ++size; 932 } else { 933 /* space for digits before decimal point */ 934 if (expt > 0) 935 size = expt; 936 else /* "0" */ 937 size = 1; 938 /* space for decimal pt and following digits */ 939 if (prec || flags & ALT) 940 size += prec + 1; 941 if (grouping && expt > 0) { 942 /* space for thousands' grouping */ 943 nseps = nrepeats = 0; 944 lead = expt; 945 while (*grouping != CHAR_MAX) { 946 if (lead <= *grouping) 947 break; 948 lead -= *grouping; 949 if (*(grouping+1)) { 950 nseps++; 951 grouping++; 952 } else 953 nrepeats++; 954 } 955 size += nseps + nrepeats; 956 } else 957 lead = expt; 958 } 959 break; 960 #endif /* !NO_FLOATING_POINT */ 961 case 'n': 962 /* 963 * Assignment-like behavior is specified if the 964 * value overflows or is otherwise unrepresentable. 965 * C99 says to use `signed char' for %hhn conversions. 966 */ 967 if (flags & LLONGINT) 968 *GETARG(long long *) = ret; 969 else if (flags & SIZET) 970 *GETARG(ssize_t *) = (ssize_t)ret; 971 else if (flags & PTRDIFFT) 972 *GETARG(ptrdiff_t *) = ret; 973 else if (flags & INTMAXT) 974 *GETARG(intmax_t *) = ret; 975 else if (flags & LONGINT) 976 *GETARG(long *) = ret; 977 else if (flags & SHORTINT) 978 *GETARG(short *) = ret; 979 else if (flags & CHARINT) 980 *GETARG(signed char *) = ret; 981 else 982 *GETARG(int *) = ret; 983 continue; /* no output */ 984 case 'O': 985 flags |= LONGINT; 986 /*FALLTHROUGH*/ 987 case 'o': 988 if (flags & INTMAX_SIZE) 989 ujval = UJARG(); 990 else 991 ulval = UARG(); 992 base = 8; 993 goto nosign; 994 case 'p': 995 /*- 996 * ``The argument shall be a pointer to void. The 997 * value of the pointer is converted to a sequence 998 * of printable characters, in an implementation- 999 * defined manner.'' 1000 * -- ANSI X3J11 1001 */ 1002 ujval = (uintmax_t)(uintptr_t)GETARG(void *); 1003 base = 16; 1004 xdigs = xdigs_lower; 1005 flags = flags | INTMAXT; 1006 ox[1] = 'x'; 1007 goto nosign; 1008 case 'S': 1009 flags |= LONGINT; 1010 /*FALLTHROUGH*/ 1011 case 's': 1012 if (flags & LONGINT) { 1013 if ((cp = GETARG(wchar_t *)) == NULL) 1014 cp = L"(null)"; 1015 } else { 1016 char *mbp; 1017 1018 if (convbuf != NULL) 1019 free(convbuf); 1020 if ((mbp = GETARG(char *)) == NULL) 1021 cp = L"(null)"; 1022 else { 1023 convbuf = __mbsconv(mbp, prec); 1024 if (convbuf == NULL) { 1025 fp->_flags |= __SERR; 1026 goto error; 1027 } 1028 cp = convbuf; 1029 } 1030 } 1031 1032 if (prec >= 0) { 1033 /* 1034 * can't use wcslen; can only look for the 1035 * NUL in the first `prec' characters, and 1036 * wcslen() will go further. 1037 */ 1038 wchar_t *p = wmemchr(cp, 0, (size_t)prec); 1039 1040 if (p != NULL) { 1041 size = p - cp; 1042 if (size > prec) 1043 size = prec; 1044 } else 1045 size = prec; 1046 } else 1047 size = wcslen(cp); 1048 sign = '\0'; 1049 break; 1050 case 'U': 1051 flags |= LONGINT; 1052 /*FALLTHROUGH*/ 1053 case 'u': 1054 if (flags & INTMAX_SIZE) 1055 ujval = UJARG(); 1056 else 1057 ulval = UARG(); 1058 base = 10; 1059 goto nosign; 1060 case 'X': 1061 xdigs = xdigs_upper; 1062 goto hex; 1063 case 'x': 1064 xdigs = xdigs_lower; 1065 hex: 1066 if (flags & INTMAX_SIZE) 1067 ujval = UJARG(); 1068 else 1069 ulval = UARG(); 1070 base = 16; 1071 /* leading 0x/X only if non-zero */ 1072 if (flags & ALT && 1073 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) 1074 ox[1] = ch; 1075 1076 flags &= ~GROUPING; 1077 /* unsigned conversions */ 1078 nosign: sign = '\0'; 1079 /*- 1080 * ``... diouXx conversions ... if a precision is 1081 * specified, the 0 flag will be ignored.'' 1082 * -- ANSI X3J11 1083 */ 1084 number: if ((dprec = prec) >= 0) 1085 flags &= ~ZEROPAD; 1086 1087 /*- 1088 * ``The result of converting a zero value with an 1089 * explicit precision of zero is no characters.'' 1090 * -- ANSI X3J11 1091 * 1092 * ``The C Standard is clear enough as is. The call 1093 * printf("%#.0o", 0) should print 0.'' 1094 * -- Defect Report #151 1095 */ 1096 cp = buf + BUF; 1097 if (flags & INTMAX_SIZE) { 1098 if (ujval != 0 || prec != 0 || 1099 (flags & ALT && base == 8)) 1100 cp = __ujtoa(ujval, cp, base, 1101 flags & ALT, xdigs, 1102 flags & GROUPING, thousands_sep, 1103 grouping); 1104 } else { 1105 if (ulval != 0 || prec != 0 || 1106 (flags & ALT && base == 8)) 1107 cp = __ultoa(ulval, cp, base, 1108 flags & ALT, xdigs, 1109 flags & GROUPING, thousands_sep, 1110 grouping); 1111 } 1112 size = buf + BUF - cp; 1113 if (size > BUF) /* should never happen */ 1114 abort(); 1115 break; 1116 default: /* "%?" prints ?, unless ? is NUL */ 1117 if (ch == '\0') 1118 goto done; 1119 /* pretend it was %c with argument ch */ 1120 cp = buf; 1121 *cp = ch; 1122 size = 1; 1123 sign = '\0'; 1124 break; 1125 } 1126 1127 /* 1128 * All reasonable formats wind up here. At this point, `cp' 1129 * points to a string which (if not flags&LADJUST) should be 1130 * padded out to `width' places. If flags&ZEROPAD, it should 1131 * first be prefixed by any sign or other prefix; otherwise, 1132 * it should be blank padded before the prefix is emitted. 1133 * After any left-hand padding and prefixing, emit zeroes 1134 * required by a decimal [diouxX] precision, then print the 1135 * string proper, then emit zeroes required by any leftover 1136 * floating precision; finally, if LADJUST, pad with blanks. 1137 * 1138 * Compute actual size, so we know how much to pad. 1139 * size excludes decimal prec; realsz includes it. 1140 */ 1141 realsz = dprec > size ? dprec : size; 1142 if (sign) 1143 realsz++; 1144 if (ox[1]) 1145 realsz += 2; 1146 1147 prsize = width > realsz ? width : realsz; 1148 if ((unsigned)ret + prsize > INT_MAX) { 1149 ret = EOF; 1150 goto error; 1151 } 1152 1153 /* right-adjusting blank padding */ 1154 if ((flags & (LADJUST|ZEROPAD)) == 0) 1155 PAD(width - realsz, blanks); 1156 1157 /* prefix */ 1158 if (sign) 1159 PRINT(&sign, 1); 1160 1161 if (ox[1]) { /* ox[1] is either x, X, or \0 */ 1162 ox[0] = '0'; 1163 PRINT(ox, 2); 1164 } 1165 1166 /* right-adjusting zero padding */ 1167 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 1168 PAD(width - realsz, zeroes); 1169 1170 /* leading zeroes from decimal precision */ 1171 PAD(dprec - size, zeroes); 1172 1173 /* the string or number proper */ 1174 #ifndef NO_FLOATING_POINT 1175 if ((flags & FPT) == 0) { 1176 PRINT(cp, size); 1177 } else { /* glue together f_p fragments */ 1178 if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 1179 if (expt <= 0) { 1180 PRINT(zeroes, 1); 1181 if (prec || flags & ALT) 1182 PRINT(decimal_point, 1); 1183 PAD(-expt, zeroes); 1184 /* already handled initial 0's */ 1185 prec += expt; 1186 } else { 1187 PRINTANDPAD(cp, convbuf + ndig, lead, zeroes); 1188 cp += lead; 1189 if (grouping) { 1190 while (nseps>0 || nrepeats>0) { 1191 if (nrepeats > 0) 1192 nrepeats--; 1193 else { 1194 grouping--; 1195 nseps--; 1196 } 1197 PRINT(&thousands_sep, 1198 1); 1199 PRINTANDPAD(cp, 1200 convbuf + ndig, 1201 *grouping, zeroes); 1202 cp += *grouping; 1203 } 1204 if (cp > convbuf + ndig) 1205 cp = convbuf + ndig; 1206 } 1207 if (prec || flags & ALT) { 1208 buf[0] = *decimal_point; 1209 PRINT(buf, 1); 1210 } 1211 } 1212 PRINTANDPAD(cp, convbuf + ndig, prec, zeroes); 1213 } else { /* %[eE] or sufficiently long %[gG] */ 1214 if (prec > 1 || flags & ALT) { 1215 buf[0] = *cp++; 1216 buf[1] = *decimal_point; 1217 PRINT(buf, 2); 1218 PRINT(cp, ndig-1); 1219 PAD(prec - ndig, zeroes); 1220 } else /* XeYYY */ 1221 PRINT(cp, 1); 1222 PRINT(expstr, expsize); 1223 } 1224 } 1225 #else 1226 PRINT(cp, size); 1227 #endif 1228 /* left-adjusting padding (always blank) */ 1229 if (flags & LADJUST) 1230 PAD(width - realsz, blanks); 1231 1232 /* finally, adjust ret */ 1233 ret += prsize; 1234 } 1235 done: 1236 error: 1237 va_end(orgap); 1238 if (convbuf != NULL) 1239 free(convbuf); 1240 if (__sferror(fp)) 1241 ret = EOF; 1242 if ((argtable != NULL) && (argtable != statargtable)) 1243 free (argtable); 1244 return (ret); 1245 /* NOTREACHED */ 1246 } 1247 1248 /* 1249 * Find all arguments when a positional parameter is encountered. Returns a 1250 * table, indexed by argument number, of pointers to each arguments. The 1251 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. 1252 * It will be replaces with a malloc-ed one if it overflows. 1253 */ 1254 static void 1255 __find_arguments (const wchar_t *fmt0, va_list ap, union arg **argtable) 1256 { 1257 wchar_t *fmt; /* format string */ 1258 wchar_t ch; /* character from fmt */ 1259 int n, n2; /* handy integer (short term usage) */ 1260 wchar_t *cp; /* handy char pointer (short term usage) */ 1261 int flags; /* flags as above */ 1262 int width; /* width from format (%8d), or 0 */ 1263 enum typeid *typetable; /* table of types */ 1264 enum typeid stattypetable [STATIC_ARG_TBL_SIZE]; 1265 int tablesize; /* current size of type table */ 1266 int tablemax; /* largest used index in table */ 1267 int nextarg; /* 1-based argument index */ 1268 1269 /* 1270 * Add an argument type to the table, expanding if necessary. 1271 */ 1272 #define ADDTYPE(type) \ 1273 ((nextarg >= tablesize) ? \ 1274 __grow_type_table(nextarg, &typetable, &tablesize) : (void)0, \ 1275 (nextarg > tablemax) ? tablemax = nextarg : 0, \ 1276 typetable[nextarg++] = type) 1277 1278 #define ADDSARG() \ 1279 ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \ 1280 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \ 1281 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \ 1282 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \ 1283 ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT)))))) 1284 1285 #define ADDUARG() \ 1286 ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \ 1287 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \ 1288 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \ 1289 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \ 1290 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT)))))) 1291 1292 /* 1293 * Add * arguments to the type array. 1294 */ 1295 #define ADDASTER() \ 1296 n2 = 0; \ 1297 cp = fmt; \ 1298 while (is_digit(*cp)) { \ 1299 n2 = 10 * n2 + to_digit(*cp); \ 1300 cp++; \ 1301 } \ 1302 if (*cp == '$') { \ 1303 int hold = nextarg; \ 1304 nextarg = n2; \ 1305 ADDTYPE (T_INT); \ 1306 nextarg = hold; \ 1307 fmt = ++cp; \ 1308 } else { \ 1309 ADDTYPE (T_INT); \ 1310 } 1311 fmt = (wchar_t *)fmt0; 1312 typetable = stattypetable; 1313 tablesize = STATIC_ARG_TBL_SIZE; 1314 tablemax = 0; 1315 nextarg = 1; 1316 for (n = 0; n < STATIC_ARG_TBL_SIZE; n++) 1317 typetable[n] = T_UNUSED; 1318 1319 /* 1320 * Scan the format for conversions (`%' character). 1321 */ 1322 for (;;) { 1323 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 1324 /* void */; 1325 if (ch == '\0') 1326 goto done; 1327 fmt++; /* skip over '%' */ 1328 1329 flags = 0; 1330 width = 0; 1331 1332 rflag: ch = *fmt++; 1333 reswitch: switch (ch) { 1334 case ' ': 1335 case '#': 1336 goto rflag; 1337 case '*': 1338 ADDASTER (); 1339 goto rflag; 1340 case '-': 1341 case '+': 1342 case '\'': 1343 goto rflag; 1344 case '.': 1345 if ((ch = *fmt++) == '*') { 1346 ADDASTER (); 1347 goto rflag; 1348 } 1349 while (is_digit(ch)) { 1350 ch = *fmt++; 1351 } 1352 goto reswitch; 1353 case '0': 1354 goto rflag; 1355 case '1': case '2': case '3': case '4': 1356 case '5': case '6': case '7': case '8': case '9': 1357 n = 0; 1358 do { 1359 n = 10 * n + to_digit(ch); 1360 ch = *fmt++; 1361 } while (is_digit(ch)); 1362 if (ch == '$') { 1363 nextarg = n; 1364 goto rflag; 1365 } 1366 width = n; 1367 goto reswitch; 1368 #ifndef NO_FLOATING_POINT 1369 case 'L': 1370 flags |= LONGDBL; 1371 goto rflag; 1372 #endif 1373 case 'h': 1374 if (flags & SHORTINT) { 1375 flags &= ~SHORTINT; 1376 flags |= CHARINT; 1377 } else 1378 flags |= SHORTINT; 1379 goto rflag; 1380 case 'j': 1381 flags |= INTMAXT; 1382 goto rflag; 1383 case 'l': 1384 if (flags & LONGINT) { 1385 flags &= ~LONGINT; 1386 flags |= LLONGINT; 1387 } else 1388 flags |= LONGINT; 1389 goto rflag; 1390 case 'q': 1391 flags |= LLONGINT; /* not necessarily */ 1392 goto rflag; 1393 case 't': 1394 flags |= PTRDIFFT; 1395 goto rflag; 1396 case 'z': 1397 flags |= SIZET; 1398 goto rflag; 1399 case 'C': 1400 flags |= LONGINT; 1401 /*FALLTHROUGH*/ 1402 case 'c': 1403 if (flags & LONGINT) 1404 ADDTYPE(T_WINT); 1405 else 1406 ADDTYPE(T_INT); 1407 break; 1408 case 'D': 1409 flags |= LONGINT; 1410 /*FALLTHROUGH*/ 1411 case 'd': 1412 case 'i': 1413 ADDSARG(); 1414 break; 1415 #ifndef NO_FLOATING_POINT 1416 case 'a': 1417 case 'A': 1418 case 'e': 1419 case 'E': 1420 case 'f': 1421 case 'g': 1422 case 'G': 1423 if (flags & LONGDBL) 1424 ADDTYPE(T_LONG_DOUBLE); 1425 else 1426 ADDTYPE(T_DOUBLE); 1427 break; 1428 #endif /* !NO_FLOATING_POINT */ 1429 case 'n': 1430 if (flags & INTMAXT) 1431 ADDTYPE(TP_INTMAXT); 1432 else if (flags & PTRDIFFT) 1433 ADDTYPE(TP_PTRDIFFT); 1434 else if (flags & SIZET) 1435 ADDTYPE(TP_SIZET); 1436 else if (flags & LLONGINT) 1437 ADDTYPE(TP_LLONG); 1438 else if (flags & LONGINT) 1439 ADDTYPE(TP_LONG); 1440 else if (flags & SHORTINT) 1441 ADDTYPE(TP_SHORT); 1442 else if (flags & CHARINT) 1443 ADDTYPE(TP_SCHAR); 1444 else 1445 ADDTYPE(TP_INT); 1446 continue; /* no output */ 1447 case 'O': 1448 flags |= LONGINT; 1449 /*FALLTHROUGH*/ 1450 case 'o': 1451 ADDUARG(); 1452 break; 1453 case 'p': 1454 ADDTYPE(TP_VOID); 1455 break; 1456 case 'S': 1457 flags |= LONGINT; 1458 /*FALLTHROUGH*/ 1459 case 's': 1460 if (flags & LONGINT) 1461 ADDTYPE(TP_WCHAR); 1462 else 1463 ADDTYPE(TP_CHAR); 1464 break; 1465 case 'U': 1466 flags |= LONGINT; 1467 /*FALLTHROUGH*/ 1468 case 'u': 1469 case 'X': 1470 case 'x': 1471 ADDUARG(); 1472 break; 1473 default: /* "%?" prints ?, unless ? is NUL */ 1474 if (ch == '\0') 1475 goto done; 1476 break; 1477 } 1478 } 1479 done: 1480 /* 1481 * Build the argument table. 1482 */ 1483 if (tablemax >= STATIC_ARG_TBL_SIZE) { 1484 *argtable = (union arg *) 1485 malloc (sizeof (union arg) * (tablemax + 1)); 1486 } 1487 1488 (*argtable) [0].intarg = 0; 1489 for (n = 1; n <= tablemax; n++) { 1490 switch (typetable [n]) { 1491 case T_UNUSED: /* whoops! */ 1492 (*argtable) [n].intarg = va_arg (ap, int); 1493 break; 1494 case TP_SCHAR: 1495 (*argtable) [n].pschararg = va_arg (ap, signed char *); 1496 break; 1497 case TP_SHORT: 1498 (*argtable) [n].pshortarg = va_arg (ap, short *); 1499 break; 1500 case T_INT: 1501 (*argtable) [n].intarg = va_arg (ap, int); 1502 break; 1503 case T_U_INT: 1504 (*argtable) [n].uintarg = va_arg (ap, unsigned int); 1505 break; 1506 case TP_INT: 1507 (*argtable) [n].pintarg = va_arg (ap, int *); 1508 break; 1509 case T_LONG: 1510 (*argtable) [n].longarg = va_arg (ap, long); 1511 break; 1512 case T_U_LONG: 1513 (*argtable) [n].ulongarg = va_arg (ap, unsigned long); 1514 break; 1515 case TP_LONG: 1516 (*argtable) [n].plongarg = va_arg (ap, long *); 1517 break; 1518 case T_LLONG: 1519 (*argtable) [n].longlongarg = va_arg (ap, long long); 1520 break; 1521 case T_U_LLONG: 1522 (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long); 1523 break; 1524 case TP_LLONG: 1525 (*argtable) [n].plonglongarg = va_arg (ap, long long *); 1526 break; 1527 case T_PTRDIFFT: 1528 (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t); 1529 break; 1530 case TP_PTRDIFFT: 1531 (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *); 1532 break; 1533 case T_SIZET: 1534 (*argtable) [n].sizearg = va_arg (ap, size_t); 1535 break; 1536 case TP_SIZET: 1537 (*argtable) [n].psizearg = va_arg (ap, size_t *); 1538 break; 1539 case T_INTMAXT: 1540 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t); 1541 break; 1542 case T_UINTMAXT: 1543 (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t); 1544 break; 1545 case TP_INTMAXT: 1546 (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *); 1547 break; 1548 case T_DOUBLE: 1549 #ifndef NO_FLOATING_POINT 1550 (*argtable) [n].doublearg = va_arg (ap, double); 1551 #endif 1552 break; 1553 case T_LONG_DOUBLE: 1554 #ifndef NO_FLOATING_POINT 1555 (*argtable) [n].longdoublearg = va_arg (ap, long double); 1556 #endif 1557 break; 1558 case TP_CHAR: 1559 (*argtable) [n].pchararg = va_arg (ap, char *); 1560 break; 1561 case TP_VOID: 1562 (*argtable) [n].pvoidarg = va_arg (ap, void *); 1563 break; 1564 case T_WINT: 1565 (*argtable) [n].wintarg = va_arg (ap, wint_t); 1566 break; 1567 case TP_WCHAR: 1568 (*argtable) [n].pwchararg = va_arg (ap, wchar_t *); 1569 break; 1570 } 1571 } 1572 1573 if ((typetable != NULL) && (typetable != stattypetable)) 1574 free (typetable); 1575 } 1576 1577 /* 1578 * Increase the size of the type table. 1579 */ 1580 static void 1581 __grow_type_table (int nextarg, enum typeid **typetable, int *tablesize) 1582 { 1583 enum typeid *const oldtable = *typetable; 1584 const int oldsize = *tablesize; 1585 enum typeid *newtable; 1586 int n, newsize = oldsize * 2; 1587 1588 if (newsize < nextarg + 1) 1589 newsize = nextarg + 1; 1590 if (oldsize == STATIC_ARG_TBL_SIZE) { 1591 if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL) 1592 abort(); /* XXX handle better */ 1593 bcopy(oldtable, newtable, oldsize * sizeof(enum typeid)); 1594 } else { 1595 newtable = reallocf(oldtable, newsize * sizeof(enum typeid)); 1596 if (newtable == NULL) 1597 abort(); /* XXX handle better */ 1598 } 1599 for (n = oldsize; n < newsize; n++) 1600 newtable[n] = T_UNUSED; 1601 1602 *typetable = newtable; 1603 *tablesize = newsize; 1604 } 1605 1606 1607 #ifndef NO_FLOATING_POINT 1608 1609 static int 1610 exponent(wchar_t *p0, int exp, wchar_t fmtch) 1611 { 1612 wchar_t *p, *t; 1613 wchar_t expbuf[MAXEXPDIG]; 1614 1615 p = p0; 1616 *p++ = fmtch; 1617 if (exp < 0) { 1618 exp = -exp; 1619 *p++ = '-'; 1620 } 1621 else 1622 *p++ = '+'; 1623 t = expbuf + MAXEXPDIG; 1624 if (exp > 9) { 1625 do { 1626 *--t = to_char(exp % 10); 1627 } while ((exp /= 10) > 9); 1628 *--t = to_char(exp); 1629 for (; t < expbuf + MAXEXPDIG; *p++ = *t++); 1630 } 1631 else { 1632 /* 1633 * Exponents for decimal floating point conversions 1634 * (%[eEgG]) must be at least two characters long, 1635 * whereas exponents for hexadecimal conversions can 1636 * be only one character long. 1637 */ 1638 if (fmtch == 'e' || fmtch == 'E') 1639 *p++ = '0'; 1640 *p++ = to_char(exp); 1641 } 1642 return (p - p0); 1643 } 1644 #endif /* !NO_FLOATING_POINT */ 1645