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