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