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