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 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)vfprintf.c 8.1 (Berkeley) 6/4/93 37 * $FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.34 2001/12/13 19:45:41 phantom Exp $ 38 * $DragonFly: src/lib/libc/stdio/vfprintf.c,v 1.16 2006/07/05 15:04:54 joerg Exp $ 39 */ 40 41 /* 42 * Actual printf innards. 43 * 44 * This code is large and complicated... 45 */ 46 47 #include "namespace.h" 48 #include <sys/types.h> 49 50 #include <ctype.h> 51 #include <limits.h> 52 #include <locale.h> 53 #include <stddef.h> 54 #include <stdint.h> 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <string.h> 58 #include <wchar.h> 59 60 #include <stdarg.h> 61 #include "un-namespace.h" 62 63 #include "libc_private.h" 64 #include "local.h" 65 #include "priv_stdio.h" 66 67 /* Borrowed from sys/systm.h, which is _KERNEL-only: */ 68 #define CTASSERT(x) _CTASSERT(x, __LINE__) 69 #define _CTASSERT(x, y) __CTASSERT(x, y) 70 #define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] 71 72 /* This code assumes that a quad_t can fit in a long long: */ 73 CTASSERT(sizeof(quad_t) == sizeof(long long)); 74 75 union arg { 76 int intarg; 77 unsigned int uintarg; 78 long longarg; 79 unsigned long ulongarg; 80 long long longlongarg; 81 unsigned long long ulonglongarg; 82 ptrdiff_t ptrdiffarg; 83 size_t sizearg; 84 intmax_t intmaxarg; 85 uintmax_t uintmaxarg; 86 void *pvoidarg; 87 char *pchararg; 88 signed char *pschararg; 89 short *pshortarg; 90 int *pintarg; 91 long *plongarg; 92 long long *plonglongarg; 93 ptrdiff_t *pptrdiffarg; 94 size_t *psizearg; 95 intmax_t *pintmaxarg; 96 #ifndef NO_FLOATING_POINT 97 double doublearg; 98 long double longdoublearg; 99 #endif 100 wint_t wintarg; 101 wchar_t *pwchararg; 102 }; 103 104 /* 105 * Type ids for argument type table. 106 */ 107 enum typeid { 108 T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT, 109 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG, 110 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET, 111 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR, 112 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR 113 }; 114 115 static int __sprint(FILE *, struct __suio *); 116 static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0); 117 static char * __ujtoa(uintmax_t, char *, int, int, const char *, int, 118 char, const char *); 119 static char * __ultoa(u_long, char *, int, int, const char *, int, 120 char, const char *); 121 static void __find_arguments(const char *, va_list, union arg **); 122 static void __grow_type_table(int, enum typeid **, int *); 123 124 /* 125 * Flush out all the vectors defined by the given uio, 126 * then reset it so that it can be reused. 127 */ 128 static int 129 __sprint(FILE *fp, struct __suio *uio) 130 { 131 int err; 132 133 if (uio->uio_resid == 0) { 134 uio->uio_iovcnt = 0; 135 return (0); 136 } 137 err = __sfvwrite(fp, uio); 138 uio->uio_resid = 0; 139 uio->uio_iovcnt = 0; 140 return (err); 141 } 142 143 /* 144 * Helper function for `fprintf to unbuffered unix file': creates a 145 * temporary buffer. We only work on write-only files; this avoids 146 * worries about ungetc buffers and so forth. 147 */ 148 static int 149 __sbprintf(FILE *fp, const char *fmt, va_list ap) 150 { 151 int ret; 152 FILE fake; 153 unsigned char buf[BUFSIZ]; 154 155 /* copy the important variables */ 156 fake.pub._flags = fp->pub._flags & ~__SNBF; 157 fake.pub._fileno = fp->pub._fileno; 158 fake._cookie = fp->_cookie; 159 fake._write = fp->_write; 160 161 fake._up = fp->_up; 162 fake.fl_mutex = fp->fl_mutex; 163 fake.fl_owner = fp->fl_owner; 164 fake.fl_count = fp->fl_count; 165 memset(WCIO_GET(&fake), 0, sizeof(struct wchar_io_data)); 166 167 /* set up the buffer */ 168 fake._bf._base = fake.pub._p = buf; 169 fake._bf._size = fake.pub._w = sizeof(buf); 170 fake.pub._lbfsize = 0; /* not actually used, but Just In Case */ 171 172 /* do the work, then copy any error status */ 173 ret = __vfprintf(&fake, fmt, ap); 174 if (ret >= 0 && __fflush(&fake)) 175 ret = EOF; 176 if (fake.pub._flags & __SERR) 177 fp->pub._flags |= __SERR; 178 return (ret); 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 char * 195 __ultoa(u_long val, char *endp, int base, int octzero, const char *xdigs, 196 int needgrp, char thousep, const char *grp) 197 { 198 char *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[(size_t)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 char * 272 __ujtoa(uintmax_t val, char *endp, int base, int octzero, const char *xdigs, 273 int needgrp, char thousep, const char *grp) 274 { 275 char *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[(size_t)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 wide character string argument for the %ls format to a multibyte 344 * string representation. If not -1, prec specifies the maximum number of 345 * bytes to output, and also means that we can't assume that the wide char. 346 * string ends is null-terminated. 347 */ 348 static char * 349 __wcsconv(wchar_t *wcsarg, int prec) 350 { 351 static const mbstate_t initial; 352 mbstate_t mbs; 353 char buf[MB_LEN_MAX]; 354 wchar_t *p; 355 char *convbuf; 356 size_t clen, nbytes; 357 358 /* Allocate space for the maximum number of bytes we could output. */ 359 if (prec < 0) { 360 p = wcsarg; 361 mbs = initial; 362 nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs); 363 if (nbytes == (size_t)-1) 364 return (NULL); 365 } else { 366 /* 367 * Optimisation: if the output precision is small enough, 368 * just allocate enough memory for the maximum instead of 369 * scanning the string. 370 */ 371 if (prec < 128) { 372 nbytes = prec; 373 } else { 374 nbytes = 0; 375 p = wcsarg; 376 mbs = initial; 377 for (;;) { 378 clen = wcrtomb(buf, *p++, &mbs); 379 if (clen == 0 || clen == (size_t)-1 || 380 nbytes + clen > prec) 381 break; 382 nbytes += clen; 383 } 384 } 385 } 386 if ((convbuf = malloc(nbytes + 1)) == NULL) 387 return (NULL); 388 389 /* Fill the output buffer. */ 390 p = wcsarg; 391 mbs = initial; 392 if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p, 393 nbytes, &mbs)) == (size_t)-1) { 394 free(convbuf); 395 return (NULL); 396 } 397 convbuf[nbytes] = '\0'; 398 return (convbuf); 399 } 400 401 /* 402 * MT-safe version 403 */ 404 int 405 vfprintf(FILE *fp, const char *fmt0, va_list ap) 406 { 407 int ret; 408 409 FLOCKFILE(fp); 410 ret = __vfprintf(fp, fmt0, ap); 411 FUNLOCKFILE(fp); 412 return (ret); 413 } 414 415 #ifndef NO_FLOATING_POINT 416 #include <math.h> 417 #include "floatio.h" 418 419 #define BUF ((MAXEXPDIG * 2) + MAXFRACT + 1) /* + decimal point */ 420 #define DEFPREC 6 421 422 extern char *__dtoa(double, int, int, int *, int *, char **); 423 extern void __freedtoa(char *s); 424 425 static char *cvt(double, int, int, char *, int *, int, int *); 426 static int exponent (char *, int, int); 427 428 #else /* no NO_FLOATING_POINT */ 429 430 #define BUF 136 431 432 #endif /* NO_FLOATING_POINT */ 433 434 #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ 435 436 /* 437 * Flags used during conversion. 438 */ 439 #define ALT 0x001 /* alternate form */ 440 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */ 441 #define LADJUST 0x004 /* left adjustment */ 442 #define LONGDBL 0x008 /* long double */ 443 #define LONGINT 0x010 /* long integer */ 444 #define LLONGINT 0x020 /* long long integer */ 445 #define SHORTINT 0x040 /* short integer */ 446 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ 447 #define FPT 0x100 /* Floating point number */ 448 #define GROUPING 0x200 /* use grouping ("'" flag) */ 449 /* C99 additional size modifiers: */ 450 #define SIZET 0x400 /* size_t */ 451 #define PTRDIFFT 0x800 /* ptrdiff_t */ 452 #define INTMAXT 0x1000 /* intmax_t */ 453 #define CHARINT 0x2000 /* print char using int format */ 454 /* 455 * Non-MT-safe version 456 */ 457 int 458 __vfprintf(FILE *fp, const char *fmt0, va_list ap) 459 { 460 char *fmt; /* format string */ 461 int ch; /* character from fmt */ 462 int n, n2; /* handy integer (short term usage) */ 463 char *cp; /* handy char pointer (short term usage) */ 464 struct __siov *iovp; /* for PRINT macro */ 465 int flags; /* flags as above */ 466 int ret; /* return value accumulator */ 467 int width; /* width from format (%8d), or 0 */ 468 int prec; /* precision from format (%.3d), or -1 */ 469 char sign; /* sign prefix (' ', '+', '-', or \0) */ 470 char thousands_sep; /* locale specific thousands separator */ 471 const char *grouping; /* locale specific numeric grouping rules */ 472 #ifndef NO_FLOATING_POINT 473 const char *decimal_point; /* locale specific decimal point */ 474 char softsign; /* temporary negative sign for floats */ 475 double _double; /* double precision arguments %[eEfgG] */ 476 int expt; /* integer value of exponent */ 477 int expsize; /* character count for expstr */ 478 int ndig; /* actual number of digits returned by cvt */ 479 char expstr[7]; /* buffer for exponent string */ 480 char *dtoaresult; /* buffer allocated by dtoa */ 481 #endif 482 u_long ulval; /* integer arguments %[diouxX] */ 483 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */ 484 int base; /* base for [diouxX] conversion */ 485 int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 486 int realsz; /* field size expanded by dprec, sign, etc */ 487 int size; /* size of converted field or string */ 488 int prsize; /* max size of printed field */ 489 const char *xdigs; /* digits for [xX] conversion */ 490 #define NIOV 8 491 struct __suio uio; /* output information: summary */ 492 struct __siov iov[NIOV];/* ... and individual io vectors */ 493 char buf[BUF]; /* space for %c, %[diouxX], %[eEfFgG] */ 494 char ox[2]; /* space for 0x hex-prefix */ 495 union arg *argtable; /* args, built due to positional arg */ 496 union arg statargtable[STATIC_ARG_TBL_SIZE]; 497 int nextarg; /* 1-based argument index */ 498 va_list orgap; /* original argument pointer */ 499 char *convbuf; /* wide to multibyte conversion result */ 500 501 _double = 0; 502 expsize = 0; 503 ulval = 0; 504 ujval = 0; 505 xdigs = NULL; 506 507 /* 508 * Choose PADSIZE to trade efficiency vs. size. If larger printf 509 * fields occur frequently, increase PADSIZE and make the initialisers 510 * below longer. 511 */ 512 #define PADSIZE 16 /* pad chunk size */ 513 static char blanks[PADSIZE] = 514 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 515 static char zeroes[PADSIZE] = 516 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 517 518 /* 519 * BEWARE, these `goto error' on error, and PAD uses `n'. 520 */ 521 #define PRINT(ptr, len) { \ 522 iovp->iov_base = __DECONST(void *, ptr); \ 523 iovp->iov_len = (len); \ 524 uio.uio_resid += (len); \ 525 iovp++; \ 526 if (++uio.uio_iovcnt >= NIOV) { \ 527 if (__sprint(fp, &uio)) \ 528 goto error; \ 529 iovp = iov; \ 530 } \ 531 } 532 #define PAD(howmany, with) { \ 533 if ((n = (howmany)) > 0) { \ 534 while (n > PADSIZE) { \ 535 PRINT(with, PADSIZE); \ 536 n -= PADSIZE; \ 537 } \ 538 PRINT(with, n); \ 539 } \ 540 } 541 #define FLUSH() { \ 542 if (uio.uio_resid && __sprint(fp, &uio)) \ 543 goto error; \ 544 uio.uio_iovcnt = 0; \ 545 iovp = iov; \ 546 } 547 548 /* 549 * Get the argument indexed by nextarg. If the argument table is 550 * built, use it to get the argument. If its not, get the next 551 * argument (and arguments must be gotten sequentially). 552 */ 553 #define GETARG(type) \ 554 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ 555 (nextarg++, va_arg(ap, type))) 556 557 /* 558 * To extend shorts properly, we need both signed and unsigned 559 * argument extraction methods. 560 */ 561 #define SARG() \ 562 (flags&LONGINT ? GETARG(long) : \ 563 flags&SHORTINT ? (long)(short)GETARG(int) : \ 564 flags&CHARINT ? (long)(signed char)GETARG(int) : \ 565 (long)GETARG(int)) 566 #define UARG() \ 567 (flags&LONGINT ? GETARG(u_long) : \ 568 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \ 569 flags&CHARINT ? (u_long)(u_char)GETARG(int) : \ 570 (u_long)GETARG(u_int)) 571 #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT) 572 #define SJARG() \ 573 (flags&INTMAXT ? GETARG(intmax_t) : \ 574 flags&SIZET ? (intmax_t)GETARG(size_t) : \ 575 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \ 576 (intmax_t)GETARG(long long)) 577 #define UJARG() \ 578 (flags&INTMAXT ? GETARG(uintmax_t) : \ 579 flags&SIZET ? (uintmax_t)GETARG(size_t) : \ 580 flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \ 581 (uintmax_t)GETARG(unsigned long long)) 582 583 /* 584 * Get * arguments, including the form *nn$. Preserve the nextarg 585 * that the argument can be gotten once the type is determined. 586 */ 587 #define GETASTER(val) \ 588 n2 = 0; \ 589 cp = fmt; \ 590 while (is_digit(*cp)) { \ 591 n2 = 10 * n2 + to_digit(*cp); \ 592 cp++; \ 593 } \ 594 if (*cp == '$') { \ 595 int hold = nextarg; \ 596 if (argtable == NULL) { \ 597 argtable = statargtable; \ 598 __find_arguments (fmt0, orgap, &argtable); \ 599 } \ 600 nextarg = n2; \ 601 val = GETARG (int); \ 602 nextarg = hold; \ 603 fmt = ++cp; \ 604 } else { \ 605 val = GETARG (int); \ 606 } 607 608 609 thousands_sep = '\0'; 610 grouping = NULL; 611 convbuf = NULL; 612 #ifndef NO_FLOATING_POINT 613 dtoaresult = NULL; 614 decimal_point = localeconv()->decimal_point; 615 #endif 616 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ 617 if (cantwrite(fp)) { 618 return (EOF); 619 } 620 621 /* optimise fprintf(stderr) (and other unbuffered Unix files) */ 622 if ((fp->pub._flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && 623 fp->pub._fileno >= 0) { 624 return (__sbprintf(fp, fmt0, ap)); 625 } 626 627 fmt = (char *)fmt0; 628 argtable = NULL; 629 nextarg = 1; 630 va_copy(orgap, ap); 631 uio.uio_iov = iovp = iov; 632 uio.uio_resid = 0; 633 uio.uio_iovcnt = 0; 634 ret = 0; 635 636 /* 637 * Scan the format for conversions (`%' character). 638 */ 639 for (;;) { 640 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 641 /* void */; 642 if ((n = fmt - cp) != 0) { 643 if ((unsigned)ret + n > INT_MAX) { 644 ret = EOF; 645 goto error; 646 } 647 PRINT(cp, n); 648 ret += n; 649 } 650 if (ch == '\0') 651 goto done; 652 fmt++; /* skip over '%' */ 653 654 flags = 0; 655 dprec = 0; 656 width = 0; 657 prec = -1; 658 sign = '\0'; 659 660 rflag: ch = *fmt++; 661 reswitch: switch (ch) { 662 case ' ': 663 /* 664 * ``If the space and + flags both appear, the space 665 * flag will be ignored.'' 666 * -- ANSI X3J11 667 */ 668 if (!sign) 669 sign = ' '; 670 goto rflag; 671 case '#': 672 flags |= ALT; 673 goto rflag; 674 case '*': 675 /* 676 * ``A negative field width argument is taken as a 677 * - flag followed by a positive field width.'' 678 * -- ANSI X3J11 679 * They don't exclude field widths read from args. 680 */ 681 GETASTER (width); 682 if (width >= 0) 683 goto rflag; 684 width = -width; 685 /* FALLTHROUGH */ 686 case '-': 687 flags |= LADJUST; 688 goto rflag; 689 case '+': 690 sign = '+'; 691 goto rflag; 692 case '\'': 693 flags |= GROUPING; 694 thousands_sep = *(localeconv()->thousands_sep); 695 grouping = localeconv()->grouping; 696 goto rflag; 697 case '.': 698 if ((ch = *fmt++) == '*') { 699 GETASTER (n); 700 prec = n < 0 ? -1 : n; 701 goto rflag; 702 } 703 n = 0; 704 while (is_digit(ch)) { 705 n = 10 * n + to_digit(ch); 706 ch = *fmt++; 707 } 708 prec = n < 0 ? -1 : n; 709 goto reswitch; 710 case '0': 711 /* 712 * ``Note that 0 is taken as a flag, not as the 713 * beginning of a field width.'' 714 * -- ANSI X3J11 715 */ 716 flags |= ZEROPAD; 717 goto rflag; 718 case '1': case '2': case '3': case '4': 719 case '5': case '6': case '7': case '8': case '9': 720 n = 0; 721 do { 722 n = 10 * n + to_digit(ch); 723 ch = *fmt++; 724 } while (is_digit(ch)); 725 if (ch == '$') { 726 nextarg = n; 727 if (argtable == NULL) { 728 argtable = statargtable; 729 __find_arguments (fmt0, orgap, 730 &argtable); 731 } 732 goto rflag; 733 } 734 width = n; 735 goto reswitch; 736 #ifndef NO_FLOATING_POINT 737 case 'L': 738 flags |= LONGDBL; 739 goto rflag; 740 #endif 741 case 'h': 742 if (flags & SHORTINT) { 743 flags &= ~SHORTINT; 744 flags |= CHARINT; 745 } else 746 flags |= SHORTINT; 747 goto rflag; 748 case 'j': 749 flags |= INTMAXT; 750 goto rflag; 751 case 'l': 752 if (flags & LONGINT) { 753 flags &= ~LONGINT; 754 flags |= LLONGINT; 755 } else 756 flags |= LONGINT; 757 goto rflag; 758 case 'q': 759 flags |= LLONGINT; 760 goto rflag; 761 case 't': 762 flags |= PTRDIFFT; 763 goto rflag; 764 case 'z': 765 flags |= SIZET; 766 goto rflag; 767 case 'C': 768 flags |= LONGINT; 769 /*FALLTHROUGH*/ 770 case 'c': 771 if (flags & LONGINT) { 772 static const mbstate_t initial; 773 mbstate_t mbs; 774 size_t mbseqlen; 775 776 mbs = initial; 777 mbseqlen = wcrtomb(cp = buf, 778 (wchar_t)GETARG(wint_t), &mbs); 779 if (mbseqlen == (size_t)-1) { 780 fp->pub._flags |= __SERR; 781 goto error; 782 } 783 size = (int)mbseqlen; 784 } else { 785 *(cp = buf) = GETARG(int); 786 size = 1; 787 } 788 sign = '\0'; 789 break; 790 case 'D': 791 flags |= LONGINT; 792 /*FALLTHROUGH*/ 793 case 'd': 794 case 'i': 795 if (flags & INTMAX_SIZE) { 796 ujval = SJARG(); 797 if ((intmax_t)ujval < 0) { 798 ujval = -ujval; 799 sign = '-'; 800 } 801 } else { 802 ulval = SARG(); 803 if ((long)ulval < 0) { 804 ulval = -ulval; 805 sign = '-'; 806 } 807 } 808 base = 10; 809 goto number; 810 #ifndef NO_FLOATING_POINT 811 #ifdef HEXFLOAT 812 case 'a': 813 case 'A': 814 #endif 815 case 'e': 816 case 'E': 817 /* 818 * Grouping apply to %i, %d, %u, %f, %F, %g, %G 819 * conversion specifiers only. For other conversions 820 * behavior is undefined. 821 * -- POSIX 822 */ 823 flags &= ~GROUPING; 824 /*FALLTHROUGH*/ 825 case 'f': 826 case 'F': 827 goto fp_begin; 828 case 'g': 829 case 'G': 830 if (prec == 0) 831 prec = 1; 832 fp_begin: if (prec == -1) 833 prec = DEFPREC; 834 if (flags & LONGDBL) 835 /* XXX this loses precision. */ 836 _double = (double)GETARG(long double); 837 else 838 _double = GETARG(double); 839 /* do this before tricky precision changes */ 840 if (isinf(_double)) { 841 if (_double < 0) 842 sign = '-'; 843 if (isupper(ch)) 844 cp = "INF"; 845 else 846 cp = "inf"; 847 size = 3; 848 break; 849 } 850 if (isnan(_double)) { 851 if (isupper(ch)) 852 cp = "NAN"; 853 else 854 cp = "nan"; 855 size = 3; 856 break; 857 } 858 flags |= FPT; 859 if (dtoaresult != NULL) { 860 __freedtoa(dtoaresult); 861 dtoaresult = NULL; 862 } 863 dtoaresult = cp = cvt(_double, prec, flags, &softsign, 864 &expt, ch, &ndig); 865 if (ch == 'g' || ch == 'G') { 866 if (expt <= -4 || expt > prec) 867 ch = (ch == 'g') ? 'e' : 'E'; 868 else 869 ch = 'g'; 870 } 871 if (ch == 'e' || ch == 'E') { 872 --expt; 873 expsize = exponent(expstr, expt, ch); 874 size = expsize + ndig; 875 if (ndig > 1 || flags & ALT) 876 ++size; 877 } else if (ch == 'f' || ch == 'F') { 878 if (expt > 0) { 879 size = expt; 880 if (prec || flags & ALT) 881 size += prec + 1; 882 } else /* "0.X" */ 883 size = prec + 2; 884 } else if (expt >= ndig) { /* fixed g fmt */ 885 size = expt; 886 if (flags & ALT) 887 ++size; 888 } else 889 size = ndig + (expt > 0 ? 890 1 : 2 - expt); 891 892 if (softsign) 893 sign = '-'; 894 break; 895 #endif /* NO_FLOATING_POINT */ 896 case 'n': 897 /* 898 * Assignment-like behavior is specified if the 899 * value overflows or is otherwise unrepresentable. 900 * C99 says to use `signed char' for %hhn conversions. 901 */ 902 if (flags & LLONGINT) 903 *GETARG(long long *) = ret; 904 else if (flags & SIZET) 905 *GETARG(ssize_t *) = (ssize_t)ret; 906 else if (flags & PTRDIFFT) 907 *GETARG(ptrdiff_t *) = ret; 908 else if (flags & INTMAXT) 909 *GETARG(intmax_t *) = ret; 910 else if (flags & LONGINT) 911 *GETARG(long *) = ret; 912 else if (flags & SHORTINT) 913 *GETARG(short *) = ret; 914 else if (flags & CHARINT) 915 *GETARG(signed char *) = ret; 916 else 917 *GETARG(int *) = ret; 918 continue; /* no output */ 919 case 'O': 920 flags |= LONGINT; 921 /*FALLTHROUGH*/ 922 case 'o': 923 if (flags & INTMAX_SIZE) 924 ujval = UJARG(); 925 else 926 ulval = UARG(); 927 base = 8; 928 goto nosign; 929 case 'p': 930 /* 931 * ``The argument shall be a pointer to void. The 932 * value of the pointer is converted to a sequence 933 * of printable characters, in an implementation- 934 * defined manner.'' 935 * -- ANSI X3J11 936 */ 937 ujval = (uintmax_t)(uintptr_t)GETARG(void *); 938 base = 16; 939 xdigs = "0123456789abcdef"; 940 flags = flags | INTMAXT | HEXPREFIX; 941 ch = 'x'; 942 goto nosign; 943 case 'S': 944 flags |= LONGINT; 945 /*FALLTHROUGH*/ 946 case 's': 947 if (flags & LONGINT) { 948 wchar_t *wcp; 949 950 if (convbuf != NULL) 951 free(convbuf); 952 if ((wcp = GETARG(wchar_t *)) == NULL) 953 cp = "(null)"; 954 else { 955 convbuf = __wcsconv(wcp, prec); 956 if (convbuf == NULL) { 957 fp->pub._flags |= __SERR; 958 goto error; 959 } 960 cp = convbuf; 961 } 962 } else if ((cp = GETARG(char *)) == NULL) 963 cp = "(null)"; 964 if (prec >= 0) { 965 /* 966 * can't use strlen; can only look for the 967 * NUL in the first `prec' characters, and 968 * strlen() will go further. 969 */ 970 char *p = memchr(cp, 0, (size_t)prec); 971 972 if (p != NULL) { 973 size = p - cp; 974 if (size > prec) 975 size = prec; 976 } else 977 size = prec; 978 } else 979 size = strlen(cp); 980 sign = '\0'; 981 break; 982 case 'U': 983 flags |= LONGINT; 984 /*FALLTHROUGH*/ 985 case 'u': 986 if (flags & INTMAX_SIZE) 987 ujval = UJARG(); 988 else 989 ulval = UARG(); 990 base = 10; 991 goto nosign; 992 case 'X': 993 xdigs = "0123456789ABCDEF"; 994 goto hex; 995 case 'x': 996 xdigs = "0123456789abcdef"; 997 hex: 998 if (flags & INTMAX_SIZE) 999 ujval = UJARG(); 1000 else 1001 ulval = UARG(); 1002 base = 16; 1003 /* leading 0x/X only if non-zero */ 1004 if (flags & ALT && 1005 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) 1006 flags |= HEXPREFIX; 1007 1008 flags &= ~GROUPING; 1009 /* unsigned conversions */ 1010 nosign: sign = '\0'; 1011 /* 1012 * ``... diouXx conversions ... if a precision is 1013 * specified, the 0 flag will be ignored.'' 1014 * -- ANSI X3J11 1015 */ 1016 number: if ((dprec = prec) >= 0) 1017 flags &= ~ZEROPAD; 1018 1019 /* 1020 * ``The result of converting a zero value with an 1021 * explicit precision of zero is no characters.'' 1022 * -- ANSI X3J11 1023 */ 1024 cp = buf + BUF; 1025 if (flags & INTMAX_SIZE) { 1026 if (ujval != 0 || prec != 0) 1027 cp = __ujtoa(ujval, cp, base, 1028 flags & ALT, xdigs, 1029 flags & GROUPING, thousands_sep, 1030 grouping); 1031 } else { 1032 if (ulval != 0 || prec != 0) 1033 cp = __ultoa(ulval, cp, base, 1034 flags & ALT, xdigs, 1035 flags & GROUPING, thousands_sep, 1036 grouping); 1037 } 1038 size = buf + BUF - cp; 1039 break; 1040 default: /* "%?" prints ?, unless ? is NUL */ 1041 if (ch == '\0') 1042 goto done; 1043 /* pretend it was %c with argument ch */ 1044 cp = buf; 1045 *cp = ch; 1046 size = 1; 1047 sign = '\0'; 1048 break; 1049 } 1050 1051 /* 1052 * All reasonable formats wind up here. At this point, `cp' 1053 * points to a string which (if not flags&LADJUST) should be 1054 * padded out to `width' places. If flags&ZEROPAD, it should 1055 * first be prefixed by any sign or other prefix; otherwise, 1056 * it should be blank padded before the prefix is emitted. 1057 * After any left-hand padding and prefixing, emit zeroes 1058 * required by a decimal [diouxX] precision, then print the 1059 * string proper, then emit zeroes required by any leftover 1060 * floating precision; finally, if LADJUST, pad with blanks. 1061 * 1062 * Compute actual size, so we know how much to pad. 1063 * size excludes decimal prec; realsz includes it. 1064 */ 1065 realsz = dprec > size ? dprec : size; 1066 if (sign) 1067 realsz++; 1068 else if (flags & HEXPREFIX) 1069 realsz += 2; 1070 1071 prsize = width > realsz ? width : realsz; 1072 if ((unsigned)ret + prsize > INT_MAX) { 1073 ret = EOF; 1074 goto error; 1075 } 1076 1077 /* right-adjusting blank padding */ 1078 if ((flags & (LADJUST|ZEROPAD)) == 0) 1079 PAD(width - realsz, blanks); 1080 1081 /* prefix */ 1082 if (sign) { 1083 PRINT(&sign, 1); 1084 } else if (flags & HEXPREFIX) { 1085 ox[0] = '0'; 1086 ox[1] = ch; 1087 PRINT(ox, 2); 1088 } 1089 1090 /* right-adjusting zero padding */ 1091 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 1092 PAD(width - realsz, zeroes); 1093 1094 /* leading zeroes from decimal precision */ 1095 PAD(dprec - size, zeroes); 1096 1097 /* the string or number proper */ 1098 #ifndef NO_FLOATING_POINT 1099 if ((flags & FPT) == 0) { 1100 PRINT(cp, size); 1101 } else { /* glue together f_p fragments */ 1102 if (ch >= 'f') { /* 'f' or 'g' */ 1103 if (_double == 0) { 1104 /* kludge for __dtoa irregularity */ 1105 PRINT("0", 1); 1106 if (expt < ndig || (flags & ALT) != 0) { 1107 PRINT(decimal_point, 1); 1108 PAD(ndig - 1, zeroes); 1109 } 1110 } else if (expt <= 0) { 1111 PRINT("0", 1); 1112 PRINT(decimal_point, 1); 1113 PAD(-expt, zeroes); 1114 PRINT(cp, ndig); 1115 } else if (expt >= ndig) { 1116 PRINT(cp, ndig); 1117 PAD(expt - ndig, zeroes); 1118 if (flags & ALT) 1119 PRINT(decimal_point, 1); 1120 } else { 1121 PRINT(cp, expt); 1122 cp += expt; 1123 PRINT(decimal_point, 1); 1124 PRINT(cp, ndig-expt); 1125 } 1126 } else { /* 'e' or 'E' */ 1127 if (ndig > 1 || flags & ALT) { 1128 ox[0] = *cp++; 1129 ox[1] = *decimal_point; 1130 PRINT(ox, 2); 1131 if (_double) { 1132 PRINT(cp, ndig-1); 1133 } else /* 0.[0..] */ 1134 /* __dtoa irregularity */ 1135 PAD(ndig - 1, zeroes); 1136 } else /* XeYYY */ 1137 PRINT(cp, 1); 1138 PRINT(expstr, expsize); 1139 } 1140 } 1141 #else 1142 PRINT(cp, size); 1143 #endif 1144 /* left-adjusting padding (always blank) */ 1145 if (flags & LADJUST) 1146 PAD(width - realsz, blanks); 1147 1148 /* finally, adjust ret */ 1149 ret += prsize; 1150 1151 FLUSH(); /* copy out the I/O vectors */ 1152 } 1153 done: 1154 FLUSH(); 1155 error: 1156 #ifndef NO_FLOATING_POINT 1157 if (dtoaresult != NULL) 1158 __freedtoa(dtoaresult); 1159 #endif 1160 if (convbuf != NULL) 1161 free(convbuf); 1162 if (__sferror(fp)) 1163 ret = EOF; 1164 if ((argtable != NULL) && (argtable != statargtable)) 1165 free (argtable); 1166 return (ret); 1167 /* NOTREACHED */ 1168 } 1169 1170 /* 1171 * Find all arguments when a positional parameter is encountered. Returns a 1172 * table, indexed by argument number, of pointers to each arguments. The 1173 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. 1174 * It will be replaces with a malloc-ed one if it overflows. 1175 */ 1176 static void 1177 __find_arguments (const char *fmt0, va_list ap, union arg **argtable) 1178 { 1179 char *fmt; /* format string */ 1180 int ch; /* character from fmt */ 1181 int n, n2; /* handy integer (short term usage) */ 1182 char *cp; /* handy char pointer (short term usage) */ 1183 int flags; /* flags as above */ 1184 int width; /* width from format (%8d), or 0 */ 1185 enum typeid *typetable; /* table of types */ 1186 enum typeid stattypetable[STATIC_ARG_TBL_SIZE]; 1187 int tablesize; /* current size of type table */ 1188 int tablemax; /* largest used index in table */ 1189 int nextarg; /* 1-based argument index */ 1190 1191 /* 1192 * Add an argument type to the table, expanding if necessary. 1193 */ 1194 #define ADDTYPE(type) \ 1195 ((nextarg >= tablesize) ? \ 1196 __grow_type_table(nextarg, &typetable, &tablesize) : 0, \ 1197 (nextarg > tablemax) ? tablemax = nextarg : 0, \ 1198 typetable[nextarg++] = type) 1199 1200 #define ADDSARG() \ 1201 ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \ 1202 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \ 1203 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \ 1204 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \ 1205 ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT)))))) 1206 1207 #define ADDUARG() \ 1208 ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \ 1209 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \ 1210 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \ 1211 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \ 1212 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT)))))) 1213 1214 /* 1215 * Add * arguments to the type array. 1216 */ 1217 #define ADDASTER() \ 1218 n2 = 0; \ 1219 cp = fmt; \ 1220 while (is_digit(*cp)) { \ 1221 n2 = 10 * n2 + to_digit(*cp); \ 1222 cp++; \ 1223 } \ 1224 if (*cp == '$') { \ 1225 int hold = nextarg; \ 1226 nextarg = n2; \ 1227 ADDTYPE (T_INT); \ 1228 nextarg = hold; \ 1229 fmt = ++cp; \ 1230 } else { \ 1231 ADDTYPE (T_INT); \ 1232 } 1233 fmt = (char *)fmt0; 1234 typetable = stattypetable; 1235 tablesize = STATIC_ARG_TBL_SIZE; 1236 tablemax = 0; 1237 nextarg = 1; 1238 memset (typetable, T_UNUSED, STATIC_ARG_TBL_SIZE); 1239 1240 /* 1241 * Scan the format for conversions (`%' character). 1242 */ 1243 for (;;) { 1244 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 1245 /* void */; 1246 if (ch == '\0') 1247 goto done; 1248 fmt++; /* skip over '%' */ 1249 1250 flags = 0; 1251 width = 0; 1252 1253 rflag: ch = *fmt++; 1254 reswitch: switch (ch) { 1255 case ' ': 1256 case '#': 1257 goto rflag; 1258 case '*': 1259 ADDASTER (); 1260 goto rflag; 1261 case '-': 1262 case '+': 1263 case '\'': 1264 goto rflag; 1265 case '.': 1266 if ((ch = *fmt++) == '*') { 1267 ADDASTER (); 1268 goto rflag; 1269 } 1270 while (is_digit(ch)) { 1271 ch = *fmt++; 1272 } 1273 goto reswitch; 1274 case '0': 1275 goto rflag; 1276 case '1': case '2': case '3': case '4': 1277 case '5': case '6': case '7': case '8': case '9': 1278 n = 0; 1279 do { 1280 n = 10 * n + to_digit(ch); 1281 ch = *fmt++; 1282 } while (is_digit(ch)); 1283 if (ch == '$') { 1284 nextarg = n; 1285 goto rflag; 1286 } 1287 width = n; 1288 goto reswitch; 1289 #ifndef NO_FLOATING_POINT 1290 case 'L': 1291 flags |= LONGDBL; 1292 goto rflag; 1293 #endif 1294 case 'h': 1295 if (flags & SHORTINT) { 1296 flags &= ~SHORTINT; 1297 flags |= CHARINT; 1298 } else 1299 flags |= SHORTINT; 1300 goto rflag; 1301 case 'j': 1302 flags |= INTMAXT; 1303 goto rflag; 1304 case 'l': 1305 if (flags & LONGINT) { 1306 flags &= ~LONGINT; 1307 flags |= LLONGINT; 1308 } else 1309 flags |= LONGINT; 1310 goto rflag; 1311 case 'q': 1312 flags |= LLONGINT; 1313 goto rflag; 1314 case 't': 1315 flags |= PTRDIFFT; 1316 goto rflag; 1317 case 'z': 1318 flags |= SIZET; 1319 goto rflag; 1320 case 'C': 1321 flags |= LONGINT; 1322 /*FALLTHROUGH*/ 1323 case 'c': 1324 if (flags & LONGINT) 1325 ADDTYPE(T_WINT); 1326 else 1327 ADDTYPE(T_INT); 1328 break; 1329 case 'D': 1330 flags |= LONGINT; 1331 /*FALLTHROUGH*/ 1332 case 'd': 1333 case 'i': 1334 ADDSARG(); 1335 break; 1336 #ifndef NO_FLOATING_POINT 1337 #ifdef HEXFLOAT 1338 case 'a': 1339 case 'A': 1340 #endif 1341 case 'e': 1342 case 'E': 1343 case 'f': 1344 case 'g': 1345 case 'G': 1346 if (flags & LONGDBL) 1347 ADDTYPE(T_LONG_DOUBLE); 1348 else 1349 ADDTYPE(T_DOUBLE); 1350 break; 1351 #endif /* NO_FLOATING_POINT */ 1352 case 'n': 1353 if (flags & INTMAXT) 1354 ADDTYPE(TP_INTMAXT); 1355 else if (flags & PTRDIFFT) 1356 ADDTYPE(TP_PTRDIFFT); 1357 else if (flags & SIZET) 1358 ADDTYPE(TP_SIZET); 1359 else if (flags & LLONGINT) 1360 ADDTYPE(TP_LLONG); 1361 else if (flags & LONGINT) 1362 ADDTYPE(TP_LONG); 1363 else if (flags & SHORTINT) 1364 ADDTYPE(TP_SHORT); 1365 else if (flags & CHARINT) 1366 ADDTYPE(TP_SCHAR); 1367 else 1368 ADDTYPE(TP_INT); 1369 continue; /* no output */ 1370 case 'O': 1371 flags |= LONGINT; 1372 /*FALLTHROUGH*/ 1373 case 'o': 1374 ADDUARG(); 1375 break; 1376 case 'p': 1377 ADDTYPE(TP_VOID); 1378 break; 1379 case 'S': 1380 flags |= LONGINT; 1381 /*FALLTHROUGH*/ 1382 case 's': 1383 if (flags & LONGINT) 1384 ADDTYPE(TP_WCHAR); 1385 else 1386 ADDTYPE(TP_CHAR); 1387 break; 1388 case 'U': 1389 flags |= LONGINT; 1390 /*FALLTHROUGH*/ 1391 case 'u': 1392 case 'X': 1393 case 'x': 1394 ADDUARG(); 1395 break; 1396 default: /* "%?" prints ?, unless ? is NUL */ 1397 if (ch == '\0') 1398 goto done; 1399 break; 1400 } 1401 } 1402 done: 1403 /* 1404 * Build the argument table. 1405 */ 1406 if (tablemax >= STATIC_ARG_TBL_SIZE) { 1407 *argtable = (union arg *) 1408 malloc(sizeof(union arg) * (tablemax + 1)); 1409 } 1410 (*argtable)[0].intarg = 0; 1411 for (n = 1; n <= tablemax; n++) { 1412 switch (typetable [n]) { 1413 case T_UNUSED: /* "whoops" */ 1414 case T_INT: 1415 (*argtable)[n].intarg = va_arg(ap, int); 1416 break; 1417 case TP_SCHAR: 1418 (*argtable) [n].pschararg = va_arg (ap, signed char *); 1419 break; 1420 case TP_SHORT: 1421 (*argtable)[n].pshortarg = va_arg(ap, short *); 1422 break; 1423 case T_U_INT: 1424 (*argtable)[n].uintarg = va_arg(ap, unsigned int); 1425 break; 1426 case TP_INT: 1427 (*argtable)[n].pintarg = va_arg(ap, int *); 1428 break; 1429 case T_LONG: 1430 (*argtable)[n].longarg = va_arg(ap, long); 1431 break; 1432 case T_U_LONG: 1433 (*argtable)[n].ulongarg = va_arg(ap, unsigned long); 1434 break; 1435 case TP_LONG: 1436 (*argtable)[n].plongarg = va_arg(ap, long *); 1437 break; 1438 case T_LLONG: 1439 (*argtable)[n].longlongarg = va_arg(ap, long long); 1440 break; 1441 case T_U_LLONG: 1442 (*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long); 1443 break; 1444 case TP_LLONG: 1445 (*argtable)[n].plonglongarg = va_arg(ap, long long *); 1446 break; 1447 case T_PTRDIFFT: 1448 (*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t); 1449 break; 1450 case TP_PTRDIFFT: 1451 (*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *); 1452 break; 1453 case T_SIZET: 1454 (*argtable)[n].sizearg = va_arg(ap, size_t); 1455 break; 1456 case TP_SIZET: 1457 (*argtable)[n].psizearg = va_arg(ap, ssize_t *); 1458 break; 1459 case T_INTMAXT: 1460 (*argtable)[n].intmaxarg = va_arg(ap, intmax_t); 1461 break; 1462 case T_UINTMAXT: 1463 (*argtable)[n].uintmaxarg = va_arg(ap, uintmax_t); 1464 break; 1465 case TP_INTMAXT: 1466 (*argtable)[n].pintmaxarg = va_arg (ap, intmax_t *); 1467 break; 1468 case T_DOUBLE: 1469 (*argtable)[n].doublearg = va_arg(ap, double); 1470 break; 1471 case T_LONG_DOUBLE: 1472 (*argtable)[n].longdoublearg = va_arg(ap, long double); 1473 break; 1474 case TP_CHAR: 1475 (*argtable)[n].pchararg = va_arg(ap, char *); 1476 break; 1477 case TP_VOID: 1478 (*argtable)[n].pvoidarg = va_arg(ap, void *); 1479 break; 1480 case T_WINT: 1481 (*argtable)[n].wintarg = va_arg(ap, wint_t); 1482 break; 1483 case TP_WCHAR: 1484 (*argtable)[n].pwchararg = va_arg(ap, wchar_t *); 1485 break; 1486 } 1487 } 1488 1489 if ((typetable != NULL) && (typetable != stattypetable)) 1490 free (typetable); 1491 } 1492 1493 /* 1494 * Increase the size of the type table. 1495 */ 1496 static void 1497 __grow_type_table(int nextarg, enum typeid **typetable, int *tablesize) 1498 { 1499 enum typeid * const oldtable = *typetable; 1500 const int oldsize = *tablesize; 1501 enum typeid *newtable; 1502 int n, newsize = oldsize * 2; 1503 1504 if (newsize < nextarg + 1) 1505 newsize = nextarg + 1; 1506 if (oldsize == STATIC_ARG_TBL_SIZE) { 1507 if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL) 1508 abort(); /* XXX handle better */ 1509 bcopy(oldtable, newtable, oldsize * sizeof(enum typeid)); 1510 } else { 1511 if ((newtable = reallocf(oldtable, newsize * sizeof(enum typeid))) == NULL) 1512 abort(); /* XXX handle better */ 1513 } 1514 for (n = oldsize; n < newsize; n++) 1515 newtable[n] = T_UNUSED; 1516 1517 *typetable = newtable; 1518 *tablesize = newsize; 1519 } 1520 1521 1522 #ifndef NO_FLOATING_POINT 1523 1524 static char * 1525 cvt(double value, int ndigits, int flags, char *sign, int *decpt, 1526 int ch, int *length) 1527 { 1528 int mode, dsgn; 1529 char *digits, *bp, *rve; 1530 1531 if (ch == 'f') 1532 mode = 3; /* ndigits after the decimal point */ 1533 else { 1534 /* 1535 * To obtain ndigits after the decimal point for the 'e' 1536 * and 'E' formats, round to ndigits + 1 significant 1537 * figures. 1538 */ 1539 if (ch == 'e' || ch == 'E') 1540 ndigits++; 1541 mode = 2; /* ndigits significant digits */ 1542 } 1543 digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); 1544 *sign = dsgn != 0; 1545 if ((ch != 'g' && ch != 'G') || flags & ALT) { 1546 /* print trailing zeros */ 1547 bp = digits + ndigits; 1548 if (ch == 'f') { 1549 if (*digits == '0' && value) 1550 *decpt = -ndigits + 1; 1551 bp += *decpt; 1552 } 1553 if (value == 0) /* kludge for __dtoa irregularity */ 1554 rve = bp; 1555 while (rve < bp) 1556 *rve++ = '0'; 1557 } 1558 *length = rve - digits; 1559 return (digits); 1560 } 1561 1562 static int 1563 exponent(char *p0, int expo, int fmtch) 1564 { 1565 char *p, *t; 1566 char expbuf[MAXEXPDIG]; 1567 1568 p = p0; 1569 *p++ = fmtch; 1570 if (expo < 0) { 1571 expo = -expo; 1572 *p++ = '-'; 1573 } 1574 else 1575 *p++ = '+'; 1576 t = expbuf + MAXEXPDIG; 1577 if (expo > 9) { 1578 do { 1579 *--t = to_char(expo % 10); 1580 } while ((expo /= 10) > 9); 1581 *--t = to_char(expo); 1582 for (; t < expbuf + MAXEXPDIG; *p++ = *t++); 1583 } 1584 else { 1585 *p++ = '0'; 1586 *p++ = to_char(expo); 1587 } 1588 return (p - p0); 1589 } 1590 #endif /* NO_FLOATING_POINT */ 1591