]> git.saurik.com Git - apple/libc.git/blob - stdio/vfprintf-fbsd.c
3182836585deaa1089d55f250b6b7aeb736582a5
[apple/libc.git] / stdio / vfprintf-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 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #if defined(LIBC_SCCS) && !defined(lint)
34 static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
35 #endif /* LIBC_SCCS and not lint */
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.90 2009/02/28 06:06:57 das Exp $");
38
39 #include "xlocale_private.h"
40
41 /*
42 * Actual printf innards.
43 *
44 * This code is large and complicated...
45 */
46
47 #include "namespace.h"
48 #include <sys/types.h>
49
50 #include <ctype.h>
51 #include <limits.h>
52 #include <locale.h>
53 #include <stddef.h>
54 #include <stdint.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <wchar.h>
59 #if 0 // xprintf pending API review
60 #include <printf.h>
61 #endif
62 #include <errno.h>
63
64 #include <stdarg.h>
65 #include "un-namespace.h"
66
67 #include "libc_private.h"
68 #include "local.h"
69 #include "fvwrite.h"
70 #include "printflocal.h"
71
72 static int __sprint(FILE *, locale_t, struct __suio *);
73 static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0);
74 static char *__wcsconv(wchar_t *, int, locale_t);
75
76 __private_extern__ const char *__fix_nogrouping(const char *);
77
78 #define CHAR char
79 #include "printfcommon.h"
80
81 struct grouping_state {
82 char *thousands_sep; /* locale-specific thousands separator */
83 int thousep_len; /* length of thousands_sep */
84 const char *grouping; /* locale-specific numeric grouping rules */
85 int lead; /* sig figs before decimal or group sep */
86 int nseps; /* number of group separators with ' */
87 int nrepeats; /* number of repeats of the last group */
88 };
89
90 /*
91 * Initialize the thousands' grouping state in preparation to print a
92 * number with ndigits digits. This routine returns the total number
93 * of bytes that will be needed.
94 */
95 static int
96 grouping_init(struct grouping_state *gs, int ndigits, locale_t loc)
97 {
98 struct lconv *locale;
99
100 locale = localeconv_l(loc);
101 gs->grouping = __fix_nogrouping(locale->grouping);
102 gs->thousands_sep = locale->thousands_sep;
103 gs->thousep_len = strlen(gs->thousands_sep);
104
105 gs->nseps = gs->nrepeats = 0;
106 gs->lead = ndigits;
107 while (*gs->grouping != CHAR_MAX) {
108 if (gs->lead <= *gs->grouping)
109 break;
110 gs->lead -= *gs->grouping;
111 if (*(gs->grouping+1)) {
112 gs->nseps++;
113 gs->grouping++;
114 } else
115 gs->nrepeats++;
116 }
117 return ((gs->nseps + gs->nrepeats) * gs->thousep_len);
118 }
119
120 /*
121 * Print a number with thousands' separators.
122 */
123 static int
124 grouping_print(struct grouping_state *gs, struct io_state *iop,
125 const CHAR *cp, const CHAR *ep, locale_t loc)
126 {
127 const CHAR *cp0 = cp;
128
129 if (io_printandpad(iop, cp, ep, gs->lead, zeroes, loc))
130 return (-1);
131 cp += gs->lead;
132 while (gs->nseps > 0 || gs->nrepeats > 0) {
133 if (gs->nrepeats > 0)
134 gs->nrepeats--;
135 else {
136 gs->grouping--;
137 gs->nseps--;
138 }
139 if (io_print(iop, gs->thousands_sep, gs->thousep_len, loc))
140 return (-1);
141 if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, loc))
142 return (-1);
143 cp += *gs->grouping;
144 }
145 if (cp > ep)
146 cp = ep;
147 return (cp - cp0);
148 }
149
150 /*
151 * Flush out all the vectors defined by the given uio,
152 * then reset it so that it can be reused.
153 */
154 static int
155 __sprint(FILE *fp, locale_t loc __unused, struct __suio *uio)
156 {
157 int err;
158
159 if (uio->uio_resid == 0) {
160 uio->uio_iovcnt = 0;
161 return (0);
162 }
163 err = __sfvwrite(fp, uio);
164 uio->uio_resid = 0;
165 uio->uio_iovcnt = 0;
166 return (err);
167 }
168
169 /*
170 * Helper function for `fprintf to unbuffered unix file': creates a
171 * temporary buffer. We only work on write-only files; this avoids
172 * worries about ungetc buffers and so forth.
173 */
174 static int
175 __sbprintf(FILE *fp, locale_t loc, const char *fmt, va_list ap)
176 {
177 int ret;
178 FILE fake;
179 unsigned char buf[BUFSIZ];
180 struct __sFILEX ext;
181 fake._extra = &ext;
182 INITEXTRA(&fake);
183
184 /* XXX This is probably not needed. */
185 if (prepwrite(fp) != 0)
186 return (EOF);
187
188 /* copy the important variables */
189 fake._flags = fp->_flags & ~__SNBF;
190 fake._file = fp->_file;
191 fake._cookie = fp->_cookie;
192 fake._write = fp->_write;
193 fake._orientation = fp->_orientation;
194 fake._mbstate = fp->_mbstate;
195
196 /* set up the buffer */
197 fake._bf._base = fake._p = buf;
198 fake._bf._size = fake._w = sizeof(buf);
199 fake._lbfsize = 0; /* not actually used, but Just In Case */
200
201 /* do the work, then copy any error status */
202 ret = __vfprintf(&fake, loc, fmt, ap);
203 if (ret >= 0 && __fflush(&fake))
204 ret = EOF;
205 if (fake._flags & __SERR)
206 fp->_flags |= __SERR;
207 return (ret);
208 }
209
210 /*
211 * Convert a wide character string argument for the %ls format to a multibyte
212 * string representation. If not -1, prec specifies the maximum number of
213 * bytes to output, and also means that we can't assume that the wide char.
214 * string ends is null-terminated.
215 */
216 static char *
217 __wcsconv(wchar_t *wcsarg, int prec, locale_t loc)
218 {
219 static const mbstate_t initial;
220 mbstate_t mbs;
221 char buf[MB_LEN_MAX];
222 wchar_t *p;
223 char *convbuf;
224 size_t clen, nbytes;
225
226 /* Allocate space for the maximum number of bytes we could output. */
227 if (prec < 0) {
228 p = wcsarg;
229 mbs = initial;
230 nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc);
231 if (nbytes == (size_t)-1)
232 return (NULL);
233 } else {
234 /*
235 * Optimisation: if the output precision is small enough,
236 * just allocate enough memory for the maximum instead of
237 * scanning the string.
238 */
239 if (prec < 128)
240 nbytes = prec;
241 else {
242 nbytes = 0;
243 p = wcsarg;
244 mbs = initial;
245 for (;;) {
246 clen = wcrtomb_l(buf, *p++, &mbs, loc);
247 if (clen == 0 || clen == (size_t)-1 ||
248 nbytes + clen > prec)
249 break;
250 nbytes += clen;
251 }
252 }
253 }
254 if ((convbuf = malloc(nbytes + 1)) == NULL)
255 return (NULL);
256
257 /* Fill the output buffer. */
258 p = wcsarg;
259 mbs = initial;
260 if ((nbytes = wcsrtombs_l(convbuf, (const wchar_t **)&p,
261 nbytes, &mbs, loc)) == (size_t)-1) {
262 free(convbuf);
263 return (NULL);
264 }
265 convbuf[nbytes] = '\0';
266 return (convbuf);
267 }
268
269 /*
270 * MT-safe version
271 */
272 int
273 vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, va_list ap)
274
275 {
276 int ret;
277
278 NORMALIZE_LOCALE(loc);
279 FLOCKFILE(fp);
280 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
281 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
282 fp->_file >= 0)
283 ret = __sbprintf(fp, loc, fmt0, ap);
284 else
285 ret = __vfprintf(fp, loc, fmt0, ap);
286 FUNLOCKFILE(fp);
287 return (ret);
288 }
289
290 int
291 vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
292
293 {
294 return vfprintf_l(fp, __current_locale(), fmt0, ap);
295 }
296
297 /*
298 * The size of the buffer we use as scratch space for integer
299 * conversions, among other things. We need enough space to
300 * write a uintmax_t in octal (plus one byte).
301 */
302 #if UINTMAX_MAX <= UINT64_MAX
303 #define BUF 32
304 #else
305 #error "BUF must be large enough to format a uintmax_t"
306 #endif
307
308 /*
309 * Non-MT-safe version
310 */
311 __private_extern__ int
312 __vfprintf(FILE *fp, locale_t loc, const char *fmt0, va_list ap)
313 {
314 char *fmt; /* format string */
315 int ch; /* character from fmt */
316 int n, n2; /* handy integer (short term usage) */
317 char *cp; /* handy char pointer (short term usage) */
318 int flags; /* flags as above */
319 int ret; /* return value accumulator */
320 int width; /* width from format (%8d), or 0 */
321 int prec; /* precision from format; <0 for N/A */
322 char sign; /* sign prefix (' ', '+', '-', or \0) */
323 struct grouping_state gs; /* thousands' grouping info */
324
325 #ifndef NO_FLOATING_POINT
326 /*
327 * We can decompose the printed representation of floating
328 * point numbers into several parts, some of which may be empty:
329 *
330 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
331 * A B ---C--- D E F
332 *
333 * A: 'sign' holds this value if present; '\0' otherwise
334 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
335 * C: cp points to the string MMMNNN. Leading and trailing
336 * zeros are not in the string and must be added.
337 * D: expchar holds this character; '\0' if no exponent, e.g. %f
338 * F: at least two digits for decimal, at least one digit for hex
339 */
340 char *decimal_point; /* locale specific decimal point */
341 int decpt_len; /* length of decimal_point */
342 int signflag; /* true if float is negative */
343 union { /* floating point arguments %[aAeEfFgG] */
344 double dbl;
345 long double ldbl;
346 } fparg;
347 int expt; /* integer value of exponent */
348 char expchar; /* exponent character: [eEpP\0] */
349 char *dtoaend; /* pointer to end of converted digits */
350 int expsize; /* character count for expstr */
351 int ndig; /* actual number of digits returned by dtoa */
352 char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
353 char *dtoaresult; /* buffer allocated by dtoa */
354 #endif
355 #ifdef VECTORS
356 union arg vval; /* Vector argument. */
357 char *pct; /* Pointer to '%' at beginning of specifier. */
358 char vsep; /* Vector separator character. */
359 #endif
360 u_long ulval; /* integer arguments %[diouxX] */
361 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
362 int base; /* base for [diouxX] conversion */
363 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
364 int realsz; /* field size expanded by dprec, sign, etc */
365 int size; /* size of converted field or string */
366 int prsize; /* max size of printed field */
367 const char *xdigs; /* digits for %[xX] conversion */
368 struct io_state io; /* I/O buffering state */
369 char buf[BUF]; /* buffer with space for digits of uintmax_t */
370 char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
371 union arg *argtable; /* args, built due to positional arg */
372 union arg statargtable [STATIC_ARG_TBL_SIZE];
373 int nextarg; /* 1-based argument index */
374 va_list orgap; /* original argument pointer */
375 char *convbuf; /* wide to multibyte conversion result */
376
377 static const char xdigs_lower[16] = "0123456789abcdef";
378 static const char xdigs_upper[16] = "0123456789ABCDEF";
379
380 /* BEWARE, these `goto error' on error. */
381 #define PRINT(ptr, len) { \
382 if (io_print(&io, (ptr), (len), loc)) \
383 goto error; \
384 }
385 #define PAD(howmany, with) { \
386 if (io_pad(&io, (howmany), (with), loc)) \
387 goto error; \
388 }
389 #define PRINTANDPAD(p, ep, len, with) { \
390 if (io_printandpad(&io, (p), (ep), (len), (with), loc)) \
391 goto error; \
392 }
393 #define FLUSH() { \
394 if (io_flush(&io, loc)) \
395 goto error; \
396 }
397
398 /*
399 * Get the argument indexed by nextarg. If the argument table is
400 * built, use it to get the argument. If its not, get the next
401 * argument (and arguments must be gotten sequentially).
402 */
403 #define GETARG(type) \
404 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
405 (nextarg++, va_arg(ap, type)))
406
407 /*
408 * To extend shorts properly, we need both signed and unsigned
409 * argument extraction methods.
410 */
411 #define SARG() \
412 (flags&LONGINT ? GETARG(long) : \
413 flags&SHORTINT ? (long)(short)GETARG(int) : \
414 flags&CHARINT ? (long)(signed char)GETARG(int) : \
415 (long)GETARG(int))
416 #define UARG() \
417 (flags&LONGINT ? GETARG(u_long) : \
418 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
419 flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
420 (u_long)GETARG(u_int))
421 #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
422 #define SJARG() \
423 (flags&INTMAXT ? GETARG(intmax_t) : \
424 flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
425 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
426 (intmax_t)GETARG(long long))
427 #define UJARG() \
428 (flags&INTMAXT ? GETARG(uintmax_t) : \
429 flags&SIZET ? (uintmax_t)GETARG(size_t) : \
430 flags&PTRDIFFT ? (uintmax_t)(unsigned long)GETARG(ptrdiff_t) : \
431 (uintmax_t)GETARG(unsigned long long))
432
433 /*
434 * Get * arguments, including the form *nn$. Preserve the nextarg
435 * that the argument can be gotten once the type is determined.
436 */
437 #define GETASTER(val) \
438 n2 = 0; \
439 cp = fmt; \
440 while (is_digit(*cp)) { \
441 n2 = 10 * n2 + to_digit(*cp); \
442 cp++; \
443 } \
444 if (*cp == '$') { \
445 int hold = nextarg; \
446 if (argtable == NULL) { \
447 argtable = statargtable; \
448 if (__find_arguments (fmt0, orgap, &argtable)) { \
449 ret = EOF; \
450 goto error; \
451 } \
452 } \
453 nextarg = n2; \
454 val = GETARG (int); \
455 nextarg = hold; \
456 fmt = ++cp; \
457 } else { \
458 val = GETARG (int); \
459 }
460
461 #if 0 // xprintf pending API review
462 if (__use_xprintf == 0 && getenv("USE_XPRINTF"))
463 __use_xprintf = 1;
464 if (__use_xprintf > 0)
465 return (__xvprintf(fp, loc, fmt0, ap));
466 #endif
467
468 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
469 if (prepwrite(fp) != 0) {
470 errno = EBADF;
471 return (EOF);
472 }
473 ORIENT(fp, -1);
474
475 convbuf = NULL;
476 fmt = (char *)fmt0;
477 argtable = NULL;
478 nextarg = 1;
479 va_copy(orgap, ap);
480 io_init(&io, fp);
481 ret = 0;
482 #ifndef NO_FLOATING_POINT
483 dtoaresult = NULL;
484 decimal_point = localeconv_l(loc)->decimal_point;
485 /* The overwhelmingly common case is decpt_len == 1. */
486 decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
487 #endif
488
489 /*
490 * Scan the format for conversions (`%' character).
491 */
492 for (;;) {
493 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
494 /* void */;
495 if ((n = fmt - cp) != 0) {
496 if ((unsigned)ret + n > INT_MAX) {
497 ret = EOF;
498 goto error;
499 }
500 PRINT(cp, n);
501 ret += n;
502 }
503 if (ch == '\0')
504 goto done;
505 #ifdef VECTORS
506 pct = fmt;
507 #endif /* VECTORS */
508 fmt++; /* skip over '%' */
509
510 flags = 0;
511 dprec = 0;
512 width = 0;
513 prec = -1;
514 gs.grouping = NULL;
515 sign = '\0';
516 ox[1] = '\0';
517 #ifdef VECTORS
518 vsep = 'X'; /* Illegal value, changed to defaults later. */
519 #endif /* VECTORS */
520
521 rflag: ch = *fmt++;
522 reswitch: switch (ch) {
523 case ' ':
524 /*-
525 * ``If the space and + flags both appear, the space
526 * flag will be ignored.''
527 * -- ANSI X3J11
528 */
529 if (!sign)
530 sign = ' ';
531 goto rflag;
532 case '#':
533 flags |= ALT;
534 goto rflag;
535 #ifdef VECTORS
536 case ',': case ';': case ':': case '_':
537 vsep = ch;
538 goto rflag;
539 #endif /* VECTORS */
540 case '*':
541 /*-
542 * ``A negative field width argument is taken as a
543 * - flag followed by a positive field width.''
544 * -- ANSI X3J11
545 * They don't exclude field widths read from args.
546 */
547 GETASTER (width);
548 if (width >= 0)
549 goto rflag;
550 width = -width;
551 /* FALLTHROUGH */
552 case '-':
553 flags |= LADJUST;
554 goto rflag;
555 case '+':
556 sign = '+';
557 goto rflag;
558 case '\'':
559 flags |= GROUPING;
560 goto rflag;
561 case '.':
562 if ((ch = *fmt++) == '*') {
563 GETASTER (prec);
564 goto rflag;
565 }
566 prec = 0;
567 while (is_digit(ch)) {
568 prec = 10 * prec + to_digit(ch);
569 ch = *fmt++;
570 }
571 goto reswitch;
572 case '0':
573 /*-
574 * ``Note that 0 is taken as a flag, not as the
575 * beginning of a field width.''
576 * -- ANSI X3J11
577 */
578 flags |= ZEROPAD;
579 goto rflag;
580 case '1': case '2': case '3': case '4':
581 case '5': case '6': case '7': case '8': case '9':
582 n = 0;
583 do {
584 n = 10 * n + to_digit(ch);
585 ch = *fmt++;
586 } while (is_digit(ch));
587 if (ch == '$') {
588 nextarg = n;
589 if (argtable == NULL) {
590 argtable = statargtable;
591 if (__find_arguments (fmt0, orgap,
592 &argtable)) {
593 ret = EOF;
594 goto error;
595 }
596 }
597 goto rflag;
598 }
599 width = n;
600 goto reswitch;
601 #ifndef NO_FLOATING_POINT
602 case 'L':
603 flags |= LONGDBL;
604 goto rflag;
605 #endif
606 case 'h':
607 if (flags & SHORTINT) {
608 flags &= ~SHORTINT;
609 flags |= CHARINT;
610 } else
611 flags |= SHORTINT;
612 goto rflag;
613 case 'j':
614 flags |= INTMAXT;
615 goto rflag;
616 case 'l':
617 if (flags & LONGINT) {
618 flags &= ~LONGINT;
619 flags |= LLONGINT;
620 } else
621 flags |= LONGINT;
622 goto rflag;
623 case 'q':
624 flags |= LLONGINT; /* not necessarily */
625 goto rflag;
626 case 't':
627 flags |= PTRDIFFT;
628 goto rflag;
629 case 'z':
630 flags |= SIZET;
631 goto rflag;
632 case 'C':
633 flags |= LONGINT;
634 /*FALLTHROUGH*/
635 case 'c':
636 #ifdef VECTORS
637 if (flags & VECTOR)
638 break;
639 #endif /* VECTORS */
640 if (flags & LONGINT) {
641 static const mbstate_t initial;
642 mbstate_t mbs;
643 size_t mbseqlen;
644
645 mbs = initial;
646 mbseqlen = wcrtomb_l(cp = buf,
647 (wchar_t)GETARG(wint_t), &mbs, loc);
648 if (mbseqlen == (size_t)-1) {
649 fp->_flags |= __SERR;
650 goto error;
651 }
652 size = (int)mbseqlen;
653 } else {
654 *(cp = buf) = GETARG(int);
655 size = 1;
656 }
657 sign = '\0';
658 break;
659 case 'D':
660 flags |= LONGINT;
661 /*FALLTHROUGH*/
662 case 'd':
663 case 'i':
664 #ifdef VECTORS
665 if (flags & VECTOR)
666 break;
667 #endif /* VECTORS */
668 if (flags & INTMAX_SIZE) {
669 ujval = SJARG();
670 if ((intmax_t)ujval < 0) {
671 ujval = -ujval;
672 sign = '-';
673 }
674 } else {
675 ulval = SARG();
676 if ((long)ulval < 0) {
677 ulval = -ulval;
678 sign = '-';
679 }
680 }
681 base = 10;
682 goto number;
683 #ifndef NO_FLOATING_POINT
684 case 'a':
685 case 'A':
686 #ifdef VECTORS
687 if (flags & VECTOR) {
688 flags |= FPT;
689 break;
690 }
691 #endif /* VECTORS */
692 if (ch == 'a') {
693 ox[1] = 'x';
694 xdigs = xdigs_lower;
695 expchar = 'p';
696 } else {
697 ox[1] = 'X';
698 xdigs = xdigs_upper;
699 expchar = 'P';
700 }
701 if (prec >= 0)
702 prec++;
703 if (dtoaresult != NULL)
704 freedtoa(dtoaresult);
705 #ifdef LDBL_COMPAT
706 fparg.dbl = GETARG(double);
707 dtoaresult = cp =
708 __hdtoa(fparg.dbl, xdigs, prec,
709 &expt, &signflag, &dtoaend);
710 #else /* !LDBL_COMPAT */
711 if (flags & LONGDBL) {
712 fparg.ldbl = GETARG(long double);
713 dtoaresult = cp =
714 __hldtoa(fparg.ldbl, xdigs, prec,
715 &expt, &signflag, &dtoaend);
716 } else {
717 fparg.dbl = GETARG(double);
718 dtoaresult = cp =
719 __hdtoa(fparg.dbl, xdigs, prec,
720 &expt, &signflag, &dtoaend);
721 }
722 #endif /* LDBL_COMPAT */
723 if (prec < 0)
724 prec = dtoaend - cp;
725 if (expt == INT_MAX)
726 ox[1] = '\0';
727 goto fp_common;
728 case 'e':
729 case 'E':
730 #ifdef VECTORS
731 if (flags & VECTOR) {
732 flags |= FPT;
733 break;
734 }
735 #endif /* VECTORS */
736 expchar = ch;
737 if (prec < 0) /* account for digit before decpt */
738 prec = DEFPREC + 1;
739 else
740 prec++;
741 goto fp_begin;
742 case 'f':
743 case 'F':
744 #ifdef VECTORS
745 if (flags & VECTOR) {
746 flags |= FPT;
747 break;
748 }
749 #endif /* VECTORS */
750 expchar = '\0';
751 goto fp_begin;
752 case 'g':
753 case 'G':
754 #ifdef VECTORS
755 if (flags & VECTOR) {
756 flags |= FPT;
757 break;
758 }
759 #endif /* VECTORS */
760 expchar = ch - ('g' - 'e');
761 if (prec == 0)
762 prec = 1;
763 fp_begin:
764 if (prec < 0)
765 prec = DEFPREC;
766 if (dtoaresult != NULL)
767 freedtoa(dtoaresult);
768 #ifdef LDBL_COMPAT
769 fparg.dbl = GETARG(double);
770 dtoaresult = cp =
771 dtoa(fparg.dbl, expchar ? 2 : 3, prec,
772 &expt, &signflag, &dtoaend);
773 if (expt == 9999)
774 expt = INT_MAX;
775 #else /* !LDBL_COMPAT */
776 if (flags & LONGDBL) {
777 fparg.ldbl = GETARG(long double);
778 dtoaresult = cp =
779 __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
780 &expt, &signflag, &dtoaend);
781 } else {
782 fparg.dbl = GETARG(double);
783 dtoaresult = cp =
784 dtoa(fparg.dbl, expchar ? 2 : 3, prec,
785 &expt, &signflag, &dtoaend);
786 if (expt == 9999)
787 expt = INT_MAX;
788 }
789 #endif /* LDBL_COMPAT */
790 fp_common:
791 if (signflag)
792 sign = '-';
793 if (expt == INT_MAX) { /* inf or nan */
794 if (*cp == 'N') {
795 cp = (ch >= 'a') ? "nan" : "NAN";
796 sign = '\0';
797 } else
798 cp = (ch >= 'a') ? "inf" : "INF";
799 size = 3;
800 flags &= ~ZEROPAD;
801 break;
802 }
803 flags |= FPT;
804 ndig = dtoaend - cp;
805 if (ch == 'g' || ch == 'G') {
806 if (expt > -4 && expt <= prec) {
807 /* Make %[gG] smell like %[fF] */
808 expchar = '\0';
809 if (flags & ALT)
810 prec -= expt;
811 else
812 prec = ndig - expt;
813 if (prec < 0)
814 prec = 0;
815 } else {
816 /*
817 * Make %[gG] smell like %[eE], but
818 * trim trailing zeroes if no # flag.
819 */
820 if (!(flags & ALT))
821 prec = ndig;
822 }
823 }
824 if (expchar) {
825 expsize = exponent(expstr, expt - 1, expchar);
826 size = expsize + prec;
827 if (prec > 1 || flags & ALT)
828 size += decpt_len;
829 } else {
830 /* space for digits before decimal point */
831 if (expt > 0)
832 size = expt;
833 else /* "0" */
834 size = 1;
835 /* space for decimal pt and following digits */
836 if (prec || flags & ALT)
837 size += prec + decpt_len;
838 if ((flags & GROUPING) && expt > 0)
839 size += grouping_init(&gs, expt, loc);
840 }
841 break;
842 #endif /* !NO_FLOATING_POINT */
843 case 'n':
844 {
845 /*
846 * Assignment-like behavior is specified if the
847 * value overflows or is otherwise unrepresentable.
848 * C99 says to use `signed char' for %hhn conversions.
849 */
850 void *ptr = GETARG(void *);
851 if (ptr == NULL)
852 continue;
853 else if (flags & LLONGINT)
854 *(long long *)ptr = ret;
855 else if (flags & SIZET)
856 *(ssize_t *)ptr = (ssize_t)ret;
857 else if (flags & PTRDIFFT)
858 *(ptrdiff_t *)ptr = ret;
859 else if (flags & INTMAXT)
860 *(intmax_t *)ptr = ret;
861 else if (flags & LONGINT)
862 *(long *)ptr = ret;
863 else if (flags & SHORTINT)
864 *(short *)ptr = ret;
865 else if (flags & CHARINT)
866 *(signed char *)ptr = ret;
867 else
868 *(int *)ptr = ret;
869 continue; /* no output */
870 }
871 case 'O':
872 flags |= LONGINT;
873 /*FALLTHROUGH*/
874 case 'o':
875 #ifdef VECTORS
876 if (flags & VECTOR)
877 break;
878 #endif /* VECTORS */
879 if (flags & INTMAX_SIZE)
880 ujval = UJARG();
881 else
882 ulval = UARG();
883 base = 8;
884 goto nosign;
885 case 'p':
886 /*-
887 * ``The argument shall be a pointer to void. The
888 * value of the pointer is converted to a sequence
889 * of printable characters, in an implementation-
890 * defined manner.''
891 * -- ANSI X3J11
892 */
893 #ifdef VECTORS
894 if (flags & VECTOR)
895 break;
896 #endif /* VECTORS */
897 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
898 base = 16;
899 xdigs = xdigs_lower;
900 flags = flags | INTMAXT;
901 ox[1] = 'x';
902 goto nosign;
903 case 'S':
904 flags |= LONGINT;
905 /*FALLTHROUGH*/
906 case 's':
907 if (flags & LONGINT) {
908 wchar_t *wcp;
909
910 if (convbuf != NULL)
911 free(convbuf);
912 if ((wcp = GETARG(wchar_t *)) == NULL)
913 cp = "(null)";
914 else {
915 convbuf = __wcsconv(wcp, prec, loc);
916 if (convbuf == NULL) {
917 fp->_flags |= __SERR;
918 goto error;
919 }
920 cp = convbuf;
921 }
922 } else if ((cp = GETARG(char *)) == NULL)
923 cp = "(null)";
924 size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
925 sign = '\0';
926 break;
927 case 'U':
928 flags |= LONGINT;
929 /*FALLTHROUGH*/
930 case 'u':
931 #ifdef VECTORS
932 if (flags & VECTOR)
933 break;
934 #endif /* VECTORS */
935 if (flags & INTMAX_SIZE)
936 ujval = UJARG();
937 else
938 ulval = UARG();
939 base = 10;
940 goto nosign;
941 case 'X':
942 xdigs = xdigs_upper;
943 goto hex;
944 case 'x':
945 xdigs = xdigs_lower;
946 hex:
947 #ifdef VECTORS
948 if (flags & VECTOR)
949 break;
950 #endif /* VECTORS */
951 if (flags & INTMAX_SIZE)
952 ujval = UJARG();
953 else
954 ulval = UARG();
955 base = 16;
956 /* leading 0x/X only if non-zero */
957 if (flags & ALT &&
958 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
959 ox[1] = ch;
960
961 flags &= ~GROUPING;
962 /* unsigned conversions */
963 nosign: sign = '\0';
964 /*-
965 * ``... diouXx conversions ... if a precision is
966 * specified, the 0 flag will be ignored.''
967 * -- ANSI X3J11
968 * except for %#.0o and zero value
969 */
970 number: if ((dprec = prec) >= 0)
971 flags &= ~ZEROPAD;
972
973 /*-
974 * ``The result of converting a zero value with an
975 * explicit precision of zero is no characters.''
976 * -- ANSI X3J11
977 *
978 * ``The C Standard is clear enough as is. The call
979 * printf("%#.0o", 0) should print 0.''
980 * -- Defect Report #151
981 */
982 cp = buf + BUF;
983 if (flags & INTMAX_SIZE) {
984 if (ujval != 0 || prec != 0 ||
985 (flags & ALT && base == 8))
986 cp = __ujtoa(ujval, cp, base,
987 flags & ALT, xdigs);
988 } else {
989 if (ulval != 0 || prec != 0 ||
990 (flags & ALT && base == 8))
991 cp = __ultoa(ulval, cp, base,
992 flags & ALT, xdigs);
993 }
994 size = buf + BUF - cp;
995 if (size > BUF) /* should never happen */
996 LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
997 if ((flags & GROUPING) && size != 0)
998 size += grouping_init(&gs, size, loc);
999 break;
1000 #ifdef VECTORS
1001 case 'v':
1002 flags |= VECTOR;
1003 goto rflag;
1004 #endif /* VECTORS */
1005 default: /* "%?" prints ?, unless ? is NUL */
1006 if (ch == '\0')
1007 goto done;
1008 /* pretend it was %c with argument ch */
1009 cp = buf;
1010 *cp = ch;
1011 size = 1;
1012 sign = '\0';
1013 break;
1014 }
1015
1016 #ifdef VECTORS
1017 if (flags & VECTOR) {
1018 /*
1019 * Do the minimum amount of work necessary to construct
1020 * a format specifier that can be used to recursively
1021 * call vfprintf() for each element in the vector.
1022 */
1023 int i, j; /* Counter. */
1024 int vcnt; /* Number of elements in vector. */
1025 char *vfmt; /* Pointer to format specifier. */
1026 #define EXTRAHH 2
1027 char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
1028 int vwidth = 0; /* Width specified via '*'. */
1029 int vprec = 0; /* Precision specified via '*'. */
1030 char *vstr; /* Used for asprintf(). */
1031 int vlen; /* Length returned by asprintf(). */
1032 enum {
1033 V_CHAR, V_SHORT, V_INT,
1034 V_PCHAR, V_PSHORT, V_PINT,
1035 V_FLOAT,
1036 #ifdef V64TYPE
1037 V_LONGLONG, V_PLONGLONG,
1038 V_DOUBLE,
1039 #endif /* V64TYPE */
1040 } vtype;
1041
1042 vval.vectorarg = GETARG(VECTORTYPE);
1043 /*
1044 * Set vfmt. If vfmt_buf may not be big enough,
1045 * malloc() space, taking care to free it later.
1046 * (EXTRAHH is for possible extra "hh")
1047 */
1048 if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
1049 vfmt = vfmt_buf;
1050 else
1051 vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
1052
1053 /* Set the separator character, if not specified. */
1054 if (vsep == 'X') {
1055 if (ch == 'c')
1056 vsep = '\0';
1057 else
1058 vsep = ' ';
1059 }
1060
1061 /* Create the format specifier. */
1062 for (i = j = 0; i < &fmt[-1] - pct; i++) {
1063 switch (pct[i]) {
1064 case ',': case ';': case ':': case '_':
1065 case 'v': case 'h': case 'l':
1066 /* Ignore. */
1067 break;
1068 case '*':
1069 if (pct[i - 1] != '.')
1070 vwidth = 1;
1071 else
1072 vprec = 1;
1073 /* FALLTHROUGH */
1074 default:
1075 vfmt[j++] = pct[i];
1076 }
1077 }
1078
1079 /*
1080 * Determine the number of elements in the vector and
1081 * finish up the format specifier.
1082 */
1083 if (flags & SHORTINT) {
1084 switch (ch) {
1085 case 'c':
1086 vtype = V_SHORT;
1087 break;
1088 case 'p':
1089 vtype = V_PSHORT;
1090 break;
1091 default:
1092 vfmt[j++] = 'h';
1093 vtype = V_SHORT;
1094 break;
1095 }
1096 vcnt = 8;
1097 } else if (flags & LONGINT) {
1098 vcnt = 4;
1099 vtype = (ch == 'p') ? V_PINT : V_INT;
1100 #ifdef V64TYPE
1101 } else if (flags & LLONGINT) {
1102 switch (ch) {
1103 case 'a':
1104 case 'A':
1105 case 'e':
1106 case 'E':
1107 case 'f':
1108 case 'g':
1109 case 'G':
1110 vcnt = 2;
1111 vtype = V_DOUBLE;
1112 break;
1113 case 'd':
1114 case 'i':
1115 case 'u':
1116 case 'o':
1117 case 'p':
1118 case 'x':
1119 case 'X':
1120 vfmt[j++] = 'l';
1121 vfmt[j++] = 'l';
1122 vcnt = 2;
1123 vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
1124 break;
1125 default:
1126 /*
1127 * The default case should never
1128 * happen.
1129 */
1130 case 'c':
1131 vcnt = 16;
1132 vtype = V_CHAR;
1133 }
1134 #endif /* V64TYPE */
1135 } else {
1136 switch (ch) {
1137 case 'a':
1138 case 'A':
1139 case 'e':
1140 case 'E':
1141 case 'f':
1142 case 'g':
1143 case 'G':
1144 vcnt = 4;
1145 vtype = V_FLOAT;
1146 break;
1147 default:
1148 /*
1149 * The default case should never
1150 * happen.
1151 */
1152 case 'd':
1153 case 'i':
1154 case 'u':
1155 case 'o':
1156 case 'x':
1157 case 'X':
1158 vfmt[j++] = 'h';
1159 vfmt[j++] = 'h';
1160 /* drop through */
1161 case 'p':
1162 case 'c':
1163 vcnt = 16;
1164 vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
1165 }
1166 }
1167 vfmt[j++] = ch;
1168 vfmt[j++] = '\0';
1169
1170 /* Get a vector element. */
1171 #ifdef V64TYPE
1172 #define VPRINT(type, ind, args...) do { \
1173 switch (type) { \
1174 case V_CHAR: \
1175 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
1176 break; \
1177 case V_PCHAR: \
1178 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
1179 break; \
1180 case V_SHORT: \
1181 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
1182 break; \
1183 case V_PSHORT: \
1184 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
1185 break; \
1186 case V_INT: \
1187 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
1188 break; \
1189 case V_PINT: \
1190 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
1191 break; \
1192 case V_LONGLONG: \
1193 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
1194 break; \
1195 case V_PLONGLONG: \
1196 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \
1197 break; \
1198 case V_FLOAT: \
1199 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
1200 break; \
1201 case V_DOUBLE: \
1202 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
1203 break; \
1204 } \
1205 ret += vlen; \
1206 PRINT(vstr, vlen); \
1207 FLUSH(); \
1208 free(vstr); \
1209 } while (0)
1210 #else /* !V64TYPE */
1211 #define VPRINT(type, ind, args...) do { \
1212 switch (type) { \
1213 case V_CHAR: \
1214 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
1215 break; \
1216 case V_PCHAR: \
1217 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
1218 break; \
1219 case V_SHORT: \
1220 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
1221 break; \
1222 case V_PSHORT: \
1223 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
1224 break; \
1225 case V_INT: \
1226 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
1227 break; \
1228 case V_PINT: \
1229 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
1230 break; \
1231 case V_FLOAT: \
1232 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
1233 break; \
1234 } \
1235 ret += vlen; \
1236 PRINT(vstr, vlen); \
1237 FLUSH(); \
1238 free(vstr); \
1239 } while (0)
1240 #endif /* V64TYPE */
1241
1242 /* Actually print. */
1243 if (vwidth == 0) {
1244 if (vprec == 0) {
1245 /* First element. */
1246 VPRINT(vtype, 0);
1247 for (i = 1; i < vcnt; i++) {
1248 /* Separator. */
1249 if(vsep)
1250 PRINT(&vsep, 1);
1251
1252 /* Element. */
1253 VPRINT(vtype, i);
1254 }
1255 } else {
1256 /* First element. */
1257 VPRINT(vtype, 0, prec);
1258 for (i = 1; i < vcnt; i++) {
1259 /* Separator. */
1260 if(vsep)
1261 PRINT(&vsep, 1);
1262
1263 /* Element. */
1264 VPRINT(vtype, i, prec);
1265 }
1266 }
1267 } else {
1268 if (vprec == 0) {
1269 /* First element. */
1270 VPRINT(vtype, 0, width);
1271 for (i = 1; i < vcnt; i++) {
1272 /* Separator. */
1273 if(vsep)
1274 PRINT(&vsep, 1);
1275
1276 /* Element. */
1277 VPRINT(vtype, i, width);
1278 }
1279 } else {
1280 /* First element. */
1281 VPRINT(vtype, 0, width, prec);
1282 for (i = 1; i < vcnt; i++) {
1283 /* Separator. */
1284 if(vsep)
1285 PRINT(&vsep, 1);
1286
1287 /* Element. */
1288 VPRINT(vtype, i, width, prec);
1289 }
1290 }
1291 }
1292 #undef VPRINT
1293
1294 if (vfmt != vfmt_buf)
1295 free(vfmt);
1296
1297 continue;
1298 }
1299 #endif /* VECTORS */
1300 /*
1301 * All reasonable formats wind up here. At this point, `cp'
1302 * points to a string which (if not flags&LADJUST) should be
1303 * padded out to `width' places. If flags&ZEROPAD, it should
1304 * first be prefixed by any sign or other prefix; otherwise,
1305 * it should be blank padded before the prefix is emitted.
1306 * After any left-hand padding and prefixing, emit zeroes
1307 * required by a decimal [diouxX] precision, then print the
1308 * string proper, then emit zeroes required by any leftover
1309 * floating precision; finally, if LADJUST, pad with blanks.
1310 *
1311 * Compute actual size, so we know how much to pad.
1312 * size excludes decimal prec; realsz includes it.
1313 */
1314 realsz = dprec > size ? dprec : size;
1315 if (sign)
1316 realsz++;
1317 if (ox[1])
1318 realsz += 2;
1319
1320 prsize = width > realsz ? width : realsz;
1321 if ((unsigned)ret + prsize > INT_MAX) {
1322 ret = EOF;
1323 goto error;
1324 }
1325
1326 /* right-adjusting blank padding */
1327 if ((flags & (LADJUST|ZEROPAD)) == 0)
1328 PAD(width - realsz, blanks);
1329
1330 /* prefix */
1331 if (sign)
1332 PRINT(&sign, 1);
1333
1334 if (ox[1]) { /* ox[1] is either x, X, or \0 */
1335 ox[0] = '0';
1336 PRINT(ox, 2);
1337 }
1338
1339 /* right-adjusting zero padding */
1340 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1341 PAD(width - realsz, zeroes);
1342
1343 /* the string or number proper */
1344 #ifndef NO_FLOATING_POINT
1345 if ((flags & FPT) == 0) {
1346 #endif
1347 /* leading zeroes from decimal precision */
1348 PAD(dprec - size, zeroes);
1349 if (gs.grouping) {
1350 if (grouping_print(&gs, &io, cp, buf+BUF, loc) < 0)
1351 goto error;
1352 } else {
1353 PRINT(cp, size);
1354 }
1355 #ifndef NO_FLOATING_POINT
1356 } else { /* glue together f_p fragments */
1357 if (!expchar) { /* %[fF] or sufficiently short %[gG] */
1358 if (expt <= 0) {
1359 PRINT(zeroes, 1);
1360 if (prec || flags & ALT)
1361 PRINT(decimal_point,decpt_len);
1362 PAD(-expt, zeroes);
1363 /* already handled initial 0's */
1364 prec += expt;
1365 } else {
1366 if (gs.grouping) {
1367 n = grouping_print(&gs, &io,
1368 cp, dtoaend, loc);
1369 if (n < 0)
1370 goto error;
1371 cp += n;
1372 } else {
1373 PRINTANDPAD(cp, dtoaend,
1374 expt, zeroes);
1375 cp += expt;
1376 }
1377 if (prec || flags & ALT)
1378 PRINT(decimal_point,decpt_len);
1379 }
1380 PRINTANDPAD(cp, dtoaend, prec, zeroes);
1381 } else { /* %[eE] or sufficiently long %[gG] */
1382 if (prec > 1 || flags & ALT) {
1383 PRINT(cp++, 1);
1384 PRINT(decimal_point, decpt_len);
1385 PRINT(cp, ndig-1);
1386 PAD(prec - ndig, zeroes);
1387 } else /* XeYYY */
1388 PRINT(cp, 1);
1389 PRINT(expstr, expsize);
1390 }
1391 }
1392 #endif
1393 /* left-adjusting padding (always blank) */
1394 if (flags & LADJUST)
1395 PAD(width - realsz, blanks);
1396
1397 /* finally, adjust ret */
1398 ret += prsize;
1399
1400 FLUSH(); /* copy out the I/O vectors */
1401 }
1402 done:
1403 FLUSH();
1404 error:
1405 va_end(orgap);
1406 #ifndef NO_FLOATING_POINT
1407 if (dtoaresult != NULL)
1408 freedtoa(dtoaresult);
1409 #endif
1410 if (convbuf != NULL)
1411 free(convbuf);
1412 if (__sferror(fp))
1413 ret = EOF;
1414 if ((argtable != NULL) && (argtable != statargtable))
1415 free (argtable);
1416 return (ret);
1417 /* NOTREACHED */
1418 }
1419