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