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