1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * 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. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 /*
34 FUNCTION
35 <<vfprintf>>, <<vprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, <<vasnprintf>>---format argument list
36
37 INDEX
38 vfprintf
39 INDEX
40 _vfprintf_r
41 INDEX
42 vprintf
43 INDEX
44 _vprintf_r
45 INDEX
46 vsprintf
47 INDEX
48 _vsprintf_r
49 INDEX
50 vsnprintf
51 INDEX
52 _vsnprintf_r
53 INDEX
54 vasprintf
55 INDEX
56 _vasprintf_r
57 INDEX
58 vasnprintf
59 INDEX
60 _vasnprintf_r
61
62 SYNOPSIS
63 #include <stdio.h>
64 #include <stdarg.h>
65 int vprintf(const char *<[fmt]>, va_list <[list]>);
66 int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
67 int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
68 int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>,
69 va_list <[list]>);
70 int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
71 char *vasnprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
72 va_list <[list]>);
73
74 int vprintf( const char *<[fmt]>,
75 va_list <[list]>);
76 int vfprintf( FILE *<[fp]>,
77 const char *<[fmt]>, va_list <[list]>);
78 int vsprintf( char *<[str]>,
79 const char *<[fmt]>, va_list <[list]>);
80 int vasprintf( char **<[str]>,
81 const char *<[fmt]>, va_list <[list]>);
82 int vsnprintf( char *<[str]>,
83 size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
84 char *vasnprintf( char *<[str]>,
85 size_t *<[size]>, const char *<[fmt]>, va_list <[list]>);
86
87 DESCRIPTION
88 <<vprintf>>, <<vfprintf>>, <<vasprintf>>, <<vsprintf>>, <<vsnprintf>>,
89 and <<vasnprintf>> are (respectively) variants of <<printf>>,
90 <<fprintf>>, <<asprintf>>, <<sprintf>>, <<snprintf>>, and
91 <<asnprintf>>. They differ only in allowing their caller to pass the
92 variable argument list as a <<va_list>> object (initialized by
93 <<va_start>>) rather than directly accepting a variable number of
94 arguments. The caller is responsible for calling <<va_end>>.
95
96 <<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
97 <<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
98 above.
99
100 RETURNS
101 The return values are consistent with the corresponding functions.
102
103 PORTABILITY
104 ANSI C requires <<vprintf>>, <<vfprintf>>, <<vsprintf>>, and
105 <<vsnprintf>>. The remaining functions are newlib extensions.
106
107 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
108 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
109 */
110
111 #if defined(LIBC_SCCS) && !defined(lint)
112 /*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/
113 static char *rcsid = "$Id$";
114 #endif /* LIBC_SCCS and not lint */
115
116 /*
117 * Actual printf innards.
118 *
119 * This code is large and complicated...
120 */
121 #define _DEFAULT_SOURCE
122
123 #ifdef INTEGER_ONLY
124 # ifdef STRING_ONLY
125 # define VFPRINTF svfiprintf
126 # else
127 # define VFPRINTF vfiprintf
128 # endif
129 #else
130 # ifdef STRING_ONLY
131 # define VFPRINTF svfprintf
132 # else
133 # define VFPRINTF vfprintf
134 # endif
135 # ifndef NO_FLOATING_POINT
136 # define FLOATING_POINT
137 # endif
138 #endif
139
140 #define _NO_POS_ARGS
141 #ifdef _WANT_IO_POS_ARGS
142 # undef _NO_POS_ARGS
143 #endif
144
145 #define _DEFAULT_SOURCE
146 #include <stdio.h>
147 #include <stdlib.h>
148 #include <string.h>
149 #include <limits.h>
150 #include <stdint.h>
151 #include <wchar.h>
152 #include <sys/lock.h>
153 #include <sys/types.h>
154 #include <stdarg.h>
155 #include "local.h"
156 #include "../stdlib/local.h"
157 #include "fvwrite.h"
158 #include "vfieeefp.h"
159
160 /* Currently a test is made to see if long double processing is warranted.
161 This could be changed in the future should the __ldtoa code be
162 preferred over __dtoa. */
163 #define _NO_LONGDBL
164 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
165 #undef _NO_LONGDBL
166 #endif
167
168 #define _NO_LONGLONG
169 #if defined _WANT_IO_LONG_LONG \
170 && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
171 # undef _NO_LONGLONG
172 #endif
173
174 #ifdef STRING_ONLY
175
176 # ifdef _FVWRITE_IN_STREAMIO
177 # define __SPRINT __ssprint
178 # else
179 # define __SPRINT __ssputs
180 # endif
181
182 #else /* !STRING_ONLY */
183
184 # ifdef _FVWRITE_IN_STREAMIO
185 # define __SPRINT __sprint
186 # else
187 # define __SPRINT __sfputs
188 # endif
189
190 #ifdef _UNBUF_STREAM_OPT
191 /*
192 * Helper function for `fprintf to unbuffered unix file': creates a
193 * temporary buffer. We only work on write-only files; this avoids
194 * worries about ungetc buffers and so forth.
195 *
196 * Make sure to avoid inlining.
197 */
198 _NOINLINE_STATIC int
__sbprintf(register FILE * fp,const char * fmt,va_list ap)199 __sbprintf (
200 register FILE *fp,
201 const char *fmt,
202 va_list ap)
203 {
204 int ret;
205 FILE fake;
206 unsigned char buf[BUFSIZ];
207
208 /* copy the important variables */
209 fake._flags = fp->_flags & ~__SNBF;
210 fake._flags2 = fp->_flags2;
211 fake._file = fp->_file;
212 fake._cookie = fp->_cookie;
213 fake._write = fp->_write;
214
215 /* set up the buffer */
216 fake._bf._base = fake._p = buf;
217 fake._bf._size = fake._w = sizeof (buf);
218 fake._lbfsize = 0; /* not actually used, but Just In Case */
219 #ifndef __SINGLE_THREAD__
220 __lock_init_recursive (fake._lock);
221 #endif
222
223 /* do the work, then copy any error status */
224 ret = VFPRINTF (&fake, fmt, ap);
225 if (ret >= 0 && fflush ( &fake))
226 ret = EOF;
227 if (fake._flags & __SERR)
228 fp->_flags |= __SERR;
229
230 #ifndef __SINGLE_THREAD__
231 __lock_close_recursive (fake._lock);
232 #endif
233 return (ret);
234 }
235 #endif /* _UNBUF_STREAM_OPT */
236 #endif /* !STRING_ONLY */
237
238
239 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
240 # include <locale.h>
241 #endif
242 #ifdef FLOATING_POINT
243 # include <math.h>
244
245 /* For %La, an exponent of 15 bits occupies the exponent character, a
246 sign, and up to 5 digits. */
247 # define MAXEXPLEN 7
248 # define DEFPREC 6
249
250 # ifdef _NO_LONGDBL
251
252 # define _PRINTF_FLOAT_TYPE double
253 # define _DTOA __dtoa
254 # define FREXP frexp
255
256 # else /* !_NO_LONGDBL */
257
258 extern int _ldcheck (_LONG_DOUBLE *);
259
260 # define _PRINTF_FLOAT_TYPE _LONG_DOUBLE
261 # define _DTOA __ldtoa
262 # define FREXP frexpl
263 # endif /* !_NO_LONGDBL */
264
265 static char *cvt(_PRINTF_FLOAT_TYPE, int, int, char *, int *,
266 int, int *, char *);
267
268 static int exponent(char *, int, int);
269
270 #endif /* FLOATING_POINT */
271
272 /* BUF must be big enough for the maximum %#llo (assuming long long is
273 at most 64 bits, this would be 23 characters), the maximum
274 multibyte character %C, and the maximum default precision of %La
275 (assuming long double is at most 128 bits with 113 bits of
276 mantissa, this would be 29 characters). %e, %f, and %g use
277 reentrant storage shared with mprec. All other formats that use
278 buf get by with fewer characters. Making BUF slightly bigger
279 reduces the need for malloc in %.*a and %S, when large precision or
280 long strings are processed.
281 The bigger size of 100 bytes is used on systems which allow number
282 strings using the locale's grouping character. Since that's a multibyte
283 value, we should use a conservative value.
284 */
285 #ifdef _WANT_IO_C99_FORMATS
286 #define BUF 100
287 #else
288 #define BUF 40
289 #endif
290 #if defined _MB_CAPABLE && MB_LEN_MAX > BUF
291 # undef BUF
292 # define BUF MB_LEN_MAX
293 #endif
294
295 #ifndef _NO_LONGLONG
296 # define quad_t long long
297 # define u_quad_t unsigned long long
298 #else
299 # define quad_t long
300 # define u_quad_t unsigned long
301 #endif
302
303 typedef quad_t * quad_ptr_t;
304 typedef void *void_ptr_t;
305 typedef char * char_ptr_t;
306 typedef long * long_ptr_t;
307 typedef int * int_ptr_t;
308 typedef short * short_ptr_t;
309
310 #ifndef _NO_POS_ARGS
311 # ifdef NL_ARGMAX
312 # define MAX_POS_ARGS NL_ARGMAX
313 # else
314 # define MAX_POS_ARGS 32
315 # endif
316
317 union arg_val
318 {
319 int val_int;
320 u_int val_u_int;
321 long val_long;
322 u_long val_u_long;
323 float val_float;
324 double val_double;
325 _LONG_DOUBLE val__LONG_DOUBLE;
326 int_ptr_t val_int_ptr_t;
327 short_ptr_t val_short_ptr_t;
328 long_ptr_t val_long_ptr_t;
329 char_ptr_t val_char_ptr_t;
330 quad_ptr_t val_quad_ptr_t;
331 void_ptr_t val_void_ptr_t;
332 quad_t val_quad_t;
333 u_quad_t val_u_quad_t;
334 wint_t val_wint_t;
335 };
336
337 typedef struct {
338 va_list ap;
339 } my_va_list;
340
341 static union arg_val *
342 get_arg (int n, char *fmt,
343 my_va_list *ap, int *numargs, union arg_val *args,
344 int *arg_type, char **last_fmt);
345 #endif /* !_NO_POS_ARGS */
346
347 /*
348 * Macros for converting digits to letters and vice versa
349 */
350 #define to_digit(c) ((c) - '0')
351 #define is_digit(c) ((unsigned)to_digit (c) <= 9)
352 #define to_char(n) ((n) + '0')
353
354 /*
355 * Flags used during conversion.
356 */
357 #define ALT 0x001 /* alternate form */
358 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
359 #define LADJUST 0x004 /* left adjustment */
360 #define LONGDBL 0x008 /* long double */
361 #define LONGINT 0x010 /* long integer */
362 #ifndef _NO_LONGLONG
363 # define QUADINT 0x020 /* quad integer */
364 #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
365 that %lld behaves the same as %ld, not as %d, as expected if:
366 sizeof (long long) = sizeof long > sizeof int */
367 # define QUADINT LONGINT
368 #endif
369 #define SHORTINT 0x040 /* short integer */
370 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
371 #define FPT 0x100 /* Floating point number */
372 #ifdef _WANT_IO_C99_FORMATS
373 # define CHARINT 0x200 /* char as integer */
374 #else /* define as 0, to make SARG and UARG occupy fewer instructions */
375 # define CHARINT 0
376 #endif
377 #ifdef _WANT_IO_C99_FORMATS
378 # define GROUPING 0x400 /* use grouping ("'" flag) */
379 #endif
380
381 int
VFPRINTF(FILE * fp,const char * fmt0,va_list ap)382 VFPRINTF (
383 FILE * fp,
384 const char *fmt0,
385 va_list ap)
386 {
387 register char *fmt; /* format string */
388 register int ch; /* character from fmt */
389 register int n, m; /* handy integers (short term usage) */
390 register char *cp; /* handy char pointer (short term usage) */
391 register int flags; /* flags as above */
392 #ifndef _NO_POS_ARGS
393 char *fmt_anchor; /* current format spec being processed */
394 int N; /* arg number */
395 int arg_index; /* index into args processed directly */
396 int numargs; /* number of varargs read */
397 char *saved_fmt; /* saved fmt pointer */
398 my_va_list my_ap;
399 va_copy(my_ap.ap, ap);
400 union arg_val args[MAX_POS_ARGS];
401 int arg_type[MAX_POS_ARGS];
402 int is_pos_arg; /* is current format positional? */
403 int old_is_pos_arg; /* is current format positional? */
404 #endif
405 int ret; /* return value accumulator */
406 int width; /* width from format (%8d), or 0 */
407 int prec; /* precision from format (%.3d), or -1 */
408 char sign; /* sign prefix (' ', '+', '-', or \0) */
409 #ifdef _WANT_IO_C99_FORMATS
410 /* locale specific numeric grouping */
411 char *thousands_sep = NULL;
412 size_t thsnd_len = 0;
413 const char *grouping = NULL;
414 #endif
415 #ifdef FLOATING_POINT
416 char *decimal_point = localeconv ()->decimal_point;
417 size_t decp_len = strlen (decimal_point);
418 char softsign; /* temporary negative sign for floats */
419 union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
420 # define _fpvalue (_double_.fp)
421 int expt; /* integer value of exponent */
422 int expsize = 0; /* character count for expstr */
423 char expstr[MAXEXPLEN]; /* buffer for exponent string */
424 int lead; /* sig figs before decimal or group sep */
425 #endif /* FLOATING_POINT */
426 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
427 int ndig = 0; /* actual number of digits returned by cvt */
428 #endif
429 #if defined (FLOATING_POINT) && defined (_WANT_IO_C99_FORMATS)
430 int nseps; /* number of group separators with ' */
431 int nrepeats; /* number of repeats of the last group */
432 #endif
433 u_quad_t _uquad; /* integer arguments %[diouxX] */
434 enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
435 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
436 int realsz; /* field size expanded by dprec */
437 int size; /* size of converted field or string */
438 char *xdigs = NULL; /* digits for [xX] conversion */
439 #ifdef _FVWRITE_IN_STREAMIO
440 #define NIOV 8
441 struct __suio uio; /* output information: summary */
442 struct __siov iov[NIOV];/* ... and individual io vectors */
443 register struct __siov *iovp;/* for PRINT macro */
444 #endif
445 char buf[BUF]; /* space for %c, %S, %[diouxX], %[aA] */
446 char ox[2] = {0}; /* space for 0x hex-prefix */
447 #ifdef _MB_CAPABLE
448 wchar_t wc;
449 mbstate_t state; /* mbtowc calls from library must not change state */
450 #endif
451 char *malloc_buf = NULL;/* handy pointer for malloced buffers */
452
453 /*
454 * Choose PADSIZE to trade efficiency vs. size. If larger printf
455 * fields occur frequently, increase PADSIZE and make the initialisers
456 * below longer.
457 */
458 #define PADSIZE 16 /* pad chunk size */
459 static const char blanks[PADSIZE] =
460 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
461 static const char zeroes[PADSIZE] =
462 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
463
464 #ifdef _MB_CAPABLE
465 memset (&state, '\0', sizeof (state));
466 #endif
467 /*
468 * BEWARE, these `goto error' on error, and PAD uses `n'.
469 */
470 #ifdef _FVWRITE_IN_STREAMIO
471 #define PRINT(ptr, len) { \
472 iovp->iov_base = (ptr); \
473 iovp->iov_len = (len); \
474 uio.uio_resid += (len); \
475 iovp++; \
476 if (++uio.uio_iovcnt >= NIOV) { \
477 if (__SPRINT(fp, &uio)) \
478 goto error; \
479 iovp = iov; \
480 } \
481 }
482 #define PAD(howmany, with) { \
483 if ((n = (howmany)) > 0) { \
484 while (n > PADSIZE) { \
485 PRINT (with, PADSIZE); \
486 n -= PADSIZE; \
487 } \
488 PRINT (with, n); \
489 } \
490 }
491 #define PRINTANDPAD(p, ep, len, with) { \
492 int n = (ep) - (p); \
493 if (n > (len)) \
494 n = (len); \
495 if (n > 0) \
496 PRINT((p), n); \
497 PAD((len) - (n > 0 ? n : 0), (with)); \
498 }
499 #define FLUSH() { \
500 if (uio.uio_resid && __SPRINT(fp, &uio)) \
501 goto error; \
502 uio.uio_iovcnt = 0; \
503 iovp = iov; \
504 }
505 #else
506 #define PRINT(ptr, len) { \
507 if (__SPRINT (fp, (ptr), (len)) == EOF) \
508 goto error; \
509 }
510 #define PAD(howmany, with) { \
511 if ((n = (howmany)) > 0) { \
512 while (n > PADSIZE) { \
513 PRINT (with, PADSIZE); \
514 n -= PADSIZE; \
515 } \
516 PRINT (with, n); \
517 } \
518 }
519 #define PRINTANDPAD(p, ep, len, with) { \
520 int n = (ep) - (p); \
521 if (n > (len)) \
522 n = (len); \
523 if (n > 0) \
524 PRINT((p), n); \
525 PAD((len) - (n > 0 ? n : 0), (with)); \
526 }
527 #define FLUSH()
528 #endif
529
530 /* Macros to support positional arguments */
531 #ifndef _NO_POS_ARGS
532 # define GET_ARG(n, ap, type) \
533 (is_pos_arg \
534 ? (n < numargs \
535 ? args[n].val_##type \
536 : get_arg (n, fmt_anchor, &my_ap, &numargs, args, \
537 arg_type, &saved_fmt)->val_##type) \
538 : (arg_index++ < numargs \
539 ? args[n].val_##type \
540 : (numargs < MAX_POS_ARGS \
541 ? args[numargs++].val_##type = va_arg (my_ap.ap, type) \
542 : va_arg (my_ap.ap, type))))
543 #else
544 # define GET_ARG(n, ap, type) (va_arg (ap, type))
545 #endif
546
547 /*
548 * To extend shorts properly, we need both signed and unsigned
549 * argument extraction methods.
550 */
551 #ifndef _NO_LONGLONG
552 #define SARG() \
553 (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
554 flags&LONGINT ? GET_ARG (N, ap, long) : \
555 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
556 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
557 (long)GET_ARG (N, ap, int))
558 #ifdef __MSP430__
559 #define UARG() \
560 (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
561 flags&LONGINT ? GET_ARG (N, ap, u_long) : \
562 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
563 flags&CHARINT ? (u_long)(GET_ARG (N, ap, int) & 0xff) : \
564 (u_long)GET_ARG (N, ap, u_int))
565 #else
566 #define UARG() \
567 (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
568 flags&LONGINT ? GET_ARG (N, ap, u_long) : \
569 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
570 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
571 (u_long)GET_ARG (N, ap, u_int))
572 #endif
573 #else
574 #define SARG() \
575 (flags&LONGINT ? GET_ARG (N, ap, long) : \
576 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
577 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
578 (long)GET_ARG (N, ap, int))
579 #ifdef __MSP430__
580 #define UARG() \
581 (flags&LONGINT ? GET_ARG (N, ap, u_long) : \
582 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
583 flags&CHARINT ? (u_long)(GET_ARG (N, ap, int) & 0xff) : \
584 (u_long)GET_ARG (N, ap, u_int))
585 #else
586 #define UARG() \
587 (flags&LONGINT ? GET_ARG (N, ap, u_long) : \
588 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
589 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
590 (u_long)GET_ARG (N, ap, u_int))
591 #endif
592 #endif
593
594 #ifndef STRING_ONLY
595 /* Initialize std streams if not dealing with sprintf family. */
596 CHECK_INIT (data, fp);
597 _newlib_flockfile_start (fp);
598
599 if (ORIENT(fp, -1) != -1) {
600 _newlib_flockfile_exit (fp);
601 return (EOF);
602 }
603
604 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
605 if (cantwrite (data, fp)) {
606 _newlib_flockfile_exit (fp);
607 return (EOF);
608 }
609
610 #ifdef _UNBUF_STREAM_OPT
611 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
612 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
613 fp->_file >= 0) {
614 _newlib_flockfile_exit (fp);
615 return (__sbprintf (fp, fmt0, ap));
616 }
617 #endif
618 #else /* STRING_ONLY */
619 /* Create initial buffer if we are called by asprintf family. */
620 if (fp->_flags & __SMBF && !fp->_bf._base)
621 {
622 fp->_bf._base = fp->_p = malloc (64);
623 if (!fp->_p)
624 {
625 _REENT_ERRNO(data) = ENOMEM;
626 return EOF;
627 }
628 fp->_bf._size = 64;
629 }
630 #endif /* STRING_ONLY */
631
632 fmt = (char *)fmt0;
633 #ifdef _FVWRITE_IN_STREAMIO
634 uio.uio_iov = iovp = iov;
635 uio.uio_resid = 0;
636 uio.uio_iovcnt = 0;
637 #endif
638 ret = 0;
639 #ifndef _NO_POS_ARGS
640 arg_index = 0;
641 saved_fmt = NULL;
642 arg_type[0] = -1;
643 numargs = 0;
644 is_pos_arg = 0;
645 #endif
646
647 /*
648 * Scan the format for conversions (`%' character).
649 */
650 for (;;) {
651 cp = fmt;
652 #ifdef _MB_CAPABLE
653 while ((n = __MBTOWC (&wc, fmt, MB_CUR_MAX,
654 &state)) != 0) {
655 if (n < 0) {
656 /* Wave invalid chars through. */
657 memset (&state, 0, sizeof state);
658 n = 1;
659 }
660 else if (wc == '%')
661 break;
662 fmt += n;
663 }
664 #else
665 while (*fmt != '\0' && *fmt != '%')
666 fmt += 1;
667 #endif
668 if ((m = fmt - cp) != 0) {
669 PRINT (cp, m);
670 ret += m;
671 }
672 #ifdef _MB_CAPABLE
673 if (n <= 0)
674 goto done;
675 #else
676 if (*fmt == '\0')
677 goto done;
678 #endif
679 #ifndef _NO_POS_ARGS
680 fmt_anchor = fmt;
681 #endif
682 fmt++; /* skip over '%' */
683
684 flags = 0;
685 dprec = 0;
686 width = 0;
687 prec = -1;
688 sign = '\0';
689 #ifdef FLOATING_POINT
690 lead = 0;
691 #ifdef _WANT_IO_C99_FORMATS
692 nseps = nrepeats = 0;
693 #endif
694 #endif
695 #ifndef _NO_POS_ARGS
696 N = arg_index;
697 is_pos_arg = 0;
698 #endif
699
700 rflag: ch = *fmt++;
701 reswitch: switch (ch) {
702 #ifdef _WANT_IO_C99_FORMATS
703 case '\'':
704 thousands_sep = localeconv ()->thousands_sep;
705 thsnd_len = strlen (thousands_sep);
706 grouping = localeconv ()->grouping;
707 if (thsnd_len > 0 && grouping && *grouping)
708 flags |= GROUPING;
709 goto rflag;
710 #endif
711 case ' ':
712 /*
713 * ``If the space and + flags both appear, the space
714 * flag will be ignored.''
715 * -- ANSI X3J11
716 */
717 if (!sign)
718 sign = ' ';
719 goto rflag;
720 case '#':
721 flags |= ALT;
722 goto rflag;
723 case '*':
724 #ifndef _NO_POS_ARGS
725 /* we must check for positional arg used for dynamic width */
726 n = N;
727 old_is_pos_arg = is_pos_arg;
728 is_pos_arg = 0;
729 if (is_digit (*fmt)) {
730 char *old_fmt = fmt;
731
732 n = 0;
733 ch = *fmt++;
734 do {
735 n = 10 * n + to_digit (ch);
736 ch = *fmt++;
737 } while (is_digit (ch));
738
739 if (ch == '$') {
740 if (n <= MAX_POS_ARGS) {
741 n -= 1;
742 is_pos_arg = 1;
743 }
744 else
745 goto error;
746 }
747 else {
748 fmt = old_fmt;
749 goto rflag;
750 }
751 }
752 #endif /* !_NO_POS_ARGS */
753
754 /*
755 * ``A negative field width argument is taken as a
756 * - flag followed by a positive field width.''
757 * -- ANSI X3J11
758 * They don't exclude field widths read from args.
759 */
760 width = GET_ARG (n, ap, int);
761 #ifndef _NO_POS_ARGS
762 is_pos_arg = old_is_pos_arg;
763 #endif
764 if (width >= 0)
765 goto rflag;
766 width = -width;
767 __PICOLIBC_FALLTHROUGH;
768 case '-':
769 flags |= LADJUST;
770 goto rflag;
771 case '+':
772 sign = '+';
773 goto rflag;
774 case '.':
775 if ((ch = *fmt++) == '*') {
776 #ifndef _NO_POS_ARGS
777 /* we must check for positional arg used for dynamic width */
778 n = N;
779 old_is_pos_arg = is_pos_arg;
780 is_pos_arg = 0;
781 if (is_digit (*fmt)) {
782 char *old_fmt = fmt;
783
784 n = 0;
785 ch = *fmt++;
786 do {
787 n = 10 * n + to_digit (ch);
788 ch = *fmt++;
789 } while (is_digit (ch));
790
791 if (ch == '$') {
792 if (n <= MAX_POS_ARGS) {
793 n -= 1;
794 is_pos_arg = 1;
795 }
796 else
797 goto error;
798 }
799 else {
800 fmt = old_fmt;
801 goto rflag;
802 }
803 }
804 #endif /* !_NO_POS_ARGS */
805 prec = GET_ARG (n, ap, int);
806 #ifndef _NO_POS_ARGS
807 is_pos_arg = old_is_pos_arg;
808 #endif
809 if (prec < 0)
810 prec = -1;
811 goto rflag;
812 }
813 n = 0;
814 while (is_digit (ch)) {
815 n = 10 * n + to_digit (ch);
816 ch = *fmt++;
817 }
818 prec = n < 0 ? -1 : n;
819 goto reswitch;
820 case '0':
821 /*
822 * ``Note that 0 is taken as a flag, not as the
823 * beginning of a field width.''
824 * -- ANSI X3J11
825 */
826 flags |= ZEROPAD;
827 goto rflag;
828 case '1': case '2': case '3': case '4':
829 case '5': case '6': case '7': case '8': case '9':
830 n = 0;
831 do {
832 n = 10 * n + to_digit (ch);
833 ch = *fmt++;
834 } while (is_digit (ch));
835 #ifndef _NO_POS_ARGS
836 if (ch == '$') {
837 if (n <= MAX_POS_ARGS) {
838 N = n - 1;
839 is_pos_arg = 1;
840 goto rflag;
841 }
842 else
843 goto error;
844 }
845 #endif /* !_NO_POS_ARGS */
846 width = n;
847 goto reswitch;
848 #ifdef FLOATING_POINT
849 case 'L':
850 flags |= LONGDBL;
851 goto rflag;
852 #endif
853 case 'h':
854 #ifdef _WANT_IO_C99_FORMATS
855 if (*fmt == 'h') {
856 fmt++;
857 flags |= CHARINT;
858 } else
859 #endif
860 flags |= SHORTINT;
861 goto rflag;
862 case 'l':
863 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
864 if (*fmt == 'l') {
865 fmt++;
866 flags |= QUADINT;
867 } else
868 #endif
869 flags |= LONGINT;
870 goto rflag;
871 case 'q': /* extension */
872 flags |= QUADINT;
873 goto rflag;
874 #ifdef _WANT_IO_C99_FORMATS
875 case 'j':
876 if (sizeof (intmax_t) == sizeof (long))
877 flags |= LONGINT;
878 else
879 flags |= QUADINT;
880 goto rflag;
881 case 'z':
882 if (sizeof (size_t) < sizeof (int))
883 /* POSIX states size_t is 16 or more bits, as is short. */
884 flags |= SHORTINT;
885 else if (sizeof (size_t) == sizeof (int))
886 /* no flag needed */;
887 else if (sizeof (size_t) <= sizeof (long))
888 flags |= LONGINT;
889 else
890 /* POSIX states that at least one programming
891 environment must support size_t no wider than
892 long, but that means other environments can
893 have size_t as wide as long long. */
894 flags |= QUADINT;
895 goto rflag;
896 case 't':
897 if (sizeof (ptrdiff_t) < sizeof (int))
898 /* POSIX states ptrdiff_t is 16 or more bits, as
899 is short. */
900 flags |= SHORTINT;
901 else if (sizeof (ptrdiff_t) == sizeof (int))
902 /* no flag needed */;
903 else if (sizeof (ptrdiff_t) <= sizeof (long))
904 flags |= LONGINT;
905 else
906 /* POSIX states that at least one programming
907 environment must support ptrdiff_t no wider than
908 long, but that means other environments can
909 have ptrdiff_t as wide as long long. */
910 flags |= QUADINT;
911 goto rflag;
912 case 'C':
913 #endif /* _WANT_IO_C99_FORMATS */
914 case 'c':
915 cp = buf;
916 #ifdef _MB_CAPABLE
917 if (ch == 'C' || (flags & LONGINT)) {
918 mbstate_t ps;
919
920 memset ((void *)&ps, '\0', sizeof (mbstate_t));
921 if ((size = (int)wcrtomb (cp,
922 (wchar_t)GET_ARG (N, ap, wint_t),
923 &ps)) == -1) {
924 fp->_flags |= __SERR;
925 goto error;
926 }
927 }
928 else
929 #endif /* _MB_CAPABLE */
930 {
931 *cp = GET_ARG (N, ap, int);
932 size = 1;
933 }
934 sign = '\0';
935 break;
936 case 'D': /* extension */
937 flags |= LONGINT;
938 __PICOLIBC_FALLTHROUGH;
939 case 'd':
940 case 'i':
941 _uquad = SARG ();
942 #ifndef _NO_LONGLONG
943 if ((quad_t)_uquad < 0)
944 #else
945 if ((long) _uquad < 0)
946 #endif
947 {
948
949 _uquad = -_uquad;
950 sign = '-';
951 }
952 base = DEC;
953 goto number;
954 #ifdef FLOATING_POINT
955 # ifdef _WANT_IO_C99_FORMATS
956 case 'a':
957 case 'A':
958 case 'F':
959 # endif
960 case 'e':
961 case 'E':
962 case 'f':
963 case 'g':
964 case 'G':
965 # ifdef _NO_LONGDBL
966 if (flags & LONGDBL) {
967 _fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE);
968 } else {
969 _fpvalue = GET_ARG (N, ap, double);
970 }
971
972 /* do this before tricky precision changes
973
974 If the output is infinite or NaN, leading
975 zeros are not permitted. Otherwise, scanf
976 could not read what printf wrote.
977 */
978 if (isinf (_fpvalue)) {
979 if (_fpvalue < 0)
980 sign = '-';
981 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
982 cp = "INF";
983 else
984 cp = "inf";
985 size = 3;
986 flags &= ~ZEROPAD;
987 break;
988 }
989 if (isnan (_fpvalue)) {
990 if (signbit (_fpvalue))
991 sign = '-';
992 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
993 cp = "NAN";
994 else
995 cp = "nan";
996 size = 3;
997 flags &= ~ZEROPAD;
998 break;
999 }
1000
1001 # else /* !_NO_LONGDBL */
1002
1003 if (flags & LONGDBL) {
1004 _fpvalue = GET_ARG (N, ap, _LONG_DOUBLE);
1005 } else {
1006 _fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double);
1007 }
1008
1009 /* do this before tricky precision changes */
1010 expt = _ldcheck (&_fpvalue);
1011 if (expt == 2) {
1012 if (_fpvalue < 0)
1013 sign = '-';
1014 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1015 cp = "INF";
1016 else
1017 cp = "inf";
1018 size = 3;
1019 flags &= ~ZEROPAD;
1020 break;
1021 }
1022 if (expt == 1) {
1023 if (signbit (_fpvalue))
1024 sign = '-';
1025 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1026 cp = "NAN";
1027 else
1028 cp = "nan";
1029 size = 3;
1030 flags &= ~ZEROPAD;
1031 break;
1032 }
1033 # endif /* !_NO_LONGDBL */
1034
1035 # ifdef _WANT_IO_C99_FORMATS
1036 if (ch == 'a' || ch == 'A') {
1037 ox[0] = '0';
1038 ox[1] = ch == 'a' ? 'x' : 'X';
1039 flags |= HEXPREFIX;
1040 if (prec >= BUF)
1041 {
1042 if ((malloc_buf =
1043 (char *)malloc (prec + 1))
1044 == NULL)
1045 {
1046 fp->_flags |= __SERR;
1047 goto error;
1048 }
1049 cp = malloc_buf;
1050 }
1051 else
1052 cp = buf;
1053 } else
1054 # endif /* _WANT_IO_C99_FORMATS */
1055 if (prec == -1) {
1056 prec = DEFPREC;
1057 } else if ((ch == 'g' || ch == 'G') && prec == 0) {
1058 prec = 1;
1059 }
1060
1061 flags |= FPT;
1062
1063 cp = cvt (_fpvalue, prec, flags, &softsign,
1064 &expt, ch, &ndig, cp);
1065 if (!cp)
1066 goto error;
1067
1068 if (ch == 'g' || ch == 'G') {
1069 if (expt <= -4 || expt > prec)
1070 ch -= 2; /* 'e' or 'E' */
1071 else
1072 ch = 'g';
1073 }
1074 # ifdef _WANT_IO_C99_FORMATS
1075 else if (ch == 'F')
1076 ch = 'f';
1077 # endif
1078 if (ch <= 'e') { /* 'a', 'A', 'e', or 'E' fmt */
1079 --expt;
1080 expsize = exponent (expstr, expt, ch);
1081 size = expsize + ndig;
1082 if (ndig > 1 || flags & ALT)
1083 size += decp_len;
1084 # ifdef _WANT_IO_C99_FORMATS
1085 flags &= ~GROUPING;
1086 # endif
1087 } else {
1088 if (ch == 'f') { /* f fmt */
1089 if (expt > 0) {
1090 size = expt;
1091 if (prec || flags & ALT)
1092 size += prec + decp_len;
1093 } else /* "0.X" */
1094 size = (prec || flags & ALT)
1095 ? prec + 1 + decp_len
1096 : 1;
1097 } else if (expt >= ndig) { /* fixed g fmt */
1098 size = expt;
1099 if (flags & ALT)
1100 size += decp_len;
1101 } else {
1102 size = ndig + decp_len;
1103 if (expt <= 0)
1104 size += 1 - expt;
1105 }
1106 # ifdef _WANT_IO_C99_FORMATS
1107 if ((flags & GROUPING) && expt > 0) {
1108 /* space for thousands' grouping */
1109 nseps = nrepeats = 0;
1110 lead = expt;
1111 while (*grouping != CHAR_MAX) {
1112 if (lead <= *grouping)
1113 break;
1114 lead -= *grouping;
1115 if (grouping[1]) {
1116 nseps++;
1117 grouping++;
1118 } else
1119 nrepeats++;
1120 }
1121 size += (nseps + nrepeats) * thsnd_len;
1122 } else
1123 # endif
1124 lead = expt;
1125 }
1126
1127 if (softsign)
1128 sign = '-';
1129 break;
1130 #endif /* FLOATING_POINT */
1131 #ifdef _GLIBC_EXTENSION
1132 case 'm': /* extension */
1133 {
1134 int dummy;
1135 cp = strerror ( _REENT_ERRNO(data), 1, &dummy);
1136 }
1137 flags &= ~LONGINT;
1138 goto string;
1139 #endif
1140 case 'n':
1141 #ifndef _NO_LONGLONG
1142 if (flags & QUADINT)
1143 *GET_ARG (N, ap, quad_ptr_t) = ret;
1144 else
1145 #endif
1146 if (flags & LONGINT)
1147 *GET_ARG (N, ap, long_ptr_t) = ret;
1148 else if (flags & SHORTINT)
1149 *GET_ARG (N, ap, short_ptr_t) = ret;
1150 #ifdef _WANT_IO_C99_FORMATS
1151 else if (flags & CHARINT)
1152 *GET_ARG (N, ap, char_ptr_t) = ret;
1153 #endif
1154 else
1155 *GET_ARG (N, ap, int_ptr_t) = ret;
1156 continue; /* no output */
1157 case 'O': /* extension */
1158 flags |= LONGINT;
1159 __PICOLIBC_FALLTHROUGH;
1160 case 'o':
1161 _uquad = UARG ();
1162 base = OCT;
1163 #ifdef _WANT_IO_C99_FORMATS
1164 flags &= ~GROUPING;
1165 #endif
1166 goto nosign;
1167 case 'p':
1168 /*
1169 * ``The argument shall be a pointer to void. The
1170 * value of the pointer is converted to a sequence
1171 * of printable characters, in an implementation-
1172 * defined manner.''
1173 * -- ANSI X3J11
1174 */
1175 /* NOSTRICT */
1176 _uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t);
1177 base = HEX;
1178 xdigs = "0123456789abcdef";
1179 flags |= HEXPREFIX;
1180 ox[0] = '0';
1181 ox[1] = ch = 'x';
1182 goto nosign;
1183 case 's':
1184 #ifdef _WANT_IO_C99_FORMATS
1185 case 'S':
1186 #endif
1187 cp = GET_ARG (N, ap, char_ptr_t);
1188 #ifdef _GLIBC_EXTENSION
1189 string:
1190 #endif
1191 sign = '\0';
1192 /* Behavior is undefined if the user passed a
1193 NULL string when precision is not 0.
1194 However, we might as well mirror glibc behavior. */
1195 if (cp == NULL) {
1196 cp = "(null)";
1197 size = ((unsigned) prec > 6U) ? 6 : prec;
1198 }
1199 else
1200 #ifdef _MB_CAPABLE
1201 if (ch == 'S' || (flags & LONGINT)) {
1202 mbstate_t ps;
1203 const wchar_t *wcp;
1204
1205 wcp = (const wchar_t *)cp;
1206 size = m = 0;
1207 memset ((void *)&ps, '\0', sizeof (mbstate_t));
1208
1209 /* Count number of bytes needed for multibyte
1210 string that will be produced from widechar
1211 string. */
1212 if (prec >= 0) {
1213 while (1) {
1214 if (wcp[m] == L'\0')
1215 break;
1216 if ((n = (int)wcrtomb (
1217 buf, wcp[m], &ps)) == -1) {
1218 fp->_flags |= __SERR;
1219 goto error;
1220 }
1221 if (n + size > prec)
1222 break;
1223 m += 1;
1224 size += n;
1225 if (size == prec)
1226 break;
1227 }
1228 }
1229 else {
1230 if ((size = (int)wcsrtombs (
1231 NULL, &wcp, 0, &ps)) == -1) {
1232 fp->_flags |= __SERR;
1233 goto error;
1234 }
1235 wcp = (const wchar_t *)cp;
1236 }
1237
1238 if (size == 0)
1239 break;
1240
1241 if (size >= BUF) {
1242 if ((malloc_buf =
1243 (char *)malloc (size + 1))
1244 == NULL) {
1245 fp->_flags |= __SERR;
1246 goto error;
1247 }
1248 cp = malloc_buf;
1249 } else
1250 cp = buf;
1251
1252 /* Convert widechar string to multibyte string. */
1253 memset ((void *)&ps, '\0', sizeof (mbstate_t));
1254 if ((int)wcsrtombs (cp, &wcp, size, &ps)
1255 != size) {
1256 fp->_flags |= __SERR;
1257 goto error;
1258 }
1259 cp[size] = '\0';
1260 }
1261 else
1262 #endif /* _MB_CAPABLE */
1263 if (prec >= 0) {
1264 /*
1265 * can't use strlen; can only look for the
1266 * NUL in the first `prec' characters, and
1267 * strlen () will go further.
1268 */
1269 char *p = memchr (cp, 0, prec);
1270
1271 if (p != NULL)
1272 size = p - cp;
1273 else
1274 size = prec;
1275 } else
1276 size = strlen (cp);
1277
1278 break;
1279 case 'U': /* extension */
1280 flags |= LONGINT;
1281 __PICOLIBC_FALLTHROUGH;
1282 case 'u':
1283 _uquad = UARG ();
1284 base = DEC;
1285 goto nosign;
1286 case 'X':
1287 xdigs = "0123456789ABCDEF";
1288 goto hex;
1289 case 'x':
1290 xdigs = "0123456789abcdef";
1291 hex: _uquad = UARG ();
1292 base = HEX;
1293 /* leading 0x/X only if non-zero */
1294 if (flags & ALT && _uquad != 0) {
1295 ox[0] = '0';
1296 ox[1] = ch;
1297 flags |= HEXPREFIX;
1298 }
1299
1300 #ifdef _WANT_IO_C99_FORMATS
1301 flags &= ~GROUPING;
1302 #endif
1303 /* unsigned conversions */
1304 nosign: sign = '\0';
1305 /*
1306 * ``... diouXx conversions ... if a precision is
1307 * specified, the 0 flag will be ignored.''
1308 * -- ANSI X3J11
1309 */
1310 number: if ((dprec = prec) >= 0)
1311 flags &= ~ZEROPAD;
1312
1313 /*
1314 * ``The result of converting a zero value with an
1315 * explicit precision of zero is no characters.''
1316 * -- ANSI X3J11
1317 */
1318 cp = buf + BUF;
1319 if (_uquad != 0 || prec != 0) {
1320 /*
1321 * Unsigned mod is hard, and unsigned mod
1322 * by a constant is easier than that by
1323 * a variable; hence this switch.
1324 */
1325 switch (base) {
1326 case OCT:
1327 do {
1328 *--cp = to_char (_uquad & 7);
1329 _uquad >>= 3;
1330 } while (_uquad);
1331 /* handle octal leading 0 */
1332 if (flags & ALT && *cp != '0')
1333 *--cp = '0';
1334 break;
1335
1336 case DEC:
1337 /* many numbers are 1 digit */
1338 if (_uquad < 10) {
1339 *--cp = to_char(_uquad);
1340 break;
1341 }
1342 #ifdef _WANT_IO_C99_FORMATS
1343 ndig = 0;
1344 #endif
1345 do {
1346 *--cp = to_char (_uquad % 10);
1347 #ifdef _WANT_IO_C99_FORMATS
1348 ndig++;
1349 /* If (*grouping == CHAR_MAX) then no
1350 more grouping */
1351 if ((flags & GROUPING)
1352 && ndig == *grouping
1353 && *grouping != CHAR_MAX
1354 && _uquad > 9) {
1355 cp -= thsnd_len;
1356 strncpy (cp, thousands_sep,
1357 thsnd_len);
1358 ndig = 0;
1359 /* If (grouping[1] == '\0') then we
1360 have to use *grouping character
1361 (last grouping rule) for all
1362 next cases. */
1363 if (grouping[1] != '\0')
1364 grouping++;
1365 }
1366 #endif
1367 _uquad /= 10;
1368 } while (_uquad != 0);
1369 break;
1370
1371 case HEX:
1372 do {
1373 *--cp = xdigs[_uquad & 15];
1374 _uquad >>= 4;
1375 } while (_uquad);
1376 break;
1377
1378 default:
1379 cp = "bug in vfprintf: bad base";
1380 size = strlen (cp);
1381 goto skipsize;
1382 }
1383 }
1384 /*
1385 * ...result is to be converted to an 'alternate form'.
1386 * For o conversion, it increases the precision to force
1387 * the first digit of the result to be a zero."
1388 * -- ANSI X3J11
1389 *
1390 * To demonstrate this case, compile and run:
1391 * printf ("%#.0o",0);
1392 */
1393 else if (base == OCT && (flags & ALT))
1394 *--cp = '0';
1395
1396 size = buf + BUF - cp;
1397 skipsize:
1398 break;
1399 default: /* "%?" prints ?, unless ? is NUL */
1400 if (ch == '\0')
1401 goto done;
1402 /* pretend it was %c with argument ch */
1403 cp = buf;
1404 *cp = ch;
1405 size = 1;
1406 sign = '\0';
1407 break;
1408 }
1409
1410 /*
1411 * All reasonable formats wind up here. At this point, `cp'
1412 * points to a string which (if not flags&LADJUST) should be
1413 * padded out to `width' places. If flags&ZEROPAD, it should
1414 * first be prefixed by any sign or other prefix; otherwise,
1415 * it should be blank padded before the prefix is emitted.
1416 * After any left-hand padding and prefixing, emit zeroes
1417 * required by a decimal [diouxX] precision, then print the
1418 * string proper, then emit zeroes required by any leftover
1419 * floating precision; finally, if LADJUST, pad with blanks.
1420 * If flags&FPT, ch must be in [aAeEfg].
1421 *
1422 * Compute actual size, so we know how much to pad.
1423 * size excludes decimal prec; realsz includes it.
1424 */
1425 realsz = dprec > size ? dprec : size;
1426 if (sign)
1427 realsz++;
1428 if (flags & HEXPREFIX)
1429 realsz+= 2;
1430
1431 /* right-adjusting blank padding */
1432 if ((flags & (LADJUST|ZEROPAD)) == 0)
1433 PAD (width - realsz, blanks);
1434
1435 /* prefix */
1436 if (sign)
1437 PRINT (&sign, 1);
1438 if (flags & HEXPREFIX)
1439 PRINT (ox, 2);
1440
1441 /* right-adjusting zero padding */
1442 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1443 PAD (width - realsz, zeroes);
1444
1445 /* leading zeroes from decimal precision */
1446 PAD (dprec - size, zeroes);
1447
1448 /* the string or number proper */
1449 #ifdef FLOATING_POINT
1450 if ((flags & FPT) == 0) {
1451 PRINT (cp, size);
1452 } else { /* glue together f_p fragments */
1453 if (ch >= 'f') { /* 'f' or 'g' */
1454 if (_fpvalue == 0) {
1455 /* kludge for __dtoa irregularity */
1456 PRINT ("0", 1);
1457 if (expt < ndig || flags & ALT) {
1458 PRINT (decimal_point, decp_len);
1459 PAD (ndig - 1, zeroes);
1460 }
1461 } else if (expt <= 0) {
1462 PRINT ("0", 1);
1463 if (expt || ndig || flags & ALT) {
1464 PRINT (decimal_point, decp_len);
1465 PAD (-expt, zeroes);
1466 PRINT (cp, ndig);
1467 }
1468 } else {
1469 char *convbuf = cp;
1470 PRINTANDPAD(cp, convbuf + ndig,
1471 lead, zeroes);
1472 cp += lead;
1473 #ifdef _WANT_IO_C99_FORMATS
1474 if (flags & GROUPING) {
1475 while (nseps > 0 || nrepeats > 0) {
1476 if (nrepeats > 0)
1477 nrepeats--;
1478 else {
1479 grouping--;
1480 nseps--;
1481 }
1482 PRINT(thousands_sep, thsnd_len);
1483 PRINTANDPAD (cp, convbuf + ndig,
1484 *grouping, zeroes);
1485 cp += *grouping;
1486 }
1487 if (cp > convbuf + ndig)
1488 cp = convbuf + ndig;
1489 }
1490 #endif
1491 if (expt < ndig || flags & ALT)
1492 PRINT (decimal_point, decp_len);
1493 PRINTANDPAD (cp, convbuf + ndig,
1494 ndig - expt, zeroes);
1495 }
1496 } else { /* 'a', 'A', 'e', or 'E' */
1497 if (ndig > 1 || flags & ALT) {
1498 PRINT (cp, 1);
1499 cp++;
1500 PRINT (decimal_point, decp_len);
1501 if (_fpvalue) {
1502 PRINT (cp, ndig - 1);
1503 } else /* 0.[0..] */
1504 /* __dtoa irregularity */
1505 PAD (ndig - 1, zeroes);
1506 } else /* XeYYY */
1507 PRINT (cp, 1);
1508 PRINT (expstr, expsize);
1509 }
1510 }
1511 #else /* !FLOATING_POINT */
1512 PRINT (cp, size);
1513 #endif
1514 /* left-adjusting padding (always blank) */
1515 if (flags & LADJUST)
1516 PAD (width - realsz, blanks);
1517
1518 /* finally, adjust ret */
1519 ret += width > realsz ? width : realsz;
1520
1521 FLUSH (); /* copy out the I/O vectors */
1522
1523 if (malloc_buf != NULL) {
1524 free (malloc_buf);
1525 malloc_buf = NULL;
1526 }
1527 }
1528 done:
1529 FLUSH ();
1530 error:
1531 if (malloc_buf != NULL)
1532 free (malloc_buf);
1533 #ifndef STRING_ONLY
1534 _newlib_flockfile_end (fp);
1535 #endif
1536 return (__sferror (fp) ? EOF : ret);
1537 /* NOTREACHED */
1538 }
1539
1540 #ifdef FLOATING_POINT
1541
1542 /* Using reentrant DATA, convert finite VALUE into a string of digits
1543 with no decimal point, using NDIGITS precision and FLAGS as guides
1544 to whether trailing zeros must be included. Set *SIGN to nonzero
1545 if VALUE was negative. Set *DECPT to the exponent plus one. Set
1546 *LENGTH to the length of the returned string. CH must be one of
1547 [aAeEfFgG]; if it is [aA], then the return string lives in BUF,
1548 otherwise the return value shares the mprec reentrant storage. */
1549 static char *
cvt(_PRINTF_FLOAT_TYPE value,int ndigits,int flags,char * sign,int * decpt,int ch,int * length,char * buf)1550 cvt(_PRINTF_FLOAT_TYPE value, int ndigits, int flags,
1551 char *sign, int *decpt, int ch, int *length, char *buf)
1552 {
1553 int mode, dsgn;
1554 char *digits, *bp, *rve;
1555 # ifdef _NO_LONGDBL
1556 union double_union tmp;
1557
1558 tmp.d = value;
1559 if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1560 value = -value;
1561 *sign = '-';
1562 } else
1563 *sign = '\000';
1564 # else /* !_NO_LONGDBL */
1565 union
1566 {
1567 struct ldieee ieee;
1568 _LONG_DOUBLE val;
1569 } ld;
1570
1571 ld.val = value;
1572 if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
1573 value = -value;
1574 *sign = '-';
1575 } else
1576 *sign = '\000';
1577 # endif /* !_NO_LONGDBL */
1578
1579 # ifdef _WANT_IO_C99_FORMATS
1580 if (ch == 'a' || ch == 'A') {
1581 /* This code assumes FLT_RADIX is a power of 2. The initial
1582 division ensures the digit before the decimal will be less
1583 than FLT_RADIX (unless it is rounded later). There is no
1584 loss of precision in these calculations. */
1585 value = FREXP (value, decpt) / 8;
1586 if (!value)
1587 *decpt = 1;
1588 digits = ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF";
1589 bp = buf;
1590 do {
1591 value *= 16;
1592 mode = (int) value;
1593 value -= mode;
1594 *bp++ = digits[mode];
1595 } while (ndigits-- && value);
1596 if (value > (_PRINTF_FLOAT_TYPE) 0.5 || (value == (_PRINTF_FLOAT_TYPE) 0.5 && mode & 1)) {
1597 /* round to even */
1598 rve = bp;
1599 while (*--rve == digits[0xf]) {
1600 *rve = '0';
1601 }
1602 *rve = *rve == '9' ? digits[0xa] : *rve + 1;
1603 } else {
1604 while (ndigits-- >= 0) {
1605 *bp++ = '0';
1606 }
1607 }
1608 *length = bp - buf;
1609 return buf;
1610 }
1611 # endif /* _WANT_IO_C99_FORMATS */
1612 if (ch == 'f' || ch == 'F') {
1613 mode = 3; /* ndigits after the decimal point */
1614 } else {
1615 /* To obtain ndigits after the decimal point for the 'e'
1616 * and 'E' formats, round to ndigits + 1 significant
1617 * figures.
1618 */
1619 if (ch == 'e' || ch == 'E') {
1620 ndigits++;
1621 }
1622 mode = 2; /* ndigits significant digits */
1623 }
1624
1625 digits = _DTOA (value, mode, ndigits, decpt, &dsgn, &rve);
1626 if (!digits)
1627 return NULL;
1628
1629 if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */
1630 bp = digits + ndigits;
1631 if (ch == 'f' || ch == 'F') {
1632 if (*digits == '0' && value)
1633 *decpt = -ndigits + 1;
1634 bp += *decpt;
1635 }
1636 if (value == 0) /* kludge for __dtoa irregularity */
1637 rve = bp;
1638 while (rve < bp)
1639 *rve++ = '0';
1640 }
1641 *length = rve - digits;
1642 return (digits);
1643 }
1644
1645 static int
exponent(char * p0,int exp,int fmtch)1646 exponent(char *p0, int exp, int fmtch)
1647 {
1648 register char *p, *t;
1649 char expbuf[MAXEXPLEN];
1650 # ifdef _WANT_IO_C99_FORMATS
1651 int isa = fmtch == 'a' || fmtch == 'A';
1652 # else
1653 # define isa 0
1654 # endif
1655
1656 p = p0;
1657 *p++ = isa ? 'p' - 'a' + fmtch : fmtch;
1658 if (exp < 0) {
1659 exp = -exp;
1660 *p++ = '-';
1661 }
1662 else
1663 *p++ = '+';
1664 t = expbuf + MAXEXPLEN;
1665 if (exp > 9) {
1666 do {
1667 *--t = to_char (exp % 10);
1668 } while ((exp /= 10) > 9);
1669 *--t = to_char (exp);
1670 for (; t < expbuf + MAXEXPLEN; *p++ = *t++);
1671 }
1672 else {
1673 if (!isa)
1674 *p++ = '0';
1675 *p++ = to_char (exp);
1676 }
1677 return (p - p0);
1678 }
1679 #endif /* FLOATING_POINT */
1680
1681
1682 #ifndef _NO_POS_ARGS
1683
1684 /* Positional argument support.
1685 Written by Jeff Johnston
1686
1687 Copyright (c) 2002 Red Hat Incorporated.
1688 All rights reserved.
1689
1690 Redistribution and use in source and binary forms, with or without
1691 modification, are permitted provided that the following conditions are met:
1692
1693 Redistributions of source code must retain the above copyright
1694 notice, this list of conditions and the following disclaimer.
1695
1696 Redistributions in binary form must reproduce the above copyright
1697 notice, this list of conditions and the following disclaimer in the
1698 documentation and/or other materials provided with the distribution.
1699
1700 The name of Red Hat Incorporated may not be used to endorse
1701 or promote products derived from this software without specific
1702 prior written permission.
1703
1704 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1705 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1706 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1707 DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1708 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1709 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1710 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1711 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1712 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1713 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1714
1715 /* The below constant state tables are shared between all versions of
1716 vfprintf and vfwprintf. They must only be defined once, which we do in
1717 the STRING_ONLY/INTEGER_ONLY versions here. */
1718 #if defined (STRING_ONLY) && defined(INTEGER_ONLY)
1719
1720 const __CH_CLASS __chclass[256] = {
1721 /* 00-07 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1722 /* 08-0f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1723 /* 10-17 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1724 /* 18-1f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1725 /* 20-27 */ FLAG, OTHER, OTHER, FLAG, DOLLAR, OTHER, OTHER, FLAG,
1726 /* 28-2f */ OTHER, OTHER, STAR, FLAG, OTHER, FLAG, DOT, OTHER,
1727 /* 30-37 */ ZERO, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
1728 /* 38-3f */ DIGIT, DIGIT, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1729 /* 40-47 */ OTHER, SPEC, OTHER, SPEC, SPEC, SPEC, SPEC, SPEC,
1730 /* 48-4f */ OTHER, OTHER, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC,
1731 /* 50-57 */ OTHER, OTHER, OTHER, SPEC, OTHER, SPEC, OTHER, OTHER,
1732 /* 58-5f */ SPEC, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1733 /* 60-67 */ OTHER, SPEC, OTHER, SPEC, SPEC, SPEC, SPEC, SPEC,
1734 /* 68-6f */ MODFR, SPEC, MODFR, OTHER, MODFR, OTHER, SPEC, SPEC,
1735 /* 70-77 */ SPEC, MODFR, OTHER, SPEC, MODFR, SPEC, OTHER, OTHER,
1736 /* 78-7f */ SPEC, OTHER, MODFR, OTHER, OTHER, OTHER, OTHER, OTHER,
1737 /* 80-87 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1738 /* 88-8f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1739 /* 90-97 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1740 /* 98-9f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1741 /* a0-a7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1742 /* a8-af */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1743 /* b0-b7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1744 /* b8-bf */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1745 /* c0-c7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1746 /* c8-cf */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1747 /* d0-d7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1748 /* d8-df */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1749 /* e0-e7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1750 /* e8-ef */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1751 /* f0-f7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1752 /* f8-ff */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1753 };
1754
1755 const __STATE __state_table[MAX_STATE][MAX_CH_CLASS] = {
1756 /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
1757 /* START */ { SFLAG, WDIG, DONE, SMOD, DONE, SDOT, VARW, SFLAG, DONE },
1758 /* SFLAG */ { SFLAG, WDIG, DONE, SMOD, DONE, SDOT, VARW, SFLAG, DONE },
1759 /* WDIG */ { DONE, DONE, WIDTH, SMOD, DONE, SDOT, DONE, DONE, DONE },
1760 /* WIDTH */ { DONE, DONE, DONE, SMOD, DONE, SDOT, DONE, DONE, DONE },
1761 /* SMOD */ { DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE },
1762 /* SDOT */ { SDOT, PREC, DONE, SMOD, DONE, DONE, VARP, DONE, DONE },
1763 /* VARW */ { DONE, VWDIG, DONE, SMOD, DONE, SDOT, DONE, DONE, DONE },
1764 /* VARP */ { DONE, VPDIG, DONE, SMOD, DONE, DONE, DONE, DONE, DONE },
1765 /* PREC */ { DONE, DONE, DONE, SMOD, DONE, DONE, DONE, DONE, DONE },
1766 /* VWDIG */ { DONE, DONE, WIDTH, DONE, DONE, DONE, DONE, DONE, DONE },
1767 /* VPDIG */ { DONE, DONE, PREC, DONE, DONE, DONE, DONE, DONE, DONE },
1768 };
1769
1770 const __ACTION __action_table[MAX_STATE][MAX_CH_CLASS] = {
1771 /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
1772 /* START */ { NOOP, NUMBER, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1773 /* SFLAG */ { NOOP, NUMBER, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1774 /* WDIG */ { NOOP, NOOP, GETPOS, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1775 /* WIDTH */ { NOOP, NOOP, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1776 /* SMOD */ { NOOP, NOOP, NOOP, NOOP, GETARG, NOOP, NOOP, NOOP, NOOP },
1777 /* SDOT */ { NOOP, SKIPNUM, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1778 /* VARW */ { NOOP, NUMBER, NOOP, GETPW, GETPWB, GETPW, NOOP, NOOP, NOOP },
1779 /* VARP */ { NOOP, NUMBER, NOOP, GETPW, GETPWB, NOOP, NOOP, NOOP, NOOP },
1780 /* PREC */ { NOOP, NOOP, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1781 /* VWDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP },
1782 /* VPDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP },
1783 };
1784
1785 #endif /* STRING_ONLY && INTEGER_ONLY */
1786
1787 /* function to get positional parameter N where n = N - 1 */
1788 static union arg_val *
get_arg(int n,char * fmt,my_va_list * ap,int * numargs_p,union arg_val * args,int * arg_type,char ** last_fmt)1789 get_arg (
1790 int n,
1791 char *fmt,
1792 my_va_list *ap,
1793 int *numargs_p,
1794 union arg_val *args,
1795 int *arg_type,
1796 char **last_fmt)
1797 {
1798 int ch;
1799 int number, flags;
1800 int spec_type;
1801 int numargs = *numargs_p;
1802 __CH_CLASS chtype;
1803 __STATE state, next_state;
1804 __ACTION action;
1805 int pos, last_arg;
1806 int max_pos_arg = n;
1807 /* Only need types that can be reached via vararg promotions. */
1808 enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
1809 # ifdef _MB_CAPABLE
1810 wchar_t wc;
1811 mbstate_t wc_state;
1812 int nbytes;
1813 # endif
1814
1815 /* if this isn't the first call, pick up where we left off last time */
1816 if (*last_fmt != NULL)
1817 fmt = *last_fmt;
1818
1819 # ifdef _MB_CAPABLE
1820 memset (&wc_state, '\0', sizeof (wc_state));
1821 # endif
1822
1823 /* we need to process either to end of fmt string or until we have actually
1824 read the desired parameter from the vararg list. */
1825 while (*fmt && n >= numargs)
1826 {
1827 # ifdef _MB_CAPABLE
1828 while ((nbytes = __MBTOWC (data, &wc, fmt, MB_CUR_MAX, &wc_state)) > 0)
1829 {
1830 fmt += nbytes;
1831 if (wc == '%')
1832 break;
1833 }
1834
1835 if (nbytes <= 0)
1836 break;
1837 # else
1838 while (*fmt != '\0' && *fmt != '%')
1839 fmt += 1;
1840
1841 if (*fmt == '\0')
1842 break;
1843
1844 fmt++;
1845 # endif /* ! _MB_CAPABLE */
1846 state = START;
1847 flags = 0;
1848 pos = -1;
1849 number = 0;
1850 spec_type = INT;
1851
1852 /* Use state/action table to process format specifiers. We ignore invalid
1853 formats and we are only interested in information that tells us how to
1854 read the vararg list. */
1855 while (state != DONE)
1856 {
1857 ch = *fmt++;
1858 chtype = __chclass[ch];
1859 next_state = __state_table[state][chtype];
1860 action = __action_table[state][chtype];
1861 state = next_state;
1862
1863 switch (action)
1864 {
1865 case GETMOD: /* we have format modifier */
1866 switch (ch)
1867 {
1868 case 'h':
1869 /* No flag needed, since short and char promote to int. */
1870 break;
1871 case 'L':
1872 flags |= LONGDBL;
1873 break;
1874 case 'q':
1875 flags |= QUADINT;
1876 break;
1877 # ifdef _WANT_IO_C99_FORMATS
1878 case 'j':
1879 if (sizeof (intmax_t) == sizeof (long))
1880 flags |= LONGINT;
1881 else
1882 flags |= QUADINT;
1883 break;
1884 case 'z':
1885 if (sizeof (size_t) <= sizeof (int))
1886 /* no flag needed */;
1887 else if (sizeof (size_t) <= sizeof (long))
1888 flags |= LONGINT;
1889 else
1890 /* POSIX states that at least one programming
1891 environment must support size_t no wider than
1892 long, but that means other environments can
1893 have size_t as wide as long long. */
1894 flags |= QUADINT;
1895 break;
1896 case 't':
1897 if (sizeof (ptrdiff_t) <= sizeof (int))
1898 /* no flag needed */;
1899 else if (sizeof (ptrdiff_t) <= sizeof (long))
1900 flags |= LONGINT;
1901 else
1902 /* POSIX states that at least one programming
1903 environment must support ptrdiff_t no wider than
1904 long, but that means other environments can
1905 have ptrdiff_t as wide as long long. */
1906 flags |= QUADINT;
1907 break;
1908 # endif /* _WANT_IO_C99_FORMATS */
1909 case 'l':
1910 default:
1911 # if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
1912 if (*fmt == 'l')
1913 {
1914 flags |= QUADINT;
1915 ++fmt;
1916 }
1917 else
1918 # endif
1919 flags |= LONGINT;
1920 break;
1921 }
1922 break;
1923 case GETARG: /* we have format specifier */
1924 {
1925 numargs &= (MAX_POS_ARGS - 1);
1926 /* process the specifier and translate it to a type to fetch from varargs */
1927 switch (ch)
1928 {
1929 case 'd':
1930 case 'i':
1931 case 'o':
1932 case 'x':
1933 case 'X':
1934 case 'u':
1935 if (flags & LONGINT)
1936 spec_type = LONG_INT;
1937 # ifndef _NO_LONGLONG
1938 else if (flags & QUADINT)
1939 spec_type = QUAD_INT;
1940 # endif
1941 else
1942 spec_type = INT;
1943 break;
1944 case 'D':
1945 case 'U':
1946 case 'O':
1947 spec_type = LONG_INT;
1948 break;
1949 # ifdef _WANT_IO_C99_FORMATS
1950 case 'a':
1951 case 'A':
1952 case 'F':
1953 # endif
1954 case 'f':
1955 case 'g':
1956 case 'G':
1957 case 'E':
1958 case 'e':
1959 # ifndef _NO_LONGDBL
1960 if (flags & LONGDBL)
1961 spec_type = LONG_DOUBLE;
1962 else
1963 # endif
1964 spec_type = DOUBLE;
1965 break;
1966 case 's':
1967 # ifdef _WANT_IO_C99_FORMATS
1968 case 'S':
1969 # endif
1970 case 'p':
1971 case 'n':
1972 spec_type = CHAR_PTR;
1973 break;
1974 case 'c':
1975 # ifdef _WANT_IO_C99_FORMATS
1976 if (flags & LONGINT)
1977 spec_type = WIDE_CHAR;
1978 else
1979 # endif
1980 spec_type = INT;
1981 break;
1982 # ifdef _WANT_IO_C99_FORMATS
1983 case 'C':
1984 spec_type = WIDE_CHAR;
1985 break;
1986 # endif
1987 }
1988
1989 /* if we have a positional parameter, just store the type, otherwise
1990 fetch the parameter from the vararg list */
1991 if (pos != -1)
1992 arg_type[pos] = spec_type;
1993 else
1994 {
1995 switch (spec_type)
1996 {
1997 case LONG_INT:
1998 args[numargs++].val_long = va_arg (ap->ap, long);
1999 break;
2000 case QUAD_INT:
2001 args[numargs++].val_quad_t = va_arg (ap->ap, quad_t);
2002 break;
2003 case WIDE_CHAR:
2004 args[numargs++].val_wint_t = va_arg (ap->ap, wint_t);
2005 break;
2006 case INT:
2007 args[numargs++].val_int = va_arg (ap->ap, int);
2008 break;
2009 case CHAR_PTR:
2010 args[numargs++].val_char_ptr_t = va_arg (ap->ap, char *);
2011 break;
2012 case DOUBLE:
2013 args[numargs++].val_double = va_arg (ap->ap, double);
2014 break;
2015 case LONG_DOUBLE:
2016 args[numargs++].val__LONG_DOUBLE = va_arg (ap->ap, _LONG_DOUBLE);
2017 break;
2018 }
2019 }
2020 }
2021 break;
2022 case GETPOS: /* we have positional specifier */
2023 if (arg_type[0] == -1)
2024 memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2025 pos = number - 1;
2026 max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos);
2027 break;
2028 case PWPOS: /* we have positional specifier for width or precision */
2029 if (arg_type[0] == -1)
2030 memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2031 number -= 1;
2032 arg_type[number] = INT;
2033 max_pos_arg = (max_pos_arg > number ? max_pos_arg : number);
2034 break;
2035 case GETPWB: /* we require format pushback */
2036 --fmt;
2037 __PICOLIBC_FALLTHROUGH;
2038 case GETPW: /* we have a variable precision or width to acquire */
2039 args[numargs++].val_int = va_arg (ap->ap, int);
2040 break;
2041 case NUMBER: /* we have a number to process */
2042 number = (ch - '0');
2043 while ((ch = *fmt) != '\0' && is_digit (ch))
2044 {
2045 number = number * 10 + (ch - '0');
2046 ++fmt;
2047 }
2048 break;
2049 case SKIPNUM: /* we have a number to skip */
2050 while ((ch = *fmt) != '\0' && is_digit (ch))
2051 ++fmt;
2052 break;
2053 case NOOP:
2054 default:
2055 break; /* do nothing */
2056 }
2057 }
2058 }
2059
2060 /* process all arguments up to at least the one we are looking for and if we
2061 have seen the end of the string, then process up to the max argument needed */
2062 if (*fmt == '\0')
2063 last_arg = max_pos_arg;
2064 else
2065 last_arg = n;
2066
2067 while (numargs <= last_arg)
2068 {
2069 switch (arg_type[numargs])
2070 {
2071 case LONG_INT:
2072 args[numargs++].val_long = va_arg (ap->ap, long);
2073 break;
2074 case QUAD_INT:
2075 args[numargs++].val_quad_t = va_arg (ap->ap, quad_t);
2076 break;
2077 case CHAR_PTR:
2078 args[numargs++].val_char_ptr_t = va_arg (ap->ap, char *);
2079 break;
2080 case DOUBLE:
2081 args[numargs++].val_double = va_arg (ap->ap, double);
2082 break;
2083 case LONG_DOUBLE:
2084 args[numargs++].val__LONG_DOUBLE = va_arg (ap->ap, _LONG_DOUBLE);
2085 break;
2086 case WIDE_CHAR:
2087 args[numargs++].val_wint_t = va_arg (ap->ap, wint_t);
2088 break;
2089 case INT:
2090 default:
2091 args[numargs++].val_char_ptr_t = va_arg (ap->ap, char *);
2092 break;
2093 }
2094 }
2095
2096 /* alter the global numargs value and keep a reference to the last bit of the fmt
2097 string we processed here because the caller will continue processing where we started */
2098 *numargs_p = numargs;
2099 *last_fmt = fmt;
2100 return &args[n];
2101 }
2102 #endif /* !_NO_POS_ARGS */
2103