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