1 /* $NetBSD: vfwprintf.c,v 1.43 2026/10/13 04:36:54 kre Exp $ */ 2 3 /*- 4 * Copyright (c) 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Chris Torek. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include <sys/cdefs.h> 36 #if defined(LIBC_SCCS) && !defined(lint) 37 #if 0 38 static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; 39 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.27 2007/01/09 00:28:08 imp Exp $"); 40 #else 41 __RCSID("$NetBSD: vfwprintf.c,v 1.43 2026/10/13 04:36:54 kre Exp $"); 42 #endif 43 #endif /* LIBC_SCCS and not lint */ 44 45 /* 46 * Actual {w,}printf innards. 47 */ 48 49 #include "namespace.h" 50 #include <sys/types.h> 51 52 #include <assert.h> 53 #include <ctype.h> 54 #include <limits.h> 55 #include <locale.h> 56 #include <stdarg.h> 57 #include <stddef.h> 58 #include <stdint.h> 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <string.h> 62 #include <errno.h> 63 #include <wchar.h> 64 #include <wctype.h> 65 66 #include "reentrant.h" 67 #include "setlocale_local.h" 68 #include "local.h" 69 #include "extern.h" 70 #include "fvwrite.h" 71 72 #ifndef NARROW 73 #define MCHAR_T char 74 #define CHAR_T wchar_t 75 #define STRLEN(a) wcslen(a) 76 #define MEMCHR(a, b, c) wmemchr(a, b, c) 77 #define SCONV(a, b, loc) __mbsconv(a, b, loc) 78 #define STRCONST(a) L ## a 79 #define WDECL(a, b) a ## w ## b 80 #define END_OF_FILE WEOF 81 #define MULTI 0 82 #else 83 #define MCHAR_T wchar_t 84 #define CHAR_T char 85 #define STRLEN(a) strlen(a) 86 #define MEMCHR(a, b, c) memchr(a, b, c) 87 #define SCONV(a, b, loc) __wcsconv(a, b, loc) 88 #define STRCONST(a) a 89 #define WDECL(a, b) a ## b 90 #define END_OF_FILE EOF 91 #define MULTI LONGINT 92 #endif 93 94 union arg { 95 int intarg; 96 u_int uintarg; 97 long longarg; 98 u_long ulongarg; 99 long long longlongarg; 100 unsigned long long ulonglongarg; 101 ptrdiff_t ptrdiffarg; 102 ssize_t ssizearg; 103 size_t sizearg; 104 intmax_t intmaxarg; 105 uintmax_t uintmaxarg; 106 void *pvoidarg; 107 char *pchararg; 108 signed char *pschararg; 109 short *pshortarg; 110 int *pintarg; 111 long *plongarg; 112 long long *plonglongarg; 113 ptrdiff_t *pptrdiffarg; 114 size_t *psizearg; 115 intmax_t *pintmaxarg; 116 #ifndef NO_FLOATING_POINT 117 double doublearg; 118 long double longdoublearg; 119 #endif 120 wint_t wintarg; 121 wchar_t *pwchararg; 122 }; 123 124 /* 125 * Type ids for argument type table. 126 */ 127 enum typeid { 128 T_UNUSED = 0, TP_SHORT, T_INT, T_U_INT, TP_INT, 129 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG, 130 T_PTRDIFFT, TP_PTRDIFFT, T_SSIZET, T_SIZET, TP_SIZET, 131 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR, 132 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR 133 }; 134 135 #ifdef NARROW 136 __printflike(3, 0) 137 #endif 138 static int __sbprintf(FILE *, locale_t, const CHAR_T *, va_list); 139 140 static CHAR_T *__ujtoa(uintmax_t, CHAR_T *, int, int, const char *, int, 141 char *, const char *); 142 static CHAR_T *__ultoa(u_long, CHAR_T *, int, int, const char *, int, 143 char *, const char *); 144 #ifndef NARROW 145 static CHAR_T *__mbsconv(char *, int, locale_t); 146 static wint_t __xfputwc(CHAR_T, FILE *, locale_t); 147 #else 148 static char *__wcsconv(wchar_t *, int, locale_t); 149 static int __sprint(FILE *, struct __suio *); 150 #endif 151 static int __find_arguments(const CHAR_T *, va_list, union arg **); 152 static int __grow_type_table(size_t, enum typeid **, size_t *); 153 154 /* 155 * Helper function for `fprintf to unbuffered unix file': creates a 156 * temporary buffer. We only work on write-only files; this avoids 157 * worries about ungetc buffers and so forth. 158 */ 159 static int 160 __sbprintf(FILE *fp, locale_t loc, const CHAR_T *fmt, va_list ap) 161 { 162 int ret; 163 FILE fake; 164 struct __sfileext fakeext; 165 unsigned char buf[BUFSIZ]; 166 167 _DIAGASSERT(fp != NULL); 168 _DIAGASSERT(fmt != NULL); 169 170 _FILEEXT_SETUP(&fake, &fakeext); 171 memset(WCIO_GET(&fake), 0, sizeof(struct wchar_io_data)); 172 173 /* copy the important variables */ 174 fake._flags = fp->_flags & ~__SNBF; 175 fake._file = fp->_file; 176 fake._cookie = fp->_cookie; 177 fake._write = fp->_write; 178 fake._flush = fp->_flush; 179 180 /* set up the buffer */ 181 fake._bf._base = fake._p = buf; 182 fake._bf._size = fake._w = sizeof(buf); 183 fake._lbfsize = 0; /* not actually used, but Just In Case */ 184 185 /* do the work, then copy any error status */ 186 ret = WDECL(__vf,printf_unlocked_l)(&fake, loc, fmt, ap); 187 if (ret >= 0 && fflush(&fake)) 188 ret = END_OF_FILE; 189 if (fake._flags & __SERR) 190 fp->_flags |= __SERR; 191 return ret; 192 } 193 194 #ifndef NARROW 195 /* 196 * Like __fputwc, but handles fake string (__SSTR) files properly. 197 * File must already be locked. 198 */ 199 static wint_t 200 __xfputwc(wchar_t wc, FILE *fp, locale_t loc) 201 { 202 static const mbstate_t initial; 203 mbstate_t mbs; 204 char buf[MB_LEN_MAX]; 205 struct __suio uio; 206 struct __siov iov; 207 size_t len; 208 209 if ((fp->_flags & __SSTR) == 0) 210 return __fputwc_unlock(wc, fp); 211 212 mbs = initial; 213 if ((len = wcrtomb_l(buf, wc, &mbs, loc)) == (size_t)-1) { 214 fp->_flags |= __SERR; 215 return END_OF_FILE; 216 } 217 uio.uio_iov = &iov; 218 uio.uio_resid = len; 219 uio.uio_iovcnt = 1; 220 iov.iov_base = buf; 221 iov.iov_len = len; 222 return __sfvwrite(fp, &uio) != EOF ? (wint_t)wc : END_OF_FILE; 223 } 224 #else 225 /* 226 * Flush out all the vectors defined by the given uio, 227 * then reset it so that it can be reused. 228 */ 229 static int 230 __sprint(FILE *fp, struct __suio *uio) 231 { 232 int err; 233 234 _DIAGASSERT(fp != NULL); 235 _DIAGASSERT(uio != NULL); 236 237 if (uio->uio_resid == 0) { 238 uio->uio_iovcnt = 0; 239 return 0; 240 } 241 err = __sfvwrite(fp, uio); 242 uio->uio_resid = 0; 243 uio->uio_iovcnt = 0; 244 return err; 245 } 246 #endif 247 248 /* 249 * Macros for converting digits to letters and vice versa 250 */ 251 #define to_digit(c) ((c) - '0') 252 #define is_digit(c) ((unsigned)to_digit(c) <= 9) 253 #define to_char(n) (CHAR_T)((n) + '0') 254 255 /* 256 * Convert an unsigned long to ASCII for printf purposes, returning 257 * a pointer to the first character of the string representation. 258 * Octal numbers can be forced to have a leading zero; hex numbers 259 * use the given digits. 260 */ 261 static CHAR_T * 262 __ultoa(u_long val, CHAR_T *endp, int base, int octzero, const char *xdigs, 263 int needgrp, char *thousep, const char *grp) 264 { 265 CHAR_T *cp = endp; 266 long sval; 267 int ndig; 268 269 /* 270 * Handle the three cases separately, in the hope of getting 271 * better/faster code. 272 */ 273 switch (base) { 274 case 10: 275 if (val < 10) { /* many numbers are 1 digit */ 276 *--cp = to_char(val); 277 return cp; 278 } 279 ndig = 0; 280 /* 281 * On many machines, unsigned arithmetic is harder than 282 * signed arithmetic, so we do at most one unsigned mod and 283 * divide; this is sufficient to reduce the range of 284 * the incoming value to where signed arithmetic works. 285 */ 286 if (val > LONG_MAX) { 287 *--cp = to_char(val % 10); 288 ndig++; 289 sval = val / 10; 290 } else 291 sval = val; 292 do { 293 *--cp = to_char(sval % 10); 294 ndig++; 295 /* 296 * If (*grp == CHAR_MAX) then no more grouping 297 * should be performed. 298 */ 299 if (needgrp && ndig == *grp 300 && (unsigned char)*grp != (unsigned char)CHAR_MAX 301 && sval > 9) { 302 cp -= needgrp; 303 memcpy(cp, thousep, needgrp); 304 ndig = 0; 305 /* 306 * If (*(grp+1) == '\0') then we have to 307 * use *grp character (last grouping rule) 308 * for all next cases 309 */ 310 if (*(grp+1) != '\0') 311 grp++; 312 } 313 sval /= 10; 314 } while (sval != 0); 315 break; 316 317 case 8: 318 do { 319 *--cp = to_char(val & 7); 320 val >>= 3; 321 } while (val); 322 if (octzero && *cp != '0') 323 *--cp = '0'; 324 break; 325 326 case 16: 327 do { 328 *--cp = xdigs[(size_t)val & 15]; 329 val >>= 4; 330 } while (val); 331 break; 332 333 default: /* oops */ 334 abort(); 335 } 336 return cp; 337 } 338 339 /* Identical to __ultoa, but for intmax_t. */ 340 static CHAR_T * 341 __ujtoa(uintmax_t val, CHAR_T *endp, int base, int octzero, 342 const char *xdigs, int needgrp, char *thousep, const char *grp) 343 { 344 CHAR_T *cp = endp; 345 intmax_t sval; 346 int ndig; 347 348 /* quick test for small values; __ultoa is typically much faster */ 349 /* (perhaps instead we should run until small, then call __ultoa?) */ 350 if (val <= ULONG_MAX) 351 return __ultoa((u_long)val, endp, base, octzero, xdigs, 352 needgrp, thousep, grp); 353 switch (base) { 354 case 10: 355 if (val < 10) { 356 *--cp = to_char(val % 10); 357 return cp; 358 } 359 ndig = 0; 360 if (val > INTMAX_MAX) { 361 *--cp = to_char(val % 10); 362 ndig++; 363 sval = val / 10; 364 } else 365 sval = val; 366 do { 367 *--cp = to_char(sval % 10); 368 ndig++; 369 /* 370 * If (*grp == CHAR_MAX) then no more grouping 371 * should be performed. 372 */ 373 if (needgrp && ndig == *grp 374 && (unsigned char)*grp != (unsigned char)CHAR_MAX 375 && sval > 9) { 376 cp -= needgrp; 377 memcpy(cp, thousep, needgrp); 378 ndig = 0; 379 /* 380 * If (*(grp+1) == '\0') then we have to 381 * use *grp character (last grouping rule) 382 * for all next cases 383 */ 384 if (*(grp+1) != '\0') 385 grp++; 386 } 387 sval /= 10; 388 } while (sval != 0); 389 break; 390 391 case 8: 392 do { 393 *--cp = to_char(val & 7); 394 val >>= 3; 395 } while (val); 396 if (octzero && *cp != '0') 397 *--cp = '0'; 398 break; 399 400 case 16: 401 do { 402 *--cp = xdigs[(size_t)val & 15]; 403 val >>= 4; 404 } while (val); 405 break; 406 407 default: 408 abort(); 409 } 410 return cp; 411 } 412 413 #ifndef NARROW 414 /* 415 * Convert a multibyte character string argument for the %s format to a wide 416 * string representation. ``prec'' specifies the maximum number of bytes 417 * to output. If ``prec'' is greater than or equal to zero, we can't assume 418 * that the multibyte char. string ends in a null character. 419 */ 420 static wchar_t * 421 __mbsconv(char *mbsarg, int prec, locale_t loc) 422 { 423 static const mbstate_t initial; 424 mbstate_t mbs; 425 wchar_t *convbuf, *wcp; 426 const char *p; 427 size_t insize, nchars, nconv; 428 429 if (mbsarg == NULL) 430 return NULL; 431 432 /* 433 * Supplied argument is a multibyte string; convert it to wide 434 * characters first. 435 */ 436 if (prec >= 0) { 437 /* 438 * String is not guaranteed to be NUL-terminated. Find the 439 * number of characters to print. 440 */ 441 p = mbsarg; 442 insize = nchars = nconv = 0; 443 mbs = initial; 444 while (nchars != (size_t)prec) { 445 nconv = mbrlen_l(p, MB_CUR_MAX_L(loc), &mbs, loc); 446 if (nconv == 0 || nconv == (size_t)-1 || 447 nconv == (size_t)-2) 448 break; 449 p += nconv; 450 nchars++; 451 insize += nconv; 452 } 453 if (nconv == (size_t)-1 || nconv == (size_t)-2) 454 return NULL; 455 } else 456 insize = strlen(mbsarg); 457 458 /* 459 * Allocate buffer for the result and perform the conversion, 460 * converting at most `size' bytes of the input multibyte string to 461 * wide characters for printing. 462 */ 463 convbuf = NULL; 464 errno = reallocarr(&convbuf, insize + 1, sizeof(*convbuf)); 465 if (errno) 466 return NULL; 467 wcp = convbuf; 468 p = mbsarg; 469 mbs = initial; 470 nconv = 0; 471 while (insize != 0) { 472 nconv = mbrtowc_l(wcp, p, insize, &mbs, loc); 473 if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2) 474 break; 475 wcp++; 476 p += nconv; 477 insize -= nconv; 478 } 479 if (nconv == (size_t)-1 || nconv == (size_t)-2) { 480 int serrno = errno; 481 free(convbuf); 482 errno = serrno; 483 return NULL; 484 } 485 *wcp = L'\0'; 486 487 return convbuf; 488 } 489 #else 490 /* 491 * Convert a wide-character string argument for the %ls format to a multibyte 492 * string representation. If not -1, prec specifies the maximum number of 493 * bytes to output, and also means that we can't assume that the wide-char. 494 * string ends is null-terminated. 495 */ 496 static char * 497 __wcsconv(wchar_t *wcsarg, int prec, locale_t loc) 498 { 499 static const mbstate_t initial; 500 mbstate_t mbs; 501 char buf[MB_LEN_MAX]; 502 wchar_t *p; 503 char *convbuf; 504 size_t clen, nbytes; 505 506 /* Allocate space for the maximum number of bytes we could output. */ 507 if (prec < 0) { 508 p = wcsarg; 509 mbs = initial; 510 nbytes = wcsrtombs_l(NULL, (void *)&p, 0, &mbs, loc); 511 if (nbytes == (size_t)-1) 512 return NULL; 513 } else { 514 /* 515 * Optimisation: if the output precision is small enough, 516 * just allocate enough memory for the maximum instead of 517 * scanning the string. 518 */ 519 if (prec < 128) 520 nbytes = prec; 521 else { 522 nbytes = 0; 523 p = wcsarg; 524 mbs = initial; 525 for (;;) { 526 clen = wcrtomb_l(buf, *p++, &mbs, loc); 527 if (clen == 0 || clen == (size_t)-1 || 528 nbytes + clen > (size_t)prec) 529 break; 530 nbytes += clen; 531 } 532 } 533 } 534 if ((convbuf = malloc(nbytes + 1)) == NULL) 535 return NULL; 536 537 /* Fill the output buffer. */ 538 p = wcsarg; 539 mbs = initial; 540 if ((nbytes = wcsrtombs_l(convbuf, (void *)&p, 541 nbytes, &mbs, loc)) == (size_t)-1) { 542 free(convbuf); 543 return NULL; 544 } 545 convbuf[nbytes] = '\0'; 546 return convbuf; 547 } 548 #endif 549 550 /* 551 * MT-safe version 552 */ 553 int 554 WDECL(vf,printf)(FILE * __restrict fp, const CHAR_T * __restrict fmt0, va_list ap) 555 { 556 int ret; 557 558 FLOCKFILE(fp); 559 ret = WDECL(__vf,printf_unlocked_l)(fp, _current_locale(), fmt0, ap); 560 FUNLOCKFILE(fp); 561 return ret; 562 } 563 564 int 565 WDECL(vf,printf_l)(FILE * __restrict fp, locale_t loc, const CHAR_T * __restrict fmt0, 566 va_list ap) 567 { 568 int ret; 569 570 FLOCKFILE(fp); 571 ret = WDECL(__vf,printf_unlocked_l)(fp, loc, fmt0, ap); 572 FUNLOCKFILE(fp); 573 return ret; 574 } 575 576 #ifndef NO_FLOATING_POINT 577 578 #include <float.h> 579 #include <math.h> 580 #include "floatio.h" 581 582 #define DEFPREC 6 583 584 static int exponent(CHAR_T *, int, int); 585 586 #endif /* !NO_FLOATING_POINT */ 587 588 /* 589 * The size of the buffer we use as scratch space for integer 590 * conversions, among other things. Technically, we would need the 591 * most space for base 10 conversions with thousands' grouping 592 * characters (up to 4 bytes ea) between each pair of digits. 593 * 240 bytes is a conservative overestimate even for a 128-bit uintmax_t. 594 */ 595 #define BUF 240 596 597 #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ 598 599 /* 600 * Flags used during conversion. 601 */ 602 #define ALT 0x001 /* alternate form */ 603 #define LADJUST 0x004 /* left adjustment */ 604 #define LONGDBL 0x008 /* long double */ 605 #define LONGINT 0x010 /* long integer */ 606 #define LLONGINT 0x020 /* long long integer */ 607 #define SHORTINT 0x040 /* short integer */ 608 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ 609 #define FPT 0x100 /* Floating point number */ 610 #define GROUPING 0x200 /* use grouping ("'" flag) */ 611 /* C99 additional size modifiers: */ 612 #define SIZET 0x400 /* size_t */ 613 #define PTRDIFFT 0x800 /* ptrdiff_t */ 614 #define INTMAXT 0x1000 /* intmax_t */ 615 #define CHARINT 0x2000 /* print char using int format */ 616 617 /* 618 * Non-MT-safe version 619 */ 620 int 621 WDECL(__vf,printf_unlocked_l)(FILE *fp, locale_t loc, const CHAR_T *fmt0, va_list ap) 622 { 623 CHAR_T *fmt; /* format string */ 624 int ch; /* character from fmt */ 625 int n, n2; /* handy integer (short term usage) */ 626 CHAR_T *cp; /* handy char pointer (short term usage) */ 627 int flags; /* flags as above */ 628 int ret; /* return value accumulator */ 629 int width; /* width from format (%8d), or 0 */ 630 int prec; /* precision from format; <0 for N/A */ 631 CHAR_T sign; /* sign prefix (' ', '+', '-', or \0) */ 632 char *thousands_sep; /* locale specific thousands separator */ 633 int tsl; /* strlen(thousands_sep) */ 634 const char *grouping; /* locale specific numeric grouping rules */ 635 #ifndef NO_FLOATING_POINT 636 /* 637 * We can decompose the printed representation of floating 638 * point numbers into several parts, some of which may be empty: 639 * 640 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ 641 * A B ---C--- D E F 642 * 643 * A: 'sign' holds this value if present; '\0' otherwise 644 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal 645 * C: cp points to the string MMMNNN. Leading and trailing 646 * zeros are not in the string and must be added. 647 * D: expchar holds this character; '\0' if no exponent, e.g. %f 648 * F: at least two digits for decimal, at least one digit for hex 649 */ 650 char *decimal_point; /* locale specific decimal point */ 651 int decpt_len; /* length of decimal_point */ 652 int signflag; /* true if float is negative */ 653 union { /* floating point arguments %[aAeEfFgG] */ 654 double dbl; 655 #ifdef WIDE_DOUBLE 656 long double ldbl; 657 #endif 658 } fparg; 659 char *dtoaend; /* pointer to end of converted digits */ 660 char *dtoaresult; /* buffer allocated by dtoa */ 661 int expt; /* integer value of exponent */ 662 char expchar; /* exponent character: [eEpP\0] */ 663 int expsize; /* character count for expstr */ 664 int lead; /* sig figs before decimal or group sep */ 665 int ndig; /* actual number of digits returned by dtoa */ 666 CHAR_T expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ 667 int nseps; /* number of group separators with ' */ 668 int nrepeats; /* number of repeats of the last group */ 669 #endif 670 u_long ulval; /* integer arguments %[diouxX] */ 671 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */ 672 int base; /* base for [diouxX] conversion */ 673 int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 674 int realsz; /* field size expanded by dprec, sign, etc */ 675 int size; /* size of converted field or string */ 676 int prsize; /* max size of printed field */ 677 const char *xdigs; /* digits for %[xX] conversion */ 678 #ifdef NARROW 679 #define NIOV 8 680 struct __siov *iovp; /* for PRINT macro */ 681 struct __suio uio; /* output information: summary */ 682 struct __siov iov[NIOV];/* ... and individual io vectors */ 683 #else 684 int n3; 685 #endif 686 CHAR_T buf[BUF]; /* buffer with space for digits of uintmax_t */ 687 CHAR_T ox[2]; /* space for 0x hex-prefix */ 688 union arg *argtable; /* args, built due to positional arg */ 689 union arg statargtable [STATIC_ARG_TBL_SIZE]; 690 int nextarg; /* 1-based argument index */ 691 va_list orgap; /* original argument pointer */ 692 CHAR_T *convbuf; /* multibyte to wide conversion result */ 693 694 /* 695 * Choose PADSIZE to trade efficiency vs. size. If larger printf 696 * fields occur frequently, increase PADSIZE and make the initialisers 697 * below longer. 698 */ 699 #define PADSIZE 16 /* pad chunk size */ 700 static CHAR_T blanks[PADSIZE] = 701 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 702 static CHAR_T zeroes[PADSIZE] = 703 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 704 705 static const char xdigs_lower[16] = "0123456789abcdef"; 706 static const char xdigs_upper[16] = "0123456789ABCDEF"; 707 708 /* 709 * BEWARE, these `goto error' on error, PRINT uses `n2' and 710 * PAD uses `n'. 711 */ 712 #ifndef NARROW 713 #define PRINT(ptr, len) do { \ 714 for (n3 = 0; n3 < (len); n3++) \ 715 if (__xfputwc((ptr)[n3], fp, loc) == END_OF_FILE) { \ 716 fp->_flags |= __SERR; \ 717 goto error; \ 718 } \ 719 } while (0) 720 #define FLUSH() 721 #else 722 #define PRINT(ptr, len) do { \ 723 iovp->iov_base = __UNCONST(ptr); \ 724 iovp->iov_len = (len); \ 725 uio.uio_resid += (len); \ 726 iovp++; \ 727 if (++uio.uio_iovcnt >= NIOV) { \ 728 if (__sprint(fp, &uio)) \ 729 goto error; \ 730 iovp = iov; \ 731 } \ 732 } while (0) 733 #define FLUSH() do { \ 734 if (uio.uio_resid && __sprint(fp, &uio)) \ 735 goto error; \ 736 uio.uio_iovcnt = 0; \ 737 iovp = iov; \ 738 } while (0) 739 #endif /* NARROW */ 740 741 #define PAD(howmany, with) do { \ 742 if ((n = (howmany)) > 0) { \ 743 while (n > PADSIZE) { \ 744 PRINT(with, PADSIZE); \ 745 n -= PADSIZE; \ 746 } \ 747 PRINT(with, n); \ 748 } \ 749 } while (0) 750 #define PRINTANDPAD(p, ep, len, with) do { \ 751 ptrdiff_t td = (ep) - (p); \ 752 _DIAGASSERT(__type_fit(int, td)); \ 753 n2 = (int)td; \ 754 if (n2 > (len)) \ 755 n2 = (len); \ 756 if (n2 > 0) \ 757 PRINT((p), n2); \ 758 PAD((len) - (n2 > 0 ? n2 : 0), (with)); \ 759 } while (0) 760 761 /* 762 * Get the argument indexed by nextarg. If the argument table is 763 * built, use it to get the argument. If its not, get the next 764 * argument (and arguments must be gotten sequentially). 765 */ 766 #define GETARG(type) \ 767 ((/*CONSTCOND*/argtable != NULL) ? *((type*)(void*)(&argtable[nextarg++])) : \ 768 (nextarg++, va_arg(ap, type))) 769 770 /* 771 * To extend shorts properly, we need both signed and unsigned 772 * argument extraction methods. 773 */ 774 #define SARG() \ 775 (flags&LONGINT ? GETARG(long) : \ 776 flags&SHORTINT ? (long)(short)GETARG(int) : \ 777 flags&CHARINT ? (long)(signed char)GETARG(int) : \ 778 (long)GETARG(int)) 779 #define UARG() \ 780 (flags&LONGINT ? GETARG(u_long) : \ 781 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \ 782 flags&CHARINT ? (u_long)(u_char)GETARG(int) : \ 783 (u_long)GETARG(u_int)) 784 #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT) 785 #define SJARG() \ 786 (flags&INTMAXT ? GETARG(intmax_t) : \ 787 flags&SIZET ? (intmax_t)GETARG(ssize_t) : \ 788 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \ 789 (intmax_t)GETARG(long long)) 790 #define UJARG() \ 791 (flags&INTMAXT ? GETARG(uintmax_t) : \ 792 flags&SIZET ? (uintmax_t)GETARG(size_t) : \ 793 flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \ 794 (uintmax_t)GETARG(unsigned long long)) 795 796 /* 797 * Get * arguments, including the form *nn$. Preserve the nextarg 798 * that the argument can be gotten once the type is determined. 799 */ 800 #define GETASTER(val) \ 801 n2 = 0; \ 802 cp = fmt; \ 803 while (is_digit(*cp)) { \ 804 n2 = 10 * n2 + to_digit(*cp); \ 805 cp++; \ 806 } \ 807 if (*cp == '$') { \ 808 int hold = nextarg; \ 809 if (argtable == NULL) { \ 810 argtable = statargtable; \ 811 if (__find_arguments(fmt0, orgap, &argtable) == -1) \ 812 goto oomem; \ 813 } \ 814 nextarg = n2; \ 815 val = GETARG (int); \ 816 nextarg = hold; \ 817 fmt = ++cp; \ 818 } else { \ 819 val = GETARG (int); \ 820 } 821 822 _DIAGASSERT(fp != NULL); 823 _DIAGASSERT(fmt0 != NULL); 824 825 _SET_ORIENTATION(fp, -1); 826 827 thousands_sep = NULL; 828 tsl = 0; 829 grouping = NULL; 830 #ifndef NO_FLOATING_POINT 831 /* it might make sense to move all this to after the cantwrite test */ 832 decimal_point = localeconv_l(loc)->decimal_point; 833 if (decimal_point == NULL) /* should not happen */ 834 decimal_point = __UNCONST("."); /* XXX (or "" ?) */ 835 /* avoid calling strlen() in the common case its result is 1 */ 836 decpt_len = (decimal_point[0] != '\0' && decimal_point[1] == '\0') 837 ? 1 : (int)strlen(decimal_point); 838 expsize = 0; /* XXXGCC -Wuninitialized [sh3,m68000] */ 839 ndig = -1; /* XXX gcc */ 840 #endif 841 convbuf = NULL; 842 /* sorry, f{w,}printf(read_only_file, L"") returns {W,}EOF, not 0 */ 843 if (cantwrite(fp)) { 844 errno = EBADF; 845 return END_OF_FILE; 846 } 847 848 /* optimise fprintf(stderr) (and other unbuffered Unix files) */ 849 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && 850 __sfileno(fp) != -1) 851 return __sbprintf(fp, loc, fmt0, ap); 852 853 fmt = (CHAR_T *)__UNCONST(fmt0); 854 argtable = NULL; 855 nextarg = 1; 856 va_copy(orgap, ap); 857 #ifdef NARROW 858 uio.uio_iov = iovp = iov; 859 uio.uio_resid = 0; 860 uio.uio_iovcnt = 0; 861 #endif 862 ret = 0; 863 864 /* 865 * Scan the format for conversions (`%' character). 866 */ 867 for (;;) { 868 const CHAR_T *result; 869 870 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 871 continue; 872 _DIAGASSERT(__type_fit(int, fmt - cp)); 873 if ((n = (int)(fmt - cp)) != 0) { 874 if ((unsigned)ret + n > INT_MAX) { 875 ret = END_OF_FILE; 876 goto error; 877 } 878 PRINT(cp, n); 879 ret += n; 880 } 881 if (ch == '\0') 882 goto done; 883 fmt++; /* skip over '%' */ 884 885 flags = 0; 886 dprec = 0; 887 width = 0; 888 prec = -1; 889 sign = '\0'; 890 ox[1] = '\0'; 891 #ifndef NO_FLOATING_POINT 892 expchar = '\0'; 893 lead = 0; 894 nseps = nrepeats = 0; 895 #endif 896 ulval = 0; 897 ujval = 0; 898 xdigs = NULL; 899 900 rflag: ch = *fmt++; 901 reswitch: switch (ch) { 902 case ' ': 903 /*- 904 * ``If the space and + flags both appear, the space 905 * flag will be ignored.'' 906 * -- ANSI X3J11 907 */ 908 if (!sign) 909 sign = ' '; 910 goto rflag; 911 case '#': 912 flags |= ALT; 913 goto rflag; 914 case '*': 915 /*- 916 * ``A negative field width argument is taken as a 917 * - flag followed by a positive field width.'' 918 * -- ANSI X3J11 919 * They don't exclude field widths read from args. 920 */ 921 GETASTER (width); 922 if (width >= 0) 923 goto rflag; 924 width = -width; 925 /* FALLTHROUGH */ 926 case '-': 927 flags |= LADJUST; 928 goto rflag; 929 case '+': 930 sign = '+'; 931 goto rflag; 932 case '\'': 933 thousands_sep = localeconv_l(loc)->thousands_sep; 934 grouping = localeconv_l(loc)->grouping; 935 /* Use grouping if defined by locale */ 936 if (thousands_sep && *thousands_sep && grouping && 937 (int)*grouping > 0 && *grouping != CHAR_MAX) { 938 flags |= GROUPING; 939 if (thousands_sep[1] == '\0') 940 tsl = 1; 941 else { 942 tsl = (int)strlen(thousands_sep); 943 if (tsl > 4) /*XXX*/ 944 tsl = 0; 945 } 946 } else { 947 thousands_sep = NULL; 948 tsl = 0; 949 grouping = NULL; 950 } 951 goto rflag; 952 case '.': 953 if ((ch = *fmt++) == '*') { 954 GETASTER (prec); 955 goto rflag; 956 } 957 prec = 0; 958 while (is_digit(ch)) { 959 prec = 10 * prec + to_digit(ch); 960 ch = *fmt++; 961 } 962 goto reswitch; 963 case '0': 964 /*- 965 * ``Note that 0 is taken as a flag, not as the 966 * beginning of a field width.'' 967 * -- ANSI X3J11 968 */ 969 flags |= ZEROPAD; 970 goto rflag; 971 case '1': case '2': case '3': case '4': 972 case '5': case '6': case '7': case '8': case '9': 973 n = 0; 974 do { 975 n = 10 * n + to_digit(ch); 976 ch = *fmt++; 977 } while (is_digit(ch)); 978 if (ch == '$') { 979 nextarg = n; 980 if (argtable == NULL) { 981 argtable = statargtable; 982 if (__find_arguments(fmt0, orgap, 983 &argtable) == -1) 984 goto oomem; 985 } 986 goto rflag; 987 } 988 width = n; 989 goto reswitch; 990 #ifndef NO_FLOATING_POINT 991 case 'L': 992 flags |= LONGDBL; 993 goto rflag; 994 #endif 995 case 'h': 996 if (flags & SHORTINT) { 997 flags &= ~SHORTINT; 998 flags |= CHARINT; 999 } else 1000 flags |= SHORTINT; 1001 goto rflag; 1002 case 'j': 1003 flags |= INTMAXT; 1004 goto rflag; 1005 case 'l': 1006 if (flags & LONGINT) { 1007 flags &= ~LONGINT; 1008 flags |= LLONGINT; 1009 } else 1010 flags |= LONGINT; 1011 goto rflag; 1012 case 'q': 1013 flags |= LLONGINT; /* not necessarily */ 1014 goto rflag; 1015 case 't': 1016 flags |= PTRDIFFT; 1017 goto rflag; 1018 case 'z': 1019 flags |= SIZET; 1020 goto rflag; 1021 case 'C': 1022 flags |= LONGINT; 1023 /*FALLTHROUGH*/ 1024 case 'c': 1025 #ifdef NARROW 1026 if (flags & LONGINT) { 1027 static const mbstate_t initial; 1028 mbstate_t mbs; 1029 size_t mbseqlen; 1030 1031 mbs = initial; 1032 mbseqlen = wcrtomb_l(buf, 1033 (wchar_t)GETARG(wint_t), &mbs, loc); 1034 if (mbseqlen == (size_t)-1) { 1035 fp->_flags |= __SERR; 1036 goto error; 1037 } 1038 size = (int)mbseqlen; 1039 } else { 1040 *buf = GETARG(int); 1041 size = 1; 1042 } 1043 #else 1044 if (flags & LONGINT) 1045 *buf = (wchar_t)GETARG(wint_t); 1046 else 1047 *buf = (wchar_t)btowc_l(GETARG(int), loc); 1048 size = 1; 1049 #endif 1050 result = buf; 1051 sign = '\0'; 1052 break; 1053 case 'D': 1054 flags |= LONGINT; 1055 /*FALLTHROUGH*/ 1056 case 'd': 1057 case 'i': 1058 if (flags & INTMAX_SIZE) { 1059 ujval = SJARG(); 1060 if ((intmax_t)ujval < 0) { 1061 ujval = -ujval; 1062 sign = '-'; 1063 } 1064 } else { 1065 ulval = SARG(); 1066 if ((long)ulval < 0) { 1067 ulval = -ulval; 1068 sign = '-'; 1069 } 1070 } 1071 base = 10; 1072 goto number; 1073 #ifndef NO_FLOATING_POINT 1074 case 'a': 1075 case 'A': 1076 if (ch == 'a') { 1077 ox[1] = 'x'; 1078 xdigs = xdigs_lower; 1079 expchar = 'p'; 1080 } else { 1081 ox[1] = 'X'; 1082 xdigs = xdigs_upper; 1083 expchar = 'P'; 1084 } 1085 if (prec >= 0) 1086 prec++; 1087 #ifdef WIDE_DOUBLE 1088 if (flags & LONGDBL) { 1089 fparg.ldbl = GETARG(long double); 1090 dtoaresult = 1091 __hldtoa(fparg.ldbl, xdigs, prec, 1092 &expt, &signflag, &dtoaend); 1093 } else 1094 #endif 1095 { 1096 fparg.dbl = GETARG(double); 1097 dtoaresult = 1098 __hdtoa(fparg.dbl, xdigs, prec, 1099 &expt, &signflag, &dtoaend); 1100 } 1101 if (dtoaresult == NULL) 1102 goto oomem; 1103 1104 if (prec < 0) { 1105 _DIAGASSERT(__type_fit(int, 1106 dtoaend - dtoaresult)); 1107 prec = (int)(dtoaend - dtoaresult); 1108 } 1109 if (expt == INT_MAX) 1110 ox[1] = '\0'; 1111 _DIAGASSERT(__type_fit(int, dtoaend - dtoaresult)); 1112 ndig = (int)(dtoaend - dtoaresult); 1113 if (convbuf != NULL) 1114 free(convbuf); 1115 #ifndef NARROW 1116 result = convbuf = __mbsconv(dtoaresult, -1, loc); 1117 #else 1118 /*XXX inefficient*/ 1119 result = convbuf = strdup(dtoaresult); 1120 #endif 1121 if (result == NULL) 1122 goto oomem; 1123 __freedtoa(dtoaresult); 1124 goto fp_common; 1125 case 'e': 1126 case 'E': 1127 expchar = ch; 1128 if (prec < 0) /* account for digit before decpt */ 1129 prec = DEFPREC + 1; 1130 else 1131 prec++; 1132 goto fp_begin; 1133 case 'f': 1134 case 'F': 1135 expchar = '\0'; 1136 goto fp_begin; 1137 case 'g': 1138 case 'G': 1139 expchar = ch - ('g' - 'e'); 1140 if (prec == 0) 1141 prec = 1; 1142 fp_begin: 1143 if (prec < 0) 1144 prec = DEFPREC; 1145 #ifdef WIDE_DOUBLE 1146 if (flags & LONGDBL) { 1147 fparg.ldbl = GETARG(long double); 1148 dtoaresult = 1149 __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, 1150 &expt, &signflag, &dtoaend); 1151 } else 1152 #endif 1153 { 1154 fparg.dbl = GETARG(double); 1155 dtoaresult = 1156 __dtoa(fparg.dbl, expchar ? 2 : 3, prec, 1157 &expt, &signflag, &dtoaend); 1158 if (expt == 9999) 1159 expt = INT_MAX; 1160 } 1161 if (dtoaresult == NULL) 1162 goto oomem; 1163 _DIAGASSERT(__type_fit(int, dtoaend - dtoaresult)); 1164 ndig = (int)(dtoaend - dtoaresult); 1165 if (convbuf != NULL) 1166 free(convbuf); 1167 #ifndef NARROW 1168 result = convbuf = __mbsconv(dtoaresult, -1, loc); 1169 #else 1170 /*XXX inefficient*/ 1171 result = convbuf = strdup(dtoaresult); 1172 #endif 1173 if (result == NULL) 1174 goto oomem; 1175 __freedtoa(dtoaresult); 1176 fp_common: 1177 if (signflag) 1178 sign = '-'; 1179 if (expt == INT_MAX) { /* inf or nan */ 1180 if (*result == 'N') { 1181 result = (ch >= 'a') ? STRCONST("nan") : 1182 STRCONST("NAN"); 1183 sign = '\0'; 1184 } else 1185 result = (ch >= 'a') ? STRCONST("inf") : 1186 STRCONST("INF"); 1187 size = 3; 1188 flags &= ~ZEROPAD; 1189 break; 1190 } 1191 1192 flags |= FPT; 1193 if (ch == 'g' || ch == 'G') { 1194 if (expt > -4 && expt <= prec) { 1195 /* Make %[gG] smell like %[fF] */ 1196 expchar = '\0'; 1197 if (flags & ALT) 1198 prec -= expt; 1199 else 1200 prec = ndig - expt; 1201 if (prec < 0) 1202 prec = 0; 1203 } else { 1204 /* 1205 * Make %[gG] smell like %[eE], but 1206 * trim trailing zeroes if no # flag. 1207 */ 1208 if (!(flags & ALT)) 1209 prec = ndig; 1210 } 1211 } 1212 if (expchar) { 1213 expsize = exponent(expstr, expt - 1, expchar); 1214 size = expsize + prec; 1215 if (prec > 1 || flags & ALT) 1216 size += decpt_len; 1217 } else { 1218 /* space for digits before decimal point */ 1219 if (expt > 0) 1220 size = expt; 1221 else /* "0" */ 1222 size = 1; 1223 /* space for decimal pt and following digits */ 1224 if (prec || flags & ALT) 1225 size += prec + decpt_len; 1226 if (grouping && expt > 0) { 1227 /* space for thousands' grouping */ 1228 nseps = nrepeats = 0; 1229 lead = expt; 1230 while ((unsigned char)*grouping 1231 != (unsigned char)CHAR_MAX) { 1232 if (lead <= *grouping) 1233 break; 1234 lead -= *grouping; 1235 if (*(grouping+1)) { 1236 nseps++; 1237 grouping++; 1238 } else 1239 nrepeats++; 1240 } 1241 size += (nseps + nrepeats) * tsl; 1242 } else 1243 lead = expt; 1244 } 1245 break; 1246 #endif /* !NO_FLOATING_POINT */ 1247 case 'n': 1248 /* 1249 * Assignment-like behavior is specified if the 1250 * value overflows or is otherwise unrepresentable. 1251 * C99 says to use `signed char' for %hhn conversions. 1252 */ 1253 if (flags & LLONGINT) 1254 *GETARG(long long *) = ret; 1255 else if (flags & SIZET) 1256 *GETARG(ssize_t *) = (ssize_t)ret; 1257 else if (flags & PTRDIFFT) 1258 *GETARG(ptrdiff_t *) = ret; 1259 else if (flags & INTMAXT) 1260 *GETARG(intmax_t *) = ret; 1261 else if (flags & LONGINT) 1262 *GETARG(long *) = ret; 1263 else if (flags & SHORTINT) 1264 *GETARG(short *) = ret; 1265 else if (flags & CHARINT) 1266 *GETARG(signed char *) = ret; 1267 else 1268 *GETARG(int *) = ret; 1269 continue; /* no output */ 1270 case 'O': 1271 flags |= LONGINT; 1272 /*FALLTHROUGH*/ 1273 case 'o': 1274 if (flags & INTMAX_SIZE) 1275 ujval = UJARG(); 1276 else 1277 ulval = UARG(); 1278 base = 8; 1279 goto nosign; 1280 case 'p': 1281 /*- 1282 * ``The argument shall be a pointer to void. The 1283 * value of the pointer is converted to a sequence 1284 * of printable characters, in an implementation- 1285 * defined manner.'' 1286 * -- ANSI X3J11 1287 */ 1288 ujval = (uintmax_t)(uintptr_t)GETARG(void *); 1289 base = 16; 1290 xdigs = xdigs_lower; 1291 flags = flags | INTMAXT; 1292 ox[1] = 'x'; 1293 goto nosign; 1294 case 'S': 1295 flags |= LONGINT; 1296 /*FALLTHROUGH*/ 1297 case 's': 1298 if ((flags & LONGINT) != MULTI) { 1299 if ((result = GETARG(CHAR_T *)) == NULL) 1300 result = STRCONST("(null)"); 1301 } else { 1302 MCHAR_T *mc; 1303 1304 if (convbuf != NULL) 1305 free(convbuf); 1306 if ((mc = GETARG(MCHAR_T *)) == NULL) 1307 result = STRCONST("(null)"); 1308 else { 1309 convbuf = SCONV(mc, prec, loc); 1310 if (convbuf == NULL) { 1311 fp->_flags |= __SERR; 1312 goto error; 1313 } 1314 result = convbuf; 1315 } 1316 } 1317 1318 if (prec >= 0) { 1319 /* 1320 * can't use STRLEN; can only look for the 1321 * NUL in the first `prec' characters, and 1322 * STRLEN() will go further. 1323 */ 1324 const CHAR_T *p = 1325 MEMCHR(result, 0, (size_t)prec); 1326 1327 if (p != NULL) { 1328 _DIAGASSERT(__type_fit(int, 1329 p - result)); 1330 size = (int)(p - result); 1331 if (size > prec) 1332 size = prec; 1333 } else 1334 size = prec; 1335 } else { 1336 size_t rlen = STRLEN(result); 1337 _DIAGASSERT(__type_fit(int, rlen)); 1338 size = (int)rlen; 1339 } 1340 sign = '\0'; 1341 break; 1342 case 'U': 1343 flags |= LONGINT; 1344 /*FALLTHROUGH*/ 1345 case 'u': 1346 if (flags & INTMAX_SIZE) 1347 ujval = UJARG(); 1348 else 1349 ulval = UARG(); 1350 base = 10; 1351 goto nosign; 1352 case 'X': 1353 xdigs = xdigs_upper; 1354 goto hex; 1355 case 'x': 1356 xdigs = xdigs_lower; 1357 hex: 1358 if (flags & INTMAX_SIZE) 1359 ujval = UJARG(); 1360 else 1361 ulval = UARG(); 1362 base = 16; 1363 /* leading 0x/X only if non-zero */ 1364 if (flags & ALT && 1365 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) 1366 ox[1] = ch; 1367 1368 flags &= ~GROUPING; 1369 /* unsigned conversions */ 1370 nosign: sign = '\0'; 1371 /*- 1372 * ``... diouXx conversions ... if a precision is 1373 * specified, the 0 flag will be ignored.'' 1374 * -- ANSI X3J11 1375 */ 1376 number: if ((dprec = prec) >= 0) 1377 flags &= ~ZEROPAD; 1378 1379 /*- 1380 * ``The result of converting a zero value with an 1381 * explicit precision of zero is no characters.'' 1382 * -- ANSI X3J11 1383 * 1384 * ``The C Standard is clear enough as is. The call 1385 * printf("%#.0o", 0) should print 0.'' 1386 * -- Defect Report #151 1387 */ 1388 result = cp = buf + BUF; 1389 if (flags & INTMAX_SIZE) { 1390 if (ujval != 0 || prec != 0 || 1391 (flags & ALT && base == 8)) 1392 result = __ujtoa(ujval, cp, base, 1393 flags & ALT, xdigs, 1394 ((flags & GROUPING) ? tsl : 0), 1395 thousands_sep, grouping); 1396 } else { 1397 if (ulval != 0 || prec != 0 || 1398 (flags & ALT && base == 8)) 1399 result = __ultoa(ulval, cp, base, 1400 flags & ALT, xdigs, 1401 ((flags & GROUPING) ? tsl : 0), 1402 thousands_sep, grouping); 1403 } 1404 _DIAGASSERT(__type_fit(int, buf + BUF - result)); 1405 size = (int)(buf + BUF - result); 1406 if (size > BUF) /* should never happen */ 1407 abort(); 1408 break; 1409 default: /* "%?" prints ?, unless ? is NUL */ 1410 if (ch == '\0') 1411 goto done; 1412 /* pretend it was %c with argument ch */ 1413 *buf = ch; 1414 result = buf; 1415 size = 1; 1416 sign = '\0'; 1417 break; 1418 } 1419 1420 /* 1421 * All reasonable formats wind up here. At this point, `result' 1422 * points to a string which (if not flags&LADJUST) should be 1423 * padded out to `width' places. If flags&ZEROPAD, it should 1424 * first be prefixed by any sign or other prefix; otherwise, 1425 * it should be blank padded before the prefix is emitted. 1426 * After any left-hand padding and prefixing, emit zeroes 1427 * required by a decimal [diouxX] precision, then print the 1428 * string proper, then emit zeroes required by any leftover 1429 * floating precision; finally, if LADJUST, pad with blanks. 1430 * 1431 * Compute actual size, so we know how much to pad. 1432 * size excludes decimal prec; realsz includes it. 1433 */ 1434 realsz = dprec > size ? dprec : size; 1435 if (sign) 1436 realsz++; 1437 if (ox[1]) 1438 realsz += 2; 1439 1440 prsize = width > realsz ? width : realsz; 1441 if ((unsigned)ret + prsize > INT_MAX) { 1442 ret = END_OF_FILE; 1443 goto error; 1444 } 1445 1446 /* right-adjusting blank padding */ 1447 if ((flags & (LADJUST|ZEROPAD)) == 0) 1448 PAD(width - realsz, blanks); 1449 1450 /* prefix */ 1451 if (sign) 1452 PRINT(&sign, 1); 1453 1454 if (ox[1]) { /* ox[1] is either x, X, or \0 */ 1455 ox[0] = '0'; 1456 PRINT(ox, 2); 1457 } 1458 1459 /* right-adjusting zero padding */ 1460 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 1461 PAD(width - realsz, zeroes); 1462 1463 /* leading zeroes from decimal precision */ 1464 PAD(dprec - size, zeroes); 1465 1466 /* the string or number proper */ 1467 #ifndef NO_FLOATING_POINT 1468 if ((flags & FPT) == 0) { 1469 PRINT(result, size); 1470 } else { /* glue together f_p fragments */ 1471 if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 1472 if (expt <= 0) { 1473 PRINT(zeroes, 1); 1474 if (prec || flags & ALT) 1475 PRINT(decimal_point, decpt_len); 1476 PAD(-expt, zeroes); 1477 /* already handled initial 0's */ 1478 prec += expt; 1479 } else { 1480 PRINTANDPAD(result, convbuf + ndig, 1481 lead, zeroes); 1482 result += lead; 1483 if (grouping) { 1484 while (nseps>0 || nrepeats>0) { 1485 if (nrepeats > 0) 1486 nrepeats--; 1487 else { 1488 grouping--; 1489 nseps--; 1490 } 1491 PRINT(thousands_sep, 1492 tsl); 1493 PRINTANDPAD(result, 1494 convbuf + ndig, 1495 *grouping, zeroes); 1496 result += *grouping; 1497 } 1498 if (result > convbuf + ndig) 1499 result = convbuf + ndig; 1500 } 1501 if (prec || flags & ALT) 1502 PRINT(decimal_point, decpt_len); 1503 } 1504 PRINTANDPAD(result, convbuf + ndig, prec, 1505 zeroes); 1506 } else { /* %[eE] or sufficiently long %[gG] */ 1507 if (prec > 1 || flags & ALT) { 1508 /* PRINT() ptr arg eval'd in loop */ 1509 /* using "result++" maybe OK, but... */ 1510 PRINT(result, 1); 1511 result++; 1512 PRINT(decimal_point, decpt_len); 1513 PRINT(result, ndig-1); 1514 PAD(prec - ndig, zeroes); 1515 } else /* XeYYY */ 1516 PRINT(result, 1); 1517 PRINT(expstr, expsize); 1518 } 1519 } 1520 #else 1521 PRINT(result, size); 1522 #endif 1523 /* left-adjusting padding (always blank) */ 1524 if (flags & LADJUST) 1525 PAD(width - realsz, blanks); 1526 1527 /* finally, adjust ret */ 1528 ret += prsize; 1529 FLUSH(); 1530 } 1531 done: 1532 FLUSH(); 1533 error: 1534 va_end(orgap); 1535 if (convbuf != NULL) 1536 free(convbuf); 1537 if (__sferror(fp)) 1538 ret = END_OF_FILE; 1539 if ((argtable != NULL) && (argtable != statargtable)) 1540 free (argtable); 1541 return ret; 1542 /* NOTREACHED */ 1543 oomem: 1544 errno = ENOMEM; 1545 ret = END_OF_FILE; 1546 goto error; 1547 } 1548 1549 /* 1550 * Find all arguments when a positional parameter is encountered. Returns a 1551 * table, indexed by argument number, of pointers to each arguments. The 1552 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. 1553 * It will be replaces with a malloc-ed one if it overflows. 1554 */ 1555 static int 1556 __find_arguments(const CHAR_T *fmt0, va_list ap, union arg **argtable) 1557 { 1558 CHAR_T *fmt; /* format string */ 1559 int ch; /* character from fmt */ 1560 size_t n, n2; /* handy index (short term usage) */ 1561 CHAR_T *cp; /* handy char pointer (short term usage) */ 1562 int flags; /* flags as above */ 1563 enum typeid *typetable; /* table of types */ 1564 enum typeid stattypetable [STATIC_ARG_TBL_SIZE]; 1565 size_t tablesize; /* current size of type table */ 1566 size_t tablemax; /* largest used index in table */ 1567 size_t nextarg; /* 1-based argument index */ 1568 size_t nitems; /* number of items we picked from the stack */ 1569 1570 /* 1571 * Add an argument type to the table, expanding if necessary. 1572 * Check for overflow. 1573 */ 1574 #define ADDTYPE(type) \ 1575 do { \ 1576 if (nextarg > SIZE_MAX / sizeof(**argtable)) { \ 1577 if (typetable != stattypetable) \ 1578 free(typetable); \ 1579 return -1; \ 1580 } \ 1581 if (nextarg >= tablesize) \ 1582 if (__grow_type_table(nextarg, &typetable, \ 1583 &tablesize) == -1) \ 1584 return -1; \ 1585 if (nextarg > tablemax) \ 1586 tablemax = nextarg; \ 1587 typetable[nextarg++] = type; \ 1588 nitems++; \ 1589 } while (0) 1590 1591 #define ADDSARG() \ 1592 do { \ 1593 if (flags & INTMAXT) \ 1594 ADDTYPE(T_INTMAXT); \ 1595 else if (flags & SIZET) \ 1596 ADDTYPE(T_SSIZET); \ 1597 else if (flags & PTRDIFFT) \ 1598 ADDTYPE(T_PTRDIFFT); \ 1599 else if (flags & LLONGINT) \ 1600 ADDTYPE(T_LLONG); \ 1601 else if (flags & LONGINT) \ 1602 ADDTYPE(T_LONG); \ 1603 else \ 1604 ADDTYPE(T_INT); \ 1605 } while (0) 1606 1607 #define ADDUARG() \ 1608 do { \ 1609 if (flags & INTMAXT) \ 1610 ADDTYPE(T_UINTMAXT); \ 1611 else if (flags & SIZET) \ 1612 ADDTYPE(T_SIZET); \ 1613 else if (flags & PTRDIFFT) \ 1614 ADDTYPE(T_PTRDIFFT); \ 1615 else if (flags & LLONGINT) \ 1616 ADDTYPE(T_U_LLONG); \ 1617 else if (flags & LONGINT) \ 1618 ADDTYPE(T_U_LONG); \ 1619 else \ 1620 ADDTYPE(T_U_INT); \ 1621 } while (0) 1622 /* 1623 * Add * arguments to the type array. 1624 */ 1625 #define ADDASTER() \ 1626 n2 = 0; \ 1627 cp = fmt; \ 1628 while (is_digit(*cp)) { \ 1629 n2 = 10 * n2 + to_digit(*cp); \ 1630 cp++; \ 1631 } \ 1632 if (*cp == '$') { \ 1633 size_t hold = nextarg; \ 1634 nextarg = n2; \ 1635 ADDTYPE(T_INT); \ 1636 nextarg = hold; \ 1637 fmt = ++cp; \ 1638 } else { \ 1639 ADDTYPE(T_INT); \ 1640 } 1641 fmt = (CHAR_T *)__UNCONST(fmt0); 1642 memset(stattypetable, 0, sizeof(stattypetable)); 1643 typetable = stattypetable; 1644 tablesize = STATIC_ARG_TBL_SIZE; 1645 tablemax = 0; 1646 nextarg = 1; 1647 nitems = 1; 1648 1649 /* 1650 * Scan the format for conversions (`%' character). 1651 */ 1652 for (;;) { 1653 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 1654 /* void */; 1655 if (ch == '\0') 1656 goto done; 1657 fmt++; /* skip over '%' */ 1658 1659 flags = 0; 1660 1661 rflag: ch = *fmt++; 1662 reswitch: switch (ch) { 1663 case ' ': 1664 case '#': 1665 goto rflag; 1666 case '*': 1667 ADDASTER (); 1668 goto rflag; 1669 case '-': 1670 case '+': 1671 case '\'': 1672 goto rflag; 1673 case '.': 1674 if ((ch = *fmt++) == '*') { 1675 ADDASTER (); 1676 goto rflag; 1677 } 1678 while (is_digit(ch)) { 1679 ch = *fmt++; 1680 } 1681 goto reswitch; 1682 case '0': 1683 goto rflag; 1684 case '1': case '2': case '3': case '4': 1685 case '5': case '6': case '7': case '8': case '9': 1686 n = 0; 1687 do { 1688 n = 10 * n + to_digit(ch); 1689 ch = *fmt++; 1690 } while (is_digit(ch)); 1691 if (ch == '$') { 1692 nextarg = n; 1693 goto rflag; 1694 } 1695 goto reswitch; 1696 #ifndef NO_FLOATING_POINT 1697 case 'L': 1698 flags |= LONGDBL; 1699 goto rflag; 1700 #endif 1701 case 'h': 1702 if (flags & SHORTINT) { 1703 flags &= ~SHORTINT; 1704 flags |= CHARINT; 1705 } else 1706 flags |= SHORTINT; 1707 goto rflag; 1708 case 'j': 1709 flags |= INTMAXT; 1710 goto rflag; 1711 case 'l': 1712 if (flags & LONGINT) { 1713 flags &= ~LONGINT; 1714 flags |= LLONGINT; 1715 } else 1716 flags |= LONGINT; 1717 goto rflag; 1718 case 'q': 1719 flags |= LLONGINT; /* not necessarily */ 1720 goto rflag; 1721 case 't': 1722 flags |= PTRDIFFT; 1723 goto rflag; 1724 case 'z': 1725 flags |= SIZET; 1726 goto rflag; 1727 case 'C': 1728 flags |= LONGINT; 1729 /*FALLTHROUGH*/ 1730 case 'c': 1731 if (flags & LONGINT) 1732 ADDTYPE(T_WINT); 1733 else 1734 ADDTYPE(T_INT); 1735 break; 1736 case 'D': 1737 flags |= LONGINT; 1738 /*FALLTHROUGH*/ 1739 case 'd': 1740 case 'i': 1741 ADDSARG(); 1742 break; 1743 #ifndef NO_FLOATING_POINT 1744 case 'a': 1745 case 'A': 1746 case 'e': 1747 case 'E': 1748 case 'f': 1749 case 'F': 1750 case 'g': 1751 case 'G': 1752 if (flags & LONGDBL) 1753 ADDTYPE(T_LONG_DOUBLE); 1754 else 1755 ADDTYPE(T_DOUBLE); 1756 break; 1757 #endif /* !NO_FLOATING_POINT */ 1758 case 'n': 1759 if (flags & INTMAXT) 1760 ADDTYPE(TP_INTMAXT); 1761 else if (flags & PTRDIFFT) 1762 ADDTYPE(TP_PTRDIFFT); 1763 else if (flags & SIZET) 1764 ADDTYPE(TP_SIZET); 1765 else if (flags & LLONGINT) 1766 ADDTYPE(TP_LLONG); 1767 else if (flags & LONGINT) 1768 ADDTYPE(TP_LONG); 1769 else if (flags & SHORTINT) 1770 ADDTYPE(TP_SHORT); 1771 else if (flags & CHARINT) 1772 ADDTYPE(TP_SCHAR); 1773 else 1774 ADDTYPE(TP_INT); 1775 continue; /* no output */ 1776 case 'O': 1777 flags |= LONGINT; 1778 /*FALLTHROUGH*/ 1779 case 'o': 1780 ADDUARG(); 1781 break; 1782 case 'p': 1783 ADDTYPE(TP_VOID); 1784 break; 1785 case 'S': 1786 flags |= LONGINT; 1787 /*FALLTHROUGH*/ 1788 case 's': 1789 if (flags & LONGINT) 1790 ADDTYPE(TP_WCHAR); 1791 else 1792 ADDTYPE(TP_CHAR); 1793 break; 1794 case 'U': 1795 flags |= LONGINT; 1796 /*FALLTHROUGH*/ 1797 case 'u': 1798 case 'X': 1799 case 'x': 1800 ADDUARG(); 1801 break; 1802 default: /* "%?" prints ?, unless ? is NUL */ 1803 if (ch == '\0') 1804 goto done; 1805 break; 1806 } 1807 } 1808 done: 1809 /* 1810 * nitems contains the number of arguments we picked from the stack. 1811 * If tablemax is larger, this means that some positional argument, 1812 * tried to pick an argument the number of arguments possibly supplied. 1813 * Since positional arguments are typically used to swap the order of 1814 * the printf arguments and not to pick random arguments from strange 1815 * positions in the stack, we assume that if the positional argument 1816 * is trying to pick beyond the end of arguments, then this is wrong. 1817 * Alternatively we could find a way to figure out when va_arg() runs 1818 * out, but how to do that? 1819 */ 1820 if (nitems < tablemax) { 1821 if (typetable != stattypetable) 1822 free(typetable); 1823 return -1; 1824 } 1825 /* 1826 * Build the argument table. 1827 */ 1828 if (tablemax >= STATIC_ARG_TBL_SIZE) { 1829 *argtable = malloc(sizeof(**argtable) * (tablemax + 1)); 1830 if (*argtable == NULL) { 1831 free(typetable); 1832 return -1; 1833 } 1834 } 1835 1836 (*argtable) [0].intarg = 0; 1837 for (n = 1; n <= tablemax; n++) { 1838 switch (typetable [n]) { 1839 case T_UNUSED: /* whoops! */ 1840 (*argtable) [n].intarg = va_arg (ap, int); 1841 break; 1842 case TP_SCHAR: 1843 (*argtable) [n].pschararg = va_arg (ap, signed char *); 1844 break; 1845 case TP_SHORT: 1846 (*argtable) [n].pshortarg = va_arg (ap, short *); 1847 break; 1848 case T_INT: 1849 (*argtable) [n].intarg = va_arg (ap, int); 1850 break; 1851 case T_U_INT: 1852 (*argtable) [n].uintarg = va_arg (ap, unsigned int); 1853 break; 1854 case TP_INT: 1855 (*argtable) [n].pintarg = va_arg (ap, int *); 1856 break; 1857 case T_LONG: 1858 (*argtable) [n].longarg = va_arg (ap, long); 1859 break; 1860 case T_U_LONG: 1861 (*argtable) [n].ulongarg = va_arg (ap, unsigned long); 1862 break; 1863 case TP_LONG: 1864 (*argtable) [n].plongarg = va_arg (ap, long *); 1865 break; 1866 case T_LLONG: 1867 (*argtable) [n].longlongarg = va_arg (ap, long long); 1868 break; 1869 case T_U_LLONG: 1870 (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long); 1871 break; 1872 case TP_LLONG: 1873 (*argtable) [n].plonglongarg = va_arg (ap, long long *); 1874 break; 1875 case T_PTRDIFFT: 1876 (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t); 1877 break; 1878 case TP_PTRDIFFT: 1879 (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *); 1880 break; 1881 case T_SSIZET: 1882 (*argtable) [n].ssizearg = va_arg (ap, ssize_t); 1883 break; 1884 case T_SIZET: 1885 (*argtable) [n].sizearg = va_arg (ap, size_t); 1886 break; 1887 case TP_SIZET: 1888 (*argtable) [n].psizearg = va_arg (ap, size_t *); 1889 break; 1890 case T_INTMAXT: 1891 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t); 1892 break; 1893 case T_UINTMAXT: 1894 (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t); 1895 break; 1896 case TP_INTMAXT: 1897 (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *); 1898 break; 1899 case T_DOUBLE: 1900 #ifndef NO_FLOATING_POINT 1901 (*argtable) [n].doublearg = va_arg (ap, double); 1902 #endif 1903 break; 1904 case T_LONG_DOUBLE: 1905 #ifndef NO_FLOATING_POINT 1906 (*argtable) [n].longdoublearg = va_arg (ap, long double); 1907 #endif 1908 break; 1909 case TP_CHAR: 1910 (*argtable) [n].pchararg = va_arg (ap, char *); 1911 break; 1912 case TP_VOID: 1913 (*argtable) [n].pvoidarg = va_arg (ap, void *); 1914 break; 1915 case T_WINT: 1916 (*argtable) [n].wintarg = va_arg (ap, wint_t); 1917 break; 1918 case TP_WCHAR: 1919 (*argtable) [n].pwchararg = va_arg (ap, wchar_t *); 1920 break; 1921 } 1922 } 1923 1924 if (typetable != stattypetable) 1925 free (typetable); 1926 return 0; 1927 } 1928 1929 /* 1930 * Increase the size of the type table. 1931 */ 1932 static int 1933 __grow_type_table (size_t nextarg, enum typeid **typetable, size_t *tablesize) 1934 { 1935 enum typeid *const oldtable = *typetable; 1936 const size_t oldsize = *tablesize; 1937 enum typeid *newtable; 1938 size_t newsize = oldsize * 2; 1939 1940 if (newsize < nextarg + 1) 1941 newsize = nextarg + 1; 1942 if (oldsize == STATIC_ARG_TBL_SIZE) { 1943 newtable = NULL; 1944 errno = reallocarr(&newtable, newsize, sizeof(*newtable)); 1945 if (errno) 1946 return -1; 1947 memcpy(newtable, oldtable, oldsize * sizeof(*newtable)); 1948 } else { 1949 newtable = oldtable; 1950 errno = reallocarr(&newtable, newsize, sizeof(*newtable)); 1951 if (errno) { 1952 int serrno = errno; 1953 free(oldtable); 1954 errno = serrno; 1955 return -1; 1956 } 1957 } 1958 memset(&newtable[oldsize], 0, (newsize - oldsize) * sizeof(*newtable)); 1959 1960 *typetable = newtable; 1961 *tablesize = newsize; 1962 return 0; 1963 } 1964 1965 #ifndef NO_FLOATING_POINT 1966 1967 static int 1968 exponent(CHAR_T *p0, int expo, int fmtch) 1969 { 1970 CHAR_T *p, *t; 1971 CHAR_T expbuf[MAXEXPDIG]; 1972 1973 p = p0; 1974 *p++ = fmtch; 1975 if (expo < 0) { 1976 expo = -expo; 1977 *p++ = '-'; 1978 } 1979 else 1980 *p++ = '+'; 1981 t = expbuf + MAXEXPDIG; 1982 if (expo > 9) { 1983 do { 1984 *--t = to_char(expo % 10); 1985 } while ((expo /= 10) > 9); 1986 *--t = to_char(expo); 1987 for (; t < expbuf + MAXEXPDIG; *p++ = *t++); 1988 } 1989 else { 1990 /* 1991 * Exponents for decimal floating point conversions 1992 * (%[eEgG]) must be at least two characters long, 1993 * whereas exponents for hexadecimal conversions can 1994 * be only one character long. 1995 */ 1996 if (fmtch == 'e' || fmtch == 'E') 1997 *p++ = '0'; 1998 *p++ = to_char(expo); 1999 } 2000 _DIAGASSERT(__type_fit(int, p - p0)); 2001 return (int)(p - p0); 2002 } 2003 #endif /* !NO_FLOATING_POINT */ 2004