]> git.saurik.com Git - apple/libc.git/blob - stdio/FreeBSD/vfprintf.c
Libc-825.40.1.tar.gz
[apple/libc.git] / stdio / FreeBSD / vfprintf.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 if (flags & LONGDBL) {
706 fparg.ldbl = GETARG(long double);
707 dtoaresult = cp =
708 __hldtoa(fparg.ldbl, xdigs, prec,
709 &expt, &signflag, &dtoaend);
710 } else {
711 fparg.dbl = GETARG(double);
712 dtoaresult = cp =
713 __hdtoa(fparg.dbl, xdigs, prec,
714 &expt, &signflag, &dtoaend);
715 }
716 if (prec < 0)
717 prec = dtoaend - cp;
718 if (expt == INT_MAX)
719 ox[1] = '\0';
720 goto fp_common;
721 case 'e':
722 case 'E':
723 #ifdef VECTORS
724 if (flags & VECTOR) {
725 flags |= FPT;
726 break;
727 }
728 #endif /* VECTORS */
729 expchar = ch;
730 if (prec < 0) /* account for digit before decpt */
731 prec = DEFPREC + 1;
732 else
733 prec++;
734 goto fp_begin;
735 case 'f':
736 case 'F':
737 #ifdef VECTORS
738 if (flags & VECTOR) {
739 flags |= FPT;
740 break;
741 }
742 #endif /* VECTORS */
743 expchar = '\0';
744 goto fp_begin;
745 case 'g':
746 case 'G':
747 #ifdef VECTORS
748 if (flags & VECTOR) {
749 flags |= FPT;
750 break;
751 }
752 #endif /* VECTORS */
753 expchar = ch - ('g' - 'e');
754 if (prec == 0)
755 prec = 1;
756 fp_begin:
757 if (prec < 0)
758 prec = DEFPREC;
759 if (dtoaresult != NULL)
760 freedtoa(dtoaresult);
761 if (flags & LONGDBL) {
762 fparg.ldbl = GETARG(long double);
763 dtoaresult = cp =
764 __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
765 &expt, &signflag, &dtoaend);
766 } else {
767 fparg.dbl = GETARG(double);
768 dtoaresult = cp =
769 dtoa(fparg.dbl, expchar ? 2 : 3, prec,
770 &expt, &signflag, &dtoaend);
771 if (expt == 9999)
772 expt = INT_MAX;
773 }
774 fp_common:
775 if (signflag)
776 sign = '-';
777 if (expt == INT_MAX) { /* inf or nan */
778 if (*cp == 'N') {
779 cp = (ch >= 'a') ? "nan" : "NAN";
780 sign = '\0';
781 } else
782 cp = (ch >= 'a') ? "inf" : "INF";
783 size = 3;
784 flags &= ~ZEROPAD;
785 break;
786 }
787 flags |= FPT;
788 ndig = dtoaend - cp;
789 if (ch == 'g' || ch == 'G') {
790 if (expt > -4 && expt <= prec) {
791 /* Make %[gG] smell like %[fF] */
792 expchar = '\0';
793 if (flags & ALT)
794 prec -= expt;
795 else
796 prec = ndig - expt;
797 if (prec < 0)
798 prec = 0;
799 } else {
800 /*
801 * Make %[gG] smell like %[eE], but
802 * trim trailing zeroes if no # flag.
803 */
804 if (!(flags & ALT))
805 prec = ndig;
806 }
807 }
808 if (expchar) {
809 expsize = exponent(expstr, expt - 1, expchar);
810 size = expsize + prec;
811 if (prec > 1 || flags & ALT)
812 size += decpt_len;
813 } else {
814 /* space for digits before decimal point */
815 if (expt > 0)
816 size = expt;
817 else /* "0" */
818 size = 1;
819 /* space for decimal pt and following digits */
820 if (prec || flags & ALT)
821 size += prec + decpt_len;
822 if ((flags & GROUPING) && expt > 0)
823 size += grouping_init(&gs, expt, loc);
824 }
825 break;
826 #endif /* !NO_FLOATING_POINT */
827 case 'n':
828 {
829 /*
830 * Assignment-like behavior is specified if the
831 * value overflows or is otherwise unrepresentable.
832 * C99 says to use `signed char' for %hhn conversions.
833 */
834 void *ptr = GETARG(void *);
835 if (ptr == NULL)
836 continue;
837 else if (flags & LLONGINT)
838 *(long long *)ptr = ret;
839 else if (flags & SIZET)
840 *(ssize_t *)ptr = (ssize_t)ret;
841 else if (flags & PTRDIFFT)
842 *(ptrdiff_t *)ptr = ret;
843 else if (flags & INTMAXT)
844 *(intmax_t *)ptr = ret;
845 else if (flags & LONGINT)
846 *(long *)ptr = ret;
847 else if (flags & SHORTINT)
848 *(short *)ptr = ret;
849 else if (flags & CHARINT)
850 *(signed char *)ptr = ret;
851 else
852 *(int *)ptr = ret;
853 continue; /* no output */
854 }
855 case 'O':
856 flags |= LONGINT;
857 /*FALLTHROUGH*/
858 case 'o':
859 #ifdef VECTORS
860 if (flags & VECTOR)
861 break;
862 #endif /* VECTORS */
863 if (flags & INTMAX_SIZE)
864 ujval = UJARG();
865 else
866 ulval = UARG();
867 base = 8;
868 goto nosign;
869 case 'p':
870 /*-
871 * ``The argument shall be a pointer to void. The
872 * value of the pointer is converted to a sequence
873 * of printable characters, in an implementation-
874 * defined manner.''
875 * -- ANSI X3J11
876 */
877 #ifdef VECTORS
878 if (flags & VECTOR)
879 break;
880 #endif /* VECTORS */
881 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
882 base = 16;
883 xdigs = xdigs_lower;
884 flags = flags | INTMAXT;
885 ox[1] = 'x';
886 goto nosign;
887 case 'S':
888 flags |= LONGINT;
889 /*FALLTHROUGH*/
890 case 's':
891 if (flags & LONGINT) {
892 wchar_t *wcp;
893
894 if (convbuf != NULL)
895 free(convbuf);
896 if ((wcp = GETARG(wchar_t *)) == NULL)
897 cp = "(null)";
898 else {
899 convbuf = __wcsconv(wcp, prec, loc);
900 if (convbuf == NULL) {
901 fp->_flags |= __SERR;
902 goto error;
903 }
904 cp = convbuf;
905 }
906 } else if ((cp = GETARG(char *)) == NULL)
907 cp = "(null)";
908 size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
909 sign = '\0';
910 break;
911 case 'U':
912 flags |= LONGINT;
913 /*FALLTHROUGH*/
914 case 'u':
915 #ifdef VECTORS
916 if (flags & VECTOR)
917 break;
918 #endif /* VECTORS */
919 if (flags & INTMAX_SIZE)
920 ujval = UJARG();
921 else
922 ulval = UARG();
923 base = 10;
924 goto nosign;
925 case 'X':
926 xdigs = xdigs_upper;
927 goto hex;
928 case 'x':
929 xdigs = xdigs_lower;
930 hex:
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 = 16;
940 /* leading 0x/X only if non-zero */
941 if (flags & ALT &&
942 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
943 ox[1] = ch;
944
945 flags &= ~GROUPING;
946 /* unsigned conversions */
947 nosign: sign = '\0';
948 /*-
949 * ``... diouXx conversions ... if a precision is
950 * specified, the 0 flag will be ignored.''
951 * -- ANSI X3J11
952 * except for %#.0o and zero value
953 */
954 number: if ((dprec = prec) >= 0)
955 flags &= ~ZEROPAD;
956
957 /*-
958 * ``The result of converting a zero value with an
959 * explicit precision of zero is no characters.''
960 * -- ANSI X3J11
961 *
962 * ``The C Standard is clear enough as is. The call
963 * printf("%#.0o", 0) should print 0.''
964 * -- Defect Report #151
965 */
966 cp = buf + BUF;
967 if (flags & INTMAX_SIZE) {
968 if (ujval != 0 || prec != 0 ||
969 (flags & ALT && base == 8))
970 cp = __ujtoa(ujval, cp, base,
971 flags & ALT, xdigs);
972 } else {
973 if (ulval != 0 || prec != 0 ||
974 (flags & ALT && base == 8))
975 cp = __ultoa(ulval, cp, base,
976 flags & ALT, xdigs);
977 }
978 size = buf + BUF - cp;
979 if (size > BUF) /* should never happen */
980 LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
981 if ((flags & GROUPING) && size != 0)
982 size += grouping_init(&gs, size, loc);
983 break;
984 #ifdef VECTORS
985 case 'v':
986 flags |= VECTOR;
987 goto rflag;
988 #endif /* VECTORS */
989 default: /* "%?" prints ?, unless ? is NUL */
990 if (ch == '\0')
991 goto done;
992 /* pretend it was %c with argument ch */
993 cp = buf;
994 *cp = ch;
995 size = 1;
996 sign = '\0';
997 break;
998 }
999
1000 #ifdef VECTORS
1001 if (flags & VECTOR) {
1002 /*
1003 * Do the minimum amount of work necessary to construct
1004 * a format specifier that can be used to recursively
1005 * call vfprintf() for each element in the vector.
1006 */
1007 int i, j; /* Counter. */
1008 int vcnt; /* Number of elements in vector. */
1009 char *vfmt; /* Pointer to format specifier. */
1010 #define EXTRAHH 2
1011 char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
1012 int vwidth = 0; /* Width specified via '*'. */
1013 int vprec = 0; /* Precision specified via '*'. */
1014 char *vstr; /* Used for asprintf(). */
1015 int vlen; /* Length returned by asprintf(). */
1016 enum {
1017 V_CHAR, V_SHORT, V_INT,
1018 V_PCHAR, V_PSHORT, V_PINT,
1019 V_FLOAT,
1020 #ifdef V64TYPE
1021 V_LONGLONG, V_PLONGLONG,
1022 V_DOUBLE,
1023 #endif /* V64TYPE */
1024 } vtype;
1025
1026 vval.vectorarg = GETARG(VECTORTYPE);
1027 /*
1028 * Set vfmt. If vfmt_buf may not be big enough,
1029 * malloc() space, taking care to free it later.
1030 * (EXTRAHH is for possible extra "hh")
1031 */
1032 if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
1033 vfmt = vfmt_buf;
1034 else
1035 vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
1036
1037 /* Set the separator character, if not specified. */
1038 if (vsep == 'X') {
1039 if (ch == 'c')
1040 vsep = '\0';
1041 else
1042 vsep = ' ';
1043 }
1044
1045 /* Create the format specifier. */
1046 for (i = j = 0; i < &fmt[-1] - pct; i++) {
1047 switch (pct[i]) {
1048 case ',': case ';': case ':': case '_':
1049 case 'v': case 'h': case 'l':
1050 /* Ignore. */
1051 break;
1052 case '*':
1053 if (pct[i - 1] != '.')
1054 vwidth = 1;
1055 else
1056 vprec = 1;
1057 /* FALLTHROUGH */
1058 default:
1059 vfmt[j++] = pct[i];
1060 }
1061 }
1062
1063 /*
1064 * Determine the number of elements in the vector and
1065 * finish up the format specifier.
1066 */
1067 if (flags & SHORTINT) {
1068 switch (ch) {
1069 case 'c':
1070 vtype = V_SHORT;
1071 break;
1072 case 'p':
1073 vtype = V_PSHORT;
1074 break;
1075 default:
1076 vfmt[j++] = 'h';
1077 vtype = V_SHORT;
1078 break;
1079 }
1080 vcnt = 8;
1081 } else if (flags & LONGINT) {
1082 vcnt = 4;
1083 vtype = (ch == 'p') ? V_PINT : V_INT;
1084 #ifdef V64TYPE
1085 } else if (flags & LLONGINT) {
1086 switch (ch) {
1087 case 'a':
1088 case 'A':
1089 case 'e':
1090 case 'E':
1091 case 'f':
1092 case 'g':
1093 case 'G':
1094 vcnt = 2;
1095 vtype = V_DOUBLE;
1096 break;
1097 case 'd':
1098 case 'i':
1099 case 'u':
1100 case 'o':
1101 case 'p':
1102 case 'x':
1103 case 'X':
1104 vfmt[j++] = 'l';
1105 vfmt[j++] = 'l';
1106 vcnt = 2;
1107 vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
1108 break;
1109 default:
1110 /*
1111 * The default case should never
1112 * happen.
1113 */
1114 case 'c':
1115 vcnt = 16;
1116 vtype = V_CHAR;
1117 }
1118 #endif /* V64TYPE */
1119 } else {
1120 switch (ch) {
1121 case 'a':
1122 case 'A':
1123 case 'e':
1124 case 'E':
1125 case 'f':
1126 case 'g':
1127 case 'G':
1128 vcnt = 4;
1129 vtype = V_FLOAT;
1130 break;
1131 default:
1132 /*
1133 * The default case should never
1134 * happen.
1135 */
1136 case 'd':
1137 case 'i':
1138 case 'u':
1139 case 'o':
1140 case 'x':
1141 case 'X':
1142 vfmt[j++] = 'h';
1143 vfmt[j++] = 'h';
1144 /* drop through */
1145 case 'p':
1146 case 'c':
1147 vcnt = 16;
1148 vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
1149 }
1150 }
1151 vfmt[j++] = ch;
1152 vfmt[j++] = '\0';
1153
1154 /* Get a vector element. */
1155 #ifdef V64TYPE
1156 #define VPRINT(type, ind, args...) do { \
1157 switch (type) { \
1158 case V_CHAR: \
1159 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
1160 break; \
1161 case V_PCHAR: \
1162 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
1163 break; \
1164 case V_SHORT: \
1165 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
1166 break; \
1167 case V_PSHORT: \
1168 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
1169 break; \
1170 case V_INT: \
1171 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
1172 break; \
1173 case V_PINT: \
1174 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
1175 break; \
1176 case V_LONGLONG: \
1177 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
1178 break; \
1179 case V_PLONGLONG: \
1180 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \
1181 break; \
1182 case V_FLOAT: \
1183 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
1184 break; \
1185 case V_DOUBLE: \
1186 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
1187 break; \
1188 } \
1189 ret += vlen; \
1190 PRINT(vstr, vlen); \
1191 FLUSH(); \
1192 free(vstr); \
1193 } while (0)
1194 #else /* !V64TYPE */
1195 #define VPRINT(type, ind, args...) do { \
1196 switch (type) { \
1197 case V_CHAR: \
1198 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
1199 break; \
1200 case V_PCHAR: \
1201 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
1202 break; \
1203 case V_SHORT: \
1204 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
1205 break; \
1206 case V_PSHORT: \
1207 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
1208 break; \
1209 case V_INT: \
1210 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
1211 break; \
1212 case V_PINT: \
1213 vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
1214 break; \
1215 case V_FLOAT: \
1216 vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
1217 break; \
1218 } \
1219 ret += vlen; \
1220 PRINT(vstr, vlen); \
1221 FLUSH(); \
1222 free(vstr); \
1223 } while (0)
1224 #endif /* V64TYPE */
1225
1226 /* Actually print. */
1227 if (vwidth == 0) {
1228 if (vprec == 0) {
1229 /* First element. */
1230 VPRINT(vtype, 0);
1231 for (i = 1; i < vcnt; i++) {
1232 /* Separator. */
1233 if(vsep)
1234 PRINT(&vsep, 1);
1235
1236 /* Element. */
1237 VPRINT(vtype, i);
1238 }
1239 } else {
1240 /* First element. */
1241 VPRINT(vtype, 0, prec);
1242 for (i = 1; i < vcnt; i++) {
1243 /* Separator. */
1244 if(vsep)
1245 PRINT(&vsep, 1);
1246
1247 /* Element. */
1248 VPRINT(vtype, i, prec);
1249 }
1250 }
1251 } else {
1252 if (vprec == 0) {
1253 /* First element. */
1254 VPRINT(vtype, 0, width);
1255 for (i = 1; i < vcnt; i++) {
1256 /* Separator. */
1257 if(vsep)
1258 PRINT(&vsep, 1);
1259
1260 /* Element. */
1261 VPRINT(vtype, i, width);
1262 }
1263 } else {
1264 /* First element. */
1265 VPRINT(vtype, 0, width, prec);
1266 for (i = 1; i < vcnt; i++) {
1267 /* Separator. */
1268 if(vsep)
1269 PRINT(&vsep, 1);
1270
1271 /* Element. */
1272 VPRINT(vtype, i, width, prec);
1273 }
1274 }
1275 }
1276 #undef VPRINT
1277
1278 if (vfmt != vfmt_buf)
1279 free(vfmt);
1280
1281 continue;
1282 }
1283 #endif /* VECTORS */
1284 /*
1285 * All reasonable formats wind up here. At this point, `cp'
1286 * points to a string which (if not flags&LADJUST) should be
1287 * padded out to `width' places. If flags&ZEROPAD, it should
1288 * first be prefixed by any sign or other prefix; otherwise,
1289 * it should be blank padded before the prefix is emitted.
1290 * After any left-hand padding and prefixing, emit zeroes
1291 * required by a decimal [diouxX] precision, then print the
1292 * string proper, then emit zeroes required by any leftover
1293 * floating precision; finally, if LADJUST, pad with blanks.
1294 *
1295 * Compute actual size, so we know how much to pad.
1296 * size excludes decimal prec; realsz includes it.
1297 */
1298 realsz = dprec > size ? dprec : size;
1299 if (sign)
1300 realsz++;
1301 if (ox[1])
1302 realsz += 2;
1303
1304 prsize = width > realsz ? width : realsz;
1305 if ((unsigned)ret + prsize > INT_MAX) {
1306 ret = EOF;
1307 goto error;
1308 }
1309
1310 /* right-adjusting blank padding */
1311 if ((flags & (LADJUST|ZEROPAD)) == 0)
1312 PAD(width - realsz, blanks);
1313
1314 /* prefix */
1315 if (sign)
1316 PRINT(&sign, 1);
1317
1318 if (ox[1]) { /* ox[1] is either x, X, or \0 */
1319 ox[0] = '0';
1320 PRINT(ox, 2);
1321 }
1322
1323 /* right-adjusting zero padding */
1324 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1325 PAD(width - realsz, zeroes);
1326
1327 /* the string or number proper */
1328 #ifndef NO_FLOATING_POINT
1329 if ((flags & FPT) == 0) {
1330 #endif
1331 /* leading zeroes from decimal precision */
1332 PAD(dprec - size, zeroes);
1333 if (gs.grouping) {
1334 if (grouping_print(&gs, &io, cp, buf+BUF, loc) < 0)
1335 goto error;
1336 } else {
1337 PRINT(cp, size);
1338 }
1339 #ifndef NO_FLOATING_POINT
1340 } else { /* glue together f_p fragments */
1341 if (!expchar) { /* %[fF] or sufficiently short %[gG] */
1342 if (expt <= 0) {
1343 PRINT(zeroes, 1);
1344 if (prec || flags & ALT)
1345 PRINT(decimal_point,decpt_len);
1346 PAD(-expt, zeroes);
1347 /* already handled initial 0's */
1348 prec += expt;
1349 } else {
1350 if (gs.grouping) {
1351 n = grouping_print(&gs, &io,
1352 cp, dtoaend, loc);
1353 if (n < 0)
1354 goto error;
1355 cp += n;
1356 } else {
1357 PRINTANDPAD(cp, dtoaend,
1358 expt, zeroes);
1359 cp += expt;
1360 }
1361 if (prec || flags & ALT)
1362 PRINT(decimal_point,decpt_len);
1363 }
1364 PRINTANDPAD(cp, dtoaend, prec, zeroes);
1365 } else { /* %[eE] or sufficiently long %[gG] */
1366 if (prec > 1 || flags & ALT) {
1367 PRINT(cp++, 1);
1368 PRINT(decimal_point, decpt_len);
1369 PRINT(cp, ndig-1);
1370 PAD(prec - ndig, zeroes);
1371 } else /* XeYYY */
1372 PRINT(cp, 1);
1373 PRINT(expstr, expsize);
1374 }
1375 }
1376 #endif
1377 /* left-adjusting padding (always blank) */
1378 if (flags & LADJUST)
1379 PAD(width - realsz, blanks);
1380
1381 /* finally, adjust ret */
1382 ret += prsize;
1383
1384 FLUSH(); /* copy out the I/O vectors */
1385 }
1386 done:
1387 FLUSH();
1388 error:
1389 va_end(orgap);
1390 #ifndef NO_FLOATING_POINT
1391 if (dtoaresult != NULL)
1392 freedtoa(dtoaresult);
1393 #endif
1394 if (convbuf != NULL)
1395 free(convbuf);
1396 if (__sferror(fp))
1397 ret = EOF;
1398 if ((argtable != NULL) && (argtable != statargtable))
1399 free (argtable);
1400 return (ret);
1401 /* NOTREACHED */
1402 }
1403