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