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