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