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