]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - lib/libc/stdio/vfprintf.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / lib / libc / stdio / 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$");
38
39 /*
40  * Actual printf innards.
41  *
42  * This code is large and complicated...
43  */
44
45 #include "namespace.h"
46 #include <sys/types.h>
47
48 #include <ctype.h>
49 #include <limits.h>
50 #include <locale.h>
51 #include <stddef.h>
52 #include <stdint.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <wchar.h>
57 #include <printf.h>
58
59 #include <stdarg.h>
60 #include "un-namespace.h"
61
62 #include "libc_private.h"
63 #include "local.h"
64 #include "fvwrite.h"
65 #include "printflocal.h"
66
67 static int      __sprint(FILE *, struct __suio *);
68 static int      __sbprintf(FILE *, const char *, va_list) __printflike(2, 0)
69         __noinline;
70 static char     *__wcsconv(wchar_t *, int);
71
72 #define CHAR    char
73 #include "printfcommon.h"
74
75 struct grouping_state {
76         char *thousands_sep;    /* locale-specific thousands separator */
77         int thousep_len;        /* length of thousands_sep */
78         const char *grouping;   /* locale-specific numeric grouping rules */
79         int lead;               /* sig figs before decimal or group sep */
80         int nseps;              /* number of group separators with ' */
81         int nrepeats;           /* number of repeats of the last group */
82 };
83
84 /*
85  * Initialize the thousands' grouping state in preparation to print a
86  * number with ndigits digits. This routine returns the total number
87  * of bytes that will be needed.
88  */
89 static int
90 grouping_init(struct grouping_state *gs, int ndigits)
91 {
92         struct lconv *locale;
93
94         locale = localeconv();
95         gs->grouping = locale->grouping;
96         gs->thousands_sep = locale->thousands_sep;
97         gs->thousep_len = strlen(gs->thousands_sep);
98
99         gs->nseps = gs->nrepeats = 0;
100         gs->lead = ndigits;
101         while (*gs->grouping != CHAR_MAX) {
102                 if (gs->lead <= *gs->grouping)
103                         break;
104                 gs->lead -= *gs->grouping;
105                 if (*(gs->grouping+1)) {
106                         gs->nseps++;
107                         gs->grouping++;
108                 } else
109                         gs->nrepeats++;
110         }
111         return ((gs->nseps + gs->nrepeats) * gs->thousep_len);
112 }
113
114 /*
115  * Print a number with thousands' separators.
116  */
117 static int
118 grouping_print(struct grouping_state *gs, struct io_state *iop,
119                const CHAR *cp, const CHAR *ep)
120 {
121         const CHAR *cp0 = cp;
122
123         if (io_printandpad(iop, cp, ep, gs->lead, zeroes))
124                 return (-1);
125         cp += gs->lead;
126         while (gs->nseps > 0 || gs->nrepeats > 0) {
127                 if (gs->nrepeats > 0)
128                         gs->nrepeats--;
129                 else {
130                         gs->grouping--;
131                         gs->nseps--;
132                 }
133                 if (io_print(iop, gs->thousands_sep, gs->thousep_len))
134                         return (-1);
135                 if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes))
136                         return (-1);
137                 cp += *gs->grouping;
138         }
139         if (cp > ep)
140                 cp = ep;
141         return (cp - cp0);
142 }
143
144 /*
145  * Flush out all the vectors defined by the given uio,
146  * then reset it so that it can be reused.
147  */
148 static int
149 __sprint(FILE *fp, struct __suio *uio)
150 {
151         int err;
152
153         if (uio->uio_resid == 0) {
154                 uio->uio_iovcnt = 0;
155                 return (0);
156         }
157         err = __sfvwrite(fp, uio);
158         uio->uio_resid = 0;
159         uio->uio_iovcnt = 0;
160         return (err);
161 }
162
163 /*
164  * Helper function for `fprintf to unbuffered unix file': creates a
165  * temporary buffer.  We only work on write-only files; this avoids
166  * worries about ungetc buffers and so forth.
167  */
168 static int
169 __sbprintf(FILE *fp, const char *fmt, va_list ap)
170 {
171         int ret;
172         FILE fake;
173         unsigned char buf[BUFSIZ];
174
175         /* XXX This is probably not needed. */
176         if (prepwrite(fp) != 0)
177                 return (EOF);
178
179         /* copy the important variables */
180         fake._flags = fp->_flags & ~__SNBF;
181         fake._file = fp->_file;
182         fake._cookie = fp->_cookie;
183         fake._write = fp->_write;
184         fake._orientation = fp->_orientation;
185         fake._mbstate = fp->_mbstate;
186
187         /* set up the buffer */
188         fake._bf._base = fake._p = buf;
189         fake._bf._size = fake._w = sizeof(buf);
190         fake._lbfsize = 0;      /* not actually used, but Just In Case */
191
192         /* do the work, then copy any error status */
193         ret = __vfprintf(&fake, fmt, ap);
194         if (ret >= 0 && __fflush(&fake))
195                 ret = EOF;
196         if (fake._flags & __SERR)
197                 fp->_flags |= __SERR;
198         return (ret);
199 }
200
201 /*
202  * Convert a wide character string argument for the %ls format to a multibyte
203  * string representation. If not -1, prec specifies the maximum number of
204  * bytes to output, and also means that we can't assume that the wide char.
205  * string ends is null-terminated.
206  */
207 static char *
208 __wcsconv(wchar_t *wcsarg, int prec)
209 {
210         static const mbstate_t initial;
211         mbstate_t mbs;
212         char buf[MB_LEN_MAX];
213         wchar_t *p;
214         char *convbuf;
215         size_t clen, nbytes;
216
217         /* Allocate space for the maximum number of bytes we could output. */
218         if (prec < 0) {
219                 p = wcsarg;
220                 mbs = initial;
221                 nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
222                 if (nbytes == (size_t)-1)
223                         return (NULL);
224         } else {
225                 /*
226                  * Optimisation: if the output precision is small enough,
227                  * just allocate enough memory for the maximum instead of
228                  * scanning the string.
229                  */
230                 if (prec < 128)
231                         nbytes = prec;
232                 else {
233                         nbytes = 0;
234                         p = wcsarg;
235                         mbs = initial;
236                         for (;;) {
237                                 clen = wcrtomb(buf, *p++, &mbs);
238                                 if (clen == 0 || clen == (size_t)-1 ||
239                                     nbytes + clen > prec)
240                                         break;
241                                 nbytes += clen;
242                         }
243                 }
244         }
245         if ((convbuf = malloc(nbytes + 1)) == NULL)
246                 return (NULL);
247
248         /* Fill the output buffer. */
249         p = wcsarg;
250         mbs = initial;
251         if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
252             nbytes, &mbs)) == (size_t)-1) {
253                 free(convbuf);
254                 return (NULL);
255         }
256         convbuf[nbytes] = '\0';
257         return (convbuf);
258 }
259
260 /*
261  * MT-safe version
262  */
263 int
264 vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
265
266 {
267         int ret;
268
269         FLOCKFILE(fp);
270         /* optimise fprintf(stderr) (and other unbuffered Unix files) */
271         if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
272             fp->_file >= 0)
273                 ret = __sbprintf(fp, fmt0, ap);
274         else
275                 ret = __vfprintf(fp, fmt0, ap);
276         FUNLOCKFILE(fp);
277         return (ret);
278 }
279
280 /*
281  * The size of the buffer we use as scratch space for integer
282  * conversions, among other things.  We need enough space to
283  * write a uintmax_t in octal (plus one byte).
284  */
285 #if UINTMAX_MAX <= UINT64_MAX
286 #define BUF     32
287 #else
288 #error "BUF must be large enough to format a uintmax_t"
289 #endif
290
291 /*
292  * Non-MT-safe version
293  */
294 int
295 __vfprintf(FILE *fp, const char *fmt0, va_list ap)
296 {
297         char *fmt;              /* format string */
298         int ch;                 /* character from fmt */
299         int n, n2;              /* handy integer (short term usage) */
300         char *cp;               /* handy char pointer (short term usage) */
301         int flags;              /* flags as above */
302         int ret;                /* return value accumulator */
303         int width;              /* width from format (%8d), or 0 */
304         int prec;               /* precision from format; <0 for N/A */
305         char sign;              /* sign prefix (' ', '+', '-', or \0) */
306         struct grouping_state gs; /* thousands' grouping info */
307
308 #ifndef NO_FLOATING_POINT
309         /*
310          * We can decompose the printed representation of floating
311          * point numbers into several parts, some of which may be empty:
312          *
313          * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
314          *    A       B     ---C---      D       E   F
315          *
316          * A:   'sign' holds this value if present; '\0' otherwise
317          * B:   ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
318          * C:   cp points to the string MMMNNN.  Leading and trailing
319          *      zeros are not in the string and must be added.
320          * D:   expchar holds this character; '\0' if no exponent, e.g. %f
321          * F:   at least two digits for decimal, at least one digit for hex
322          */
323         char *decimal_point;    /* locale specific decimal point */
324         int decpt_len;          /* length of decimal_point */
325         int signflag;           /* true if float is negative */
326         union {                 /* floating point arguments %[aAeEfFgG] */
327                 double dbl;
328                 long double ldbl;
329         } fparg;
330         int expt;               /* integer value of exponent */
331         char expchar;           /* exponent character: [eEpP\0] */
332         char *dtoaend;          /* pointer to end of converted digits */
333         int expsize;            /* character count for expstr */
334         int ndig;               /* actual number of digits returned by dtoa */
335         char expstr[MAXEXPDIG+2];       /* buffer for exponent string: e+ZZZ */
336         char *dtoaresult;       /* buffer allocated by dtoa */
337 #endif
338         u_long  ulval;          /* integer arguments %[diouxX] */
339         uintmax_t ujval;        /* %j, %ll, %q, %t, %z integers */
340         int base;               /* base for [diouxX] conversion */
341         int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
342         int realsz;             /* field size expanded by dprec, sign, etc */
343         int size;               /* size of converted field or string */
344         int prsize;             /* max size of printed field */
345         const char *xdigs;      /* digits for %[xX] conversion */
346         struct io_state io;     /* I/O buffering state */
347         char buf[BUF];          /* buffer with space for digits of uintmax_t */
348         char ox[2];             /* space for 0x; ox[1] is either x, X, or \0 */
349         union arg *argtable;    /* args, built due to positional arg */
350         union arg statargtable [STATIC_ARG_TBL_SIZE];
351         int nextarg;            /* 1-based argument index */
352         va_list orgap;          /* original argument pointer */
353         char *convbuf;          /* wide to multibyte conversion result */
354
355         static const char xdigs_lower[16] = "0123456789abcdef";
356         static const char xdigs_upper[16] = "0123456789ABCDEF";
357
358         /* BEWARE, these `goto error' on error. */
359 #define PRINT(ptr, len) { \
360         if (io_print(&io, (ptr), (len)))        \
361                 goto error; \
362 }
363 #define PAD(howmany, with) { \
364         if (io_pad(&io, (howmany), (with))) \
365                 goto error; \
366 }
367 #define PRINTANDPAD(p, ep, len, with) { \
368         if (io_printandpad(&io, (p), (ep), (len), (with))) \
369                 goto error; \
370 }
371 #define FLUSH() { \
372         if (io_flush(&io)) \
373                 goto error; \
374 }
375
376         /*
377          * Get the argument indexed by nextarg.   If the argument table is
378          * built, use it to get the argument.  If its not, get the next
379          * argument (and arguments must be gotten sequentially).
380          */
381 #define GETARG(type) \
382         ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
383             (nextarg++, va_arg(ap, type)))
384
385         /*
386          * To extend shorts properly, we need both signed and unsigned
387          * argument extraction methods.
388          */
389 #define SARG() \
390         (flags&LONGINT ? GETARG(long) : \
391             flags&SHORTINT ? (long)(short)GETARG(int) : \
392             flags&CHARINT ? (long)(signed char)GETARG(int) : \
393             (long)GETARG(int))
394 #define UARG() \
395         (flags&LONGINT ? GETARG(u_long) : \
396             flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
397             flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
398             (u_long)GETARG(u_int))
399 #define INTMAX_SIZE     (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
400 #define SJARG() \
401         (flags&INTMAXT ? GETARG(intmax_t) : \
402             flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
403             flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
404             (intmax_t)GETARG(long long))
405 #define UJARG() \
406         (flags&INTMAXT ? GETARG(uintmax_t) : \
407             flags&SIZET ? (uintmax_t)GETARG(size_t) : \
408             flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
409             (uintmax_t)GETARG(unsigned long long))
410
411         /*
412          * Get * arguments, including the form *nn$.  Preserve the nextarg
413          * that the argument can be gotten once the type is determined.
414          */
415 #define GETASTER(val) \
416         n2 = 0; \
417         cp = fmt; \
418         while (is_digit(*cp)) { \
419                 n2 = 10 * n2 + to_digit(*cp); \
420                 cp++; \
421         } \
422         if (*cp == '$') { \
423                 int hold = nextarg; \
424                 if (argtable == NULL) { \
425                         argtable = statargtable; \
426                         if (__find_arguments (fmt0, orgap, &argtable)) { \
427                                 ret = EOF; \
428                                 goto error; \
429                         } \
430                 } \
431                 nextarg = n2; \
432                 val = GETARG (int); \
433                 nextarg = hold; \
434                 fmt = ++cp; \
435         } else { \
436                 val = GETARG (int); \
437         }
438
439         if (__use_xprintf == 0 && getenv("USE_XPRINTF"))
440                 __use_xprintf = 1;
441         if (__use_xprintf > 0)
442                 return (__xvprintf(fp, fmt0, ap));
443
444         /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
445         if (prepwrite(fp) != 0)
446                 return (EOF);
447
448         convbuf = NULL;
449         fmt = (char *)fmt0;
450         argtable = NULL;
451         nextarg = 1;
452         va_copy(orgap, ap);
453         io_init(&io, fp);
454         ret = 0;
455 #ifndef NO_FLOATING_POINT
456         dtoaresult = NULL;
457         decimal_point = localeconv()->decimal_point;
458         /* The overwhelmingly common case is decpt_len == 1. */
459         decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
460 #endif
461
462         /*
463          * Scan the format for conversions (`%' character).
464          */
465         for (;;) {
466                 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
467                         /* void */;
468                 if ((n = fmt - cp) != 0) {
469                         if ((unsigned)ret + n > INT_MAX) {
470                                 ret = EOF;
471                                 goto error;
472                         }
473                         PRINT(cp, n);
474                         ret += n;
475                 }
476                 if (ch == '\0')
477                         goto done;
478                 fmt++;          /* skip over '%' */
479
480                 flags = 0;
481                 dprec = 0;
482                 width = 0;
483                 prec = -1;
484                 gs.grouping = NULL;
485                 sign = '\0';
486                 ox[1] = '\0';
487
488 rflag:          ch = *fmt++;
489 reswitch:       switch (ch) {
490                 case ' ':
491                         /*-
492                          * ``If the space and + flags both appear, the space
493                          * flag will be ignored.''
494                          *      -- ANSI X3J11
495                          */
496                         if (!sign)
497                                 sign = ' ';
498                         goto rflag;
499                 case '#':
500                         flags |= ALT;
501                         goto rflag;
502                 case '*':
503                         /*-
504                          * ``A negative field width argument is taken as a
505                          * - flag followed by a positive field width.''
506                          *      -- ANSI X3J11
507                          * They don't exclude field widths read from args.
508                          */
509                         GETASTER (width);
510                         if (width >= 0)
511                                 goto rflag;
512                         width = -width;
513                         /* FALLTHROUGH */
514                 case '-':
515                         flags |= LADJUST;
516                         goto rflag;
517                 case '+':
518                         sign = '+';
519                         goto rflag;
520                 case '\'':
521                         flags |= GROUPING;
522                         goto rflag;
523                 case '.':
524                         if ((ch = *fmt++) == '*') {
525                                 GETASTER (prec);
526                                 goto rflag;
527                         }
528                         prec = 0;
529                         while (is_digit(ch)) {
530                                 prec = 10 * prec + to_digit(ch);
531                                 ch = *fmt++;
532                         }
533                         goto reswitch;
534                 case '0':
535                         /*-
536                          * ``Note that 0 is taken as a flag, not as the
537                          * beginning of a field width.''
538                          *      -- ANSI X3J11
539                          */
540                         flags |= ZEROPAD;
541                         goto rflag;
542                 case '1': case '2': case '3': case '4':
543                 case '5': case '6': case '7': case '8': case '9':
544                         n = 0;
545                         do {
546                                 n = 10 * n + to_digit(ch);
547                                 ch = *fmt++;
548                         } while (is_digit(ch));
549                         if (ch == '$') {
550                                 nextarg = n;
551                                 if (argtable == NULL) {
552                                         argtable = statargtable;
553                                         if (__find_arguments (fmt0, orgap,
554                                                               &argtable)) {
555                                                 ret = EOF;
556                                                 goto error;
557                                         }
558                                 }
559                                 goto rflag;
560                         }
561                         width = n;
562                         goto reswitch;
563 #ifndef NO_FLOATING_POINT
564                 case 'L':
565                         flags |= LONGDBL;
566                         goto rflag;
567 #endif
568                 case 'h':
569                         if (flags & SHORTINT) {
570                                 flags &= ~SHORTINT;
571                                 flags |= CHARINT;
572                         } else
573                                 flags |= SHORTINT;
574                         goto rflag;
575                 case 'j':
576                         flags |= INTMAXT;
577                         goto rflag;
578                 case 'l':
579                         if (flags & LONGINT) {
580                                 flags &= ~LONGINT;
581                                 flags |= LLONGINT;
582                         } else
583                                 flags |= LONGINT;
584                         goto rflag;
585                 case 'q':
586                         flags |= LLONGINT;      /* not necessarily */
587                         goto rflag;
588                 case 't':
589                         flags |= PTRDIFFT;
590                         goto rflag;
591                 case 'z':
592                         flags |= SIZET;
593                         goto rflag;
594                 case 'C':
595                         flags |= LONGINT;
596                         /*FALLTHROUGH*/
597                 case 'c':
598                         if (flags & LONGINT) {
599                                 static const mbstate_t initial;
600                                 mbstate_t mbs;
601                                 size_t mbseqlen;
602
603                                 mbs = initial;
604                                 mbseqlen = wcrtomb(cp = buf,
605                                     (wchar_t)GETARG(wint_t), &mbs);
606                                 if (mbseqlen == (size_t)-1) {
607                                         fp->_flags |= __SERR;
608                                         goto error;
609                                 }
610                                 size = (int)mbseqlen;
611                         } else {
612                                 *(cp = buf) = GETARG(int);
613                                 size = 1;
614                         }
615                         sign = '\0';
616                         break;
617                 case 'D':
618                         flags |= LONGINT;
619                         /*FALLTHROUGH*/
620                 case 'd':
621                 case 'i':
622                         if (flags & INTMAX_SIZE) {
623                                 ujval = SJARG();
624                                 if ((intmax_t)ujval < 0) {
625                                         ujval = -ujval;
626                                         sign = '-';
627                                 }
628                         } else {
629                                 ulval = SARG();
630                                 if ((long)ulval < 0) {
631                                         ulval = -ulval;
632                                         sign = '-';
633                                 }
634                         }
635                         base = 10;
636                         goto number;
637 #ifndef NO_FLOATING_POINT
638                 case 'a':
639                 case 'A':
640                         if (ch == 'a') {
641                                 ox[1] = 'x';
642                                 xdigs = xdigs_lower;
643                                 expchar = 'p';
644                         } else {
645                                 ox[1] = 'X';
646                                 xdigs = xdigs_upper;
647                                 expchar = 'P';
648                         }
649                         if (prec >= 0)
650                                 prec++;
651                         if (dtoaresult != NULL)
652                                 freedtoa(dtoaresult);
653                         if (flags & LONGDBL) {
654                                 fparg.ldbl = GETARG(long double);
655                                 dtoaresult = cp =
656                                     __hldtoa(fparg.ldbl, xdigs, prec,
657                                     &expt, &signflag, &dtoaend);
658                         } else {
659                                 fparg.dbl = GETARG(double);
660                                 dtoaresult = cp =
661                                     __hdtoa(fparg.dbl, xdigs, prec,
662                                     &expt, &signflag, &dtoaend);
663                         }
664                         if (prec < 0)
665                                 prec = dtoaend - cp;
666                         if (expt == INT_MAX)
667                                 ox[1] = '\0';
668                         goto fp_common;
669                 case 'e':
670                 case 'E':
671                         expchar = ch;
672                         if (prec < 0)   /* account for digit before decpt */
673                                 prec = DEFPREC + 1;
674                         else
675                                 prec++;
676                         goto fp_begin;
677                 case 'f':
678                 case 'F':
679                         expchar = '\0';
680                         goto fp_begin;
681                 case 'g':
682                 case 'G':
683                         expchar = ch - ('g' - 'e');
684                         if (prec == 0)
685                                 prec = 1;
686 fp_begin:
687                         if (prec < 0)
688                                 prec = DEFPREC;
689                         if (dtoaresult != NULL)
690                                 freedtoa(dtoaresult);
691                         if (flags & LONGDBL) {
692                                 fparg.ldbl = GETARG(long double);
693                                 dtoaresult = cp =
694                                     __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
695                                     &expt, &signflag, &dtoaend);
696                         } else {
697                                 fparg.dbl = GETARG(double);
698                                 dtoaresult = cp =
699                                     dtoa(fparg.dbl, expchar ? 2 : 3, prec,
700                                     &expt, &signflag, &dtoaend);
701                                 if (expt == 9999)
702                                         expt = INT_MAX;
703                         }
704 fp_common:
705                         if (signflag)
706                                 sign = '-';
707                         if (expt == INT_MAX) {  /* inf or nan */
708                                 if (*cp == 'N') {
709                                         cp = (ch >= 'a') ? "nan" : "NAN";
710                                         sign = '\0';
711                                 } else
712                                         cp = (ch >= 'a') ? "inf" : "INF";
713                                 size = 3;
714                                 flags &= ~ZEROPAD;
715                                 break;
716                         }
717                         flags |= FPT;
718                         ndig = dtoaend - cp;
719                         if (ch == 'g' || ch == 'G') {
720                                 if (expt > -4 && expt <= prec) {
721                                         /* Make %[gG] smell like %[fF] */
722                                         expchar = '\0';
723                                         if (flags & ALT)
724                                                 prec -= expt;
725                                         else
726                                                 prec = ndig - expt;
727                                         if (prec < 0)
728                                                 prec = 0;
729                                 } else {
730                                         /*
731                                          * Make %[gG] smell like %[eE], but
732                                          * trim trailing zeroes if no # flag.
733                                          */
734                                         if (!(flags & ALT))
735                                                 prec = ndig;
736                                 }
737                         }
738                         if (expchar) {
739                                 expsize = exponent(expstr, expt - 1, expchar);
740                                 size = expsize + prec;
741                                 if (prec > 1 || flags & ALT)
742                                         size += decpt_len;
743                         } else {
744                                 /* space for digits before decimal point */
745                                 if (expt > 0)
746                                         size = expt;
747                                 else    /* "0" */
748                                         size = 1;
749                                 /* space for decimal pt and following digits */
750                                 if (prec || flags & ALT)
751                                         size += prec + decpt_len;
752                                 if ((flags & GROUPING) && expt > 0)
753                                         size += grouping_init(&gs, expt);
754                         }
755                         break;
756 #endif /* !NO_FLOATING_POINT */
757                 case 'n':
758                         /*
759                          * Assignment-like behavior is specified if the
760                          * value overflows or is otherwise unrepresentable.
761                          * C99 says to use `signed char' for %hhn conversions.
762                          */
763                         if (flags & LLONGINT)
764                                 *GETARG(long long *) = ret;
765                         else if (flags & SIZET)
766                                 *GETARG(ssize_t *) = (ssize_t)ret;
767                         else if (flags & PTRDIFFT)
768                                 *GETARG(ptrdiff_t *) = ret;
769                         else if (flags & INTMAXT)
770                                 *GETARG(intmax_t *) = ret;
771                         else if (flags & LONGINT)
772                                 *GETARG(long *) = ret;
773                         else if (flags & SHORTINT)
774                                 *GETARG(short *) = ret;
775                         else if (flags & CHARINT)
776                                 *GETARG(signed char *) = ret;
777                         else
778                                 *GETARG(int *) = ret;
779                         continue;       /* no output */
780                 case 'O':
781                         flags |= LONGINT;
782                         /*FALLTHROUGH*/
783                 case 'o':
784                         if (flags & INTMAX_SIZE)
785                                 ujval = UJARG();
786                         else
787                                 ulval = UARG();
788                         base = 8;
789                         goto nosign;
790                 case 'p':
791                         /*-
792                          * ``The argument shall be a pointer to void.  The
793                          * value of the pointer is converted to a sequence
794                          * of printable characters, in an implementation-
795                          * defined manner.''
796                          *      -- ANSI X3J11
797                          */
798                         ujval = (uintmax_t)(uintptr_t)GETARG(void *);
799                         base = 16;
800                         xdigs = xdigs_lower;
801                         flags = flags | INTMAXT;
802                         ox[1] = 'x';
803                         goto nosign;
804                 case 'S':
805                         flags |= LONGINT;
806                         /*FALLTHROUGH*/
807                 case 's':
808                         if (flags & LONGINT) {
809                                 wchar_t *wcp;
810
811                                 if (convbuf != NULL)
812                                         free(convbuf);
813                                 if ((wcp = GETARG(wchar_t *)) == NULL)
814                                         cp = "(null)";
815                                 else {
816                                         convbuf = __wcsconv(wcp, prec);
817                                         if (convbuf == NULL) {
818                                                 fp->_flags |= __SERR;
819                                                 goto error;
820                                         }
821                                         cp = convbuf;
822                                 }
823                         } else if ((cp = GETARG(char *)) == NULL)
824                                 cp = "(null)";
825                         size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
826                         sign = '\0';
827                         break;
828                 case 'U':
829                         flags |= LONGINT;
830                         /*FALLTHROUGH*/
831                 case 'u':
832                         if (flags & INTMAX_SIZE)
833                                 ujval = UJARG();
834                         else
835                                 ulval = UARG();
836                         base = 10;
837                         goto nosign;
838                 case 'X':
839                         xdigs = xdigs_upper;
840                         goto hex;
841                 case 'x':
842                         xdigs = xdigs_lower;
843 hex:
844                         if (flags & INTMAX_SIZE)
845                                 ujval = UJARG();
846                         else
847                                 ulval = UARG();
848                         base = 16;
849                         /* leading 0x/X only if non-zero */
850                         if (flags & ALT &&
851                             (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
852                                 ox[1] = ch;
853
854                         flags &= ~GROUPING;
855                         /* unsigned conversions */
856 nosign:                 sign = '\0';
857                         /*-
858                          * ``... diouXx conversions ... if a precision is
859                          * specified, the 0 flag will be ignored.''
860                          *      -- ANSI X3J11
861                          */
862 number:                 if ((dprec = prec) >= 0)
863                                 flags &= ~ZEROPAD;
864
865                         /*-
866                          * ``The result of converting a zero value with an
867                          * explicit precision of zero is no characters.''
868                          *      -- ANSI X3J11
869                          *
870                          * ``The C Standard is clear enough as is.  The call
871                          * printf("%#.0o", 0) should print 0.''
872                          *      -- Defect Report #151
873                          */
874                         cp = buf + BUF;
875                         if (flags & INTMAX_SIZE) {
876                                 if (ujval != 0 || prec != 0 ||
877                                     (flags & ALT && base == 8))
878                                         cp = __ujtoa(ujval, cp, base,
879                                             flags & ALT, xdigs);
880                         } else {
881                                 if (ulval != 0 || prec != 0 ||
882                                     (flags & ALT && base == 8))
883                                         cp = __ultoa(ulval, cp, base,
884                                             flags & ALT, xdigs);
885                         }
886                         size = buf + BUF - cp;
887                         if (size > BUF) /* should never happen */
888                                 abort();
889                         if ((flags & GROUPING) && size != 0)
890                                 size += grouping_init(&gs, size);
891                         break;
892                 default:        /* "%?" prints ?, unless ? is NUL */
893                         if (ch == '\0')
894                                 goto done;
895                         /* pretend it was %c with argument ch */
896                         cp = buf;
897                         *cp = ch;
898                         size = 1;
899                         sign = '\0';
900                         break;
901                 }
902
903                 /*
904                  * All reasonable formats wind up here.  At this point, `cp'
905                  * points to a string which (if not flags&LADJUST) should be
906                  * padded out to `width' places.  If flags&ZEROPAD, it should
907                  * first be prefixed by any sign or other prefix; otherwise,
908                  * it should be blank padded before the prefix is emitted.
909                  * After any left-hand padding and prefixing, emit zeroes
910                  * required by a decimal [diouxX] precision, then print the
911                  * string proper, then emit zeroes required by any leftover
912                  * floating precision; finally, if LADJUST, pad with blanks.
913                  *
914                  * Compute actual size, so we know how much to pad.
915                  * size excludes decimal prec; realsz includes it.
916                  */
917                 realsz = dprec > size ? dprec : size;
918                 if (sign)
919                         realsz++;
920                 if (ox[1])
921                         realsz += 2;
922
923                 prsize = width > realsz ? width : realsz;
924                 if ((unsigned)ret + prsize > INT_MAX) {
925                         ret = EOF;
926                         goto error;
927                 }
928
929                 /* right-adjusting blank padding */
930                 if ((flags & (LADJUST|ZEROPAD)) == 0)
931                         PAD(width - realsz, blanks);
932
933                 /* prefix */
934                 if (sign)
935                         PRINT(&sign, 1);
936
937                 if (ox[1]) {    /* ox[1] is either x, X, or \0 */
938                         ox[0] = '0';
939                         PRINT(ox, 2);
940                 }
941
942                 /* right-adjusting zero padding */
943                 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
944                         PAD(width - realsz, zeroes);
945
946                 /* the string or number proper */
947 #ifndef NO_FLOATING_POINT
948                 if ((flags & FPT) == 0) {
949 #endif
950                         /* leading zeroes from decimal precision */
951                         PAD(dprec - size, zeroes);
952                         if (gs.grouping) {
953                                 if (grouping_print(&gs, &io, cp, buf+BUF) < 0)
954                                         goto error;
955                         } else {
956                                 PRINT(cp, size);
957                         }
958 #ifndef NO_FLOATING_POINT
959                 } else {        /* glue together f_p fragments */
960                         if (!expchar) { /* %[fF] or sufficiently short %[gG] */
961                                 if (expt <= 0) {
962                                         PRINT(zeroes, 1);
963                                         if (prec || flags & ALT)
964                                                 PRINT(decimal_point,decpt_len);
965                                         PAD(-expt, zeroes);
966                                         /* already handled initial 0's */
967                                         prec += expt;
968                                 } else {
969                                         if (gs.grouping) {
970                                                 n = grouping_print(&gs, &io,
971                                                     cp, dtoaend);
972                                                 if (n < 0)
973                                                         goto error;
974                                                 cp += n;
975                                         } else {
976                                                 PRINTANDPAD(cp, dtoaend,
977                                                     expt, zeroes);
978                                                 cp += expt;
979                                         }
980                                         if (prec || flags & ALT)
981                                                 PRINT(decimal_point,decpt_len);
982                                 }
983                                 PRINTANDPAD(cp, dtoaend, prec, zeroes);
984                         } else {        /* %[eE] or sufficiently long %[gG] */
985                                 if (prec > 1 || flags & ALT) {
986                                         PRINT(cp++, 1);
987                                         PRINT(decimal_point, decpt_len);
988                                         PRINT(cp, ndig-1);
989                                         PAD(prec - ndig, zeroes);
990                                 } else  /* XeYYY */
991                                         PRINT(cp, 1);
992                                 PRINT(expstr, expsize);
993                         }
994                 }
995 #endif
996                 /* left-adjusting padding (always blank) */
997                 if (flags & LADJUST)
998                         PAD(width - realsz, blanks);
999
1000                 /* finally, adjust ret */
1001                 ret += prsize;
1002
1003                 FLUSH();        /* copy out the I/O vectors */
1004         }
1005 done:
1006         FLUSH();
1007 error:
1008         va_end(orgap);
1009 #ifndef NO_FLOATING_POINT
1010         if (dtoaresult != NULL)
1011                 freedtoa(dtoaresult);
1012 #endif
1013         if (convbuf != NULL)
1014                 free(convbuf);
1015         if (__sferror(fp))
1016                 ret = EOF;
1017         if ((argtable != NULL) && (argtable != statargtable))
1018                 free (argtable);
1019         return (ret);
1020         /* NOTREACHED */
1021 }
1022