Deleted Added
full compact
printf-pos.c (113142) printf-pos.c (113146)
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 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if defined(LIBC_SCCS) && !defined(lint)
38static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
39#endif /* LIBC_SCCS and not lint */
40#include <sys/cdefs.h>
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 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if defined(LIBC_SCCS) && !defined(lint)
38static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
39#endif /* LIBC_SCCS and not lint */
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD: head/lib/libc/stdio/vfprintf.c 113142 2003-04-05 22:03:43Z das $");
41__FBSDID("$FreeBSD: head/lib/libc/stdio/vfprintf.c 113146 2003-04-05 22:11:42Z das $");
42
43/*
44 * Actual printf innards.
45 *
46 * This code is large and complicated...
47 */
48
49#include "namespace.h"
50#include <sys/types.h>
51
52#include <ctype.h>
53#include <limits.h>
54#include <locale.h>
55#include <stddef.h>
56#include <stdint.h>
57#include <stdio.h>
58#include <stdlib.h>
59#include <string.h>
60#include <wchar.h>
61
62#include <stdarg.h>
63#include "un-namespace.h"
64
65#include "libc_private.h"
66#include "local.h"
67#include "fvwrite.h"
68
69/* Define FLOATING_POINT to get floating point. */
70#define FLOATING_POINT
71
72union arg {
73 int intarg;
74 u_int uintarg;
75 long longarg;
76 u_long ulongarg;
77 long long longlongarg;
78 unsigned long long ulonglongarg;
79 ptrdiff_t ptrdiffarg;
80 size_t sizearg;
81 intmax_t intmaxarg;
82 uintmax_t uintmaxarg;
83 void *pvoidarg;
84 char *pchararg;
85 signed char *pschararg;
86 short *pshortarg;
87 int *pintarg;
88 long *plongarg;
89 long long *plonglongarg;
90 ptrdiff_t *pptrdiffarg;
91 size_t *psizearg;
92 intmax_t *pintmaxarg;
93#ifdef FLOATING_POINT
94 double doublearg;
95 long double longdoublearg;
96#endif
97 wint_t wintarg;
98 wchar_t *pwchararg;
99};
100
101/*
102 * Type ids for argument type table.
103 */
104enum typeid {
105 T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
106 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
107 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
108 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
109 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
110};
111
112static int __sprint(FILE *, struct __suio *);
113static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0);
42
43/*
44 * Actual printf innards.
45 *
46 * This code is large and complicated...
47 */
48
49#include "namespace.h"
50#include <sys/types.h>
51
52#include <ctype.h>
53#include <limits.h>
54#include <locale.h>
55#include <stddef.h>
56#include <stdint.h>
57#include <stdio.h>
58#include <stdlib.h>
59#include <string.h>
60#include <wchar.h>
61
62#include <stdarg.h>
63#include "un-namespace.h"
64
65#include "libc_private.h"
66#include "local.h"
67#include "fvwrite.h"
68
69/* Define FLOATING_POINT to get floating point. */
70#define FLOATING_POINT
71
72union arg {
73 int intarg;
74 u_int uintarg;
75 long longarg;
76 u_long ulongarg;
77 long long longlongarg;
78 unsigned long long ulonglongarg;
79 ptrdiff_t ptrdiffarg;
80 size_t sizearg;
81 intmax_t intmaxarg;
82 uintmax_t uintmaxarg;
83 void *pvoidarg;
84 char *pchararg;
85 signed char *pschararg;
86 short *pshortarg;
87 int *pintarg;
88 long *plongarg;
89 long long *plonglongarg;
90 ptrdiff_t *pptrdiffarg;
91 size_t *psizearg;
92 intmax_t *pintmaxarg;
93#ifdef FLOATING_POINT
94 double doublearg;
95 long double longdoublearg;
96#endif
97 wint_t wintarg;
98 wchar_t *pwchararg;
99};
100
101/*
102 * Type ids for argument type table.
103 */
104enum typeid {
105 T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
106 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
107 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
108 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
109 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
110};
111
112static int __sprint(FILE *, struct __suio *);
113static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0);
114static char *__ujtoa(uintmax_t, char *, int, int, char *, int, char,
114static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char,
115 const char *);
115 const char *);
116static char *__ultoa(u_long, char *, int, int, char *, int, char,
116static char *__ultoa(u_long, char *, int, int, const char *, int, char,
117 const char *);
118static char *__wcsconv(wchar_t *, int);
119static void __find_arguments(const char *, va_list, union arg **);
120static void __grow_type_table(int, enum typeid **, int *);
121
122/*
123 * Flush out all the vectors defined by the given uio,
124 * then reset it so that it can be reused.
125 */
126static int
127__sprint(FILE *fp, struct __suio *uio)
128{
129 int err;
130
131 if (uio->uio_resid == 0) {
132 uio->uio_iovcnt = 0;
133 return (0);
134 }
135 err = __sfvwrite(fp, uio);
136 uio->uio_resid = 0;
137 uio->uio_iovcnt = 0;
138 return (err);
139}
140
141/*
142 * Helper function for `fprintf to unbuffered unix file': creates a
143 * temporary buffer. We only work on write-only files; this avoids
144 * worries about ungetc buffers and so forth.
145 */
146static int
147__sbprintf(FILE *fp, const char *fmt, va_list ap)
148{
149 int ret;
150 FILE fake;
151 unsigned char buf[BUFSIZ];
152
153 /* copy the important variables */
154 fake._flags = fp->_flags & ~__SNBF;
155 fake._file = fp->_file;
156 fake._cookie = fp->_cookie;
157 fake._write = fp->_write;
158 fake._extra = fp->_extra;
159
160 /* set up the buffer */
161 fake._bf._base = fake._p = buf;
162 fake._bf._size = fake._w = sizeof(buf);
163 fake._lbfsize = 0; /* not actually used, but Just In Case */
164
165 /* do the work, then copy any error status */
166 ret = __vfprintf(&fake, fmt, ap);
167 if (ret >= 0 && __fflush(&fake))
168 ret = EOF;
169 if (fake._flags & __SERR)
170 fp->_flags |= __SERR;
171 return (ret);
172}
173
174/*
175 * Macros for converting digits to letters and vice versa
176 */
177#define to_digit(c) ((c) - '0')
178#define is_digit(c) ((unsigned)to_digit(c) <= 9)
179#define to_char(n) ((n) + '0')
180
181/*
182 * Convert an unsigned long to ASCII for printf purposes, returning
183 * a pointer to the first character of the string representation.
184 * Octal numbers can be forced to have a leading zero; hex numbers
185 * use the given digits.
186 */
187static char *
117 const char *);
118static char *__wcsconv(wchar_t *, int);
119static void __find_arguments(const char *, va_list, union arg **);
120static void __grow_type_table(int, enum typeid **, int *);
121
122/*
123 * Flush out all the vectors defined by the given uio,
124 * then reset it so that it can be reused.
125 */
126static int
127__sprint(FILE *fp, struct __suio *uio)
128{
129 int err;
130
131 if (uio->uio_resid == 0) {
132 uio->uio_iovcnt = 0;
133 return (0);
134 }
135 err = __sfvwrite(fp, uio);
136 uio->uio_resid = 0;
137 uio->uio_iovcnt = 0;
138 return (err);
139}
140
141/*
142 * Helper function for `fprintf to unbuffered unix file': creates a
143 * temporary buffer. We only work on write-only files; this avoids
144 * worries about ungetc buffers and so forth.
145 */
146static int
147__sbprintf(FILE *fp, const char *fmt, va_list ap)
148{
149 int ret;
150 FILE fake;
151 unsigned char buf[BUFSIZ];
152
153 /* copy the important variables */
154 fake._flags = fp->_flags & ~__SNBF;
155 fake._file = fp->_file;
156 fake._cookie = fp->_cookie;
157 fake._write = fp->_write;
158 fake._extra = fp->_extra;
159
160 /* set up the buffer */
161 fake._bf._base = fake._p = buf;
162 fake._bf._size = fake._w = sizeof(buf);
163 fake._lbfsize = 0; /* not actually used, but Just In Case */
164
165 /* do the work, then copy any error status */
166 ret = __vfprintf(&fake, fmt, ap);
167 if (ret >= 0 && __fflush(&fake))
168 ret = EOF;
169 if (fake._flags & __SERR)
170 fp->_flags |= __SERR;
171 return (ret);
172}
173
174/*
175 * Macros for converting digits to letters and vice versa
176 */
177#define to_digit(c) ((c) - '0')
178#define is_digit(c) ((unsigned)to_digit(c) <= 9)
179#define to_char(n) ((n) + '0')
180
181/*
182 * Convert an unsigned long to ASCII for printf purposes, returning
183 * a pointer to the first character of the string representation.
184 * Octal numbers can be forced to have a leading zero; hex numbers
185 * use the given digits.
186 */
187static char *
188__ultoa(u_long val, char *endp, int base, int octzero, char *xdigs,
188__ultoa(u_long val, char *endp, int base, int octzero, const char *xdigs,
189 int needgrp, char thousep, const char *grp)
190{
191 char *cp = endp;
192 long sval;
193 int ndig;
194
195 /*
196 * Handle the three cases separately, in the hope of getting
197 * better/faster code.
198 */
199 switch (base) {
200 case 10:
201 if (val < 10) { /* many numbers are 1 digit */
202 *--cp = to_char(val);
203 return (cp);
204 }
205 ndig = 0;
206 /*
207 * On many machines, unsigned arithmetic is harder than
208 * signed arithmetic, so we do at most one unsigned mod and
209 * divide; this is sufficient to reduce the range of
210 * the incoming value to where signed arithmetic works.
211 */
212 if (val > LONG_MAX) {
213 *--cp = to_char(val % 10);
214 ndig++;
215 sval = val / 10;
216 } else
217 sval = val;
218 do {
219 *--cp = to_char(sval % 10);
220 ndig++;
221 /*
222 * If (*grp == CHAR_MAX) then no more grouping
223 * should be performed.
224 */
225 if (needgrp && ndig == *grp && *grp != CHAR_MAX
226 && sval > 9) {
227 *--cp = thousep;
228 ndig = 0;
229 /*
230 * If (*(grp+1) == '\0') then we have to
231 * use *grp character (last grouping rule)
232 * for all next cases
233 */
234 if (*(grp+1) != '\0')
235 grp++;
236 }
237 sval /= 10;
238 } while (sval != 0);
239 break;
240
241 case 8:
242 do {
243 *--cp = to_char(val & 7);
244 val >>= 3;
245 } while (val);
246 if (octzero && *cp != '0')
247 *--cp = '0';
248 break;
249
250 case 16:
251 do {
252 *--cp = xdigs[val & 15];
253 val >>= 4;
254 } while (val);
255 break;
256
257 default: /* oops */
258 abort();
259 }
260 return (cp);
261}
262
263/* Identical to __ultoa, but for intmax_t. */
264static char *
189 int needgrp, char thousep, const char *grp)
190{
191 char *cp = endp;
192 long sval;
193 int ndig;
194
195 /*
196 * Handle the three cases separately, in the hope of getting
197 * better/faster code.
198 */
199 switch (base) {
200 case 10:
201 if (val < 10) { /* many numbers are 1 digit */
202 *--cp = to_char(val);
203 return (cp);
204 }
205 ndig = 0;
206 /*
207 * On many machines, unsigned arithmetic is harder than
208 * signed arithmetic, so we do at most one unsigned mod and
209 * divide; this is sufficient to reduce the range of
210 * the incoming value to where signed arithmetic works.
211 */
212 if (val > LONG_MAX) {
213 *--cp = to_char(val % 10);
214 ndig++;
215 sval = val / 10;
216 } else
217 sval = val;
218 do {
219 *--cp = to_char(sval % 10);
220 ndig++;
221 /*
222 * If (*grp == CHAR_MAX) then no more grouping
223 * should be performed.
224 */
225 if (needgrp && ndig == *grp && *grp != CHAR_MAX
226 && sval > 9) {
227 *--cp = thousep;
228 ndig = 0;
229 /*
230 * If (*(grp+1) == '\0') then we have to
231 * use *grp character (last grouping rule)
232 * for all next cases
233 */
234 if (*(grp+1) != '\0')
235 grp++;
236 }
237 sval /= 10;
238 } while (sval != 0);
239 break;
240
241 case 8:
242 do {
243 *--cp = to_char(val & 7);
244 val >>= 3;
245 } while (val);
246 if (octzero && *cp != '0')
247 *--cp = '0';
248 break;
249
250 case 16:
251 do {
252 *--cp = xdigs[val & 15];
253 val >>= 4;
254 } while (val);
255 break;
256
257 default: /* oops */
258 abort();
259 }
260 return (cp);
261}
262
263/* Identical to __ultoa, but for intmax_t. */
264static char *
265__ujtoa(uintmax_t val, char *endp, int base, int octzero, char *xdigs,
265__ujtoa(uintmax_t val, char *endp, int base, int octzero, const char *xdigs,
266 int needgrp, char thousep, const char *grp)
267{
268 char *cp = endp;
269 intmax_t sval;
270 int ndig;
271
272 /* quick test for small values; __ultoa is typically much faster */
273 /* (perhaps instead we should run until small, then call __ultoa?) */
274 if (val <= ULONG_MAX)
275 return (__ultoa((u_long)val, endp, base, octzero, xdigs,
276 needgrp, thousep, grp));
277 switch (base) {
278 case 10:
279 if (val < 10) {
280 *--cp = to_char(val % 10);
281 return (cp);
282 }
283 ndig = 0;
284 if (val > INTMAX_MAX) {
285 *--cp = to_char(val % 10);
286 ndig++;
287 sval = val / 10;
288 } else
289 sval = val;
290 do {
291 *--cp = to_char(sval % 10);
292 ndig++;
293 /*
294 * If (*grp == CHAR_MAX) then no more grouping
295 * should be performed.
296 */
297 if (needgrp && *grp != CHAR_MAX && ndig == *grp
298 && sval > 9) {
299 *--cp = thousep;
300 ndig = 0;
301 /*
302 * If (*(grp+1) == '\0') then we have to
303 * use *grp character (last grouping rule)
304 * for all next cases
305 */
306 if (*(grp+1) != '\0')
307 grp++;
308 }
309 sval /= 10;
310 } while (sval != 0);
311 break;
312
313 case 8:
314 do {
315 *--cp = to_char(val & 7);
316 val >>= 3;
317 } while (val);
318 if (octzero && *cp != '0')
319 *--cp = '0';
320 break;
321
322 case 16:
323 do {
324 *--cp = xdigs[val & 15];
325 val >>= 4;
326 } while (val);
327 break;
328
329 default:
330 abort();
331 }
332 return (cp);
333}
334
335/*
336 * Convert a wide character string argument for the %ls format to a multibyte
337 * string representation. ``prec'' specifies the maximum number of bytes
338 * to output. If ``prec'' is greater than or equal to zero, we can't assume
339 * that the wide char. string ends in a null character.
340 */
341static char *
342__wcsconv(wchar_t *wcsarg, int prec)
343{
344 char buf[MB_LEN_MAX];
345 wchar_t *p;
346 char *convbuf, *mbp;
347 size_t clen, nbytes;
348 mbstate_t mbs;
349
350 /*
351 * Determine the number of bytes to output and allocate space for
352 * the output.
353 */
354 memset(&mbs, 0, sizeof(mbs));
355 if (prec >= 0) {
356 nbytes = 0;
357 p = wcsarg;
358 for (;;) {
359 clen = wcrtomb(buf, *p++, &mbs);
360 if (clen == 0 || clen == (size_t)-1 ||
361 nbytes + clen > prec)
362 break;
363 nbytes += clen;
364 }
365 } else {
366 p = wcsarg;
367 nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
368 if (nbytes == (size_t)-1)
369 return (NULL);
370 }
371 if ((convbuf = malloc(nbytes + 1)) == NULL)
372 return (NULL);
373
374 /*
375 * Fill the output buffer with the multibyte representations of as
376 * many wide characters as will fit.
377 */
378 mbp = convbuf;
379 p = wcsarg;
380 memset(&mbs, 0, sizeof(mbs));
381 while (mbp - convbuf < nbytes) {
382 clen = wcrtomb(mbp, *p++, &mbs);
383 if (clen == 0 || clen == (size_t)-1)
384 break;
385 mbp += clen;
386 }
387 *mbp = '\0';
388 if (clen == (size_t)-1)
389 return (NULL);
390
391 return (convbuf);
392}
393
394/*
395 * MT-safe version
396 */
397int
398vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
399
400{
401 int ret;
402
403 FLOCKFILE(fp);
404 ret = __vfprintf(fp, fmt0, ap);
405 FUNLOCKFILE(fp);
406 return (ret);
407}
408
409#ifdef FLOATING_POINT
266 int needgrp, char thousep, const char *grp)
267{
268 char *cp = endp;
269 intmax_t sval;
270 int ndig;
271
272 /* quick test for small values; __ultoa is typically much faster */
273 /* (perhaps instead we should run until small, then call __ultoa?) */
274 if (val <= ULONG_MAX)
275 return (__ultoa((u_long)val, endp, base, octzero, xdigs,
276 needgrp, thousep, grp));
277 switch (base) {
278 case 10:
279 if (val < 10) {
280 *--cp = to_char(val % 10);
281 return (cp);
282 }
283 ndig = 0;
284 if (val > INTMAX_MAX) {
285 *--cp = to_char(val % 10);
286 ndig++;
287 sval = val / 10;
288 } else
289 sval = val;
290 do {
291 *--cp = to_char(sval % 10);
292 ndig++;
293 /*
294 * If (*grp == CHAR_MAX) then no more grouping
295 * should be performed.
296 */
297 if (needgrp && *grp != CHAR_MAX && ndig == *grp
298 && sval > 9) {
299 *--cp = thousep;
300 ndig = 0;
301 /*
302 * If (*(grp+1) == '\0') then we have to
303 * use *grp character (last grouping rule)
304 * for all next cases
305 */
306 if (*(grp+1) != '\0')
307 grp++;
308 }
309 sval /= 10;
310 } while (sval != 0);
311 break;
312
313 case 8:
314 do {
315 *--cp = to_char(val & 7);
316 val >>= 3;
317 } while (val);
318 if (octzero && *cp != '0')
319 *--cp = '0';
320 break;
321
322 case 16:
323 do {
324 *--cp = xdigs[val & 15];
325 val >>= 4;
326 } while (val);
327 break;
328
329 default:
330 abort();
331 }
332 return (cp);
333}
334
335/*
336 * Convert a wide character string argument for the %ls format to a multibyte
337 * string representation. ``prec'' specifies the maximum number of bytes
338 * to output. If ``prec'' is greater than or equal to zero, we can't assume
339 * that the wide char. string ends in a null character.
340 */
341static char *
342__wcsconv(wchar_t *wcsarg, int prec)
343{
344 char buf[MB_LEN_MAX];
345 wchar_t *p;
346 char *convbuf, *mbp;
347 size_t clen, nbytes;
348 mbstate_t mbs;
349
350 /*
351 * Determine the number of bytes to output and allocate space for
352 * the output.
353 */
354 memset(&mbs, 0, sizeof(mbs));
355 if (prec >= 0) {
356 nbytes = 0;
357 p = wcsarg;
358 for (;;) {
359 clen = wcrtomb(buf, *p++, &mbs);
360 if (clen == 0 || clen == (size_t)-1 ||
361 nbytes + clen > prec)
362 break;
363 nbytes += clen;
364 }
365 } else {
366 p = wcsarg;
367 nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
368 if (nbytes == (size_t)-1)
369 return (NULL);
370 }
371 if ((convbuf = malloc(nbytes + 1)) == NULL)
372 return (NULL);
373
374 /*
375 * Fill the output buffer with the multibyte representations of as
376 * many wide characters as will fit.
377 */
378 mbp = convbuf;
379 p = wcsarg;
380 memset(&mbs, 0, sizeof(mbs));
381 while (mbp - convbuf < nbytes) {
382 clen = wcrtomb(mbp, *p++, &mbs);
383 if (clen == 0 || clen == (size_t)-1)
384 break;
385 mbp += clen;
386 }
387 *mbp = '\0';
388 if (clen == (size_t)-1)
389 return (NULL);
390
391 return (convbuf);
392}
393
394/*
395 * MT-safe version
396 */
397int
398vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
399
400{
401 int ret;
402
403 FLOCKFILE(fp);
404 ret = __vfprintf(fp, fmt0, ap);
405 FUNLOCKFILE(fp);
406 return (ret);
407}
408
409#ifdef FLOATING_POINT
410
411#define dtoa __dtoa
412#define freedtoa __freedtoa
413
414#include <float.h>
410#include <math.h>
411#include "floatio.h"
415#include <math.h>
416#include "floatio.h"
417#include "gdtoa.h"
412
413#define DEFPREC 6
414
418
419#define DEFPREC 6
420
415extern char *__dtoa(double, int, int, int *, int *, char **);
416extern void __freedtoa(char *s);
417
418static char *cvt(double, int, int, char *, int *, int, int *);
419static int exponent(char *, int, int);
420
421#endif /* FLOATING_POINT */
422
423/*
424 * The size of the buffer we use as scratch space for integer
425 * conversions, among other things. Technically, we would need the
426 * most space for base 10 conversions with thousands' grouping
427 * characters between each pair of digits. 100 bytes is a
428 * conservative overestimate even for a 128-bit uintmax_t.
429 */
430#define BUF 100
431
432#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
433
434/*
435 * Flags used during conversion.
436 */
437#define ALT 0x001 /* alternate form */
421static int exponent(char *, int, int);
422
423#endif /* FLOATING_POINT */
424
425/*
426 * The size of the buffer we use as scratch space for integer
427 * conversions, among other things. Technically, we would need the
428 * most space for base 10 conversions with thousands' grouping
429 * characters between each pair of digits. 100 bytes is a
430 * conservative overestimate even for a 128-bit uintmax_t.
431 */
432#define BUF 100
433
434#define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
435
436/*
437 * Flags used during conversion.
438 */
439#define ALT 0x001 /* alternate form */
438#define HEXPREFIX 0x002 /* add 0x or 0X prefix */
439#define LADJUST 0x004 /* left adjustment */
440#define LONGDBL 0x008 /* long double */
441#define LONGINT 0x010 /* long integer */
442#define LLONGINT 0x020 /* long long integer */
443#define SHORTINT 0x040 /* short integer */
444#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
445#define FPT 0x100 /* Floating point number */
446#define GROUPING 0x200 /* use grouping ("'" flag) */
447 /* C99 additional size modifiers: */
448#define SIZET 0x400 /* size_t */
449#define PTRDIFFT 0x800 /* ptrdiff_t */
450#define INTMAXT 0x1000 /* intmax_t */
451#define CHARINT 0x2000 /* print char using int format */
452
453/*
454 * Non-MT-safe version
455 */
456int
457__vfprintf(FILE *fp, const char *fmt0, va_list ap)
458{
459 char *fmt; /* format string */
460 int ch; /* character from fmt */
461 int n, n2; /* handy integer (short term usage) */
462 char *cp; /* handy char pointer (short term usage) */
463 struct __siov *iovp; /* for PRINT macro */
464 int flags; /* flags as above */
465 int ret; /* return value accumulator */
466 int width; /* width from format (%8d), or 0 */
440#define LADJUST 0x004 /* left adjustment */
441#define LONGDBL 0x008 /* long double */
442#define LONGINT 0x010 /* long integer */
443#define LLONGINT 0x020 /* long long integer */
444#define SHORTINT 0x040 /* short integer */
445#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
446#define FPT 0x100 /* Floating point number */
447#define GROUPING 0x200 /* use grouping ("'" flag) */
448 /* C99 additional size modifiers: */
449#define SIZET 0x400 /* size_t */
450#define PTRDIFFT 0x800 /* ptrdiff_t */
451#define INTMAXT 0x1000 /* intmax_t */
452#define CHARINT 0x2000 /* print char using int format */
453
454/*
455 * Non-MT-safe version
456 */
457int
458__vfprintf(FILE *fp, const char *fmt0, va_list ap)
459{
460 char *fmt; /* format string */
461 int ch; /* character from fmt */
462 int n, n2; /* handy integer (short term usage) */
463 char *cp; /* handy char pointer (short term usage) */
464 struct __siov *iovp; /* for PRINT macro */
465 int flags; /* flags as above */
466 int ret; /* return value accumulator */
467 int width; /* width from format (%8d), or 0 */
467 int prec; /* precision from format (%.3d), or -1 */
468 int prec; /* precision from format; <0 for N/A */
468 char sign; /* sign prefix (' ', '+', '-', or \0) */
469 char thousands_sep; /* locale specific thousands separator */
470 const char *grouping; /* locale specific numeric grouping rules */
471#ifdef FLOATING_POINT
469 char sign; /* sign prefix (' ', '+', '-', or \0) */
470 char thousands_sep; /* locale specific thousands separator */
471 const char *grouping; /* locale specific numeric grouping rules */
472#ifdef FLOATING_POINT
473 /*
474 * We can decompose the printed representation of floating
475 * point numbers into several parts, some of which may be empty:
476 *
477 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
478 * A B ---C--- D E F
479 *
480 * A: 'sign' holds this value if present; '\0' otherwise
481 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
482 * C: cp points to the string MMMNNN. Leading and trailing
483 * zeros are not in the string and must be added.
484 * D: expchar holds this character; '\0' if no exponent, e.g. %f
485 * F: at least two digits for decimal, at least one digit for hex
486 */
472 char *decimal_point; /* locale specific decimal point */
487 char *decimal_point; /* locale specific decimal point */
473 char softsign; /* temporary negative sign for floats */
474 double _double; /* double precision arguments %[eEfgG] */
488 int signflag; /* true if float is negative */
489 union { /* floating point arguments %[aAeEfFgG] */
490 double dbl;
491 long double ldbl;
492 } fparg;
475 int expt; /* integer value of exponent */
493 int expt; /* integer value of exponent */
494 char expchar; /* exponent character: [eEpP\0] */
495 char *dtoaend; /* pointer to end of converted digits */
476 int expsize; /* character count for expstr */
496 int expsize; /* character count for expstr */
477 int ndig; /* actual number of digits returned by cvt */
478 char expstr[MAXEXPDIG+2]; /* buffer for exponent string */
497 int lead; /* sig figs before decimal or group sep */
498 int ndig; /* actual number of digits returned by dtoa */
499 char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
479 char *dtoaresult; /* buffer allocated by dtoa */
500 char *dtoaresult; /* buffer allocated by dtoa */
501 int nseps; /* number of group separators with ' */
502 int nrepeats; /* number of repeats of the last group */
480#endif
481 u_long ulval; /* integer arguments %[diouxX] */
482 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
483 int base; /* base for [diouxX] conversion */
484 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
485 int realsz; /* field size expanded by dprec, sign, etc */
486 int size; /* size of converted field or string */
487 int prsize; /* max size of printed field */
503#endif
504 u_long ulval; /* integer arguments %[diouxX] */
505 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
506 int base; /* base for [diouxX] conversion */
507 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
508 int realsz; /* field size expanded by dprec, sign, etc */
509 int size; /* size of converted field or string */
510 int prsize; /* max size of printed field */
488 char *xdigs; /* digits for [xX] conversion */
511 const char *xdigs; /* digits for %[xX] conversion */
489#define NIOV 8
490 struct __suio uio; /* output information: summary */
491 struct __siov iov[NIOV];/* ... and individual io vectors */
492 char buf[BUF]; /* buffer with space for digits of uintmax_t */
512#define NIOV 8
513 struct __suio uio; /* output information: summary */
514 struct __siov iov[NIOV];/* ... and individual io vectors */
515 char buf[BUF]; /* buffer with space for digits of uintmax_t */
493 char ox[2]; /* space for 0x hex-prefix */
516 char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
494 union arg *argtable; /* args, built due to positional arg */
495 union arg statargtable [STATIC_ARG_TBL_SIZE];
496 int nextarg; /* 1-based argument index */
497 va_list orgap; /* original argument pointer */
498 char *convbuf; /* wide to multibyte conversion result */
499
500 /*
501 * Choose PADSIZE to trade efficiency vs. size. If larger printf
502 * fields occur frequently, increase PADSIZE and make the initialisers
503 * below longer.
504 */
505#define PADSIZE 16 /* pad chunk size */
506 static char blanks[PADSIZE] =
507 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
508 static char zeroes[PADSIZE] =
509 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
510
517 union arg *argtable; /* args, built due to positional arg */
518 union arg statargtable [STATIC_ARG_TBL_SIZE];
519 int nextarg; /* 1-based argument index */
520 va_list orgap; /* original argument pointer */
521 char *convbuf; /* wide to multibyte conversion result */
522
523 /*
524 * Choose PADSIZE to trade efficiency vs. size. If larger printf
525 * fields occur frequently, increase PADSIZE and make the initialisers
526 * below longer.
527 */
528#define PADSIZE 16 /* pad chunk size */
529 static char blanks[PADSIZE] =
530 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
531 static char zeroes[PADSIZE] =
532 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
533
534 static const char xdigs_lower[16] = "0123456789abcdef";
535 static const char xdigs_upper[16] = "0123456789ABCDEF";
536
511 /*
512 * BEWARE, these `goto error' on error, and PAD uses `n'.
513 */
514#define PRINT(ptr, len) { \
515 iovp->iov_base = (ptr); \
516 iovp->iov_len = (len); \
517 uio.uio_resid += (len); \
518 iovp++; \
519 if (++uio.uio_iovcnt >= NIOV) { \
520 if (__sprint(fp, &uio)) \
521 goto error; \
522 iovp = iov; \
523 } \
524}
525#define PAD(howmany, with) { \
526 if ((n = (howmany)) > 0) { \
527 while (n > PADSIZE) { \
528 PRINT(with, PADSIZE); \
529 n -= PADSIZE; \
530 } \
531 PRINT(with, n); \
532 } \
533}
534#define FLUSH() { \
535 if (uio.uio_resid && __sprint(fp, &uio)) \
536 goto error; \
537 uio.uio_iovcnt = 0; \
538 iovp = iov; \
539}
540
541 /*
542 * Get the argument indexed by nextarg. If the argument table is
543 * built, use it to get the argument. If its not, get the next
544 * argument (and arguments must be gotten sequentially).
545 */
546#define GETARG(type) \
547 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
548 (nextarg++, va_arg(ap, type)))
549
550 /*
551 * To extend shorts properly, we need both signed and unsigned
552 * argument extraction methods.
553 */
554#define SARG() \
555 (flags&LONGINT ? GETARG(long) : \
556 flags&SHORTINT ? (long)(short)GETARG(int) : \
557 flags&CHARINT ? (long)(signed char)GETARG(int) : \
558 (long)GETARG(int))
559#define UARG() \
560 (flags&LONGINT ? GETARG(u_long) : \
561 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
562 flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
563 (u_long)GETARG(u_int))
564#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
565#define SJARG() \
566 (flags&INTMAXT ? GETARG(intmax_t) : \
567 flags&SIZET ? (intmax_t)GETARG(size_t) : \
568 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
569 (intmax_t)GETARG(long long))
570#define UJARG() \
571 (flags&INTMAXT ? GETARG(uintmax_t) : \
572 flags&SIZET ? (uintmax_t)GETARG(size_t) : \
573 flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
574 (uintmax_t)GETARG(unsigned long long))
575
576 /*
577 * Get * arguments, including the form *nn$. Preserve the nextarg
578 * that the argument can be gotten once the type is determined.
579 */
580#define GETASTER(val) \
581 n2 = 0; \
582 cp = fmt; \
583 while (is_digit(*cp)) { \
584 n2 = 10 * n2 + to_digit(*cp); \
585 cp++; \
586 } \
587 if (*cp == '$') { \
588 int hold = nextarg; \
589 if (argtable == NULL) { \
590 argtable = statargtable; \
591 __find_arguments (fmt0, orgap, &argtable); \
592 } \
593 nextarg = n2; \
594 val = GETARG (int); \
595 nextarg = hold; \
596 fmt = ++cp; \
597 } else { \
598 val = GETARG (int); \
599 }
600
601
602 thousands_sep = '\0';
603 grouping = NULL;
604 convbuf = NULL;
605#ifdef FLOATING_POINT
606 dtoaresult = NULL;
607 decimal_point = localeconv()->decimal_point;
608#endif
609 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
610 if (cantwrite(fp))
611 return (EOF);
612
613 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
614 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
615 fp->_file >= 0)
616 return (__sbprintf(fp, fmt0, ap));
617
618 fmt = (char *)fmt0;
619 argtable = NULL;
620 nextarg = 1;
621 va_copy(orgap, ap);
622 uio.uio_iov = iovp = iov;
623 uio.uio_resid = 0;
624 uio.uio_iovcnt = 0;
625 ret = 0;
626
627 /*
628 * Scan the format for conversions (`%' character).
629 */
630 for (;;) {
631 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
632 /* void */;
633 if ((n = fmt - cp) != 0) {
634 if ((unsigned)ret + n > INT_MAX) {
635 ret = EOF;
636 goto error;
637 }
638 PRINT(cp, n);
639 ret += n;
640 }
641 if (ch == '\0')
642 goto done;
643 fmt++; /* skip over '%' */
644
645 flags = 0;
646 dprec = 0;
647 width = 0;
648 prec = -1;
649 sign = '\0';
537 /*
538 * BEWARE, these `goto error' on error, and PAD uses `n'.
539 */
540#define PRINT(ptr, len) { \
541 iovp->iov_base = (ptr); \
542 iovp->iov_len = (len); \
543 uio.uio_resid += (len); \
544 iovp++; \
545 if (++uio.uio_iovcnt >= NIOV) { \
546 if (__sprint(fp, &uio)) \
547 goto error; \
548 iovp = iov; \
549 } \
550}
551#define PAD(howmany, with) { \
552 if ((n = (howmany)) > 0) { \
553 while (n > PADSIZE) { \
554 PRINT(with, PADSIZE); \
555 n -= PADSIZE; \
556 } \
557 PRINT(with, n); \
558 } \
559}
560#define FLUSH() { \
561 if (uio.uio_resid && __sprint(fp, &uio)) \
562 goto error; \
563 uio.uio_iovcnt = 0; \
564 iovp = iov; \
565}
566
567 /*
568 * Get the argument indexed by nextarg. If the argument table is
569 * built, use it to get the argument. If its not, get the next
570 * argument (and arguments must be gotten sequentially).
571 */
572#define GETARG(type) \
573 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
574 (nextarg++, va_arg(ap, type)))
575
576 /*
577 * To extend shorts properly, we need both signed and unsigned
578 * argument extraction methods.
579 */
580#define SARG() \
581 (flags&LONGINT ? GETARG(long) : \
582 flags&SHORTINT ? (long)(short)GETARG(int) : \
583 flags&CHARINT ? (long)(signed char)GETARG(int) : \
584 (long)GETARG(int))
585#define UARG() \
586 (flags&LONGINT ? GETARG(u_long) : \
587 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
588 flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
589 (u_long)GETARG(u_int))
590#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
591#define SJARG() \
592 (flags&INTMAXT ? GETARG(intmax_t) : \
593 flags&SIZET ? (intmax_t)GETARG(size_t) : \
594 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
595 (intmax_t)GETARG(long long))
596#define UJARG() \
597 (flags&INTMAXT ? GETARG(uintmax_t) : \
598 flags&SIZET ? (uintmax_t)GETARG(size_t) : \
599 flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
600 (uintmax_t)GETARG(unsigned long long))
601
602 /*
603 * Get * arguments, including the form *nn$. Preserve the nextarg
604 * that the argument can be gotten once the type is determined.
605 */
606#define GETASTER(val) \
607 n2 = 0; \
608 cp = fmt; \
609 while (is_digit(*cp)) { \
610 n2 = 10 * n2 + to_digit(*cp); \
611 cp++; \
612 } \
613 if (*cp == '$') { \
614 int hold = nextarg; \
615 if (argtable == NULL) { \
616 argtable = statargtable; \
617 __find_arguments (fmt0, orgap, &argtable); \
618 } \
619 nextarg = n2; \
620 val = GETARG (int); \
621 nextarg = hold; \
622 fmt = ++cp; \
623 } else { \
624 val = GETARG (int); \
625 }
626
627
628 thousands_sep = '\0';
629 grouping = NULL;
630 convbuf = NULL;
631#ifdef FLOATING_POINT
632 dtoaresult = NULL;
633 decimal_point = localeconv()->decimal_point;
634#endif
635 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
636 if (cantwrite(fp))
637 return (EOF);
638
639 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
640 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
641 fp->_file >= 0)
642 return (__sbprintf(fp, fmt0, ap));
643
644 fmt = (char *)fmt0;
645 argtable = NULL;
646 nextarg = 1;
647 va_copy(orgap, ap);
648 uio.uio_iov = iovp = iov;
649 uio.uio_resid = 0;
650 uio.uio_iovcnt = 0;
651 ret = 0;
652
653 /*
654 * Scan the format for conversions (`%' character).
655 */
656 for (;;) {
657 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
658 /* void */;
659 if ((n = fmt - cp) != 0) {
660 if ((unsigned)ret + n > INT_MAX) {
661 ret = EOF;
662 goto error;
663 }
664 PRINT(cp, n);
665 ret += n;
666 }
667 if (ch == '\0')
668 goto done;
669 fmt++; /* skip over '%' */
670
671 flags = 0;
672 dprec = 0;
673 width = 0;
674 prec = -1;
675 sign = '\0';
676 ox[1] = '\0';
650
651rflag: ch = *fmt++;
652reswitch: switch (ch) {
653 case ' ':
654 /*-
655 * ``If the space and + flags both appear, the space
656 * flag will be ignored.''
657 * -- ANSI X3J11
658 */
659 if (!sign)
660 sign = ' ';
661 goto rflag;
662 case '#':
663 flags |= ALT;
664 goto rflag;
665 case '*':
666 /*-
667 * ``A negative field width argument is taken as a
668 * - flag followed by a positive field width.''
669 * -- ANSI X3J11
670 * They don't exclude field widths read from args.
671 */
672 GETASTER (width);
673 if (width >= 0)
674 goto rflag;
675 width = -width;
676 /* FALLTHROUGH */
677 case '-':
678 flags |= LADJUST;
679 goto rflag;
680 case '+':
681 sign = '+';
682 goto rflag;
683 case '\'':
684 flags |= GROUPING;
685 thousands_sep = *(localeconv()->thousands_sep);
686 grouping = localeconv()->grouping;
687 goto rflag;
688 case '.':
689 if ((ch = *fmt++) == '*') {
690 GETASTER (n);
691 prec = n < 0 ? -1 : n;
692 goto rflag;
693 }
694 n = 0;
695 while (is_digit(ch)) {
696 n = 10 * n + to_digit(ch);
697 ch = *fmt++;
698 }
699 prec = n < 0 ? -1 : n;
700 goto reswitch;
701 case '0':
702 /*-
703 * ``Note that 0 is taken as a flag, not as the
704 * beginning of a field width.''
705 * -- ANSI X3J11
706 */
707 flags |= ZEROPAD;
708 goto rflag;
709 case '1': case '2': case '3': case '4':
710 case '5': case '6': case '7': case '8': case '9':
711 n = 0;
712 do {
713 n = 10 * n + to_digit(ch);
714 ch = *fmt++;
715 } while (is_digit(ch));
716 if (ch == '$') {
717 nextarg = n;
718 if (argtable == NULL) {
719 argtable = statargtable;
720 __find_arguments (fmt0, orgap,
721 &argtable);
722 }
723 goto rflag;
724 }
725 width = n;
726 goto reswitch;
727#ifdef FLOATING_POINT
728 case 'L':
729 flags |= LONGDBL;
730 goto rflag;
731#endif
732 case 'h':
733 if (flags & SHORTINT) {
734 flags &= ~SHORTINT;
735 flags |= CHARINT;
736 } else
737 flags |= SHORTINT;
738 goto rflag;
739 case 'j':
740 flags |= INTMAXT;
741 goto rflag;
742 case 'l':
743 if (flags & LONGINT) {
744 flags &= ~LONGINT;
745 flags |= LLONGINT;
746 } else
747 flags |= LONGINT;
748 goto rflag;
749 case 'q':
750 flags |= LLONGINT; /* not necessarily */
751 goto rflag;
752 case 't':
753 flags |= PTRDIFFT;
754 goto rflag;
755 case 'z':
756 flags |= SIZET;
757 goto rflag;
758 case 'C':
759 flags |= LONGINT;
760 /*FALLTHROUGH*/
761 case 'c':
762 if (flags & LONGINT) {
763 mbstate_t mbs;
764 size_t mbseqlen;
765
766 memset(&mbs, 0, sizeof(mbs));
767 mbseqlen = wcrtomb(cp = buf,
768 (wchar_t)GETARG(wint_t), &mbs);
769 if (mbseqlen == (size_t)-1) {
770 fp->_flags |= __SERR;
771 goto error;
772 }
773 size = (int)mbseqlen;
774 } else {
775 *(cp = buf) = GETARG(int);
776 size = 1;
777 }
778 sign = '\0';
779 break;
780 case 'D':
781 flags |= LONGINT;
782 /*FALLTHROUGH*/
783 case 'd':
784 case 'i':
785 if (flags & INTMAX_SIZE) {
786 ujval = SJARG();
787 if ((intmax_t)ujval < 0) {
788 ujval = -ujval;
789 sign = '-';
790 }
791 } else {
792 ulval = SARG();
793 if ((long)ulval < 0) {
794 ulval = -ulval;
795 sign = '-';
796 }
797 }
798 base = 10;
799 goto number;
800#ifdef FLOATING_POINT
801#ifdef HEXFLOAT
802 case 'a':
803 case 'A':
677
678rflag: ch = *fmt++;
679reswitch: switch (ch) {
680 case ' ':
681 /*-
682 * ``If the space and + flags both appear, the space
683 * flag will be ignored.''
684 * -- ANSI X3J11
685 */
686 if (!sign)
687 sign = ' ';
688 goto rflag;
689 case '#':
690 flags |= ALT;
691 goto rflag;
692 case '*':
693 /*-
694 * ``A negative field width argument is taken as a
695 * - flag followed by a positive field width.''
696 * -- ANSI X3J11
697 * They don't exclude field widths read from args.
698 */
699 GETASTER (width);
700 if (width >= 0)
701 goto rflag;
702 width = -width;
703 /* FALLTHROUGH */
704 case '-':
705 flags |= LADJUST;
706 goto rflag;
707 case '+':
708 sign = '+';
709 goto rflag;
710 case '\'':
711 flags |= GROUPING;
712 thousands_sep = *(localeconv()->thousands_sep);
713 grouping = localeconv()->grouping;
714 goto rflag;
715 case '.':
716 if ((ch = *fmt++) == '*') {
717 GETASTER (n);
718 prec = n < 0 ? -1 : n;
719 goto rflag;
720 }
721 n = 0;
722 while (is_digit(ch)) {
723 n = 10 * n + to_digit(ch);
724 ch = *fmt++;
725 }
726 prec = n < 0 ? -1 : n;
727 goto reswitch;
728 case '0':
729 /*-
730 * ``Note that 0 is taken as a flag, not as the
731 * beginning of a field width.''
732 * -- ANSI X3J11
733 */
734 flags |= ZEROPAD;
735 goto rflag;
736 case '1': case '2': case '3': case '4':
737 case '5': case '6': case '7': case '8': case '9':
738 n = 0;
739 do {
740 n = 10 * n + to_digit(ch);
741 ch = *fmt++;
742 } while (is_digit(ch));
743 if (ch == '$') {
744 nextarg = n;
745 if (argtable == NULL) {
746 argtable = statargtable;
747 __find_arguments (fmt0, orgap,
748 &argtable);
749 }
750 goto rflag;
751 }
752 width = n;
753 goto reswitch;
754#ifdef FLOATING_POINT
755 case 'L':
756 flags |= LONGDBL;
757 goto rflag;
758#endif
759 case 'h':
760 if (flags & SHORTINT) {
761 flags &= ~SHORTINT;
762 flags |= CHARINT;
763 } else
764 flags |= SHORTINT;
765 goto rflag;
766 case 'j':
767 flags |= INTMAXT;
768 goto rflag;
769 case 'l':
770 if (flags & LONGINT) {
771 flags &= ~LONGINT;
772 flags |= LLONGINT;
773 } else
774 flags |= LONGINT;
775 goto rflag;
776 case 'q':
777 flags |= LLONGINT; /* not necessarily */
778 goto rflag;
779 case 't':
780 flags |= PTRDIFFT;
781 goto rflag;
782 case 'z':
783 flags |= SIZET;
784 goto rflag;
785 case 'C':
786 flags |= LONGINT;
787 /*FALLTHROUGH*/
788 case 'c':
789 if (flags & LONGINT) {
790 mbstate_t mbs;
791 size_t mbseqlen;
792
793 memset(&mbs, 0, sizeof(mbs));
794 mbseqlen = wcrtomb(cp = buf,
795 (wchar_t)GETARG(wint_t), &mbs);
796 if (mbseqlen == (size_t)-1) {
797 fp->_flags |= __SERR;
798 goto error;
799 }
800 size = (int)mbseqlen;
801 } else {
802 *(cp = buf) = GETARG(int);
803 size = 1;
804 }
805 sign = '\0';
806 break;
807 case 'D':
808 flags |= LONGINT;
809 /*FALLTHROUGH*/
810 case 'd':
811 case 'i':
812 if (flags & INTMAX_SIZE) {
813 ujval = SJARG();
814 if ((intmax_t)ujval < 0) {
815 ujval = -ujval;
816 sign = '-';
817 }
818 } else {
819 ulval = SARG();
820 if ((long)ulval < 0) {
821 ulval = -ulval;
822 sign = '-';
823 }
824 }
825 base = 10;
826 goto number;
827#ifdef FLOATING_POINT
828#ifdef HEXFLOAT
829 case 'a':
830 case 'A':
831 if (ch == 'a') {
832 ox[1] = 'x';
833 xdigs = xdigs_lower;
834 expchar = 'p';
835 } else {
836 ox[1] = 'X';
837 xdigs = xdigs_upper;
838 expchar = 'P';
839 }
840 /*
841 * XXX We don't actually have a conversion
842 * XXX routine for this yet.
843 */
844 if (flags & LONGDBL) {
845 fparg.ldbl = (double)GETARG(long double);
846 dtoaresult = cp =
847 __hldtoa(fparg.ldbl, xdigs, prec,
848 &expt, &signflag, &dtoaend);
849 } else {
850 fparg.dbl = GETARG(double);
851 dtoaresult = cp =
852 __hdtoa(fparg.dbl, xdigs, prec,
853 &expt, &signflag, &dtoaend);
854 }
855 goto fp_begin;
804#endif
805 case 'e':
806 case 'E':
856#endif
857 case 'e':
858 case 'E':
807 /*-
808 * Grouping apply to %i, %d, %u, %f, %F, %g, %G
809 * conversion specifiers only. For other conversions
810 * behavior is undefined.
811 * -- POSIX
812 */
813 flags &= ~GROUPING;
814 /*FALLTHROUGH*/
859 expchar = ch;
860 if (prec < 0) /* account for digit before decpt */
861 prec = DEFPREC + 1;
862 else
863 prec++;
864 goto fp_begin;
815 case 'f':
816 case 'F':
865 case 'f':
866 case 'F':
867 expchar = '\0';
817 goto fp_begin;
818 case 'g':
819 case 'G':
868 goto fp_begin;
869 case 'g':
870 case 'G':
871 expchar = ch - ('g' - 'e');
820 if (prec == 0)
821 prec = 1;
872 if (prec == 0)
873 prec = 1;
822fp_begin: if (prec == -1)
874fp_begin:
875 if (prec < 0)
823 prec = DEFPREC;
876 prec = DEFPREC;
824 if (flags & LONGDBL)
825 /* XXX this loses precision. */
826 _double = (double)GETARG(long double);
827 else
828 _double = GETARG(double);
829 /* do this before tricky precision changes */
830 if (isinf(_double)) {
831 if (_double < 0)
832 sign = '-';
833 if (isupper(ch))
834 cp = "INF";
835 else
836 cp = "inf";
837 size = 3;
838 break;
877 if (dtoaresult != NULL)
878 freedtoa(dtoaresult);
879 if (flags & LONGDBL) {
880 fparg.ldbl = GETARG(long double);
881 dtoaresult = cp =
882 __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
883 &expt, &signflag, &dtoaend);
884 } else {
885 fparg.dbl = GETARG(double);
886 dtoaresult = cp =
887 dtoa(fparg.dbl, expchar ? 2 : 3, prec,
888 &expt, &signflag, &dtoaend);
889 if (expt == 9999)
890 expt = INT_MAX;
839 }
891 }
840 if (isnan(_double)) {
841 if (isupper(ch))
842 cp = "NAN";
843 else
844 cp = "nan";
892 if (signflag)
893 sign = '-';
894 if (expt == INT_MAX) { /* inf or nan */
895 if (*cp == 'N') {
896 cp = (ch >= 'a') ? "nan" : "NAN";
897 sign = '\0';
898 } else
899 cp = (ch >= 'a') ? "inf" : "INF";
845 size = 3;
846 break;
847 }
848 flags |= FPT;
900 size = 3;
901 break;
902 }
903 flags |= FPT;
849 if (dtoaresult != NULL) {
850 __freedtoa(dtoaresult);
851 dtoaresult = NULL;
852 }
853 dtoaresult = cp = cvt(_double, prec, flags, &softsign,
854 &expt, ch, &ndig);
904 ndig = dtoaend - cp;
855 if (ch == 'g' || ch == 'G') {
905 if (ch == 'g' || ch == 'G') {
856 if (expt <= -4 || expt > prec)
857 ch = (ch == 'g') ? 'e' : 'E';
858 else
859 ch = 'g';
906 if (expt > -4 && expt <= prec) {
907 /* Make %[gG] smell like %[fF] */
908 expchar = '\0';
909 if (flags & ALT)
910 prec -= expt;
911 else
912 prec = ndig - expt;
913 if (prec < 0)
914 prec = 0;
915 }
860 }
916 }
861 if (ch == 'e' || ch == 'E') {
862 --expt;
863 expsize = exponent(expstr, expt, ch);
864 size = expsize + ndig;
865 if (ndig > 1 || flags & ALT)
917 if (expchar) {
918 expsize = exponent(expstr, expt - 1, expchar);
919 size = expsize + prec;
920 if (prec || flags & ALT)
866 ++size;
921 ++size;
867 } else if (ch == 'f' || ch == 'F') {
922 } else {
868 if (expt > 0) {
869 size = expt;
870 if (prec || flags & ALT)
871 size += prec + 1;
872 } else /* "0.X" */
873 size = prec + 2;
923 if (expt > 0) {
924 size = expt;
925 if (prec || flags & ALT)
926 size += prec + 1;
927 } else /* "0.X" */
928 size = prec + 2;
874 } else if (expt >= ndig) { /* fixed g fmt */
875 size = expt;
876 if (flags & ALT)
877 ++size;
878 } else
879 size = ndig + (expt > 0 ?
880 1 : 2 - expt);
881
882 if (softsign)
883 sign = '-';
929 if (grouping && expt > 0) {
930 /* space for thousands' grouping */
931 nseps = nrepeats = 0;
932 lead = expt;
933 while (*grouping != CHAR_MAX) {
934 if (lead <= *grouping)
935 break;
936 lead -= *grouping;
937 if (*(grouping+1)) {
938 nseps++;
939 grouping++;
940 } else
941 nrepeats++;
942 }
943 size += nseps + nrepeats;
944 } else
945 lead = (expt < ndig) ? expt : ndig;
946 }
884 break;
885#endif /* FLOATING_POINT */
886 case 'n':
887 /*
888 * Assignment-like behavior is specified if the
889 * value overflows or is otherwise unrepresentable.
890 * C99 says to use `signed char' for %hhn conversions.
891 */
892 if (flags & LLONGINT)
893 *GETARG(long long *) = ret;
894 else if (flags & SIZET)
895 *GETARG(ssize_t *) = (ssize_t)ret;
896 else if (flags & PTRDIFFT)
897 *GETARG(ptrdiff_t *) = ret;
898 else if (flags & INTMAXT)
899 *GETARG(intmax_t *) = ret;
900 else if (flags & LONGINT)
901 *GETARG(long *) = ret;
902 else if (flags & SHORTINT)
903 *GETARG(short *) = ret;
904 else if (flags & CHARINT)
905 *GETARG(signed char *) = ret;
906 else
907 *GETARG(int *) = ret;
908 continue; /* no output */
909 case 'O':
910 flags |= LONGINT;
911 /*FALLTHROUGH*/
912 case 'o':
913 if (flags & INTMAX_SIZE)
914 ujval = UJARG();
915 else
916 ulval = UARG();
917 base = 8;
918 goto nosign;
919 case 'p':
920 /*-
921 * ``The argument shall be a pointer to void. The
922 * value of the pointer is converted to a sequence
923 * of printable characters, in an implementation-
924 * defined manner.''
925 * -- ANSI X3J11
926 */
927 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
928 base = 16;
947 break;
948#endif /* FLOATING_POINT */
949 case 'n':
950 /*
951 * Assignment-like behavior is specified if the
952 * value overflows or is otherwise unrepresentable.
953 * C99 says to use `signed char' for %hhn conversions.
954 */
955 if (flags & LLONGINT)
956 *GETARG(long long *) = ret;
957 else if (flags & SIZET)
958 *GETARG(ssize_t *) = (ssize_t)ret;
959 else if (flags & PTRDIFFT)
960 *GETARG(ptrdiff_t *) = ret;
961 else if (flags & INTMAXT)
962 *GETARG(intmax_t *) = ret;
963 else if (flags & LONGINT)
964 *GETARG(long *) = ret;
965 else if (flags & SHORTINT)
966 *GETARG(short *) = ret;
967 else if (flags & CHARINT)
968 *GETARG(signed char *) = ret;
969 else
970 *GETARG(int *) = ret;
971 continue; /* no output */
972 case 'O':
973 flags |= LONGINT;
974 /*FALLTHROUGH*/
975 case 'o':
976 if (flags & INTMAX_SIZE)
977 ujval = UJARG();
978 else
979 ulval = UARG();
980 base = 8;
981 goto nosign;
982 case 'p':
983 /*-
984 * ``The argument shall be a pointer to void. The
985 * value of the pointer is converted to a sequence
986 * of printable characters, in an implementation-
987 * defined manner.''
988 * -- ANSI X3J11
989 */
990 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
991 base = 16;
929 xdigs = "0123456789abcdef";
930 flags = flags | INTMAXT | HEXPREFIX;
931 ch = 'x';
992 xdigs = xdigs_lower;
993 flags = flags | INTMAXT;
994 ox[1] = 'x';
932 goto nosign;
933 case 'S':
934 flags |= LONGINT;
935 /*FALLTHROUGH*/
936 case 's':
937 if (flags & LONGINT) {
938 wchar_t *wcp;
939
940 if (convbuf != NULL)
941 free(convbuf);
942 if ((wcp = GETARG(wchar_t *)) == NULL)
943 cp = "(null)";
944 else {
945 convbuf = __wcsconv(wcp, prec);
946 if (convbuf == NULL) {
947 fp->_flags |= __SERR;
948 goto error;
949 }
950 cp = convbuf;
951 }
952 } else if ((cp = GETARG(char *)) == NULL)
953 cp = "(null)";
954 if (prec >= 0) {
955 /*
956 * can't use strlen; can only look for the
957 * NUL in the first `prec' characters, and
958 * strlen() will go further.
959 */
960 char *p = memchr(cp, 0, (size_t)prec);
961
962 if (p != NULL) {
963 size = p - cp;
964 if (size > prec)
965 size = prec;
966 } else
967 size = prec;
968 } else
969 size = strlen(cp);
970 sign = '\0';
971 break;
972 case 'U':
973 flags |= LONGINT;
974 /*FALLTHROUGH*/
975 case 'u':
976 if (flags & INTMAX_SIZE)
977 ujval = UJARG();
978 else
979 ulval = UARG();
980 base = 10;
981 goto nosign;
982 case 'X':
995 goto nosign;
996 case 'S':
997 flags |= LONGINT;
998 /*FALLTHROUGH*/
999 case 's':
1000 if (flags & LONGINT) {
1001 wchar_t *wcp;
1002
1003 if (convbuf != NULL)
1004 free(convbuf);
1005 if ((wcp = GETARG(wchar_t *)) == NULL)
1006 cp = "(null)";
1007 else {
1008 convbuf = __wcsconv(wcp, prec);
1009 if (convbuf == NULL) {
1010 fp->_flags |= __SERR;
1011 goto error;
1012 }
1013 cp = convbuf;
1014 }
1015 } else if ((cp = GETARG(char *)) == NULL)
1016 cp = "(null)";
1017 if (prec >= 0) {
1018 /*
1019 * can't use strlen; can only look for the
1020 * NUL in the first `prec' characters, and
1021 * strlen() will go further.
1022 */
1023 char *p = memchr(cp, 0, (size_t)prec);
1024
1025 if (p != NULL) {
1026 size = p - cp;
1027 if (size > prec)
1028 size = prec;
1029 } else
1030 size = prec;
1031 } else
1032 size = strlen(cp);
1033 sign = '\0';
1034 break;
1035 case 'U':
1036 flags |= LONGINT;
1037 /*FALLTHROUGH*/
1038 case 'u':
1039 if (flags & INTMAX_SIZE)
1040 ujval = UJARG();
1041 else
1042 ulval = UARG();
1043 base = 10;
1044 goto nosign;
1045 case 'X':
983 xdigs = "0123456789ABCDEF";
1046 xdigs = xdigs_upper;
984 goto hex;
985 case 'x':
1047 goto hex;
1048 case 'x':
986 xdigs = "0123456789abcdef";
1049 xdigs = xdigs_lower;
987hex:
988 if (flags & INTMAX_SIZE)
989 ujval = UJARG();
990 else
991 ulval = UARG();
992 base = 16;
993 /* leading 0x/X only if non-zero */
994 if (flags & ALT &&
995 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
1050hex:
1051 if (flags & INTMAX_SIZE)
1052 ujval = UJARG();
1053 else
1054 ulval = UARG();
1055 base = 16;
1056 /* leading 0x/X only if non-zero */
1057 if (flags & ALT &&
1058 (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
996 flags |= HEXPREFIX;
1059 ox[1] = ch;
997
998 flags &= ~GROUPING;
999 /* unsigned conversions */
1000nosign: sign = '\0';
1001 /*-
1002 * ``... diouXx conversions ... if a precision is
1003 * specified, the 0 flag will be ignored.''
1004 * -- ANSI X3J11
1005 */
1006number: if ((dprec = prec) >= 0)
1007 flags &= ~ZEROPAD;
1008
1009 /*-
1010 * ``The result of converting a zero value with an
1011 * explicit precision of zero is no characters.''
1012 * -- ANSI X3J11
1013 */
1014 cp = buf + BUF;
1015 if (flags & INTMAX_SIZE) {
1016 if (ujval != 0 || prec != 0)
1017 cp = __ujtoa(ujval, cp, base,
1018 flags & ALT, xdigs,
1019 flags & GROUPING, thousands_sep,
1020 grouping);
1021 } else {
1022 if (ulval != 0 || prec != 0)
1023 cp = __ultoa(ulval, cp, base,
1024 flags & ALT, xdigs,
1025 flags & GROUPING, thousands_sep,
1026 grouping);
1027 }
1028 size = buf + BUF - cp;
1029 if (size > BUF) /* should never happen */
1030 abort();
1031 break;
1032 default: /* "%?" prints ?, unless ? is NUL */
1033 if (ch == '\0')
1034 goto done;
1035 /* pretend it was %c with argument ch */
1036 cp = buf;
1037 *cp = ch;
1038 size = 1;
1039 sign = '\0';
1040 break;
1041 }
1042
1043 /*
1044 * All reasonable formats wind up here. At this point, `cp'
1045 * points to a string which (if not flags&LADJUST) should be
1046 * padded out to `width' places. If flags&ZEROPAD, it should
1047 * first be prefixed by any sign or other prefix; otherwise,
1048 * it should be blank padded before the prefix is emitted.
1049 * After any left-hand padding and prefixing, emit zeroes
1050 * required by a decimal [diouxX] precision, then print the
1051 * string proper, then emit zeroes required by any leftover
1052 * floating precision; finally, if LADJUST, pad with blanks.
1053 *
1054 * Compute actual size, so we know how much to pad.
1055 * size excludes decimal prec; realsz includes it.
1056 */
1057 realsz = dprec > size ? dprec : size;
1058 if (sign)
1059 realsz++;
1060
1061 flags &= ~GROUPING;
1062 /* unsigned conversions */
1063nosign: sign = '\0';
1064 /*-
1065 * ``... diouXx conversions ... if a precision is
1066 * specified, the 0 flag will be ignored.''
1067 * -- ANSI X3J11
1068 */
1069number: if ((dprec = prec) >= 0)
1070 flags &= ~ZEROPAD;
1071
1072 /*-
1073 * ``The result of converting a zero value with an
1074 * explicit precision of zero is no characters.''
1075 * -- ANSI X3J11
1076 */
1077 cp = buf + BUF;
1078 if (flags & INTMAX_SIZE) {
1079 if (ujval != 0 || prec != 0)
1080 cp = __ujtoa(ujval, cp, base,
1081 flags & ALT, xdigs,
1082 flags & GROUPING, thousands_sep,
1083 grouping);
1084 } else {
1085 if (ulval != 0 || prec != 0)
1086 cp = __ultoa(ulval, cp, base,
1087 flags & ALT, xdigs,
1088 flags & GROUPING, thousands_sep,
1089 grouping);
1090 }
1091 size = buf + BUF - cp;
1092 if (size > BUF) /* should never happen */
1093 abort();
1094 break;
1095 default: /* "%?" prints ?, unless ? is NUL */
1096 if (ch == '\0')
1097 goto done;
1098 /* pretend it was %c with argument ch */
1099 cp = buf;
1100 *cp = ch;
1101 size = 1;
1102 sign = '\0';
1103 break;
1104 }
1105
1106 /*
1107 * All reasonable formats wind up here. At this point, `cp'
1108 * points to a string which (if not flags&LADJUST) should be
1109 * padded out to `width' places. If flags&ZEROPAD, it should
1110 * first be prefixed by any sign or other prefix; otherwise,
1111 * it should be blank padded before the prefix is emitted.
1112 * After any left-hand padding and prefixing, emit zeroes
1113 * required by a decimal [diouxX] precision, then print the
1114 * string proper, then emit zeroes required by any leftover
1115 * floating precision; finally, if LADJUST, pad with blanks.
1116 *
1117 * Compute actual size, so we know how much to pad.
1118 * size excludes decimal prec; realsz includes it.
1119 */
1120 realsz = dprec > size ? dprec : size;
1121 if (sign)
1122 realsz++;
1060 else if (flags & HEXPREFIX)
1123 else if (ox[1])
1061 realsz += 2;
1062
1063 prsize = width > realsz ? width : realsz;
1064 if ((unsigned)ret + prsize > INT_MAX) {
1065 ret = EOF;
1066 goto error;
1067 }
1068
1069 /* right-adjusting blank padding */
1070 if ((flags & (LADJUST|ZEROPAD)) == 0)
1071 PAD(width - realsz, blanks);
1072
1073 /* prefix */
1074 if (sign) {
1075 PRINT(&sign, 1);
1124 realsz += 2;
1125
1126 prsize = width > realsz ? width : realsz;
1127 if ((unsigned)ret + prsize > INT_MAX) {
1128 ret = EOF;
1129 goto error;
1130 }
1131
1132 /* right-adjusting blank padding */
1133 if ((flags & (LADJUST|ZEROPAD)) == 0)
1134 PAD(width - realsz, blanks);
1135
1136 /* prefix */
1137 if (sign) {
1138 PRINT(&sign, 1);
1076 } else if (flags & HEXPREFIX) {
1139 } else if (ox[1]) { /* ox[1] is either x, X, or \0 */
1077 ox[0] = '0';
1140 ox[0] = '0';
1078 ox[1] = ch;
1079 PRINT(ox, 2);
1080 }
1081
1082 /* right-adjusting zero padding */
1083 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1084 PAD(width - realsz, zeroes);
1085
1086 /* leading zeroes from decimal precision */
1087 PAD(dprec - size, zeroes);
1088
1089 /* the string or number proper */
1090#ifdef FLOATING_POINT
1091 if ((flags & FPT) == 0) {
1092 PRINT(cp, size);
1093 } else { /* glue together f_p fragments */
1141 PRINT(ox, 2);
1142 }
1143
1144 /* right-adjusting zero padding */
1145 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1146 PAD(width - realsz, zeroes);
1147
1148 /* leading zeroes from decimal precision */
1149 PAD(dprec - size, zeroes);
1150
1151 /* the string or number proper */
1152#ifdef FLOATING_POINT
1153 if ((flags & FPT) == 0) {
1154 PRINT(cp, size);
1155 } else { /* glue together f_p fragments */
1094 if (ch >= 'f') { /* 'f' or 'g' */
1095 if (_double == 0) {
1096 /* kludge for __dtoa irregularity */
1097 PRINT("0", 1);
1098 if (expt < ndig || (flags & ALT) != 0) {
1099 PRINT(decimal_point, 1);
1100 PAD(ndig - 1, zeroes);
1101 }
1102 } else if (expt <= 0) {
1103 PRINT("0", 1);
1104 PRINT(decimal_point, 1);
1156 if (!expchar) { /* %[fF] or sufficiently short %[gG] */
1157 if (expt <= 0) {
1158 buf[0] = '0';
1159 buf[1] = *decimal_point;
1160 PRINT(buf, 2);
1105 PAD(-expt, zeroes);
1161 PAD(-expt, zeroes);
1106 PRINT(cp, ndig);
1107 } else if (expt >= ndig) {
1108 PRINT(cp, ndig);
1109 PAD(expt - ndig, zeroes);
1110 if (flags & ALT)
1111 PRINT(decimal_point, 1);
1162 if (ndig > 0)
1163 PRINT(cp, ndig);
1112 } else {
1164 } else {
1113 PRINT(cp, expt);
1114 cp += expt;
1115 PRINT(decimal_point, 1);
1116 PRINT(cp, ndig-expt);
1165 PRINT(cp, lead);
1166 cp += lead;
1167 if (grouping) {
1168 while (nseps>0 || nrepeats>0) {
1169 if (nrepeats > 0)
1170 nrepeats--;
1171 else {
1172 grouping--;
1173 nseps--;
1174 }
1175 PRINT(&thousands_sep,
1176 1);
1177 PRINT(cp, *grouping);
1178 cp += *grouping;
1179 }
1180 } else {
1181 PAD(expt - lead, zeroes);
1182 }
1183 if (prec || flags & ALT)
1184 PRINT(decimal_point,1);
1185 if (ndig > lead)
1186 PRINT(cp, ndig - lead);
1117 }
1187 }
1118 } else { /* 'e' or 'E' */
1119 if (ndig > 1 || flags & ALT) {
1120 ox[0] = *cp++;
1121 ox[1] = *decimal_point;
1122 PRINT(ox, 2);
1123 if (_double) {
1124 PRINT(cp, ndig-1);
1125 } else /* 0.[0..] */
1126 /* __dtoa irregularity */
1127 PAD(ndig - 1, zeroes);
1188 PAD(prec - ndig + expt, zeroes);
1189 } else { /* %[eE] or sufficiently long %[gG] */
1190 if (prec || flags & ALT) {
1191 buf[0] = *cp++;
1192 buf[1] = *decimal_point;
1193 PRINT(buf, 2);
1194 PRINT(cp, ndig-1);
1195 PAD(prec - ndig, zeroes);
1128 } else /* XeYYY */
1129 PRINT(cp, 1);
1196 } else /* XeYYY */
1197 PRINT(cp, 1);
1198
1130 PRINT(expstr, expsize);
1131 }
1132 }
1133#else
1134 PRINT(cp, size);
1135#endif
1136 /* left-adjusting padding (always blank) */
1137 if (flags & LADJUST)
1138 PAD(width - realsz, blanks);
1139
1140 /* finally, adjust ret */
1141 ret += prsize;
1142
1143 FLUSH(); /* copy out the I/O vectors */
1144 }
1145done:
1146 FLUSH();
1147error:
1148#ifdef FLOATING_POINT
1149 if (dtoaresult != NULL)
1199 PRINT(expstr, expsize);
1200 }
1201 }
1202#else
1203 PRINT(cp, size);
1204#endif
1205 /* left-adjusting padding (always blank) */
1206 if (flags & LADJUST)
1207 PAD(width - realsz, blanks);
1208
1209 /* finally, adjust ret */
1210 ret += prsize;
1211
1212 FLUSH(); /* copy out the I/O vectors */
1213 }
1214done:
1215 FLUSH();
1216error:
1217#ifdef FLOATING_POINT
1218 if (dtoaresult != NULL)
1150 __freedtoa(dtoaresult);
1219 freedtoa(dtoaresult);
1151#endif
1152 if (convbuf != NULL)
1153 free(convbuf);
1154 if (__sferror(fp))
1155 ret = EOF;
1156 if ((argtable != NULL) && (argtable != statargtable))
1157 free (argtable);
1158 return (ret);
1159 /* NOTREACHED */
1160}
1161
1162/*
1163 * Find all arguments when a positional parameter is encountered. Returns a
1164 * table, indexed by argument number, of pointers to each arguments. The
1165 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
1166 * It will be replaces with a malloc-ed one if it overflows.
1167 */
1168static void
1169__find_arguments (const char *fmt0, va_list ap, union arg **argtable)
1170{
1171 char *fmt; /* format string */
1172 int ch; /* character from fmt */
1173 int n, n2; /* handy integer (short term usage) */
1174 char *cp; /* handy char pointer (short term usage) */
1175 int flags; /* flags as above */
1176 int width; /* width from format (%8d), or 0 */
1177 enum typeid *typetable; /* table of types */
1178 enum typeid stattypetable [STATIC_ARG_TBL_SIZE];
1179 int tablesize; /* current size of type table */
1180 int tablemax; /* largest used index in table */
1181 int nextarg; /* 1-based argument index */
1182
1183 /*
1184 * Add an argument type to the table, expanding if necessary.
1185 */
1186#define ADDTYPE(type) \
1187 ((nextarg >= tablesize) ? \
1188 __grow_type_table(nextarg, &typetable, &tablesize) : 0, \
1189 (nextarg > tablemax) ? tablemax = nextarg : 0, \
1190 typetable[nextarg++] = type)
1191
1192#define ADDSARG() \
1193 ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \
1194 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
1195 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
1196 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
1197 ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT))))))
1198
1199#define ADDUARG() \
1200 ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \
1201 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
1202 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
1203 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
1204 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT))))))
1205
1206 /*
1207 * Add * arguments to the type array.
1208 */
1209#define ADDASTER() \
1210 n2 = 0; \
1211 cp = fmt; \
1212 while (is_digit(*cp)) { \
1213 n2 = 10 * n2 + to_digit(*cp); \
1214 cp++; \
1215 } \
1216 if (*cp == '$') { \
1217 int hold = nextarg; \
1218 nextarg = n2; \
1219 ADDTYPE (T_INT); \
1220 nextarg = hold; \
1221 fmt = ++cp; \
1222 } else { \
1223 ADDTYPE (T_INT); \
1224 }
1225 fmt = (char *)fmt0;
1226 typetable = stattypetable;
1227 tablesize = STATIC_ARG_TBL_SIZE;
1228 tablemax = 0;
1229 nextarg = 1;
1230 memset (typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
1231
1232 /*
1233 * Scan the format for conversions (`%' character).
1234 */
1235 for (;;) {
1236 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
1237 /* void */;
1238 if (ch == '\0')
1239 goto done;
1240 fmt++; /* skip over '%' */
1241
1242 flags = 0;
1243 width = 0;
1244
1245rflag: ch = *fmt++;
1246reswitch: switch (ch) {
1247 case ' ':
1248 case '#':
1249 goto rflag;
1250 case '*':
1251 ADDASTER ();
1252 goto rflag;
1253 case '-':
1254 case '+':
1255 case '\'':
1256 goto rflag;
1257 case '.':
1258 if ((ch = *fmt++) == '*') {
1259 ADDASTER ();
1260 goto rflag;
1261 }
1262 while (is_digit(ch)) {
1263 ch = *fmt++;
1264 }
1265 goto reswitch;
1266 case '0':
1267 goto rflag;
1268 case '1': case '2': case '3': case '4':
1269 case '5': case '6': case '7': case '8': case '9':
1270 n = 0;
1271 do {
1272 n = 10 * n + to_digit(ch);
1273 ch = *fmt++;
1274 } while (is_digit(ch));
1275 if (ch == '$') {
1276 nextarg = n;
1277 goto rflag;
1278 }
1279 width = n;
1280 goto reswitch;
1281#ifdef FLOATING_POINT
1282 case 'L':
1283 flags |= LONGDBL;
1284 goto rflag;
1285#endif
1286 case 'h':
1287 if (flags & SHORTINT) {
1288 flags &= ~SHORTINT;
1289 flags |= CHARINT;
1290 } else
1291 flags |= SHORTINT;
1292 goto rflag;
1293 case 'j':
1294 flags |= INTMAXT;
1295 goto rflag;
1296 case 'l':
1297 if (flags & LONGINT) {
1298 flags &= ~LONGINT;
1299 flags |= LLONGINT;
1300 } else
1301 flags |= LONGINT;
1302 goto rflag;
1303 case 'q':
1304 flags |= LLONGINT; /* not necessarily */
1305 goto rflag;
1306 case 't':
1307 flags |= PTRDIFFT;
1308 goto rflag;
1309 case 'z':
1310 flags |= SIZET;
1311 goto rflag;
1312 case 'C':
1313 flags |= LONGINT;
1314 /*FALLTHROUGH*/
1315 case 'c':
1316 if (flags & LONGINT)
1317 ADDTYPE(T_WINT);
1318 else
1319 ADDTYPE(T_INT);
1320 break;
1321 case 'D':
1322 flags |= LONGINT;
1323 /*FALLTHROUGH*/
1324 case 'd':
1325 case 'i':
1326 ADDSARG();
1327 break;
1328#ifdef FLOATING_POINT
1329#ifdef HEXFLOAT
1330 case 'a':
1331 case 'A':
1332#endif
1333 case 'e':
1334 case 'E':
1335 case 'f':
1336 case 'g':
1337 case 'G':
1338 if (flags & LONGDBL)
1339 ADDTYPE(T_LONG_DOUBLE);
1340 else
1341 ADDTYPE(T_DOUBLE);
1342 break;
1343#endif /* FLOATING_POINT */
1344 case 'n':
1345 if (flags & INTMAXT)
1346 ADDTYPE(TP_INTMAXT);
1347 else if (flags & PTRDIFFT)
1348 ADDTYPE(TP_PTRDIFFT);
1349 else if (flags & SIZET)
1350 ADDTYPE(TP_SIZET);
1351 else if (flags & LLONGINT)
1352 ADDTYPE(TP_LLONG);
1353 else if (flags & LONGINT)
1354 ADDTYPE(TP_LONG);
1355 else if (flags & SHORTINT)
1356 ADDTYPE(TP_SHORT);
1357 else if (flags & CHARINT)
1358 ADDTYPE(TP_SCHAR);
1359 else
1360 ADDTYPE(TP_INT);
1361 continue; /* no output */
1362 case 'O':
1363 flags |= LONGINT;
1364 /*FALLTHROUGH*/
1365 case 'o':
1366 ADDUARG();
1367 break;
1368 case 'p':
1369 ADDTYPE(TP_VOID);
1370 break;
1371 case 'S':
1372 flags |= LONGINT;
1373 /*FALLTHROUGH*/
1374 case 's':
1375 if (flags & LONGINT)
1376 ADDTYPE(TP_WCHAR);
1377 else
1378 ADDTYPE(TP_CHAR);
1379 break;
1380 case 'U':
1381 flags |= LONGINT;
1382 /*FALLTHROUGH*/
1383 case 'u':
1384 case 'X':
1385 case 'x':
1386 ADDUARG();
1387 break;
1388 default: /* "%?" prints ?, unless ? is NUL */
1389 if (ch == '\0')
1390 goto done;
1391 break;
1392 }
1393 }
1394done:
1395 /*
1396 * Build the argument table.
1397 */
1398 if (tablemax >= STATIC_ARG_TBL_SIZE) {
1399 *argtable = (union arg *)
1400 malloc (sizeof (union arg) * (tablemax + 1));
1401 }
1402
1403 (*argtable) [0].intarg = 0;
1404 for (n = 1; n <= tablemax; n++) {
1405 switch (typetable [n]) {
1406 case T_UNUSED: /* whoops! */
1407 (*argtable) [n].intarg = va_arg (ap, int);
1408 break;
1409 case TP_SCHAR:
1410 (*argtable) [n].pschararg = va_arg (ap, signed char *);
1411 break;
1412 case TP_SHORT:
1413 (*argtable) [n].pshortarg = va_arg (ap, short *);
1414 break;
1415 case T_INT:
1416 (*argtable) [n].intarg = va_arg (ap, int);
1417 break;
1418 case T_U_INT:
1419 (*argtable) [n].uintarg = va_arg (ap, unsigned int);
1420 break;
1421 case TP_INT:
1422 (*argtable) [n].pintarg = va_arg (ap, int *);
1423 break;
1424 case T_LONG:
1425 (*argtable) [n].longarg = va_arg (ap, long);
1426 break;
1427 case T_U_LONG:
1428 (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
1429 break;
1430 case TP_LONG:
1431 (*argtable) [n].plongarg = va_arg (ap, long *);
1432 break;
1433 case T_LLONG:
1434 (*argtable) [n].longlongarg = va_arg (ap, long long);
1435 break;
1436 case T_U_LLONG:
1437 (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
1438 break;
1439 case TP_LLONG:
1440 (*argtable) [n].plonglongarg = va_arg (ap, long long *);
1441 break;
1442 case T_PTRDIFFT:
1443 (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
1444 break;
1445 case TP_PTRDIFFT:
1446 (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
1447 break;
1448 case T_SIZET:
1449 (*argtable) [n].sizearg = va_arg (ap, size_t);
1450 break;
1451 case TP_SIZET:
1452 (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
1453 break;
1454 case T_INTMAXT:
1455 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
1456 break;
1457 case T_UINTMAXT:
1458 (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
1459 break;
1460 case TP_INTMAXT:
1461 (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
1462 break;
1463#ifdef FLOATING_POINT
1464 case T_DOUBLE:
1465 (*argtable) [n].doublearg = va_arg (ap, double);
1466 break;
1467 case T_LONG_DOUBLE:
1468 (*argtable) [n].longdoublearg = va_arg (ap, long double);
1469 break;
1470#endif
1471 case TP_CHAR:
1472 (*argtable) [n].pchararg = va_arg (ap, char *);
1473 break;
1474 case TP_VOID:
1475 (*argtable) [n].pvoidarg = va_arg (ap, void *);
1476 break;
1477 case T_WINT:
1478 (*argtable) [n].wintarg = va_arg (ap, wint_t);
1479 break;
1480 case TP_WCHAR:
1481 (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
1482 break;
1483 }
1484 }
1485
1486 if ((typetable != NULL) && (typetable != stattypetable))
1487 free (typetable);
1488}
1489
1490/*
1491 * Increase the size of the type table.
1492 */
1493static void
1494__grow_type_table (int nextarg, enum typeid **typetable, int *tablesize)
1495{
1496 enum typeid *const oldtable = *typetable;
1497 const int oldsize = *tablesize;
1498 enum typeid *newtable;
1499 int newsize = oldsize * 2;
1500
1501 if (newsize < nextarg + 1)
1502 newsize = nextarg + 1;
1503 if (oldsize == STATIC_ARG_TBL_SIZE) {
1504 if ((newtable = malloc(newsize)) == NULL)
1505 abort(); /* XXX handle better */
1506 bcopy(oldtable, newtable, oldsize);
1507 } else {
1508 if ((newtable = reallocf(oldtable, newsize)) == NULL)
1509 abort(); /* XXX handle better */
1510 }
1511 memset(&newtable[oldsize], T_UNUSED, newsize - oldsize);
1512
1513 *typetable = newtable;
1514 *tablesize = newsize;
1515}
1516
1517
1518#ifdef FLOATING_POINT
1519
1220#endif
1221 if (convbuf != NULL)
1222 free(convbuf);
1223 if (__sferror(fp))
1224 ret = EOF;
1225 if ((argtable != NULL) && (argtable != statargtable))
1226 free (argtable);
1227 return (ret);
1228 /* NOTREACHED */
1229}
1230
1231/*
1232 * Find all arguments when a positional parameter is encountered. Returns a
1233 * table, indexed by argument number, of pointers to each arguments. The
1234 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
1235 * It will be replaces with a malloc-ed one if it overflows.
1236 */
1237static void
1238__find_arguments (const char *fmt0, va_list ap, union arg **argtable)
1239{
1240 char *fmt; /* format string */
1241 int ch; /* character from fmt */
1242 int n, n2; /* handy integer (short term usage) */
1243 char *cp; /* handy char pointer (short term usage) */
1244 int flags; /* flags as above */
1245 int width; /* width from format (%8d), or 0 */
1246 enum typeid *typetable; /* table of types */
1247 enum typeid stattypetable [STATIC_ARG_TBL_SIZE];
1248 int tablesize; /* current size of type table */
1249 int tablemax; /* largest used index in table */
1250 int nextarg; /* 1-based argument index */
1251
1252 /*
1253 * Add an argument type to the table, expanding if necessary.
1254 */
1255#define ADDTYPE(type) \
1256 ((nextarg >= tablesize) ? \
1257 __grow_type_table(nextarg, &typetable, &tablesize) : 0, \
1258 (nextarg > tablemax) ? tablemax = nextarg : 0, \
1259 typetable[nextarg++] = type)
1260
1261#define ADDSARG() \
1262 ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \
1263 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
1264 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
1265 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
1266 ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT))))))
1267
1268#define ADDUARG() \
1269 ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \
1270 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
1271 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
1272 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
1273 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT))))))
1274
1275 /*
1276 * Add * arguments to the type array.
1277 */
1278#define ADDASTER() \
1279 n2 = 0; \
1280 cp = fmt; \
1281 while (is_digit(*cp)) { \
1282 n2 = 10 * n2 + to_digit(*cp); \
1283 cp++; \
1284 } \
1285 if (*cp == '$') { \
1286 int hold = nextarg; \
1287 nextarg = n2; \
1288 ADDTYPE (T_INT); \
1289 nextarg = hold; \
1290 fmt = ++cp; \
1291 } else { \
1292 ADDTYPE (T_INT); \
1293 }
1294 fmt = (char *)fmt0;
1295 typetable = stattypetable;
1296 tablesize = STATIC_ARG_TBL_SIZE;
1297 tablemax = 0;
1298 nextarg = 1;
1299 memset (typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
1300
1301 /*
1302 * Scan the format for conversions (`%' character).
1303 */
1304 for (;;) {
1305 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
1306 /* void */;
1307 if (ch == '\0')
1308 goto done;
1309 fmt++; /* skip over '%' */
1310
1311 flags = 0;
1312 width = 0;
1313
1314rflag: ch = *fmt++;
1315reswitch: switch (ch) {
1316 case ' ':
1317 case '#':
1318 goto rflag;
1319 case '*':
1320 ADDASTER ();
1321 goto rflag;
1322 case '-':
1323 case '+':
1324 case '\'':
1325 goto rflag;
1326 case '.':
1327 if ((ch = *fmt++) == '*') {
1328 ADDASTER ();
1329 goto rflag;
1330 }
1331 while (is_digit(ch)) {
1332 ch = *fmt++;
1333 }
1334 goto reswitch;
1335 case '0':
1336 goto rflag;
1337 case '1': case '2': case '3': case '4':
1338 case '5': case '6': case '7': case '8': case '9':
1339 n = 0;
1340 do {
1341 n = 10 * n + to_digit(ch);
1342 ch = *fmt++;
1343 } while (is_digit(ch));
1344 if (ch == '$') {
1345 nextarg = n;
1346 goto rflag;
1347 }
1348 width = n;
1349 goto reswitch;
1350#ifdef FLOATING_POINT
1351 case 'L':
1352 flags |= LONGDBL;
1353 goto rflag;
1354#endif
1355 case 'h':
1356 if (flags & SHORTINT) {
1357 flags &= ~SHORTINT;
1358 flags |= CHARINT;
1359 } else
1360 flags |= SHORTINT;
1361 goto rflag;
1362 case 'j':
1363 flags |= INTMAXT;
1364 goto rflag;
1365 case 'l':
1366 if (flags & LONGINT) {
1367 flags &= ~LONGINT;
1368 flags |= LLONGINT;
1369 } else
1370 flags |= LONGINT;
1371 goto rflag;
1372 case 'q':
1373 flags |= LLONGINT; /* not necessarily */
1374 goto rflag;
1375 case 't':
1376 flags |= PTRDIFFT;
1377 goto rflag;
1378 case 'z':
1379 flags |= SIZET;
1380 goto rflag;
1381 case 'C':
1382 flags |= LONGINT;
1383 /*FALLTHROUGH*/
1384 case 'c':
1385 if (flags & LONGINT)
1386 ADDTYPE(T_WINT);
1387 else
1388 ADDTYPE(T_INT);
1389 break;
1390 case 'D':
1391 flags |= LONGINT;
1392 /*FALLTHROUGH*/
1393 case 'd':
1394 case 'i':
1395 ADDSARG();
1396 break;
1397#ifdef FLOATING_POINT
1398#ifdef HEXFLOAT
1399 case 'a':
1400 case 'A':
1401#endif
1402 case 'e':
1403 case 'E':
1404 case 'f':
1405 case 'g':
1406 case 'G':
1407 if (flags & LONGDBL)
1408 ADDTYPE(T_LONG_DOUBLE);
1409 else
1410 ADDTYPE(T_DOUBLE);
1411 break;
1412#endif /* FLOATING_POINT */
1413 case 'n':
1414 if (flags & INTMAXT)
1415 ADDTYPE(TP_INTMAXT);
1416 else if (flags & PTRDIFFT)
1417 ADDTYPE(TP_PTRDIFFT);
1418 else if (flags & SIZET)
1419 ADDTYPE(TP_SIZET);
1420 else if (flags & LLONGINT)
1421 ADDTYPE(TP_LLONG);
1422 else if (flags & LONGINT)
1423 ADDTYPE(TP_LONG);
1424 else if (flags & SHORTINT)
1425 ADDTYPE(TP_SHORT);
1426 else if (flags & CHARINT)
1427 ADDTYPE(TP_SCHAR);
1428 else
1429 ADDTYPE(TP_INT);
1430 continue; /* no output */
1431 case 'O':
1432 flags |= LONGINT;
1433 /*FALLTHROUGH*/
1434 case 'o':
1435 ADDUARG();
1436 break;
1437 case 'p':
1438 ADDTYPE(TP_VOID);
1439 break;
1440 case 'S':
1441 flags |= LONGINT;
1442 /*FALLTHROUGH*/
1443 case 's':
1444 if (flags & LONGINT)
1445 ADDTYPE(TP_WCHAR);
1446 else
1447 ADDTYPE(TP_CHAR);
1448 break;
1449 case 'U':
1450 flags |= LONGINT;
1451 /*FALLTHROUGH*/
1452 case 'u':
1453 case 'X':
1454 case 'x':
1455 ADDUARG();
1456 break;
1457 default: /* "%?" prints ?, unless ? is NUL */
1458 if (ch == '\0')
1459 goto done;
1460 break;
1461 }
1462 }
1463done:
1464 /*
1465 * Build the argument table.
1466 */
1467 if (tablemax >= STATIC_ARG_TBL_SIZE) {
1468 *argtable = (union arg *)
1469 malloc (sizeof (union arg) * (tablemax + 1));
1470 }
1471
1472 (*argtable) [0].intarg = 0;
1473 for (n = 1; n <= tablemax; n++) {
1474 switch (typetable [n]) {
1475 case T_UNUSED: /* whoops! */
1476 (*argtable) [n].intarg = va_arg (ap, int);
1477 break;
1478 case TP_SCHAR:
1479 (*argtable) [n].pschararg = va_arg (ap, signed char *);
1480 break;
1481 case TP_SHORT:
1482 (*argtable) [n].pshortarg = va_arg (ap, short *);
1483 break;
1484 case T_INT:
1485 (*argtable) [n].intarg = va_arg (ap, int);
1486 break;
1487 case T_U_INT:
1488 (*argtable) [n].uintarg = va_arg (ap, unsigned int);
1489 break;
1490 case TP_INT:
1491 (*argtable) [n].pintarg = va_arg (ap, int *);
1492 break;
1493 case T_LONG:
1494 (*argtable) [n].longarg = va_arg (ap, long);
1495 break;
1496 case T_U_LONG:
1497 (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
1498 break;
1499 case TP_LONG:
1500 (*argtable) [n].plongarg = va_arg (ap, long *);
1501 break;
1502 case T_LLONG:
1503 (*argtable) [n].longlongarg = va_arg (ap, long long);
1504 break;
1505 case T_U_LLONG:
1506 (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
1507 break;
1508 case TP_LLONG:
1509 (*argtable) [n].plonglongarg = va_arg (ap, long long *);
1510 break;
1511 case T_PTRDIFFT:
1512 (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
1513 break;
1514 case TP_PTRDIFFT:
1515 (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
1516 break;
1517 case T_SIZET:
1518 (*argtable) [n].sizearg = va_arg (ap, size_t);
1519 break;
1520 case TP_SIZET:
1521 (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
1522 break;
1523 case T_INTMAXT:
1524 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
1525 break;
1526 case T_UINTMAXT:
1527 (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
1528 break;
1529 case TP_INTMAXT:
1530 (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
1531 break;
1532#ifdef FLOATING_POINT
1533 case T_DOUBLE:
1534 (*argtable) [n].doublearg = va_arg (ap, double);
1535 break;
1536 case T_LONG_DOUBLE:
1537 (*argtable) [n].longdoublearg = va_arg (ap, long double);
1538 break;
1539#endif
1540 case TP_CHAR:
1541 (*argtable) [n].pchararg = va_arg (ap, char *);
1542 break;
1543 case TP_VOID:
1544 (*argtable) [n].pvoidarg = va_arg (ap, void *);
1545 break;
1546 case T_WINT:
1547 (*argtable) [n].wintarg = va_arg (ap, wint_t);
1548 break;
1549 case TP_WCHAR:
1550 (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
1551 break;
1552 }
1553 }
1554
1555 if ((typetable != NULL) && (typetable != stattypetable))
1556 free (typetable);
1557}
1558
1559/*
1560 * Increase the size of the type table.
1561 */
1562static void
1563__grow_type_table (int nextarg, enum typeid **typetable, int *tablesize)
1564{
1565 enum typeid *const oldtable = *typetable;
1566 const int oldsize = *tablesize;
1567 enum typeid *newtable;
1568 int newsize = oldsize * 2;
1569
1570 if (newsize < nextarg + 1)
1571 newsize = nextarg + 1;
1572 if (oldsize == STATIC_ARG_TBL_SIZE) {
1573 if ((newtable = malloc(newsize)) == NULL)
1574 abort(); /* XXX handle better */
1575 bcopy(oldtable, newtable, oldsize);
1576 } else {
1577 if ((newtable = reallocf(oldtable, newsize)) == NULL)
1578 abort(); /* XXX handle better */
1579 }
1580 memset(&newtable[oldsize], T_UNUSED, newsize - oldsize);
1581
1582 *typetable = newtable;
1583 *tablesize = newsize;
1584}
1585
1586
1587#ifdef FLOATING_POINT
1588
1520static char *
1521cvt(double value, int ndigits, int flags, char *sign, int *decpt,
1522 int ch, int *length)
1523{
1524 int mode, dsgn;
1525 char *digits, *bp, *rve;
1526
1527 if (ch == 'f')
1528 mode = 3; /* ndigits after the decimal point */
1529 else {
1530 /*
1531 * To obtain ndigits after the decimal point for the 'e'
1532 * and 'E' formats, round to ndigits + 1 significant
1533 * figures.
1534 */
1535 if (ch == 'e' || ch == 'E')
1536 ndigits++;
1537 mode = 2; /* ndigits significant digits */
1538 }
1539 digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
1540 *sign = dsgn != 0;
1541 if ((ch != 'g' && ch != 'G') || flags & ALT) {
1542 /* print trailing zeros */
1543 bp = digits + ndigits;
1544 if (ch == 'f') {
1545 if ((*digits == '0' || *digits == '\0') && value)
1546 *decpt = -ndigits + 1;
1547 bp += *decpt;
1548 }
1549 if (value == 0) /* kludge for __dtoa irregularity */
1550 rve = bp;
1551 while (rve < bp)
1552 *rve++ = '0';
1553 }
1554 *length = rve - digits;
1555 return (digits);
1556}
1557
1558static int
1559exponent(char *p0, int exp, int fmtch)
1560{
1561 char *p, *t;
1562 char expbuf[MAXEXPDIG];
1563
1564 p = p0;
1565 *p++ = fmtch;
1566 if (exp < 0) {
1567 exp = -exp;
1568 *p++ = '-';
1569 }
1570 else
1571 *p++ = '+';
1572 t = expbuf + MAXEXPDIG;
1573 if (exp > 9) {
1574 do {
1575 *--t = to_char(exp % 10);
1576 } while ((exp /= 10) > 9);
1577 *--t = to_char(exp);
1578 for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
1579 }
1580 else {
1589static int
1590exponent(char *p0, int exp, int fmtch)
1591{
1592 char *p, *t;
1593 char expbuf[MAXEXPDIG];
1594
1595 p = p0;
1596 *p++ = fmtch;
1597 if (exp < 0) {
1598 exp = -exp;
1599 *p++ = '-';
1600 }
1601 else
1602 *p++ = '+';
1603 t = expbuf + MAXEXPDIG;
1604 if (exp > 9) {
1605 do {
1606 *--t = to_char(exp % 10);
1607 } while ((exp /= 10) > 9);
1608 *--t = to_char(exp);
1609 for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
1610 }
1611 else {
1581 *p++ = '0';
1612 /*
1613 * Exponents for decimal floating point conversions
1614 * (%[eEgG]) must be at least two characters long,
1615 * whereas exponents for hexadecimal conversions can
1616 * be only one character long.
1617 */
1618 if (fmtch == 'e' || fmtch == 'E')
1619 *p++ = '0';
1582 *p++ = to_char(exp);
1583 }
1584 return (p - p0);
1585}
1586#endif /* FLOATING_POINT */
1620 *p++ = to_char(exp);
1621 }
1622 return (p - p0);
1623}
1624#endif /* FLOATING_POINT */