2 * Copyright (c) 1990 The Regents of the University of California.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 <<vfprintf>>, <<vprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, <<vasnprintf>>---format argument list
69 int vprintf(const char *<[fmt]>, va_list <[list]>);
70 int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
71 int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
72 int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>,
74 int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
75 char *vasnprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
78 int _vprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
80 int _vfprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
81 const char *<[fmt]>, va_list <[list]>);
82 int _vsprintf_r(struct _reent *<[reent]>, char *<[str]>,
83 const char *<[fmt]>, va_list <[list]>);
84 int _vasprintf_r(struct _reent *<[reent]>, char **<[str]>,
85 const char *<[fmt]>, va_list <[list]>);
86 int _vsnprintf_r(struct _reent *<[reent]>, char *<[str]>,
87 size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
88 char *_vasnprintf_r(struct _reent *<[reent]>, char *<[str]>,
89 size_t *<[size]>, const char *<[fmt]>, va_list <[list]>);
92 <<vprintf>>, <<vfprintf>>, <<vasprintf>>, <<vsprintf>>, <<vsnprintf>>,
93 and <<vasnprintf>> are (respectively) variants of <<printf>>,
94 <<fprintf>>, <<asprintf>>, <<sprintf>>, <<snprintf>>, and
95 <<asnprintf>>. They differ only in allowing their caller to pass the
96 variable argument list as a <<va_list>> object (initialized by
97 <<va_start>>) rather than directly accepting a variable number of
98 arguments. The caller is responsible for calling <<va_end>>.
100 <<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
101 <<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
105 The return values are consistent with the corresponding functions.
108 ANSI C requires <<vprintf>>, <<vfprintf>>, <<vsprintf>>, and
109 <<vsnprintf>>. The remaining functions are newlib extensions.
111 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
112 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
115 #if defined(LIBC_SCCS) && !defined(lint)
116 /*static char *sccsid = "from: @(#)vfprintf.c 5.50 (Berkeley) 12/16/92";*/
117 static char *rcsid = "$Id$";
118 #endif /* LIBC_SCCS and not lint */
121 * Actual printf innards.
123 * This code is large and complicated...
128 # define VFPRINTF vfiprintf
130 # define _VFPRINTF_R _svfiprintf_r
132 # define _VFPRINTF_R _vfiprintf_r
135 # define VFPRINTF vfprintf
137 # define _VFPRINTF_R _svfprintf_r
139 # define _VFPRINTF_R _vfprintf_r
141 # ifndef NO_FLOATING_POINT
142 # define FLOATING_POINT
147 #ifdef _WANT_IO_POS_ARGS
159 #include <sys/lock.h>
162 #include "../stdlib/local.h"
164 #include "vfieeefp.h"
166 /* Currently a test is made to see if long double processing is warranted.
167 This could be changed in the future should the _ldtoa_r code be
168 preferred over _dtoa_r. */
170 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
175 #if defined _WANT_IO_LONG_LONG \
176 && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
181 #define __SPRINT __ssprint_r
183 #define __SPRINT __sprint_r
186 /* The __sprint_r/__ssprint_r functions are shared between all versions of
187 vfprintf and vfwprintf. They must only be defined once, which we do in
188 the INTEGER_ONLY versions here. */
192 _DEFUN(__ssprint_r, (ptr, fp, uio),
193 struct _reent *ptr _AND
195 register struct __suio *uio)
199 register struct __siov *iov;
200 register _CONST char *p = NULL;
205 if (uio->uio_resid == 0) {
217 if (len >= w && fp->_flags & (__SMBF | __SOPT)) {
218 /* must be asprintf family */
220 int curpos = (fp->_p - fp->_bf._base);
221 /* Choose a geometric growth factor to avoid
222 * quadratic realloc behavior, but use a rate less
223 * than (1+sqrt(5))/2 to accomodate malloc
224 * overhead. asprintf EXPECTS us to overallocate, so
225 * that it can add a trailing \0 without
226 * reallocating. The new allocation should thus be
227 * max(prev_size*1.5, curpos+len+1). */
228 int newsize = fp->_bf._size * 3 / 2;
229 if (newsize < curpos + len + 1)
230 newsize = curpos + len + 1;
231 if (fp->_flags & __SOPT)
233 /* asnprintf leaves original buffer alone. */
234 str = (unsigned char *)_malloc_r (ptr, newsize);
237 ptr->_errno = ENOMEM;
240 memcpy (str, fp->_bf._base, curpos);
241 fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
245 str = (unsigned char *)_realloc_r (ptr, fp->_bf._base,
248 /* Free unneeded buffer. */
249 _free_r (ptr, fp->_bf._base);
250 /* Ensure correct errno, even if free
252 ptr->_errno = ENOMEM;
257 fp->_p = str + curpos;
258 fp->_bf._size = newsize;
260 fp->_w = newsize - curpos;
264 (void)memmove ((_PTR) fp->_p, (_PTR) p, (size_t) (w));
267 w = len; /* pretend we copied all */
270 } while ((uio->uio_resid -= w) != 0);
277 fp->_flags |= __SERR;
282 #else /* !INTEGER_ONLY */
283 int __ssprint_r (struct _reent *, FILE *, register struct __suio *);
284 #endif /* !INTEGER_ONLY */
286 #else /* !STRING_ONLY */
289 * Flush out all the vectors defined by the given uio,
290 * then reset it so that it can be reused.
293 _DEFUN(__sprint_r, (ptr, fp, uio),
294 struct _reent *ptr _AND
296 register struct __suio *uio)
298 register int err = 0;
300 if (uio->uio_resid == 0) {
304 if (fp->_flags2 & __SWID) {
310 for (; uio->uio_resid != 0;
311 uio->uio_resid -= len * sizeof (wchar_t), iov++) {
312 p = (wchar_t *) iov->iov_base;
313 len = iov->iov_len / sizeof (wchar_t);
314 for (i = 0; i < len; i++) {
315 if (_fputwc_r (ptr, p[i], fp) == WEOF) {
322 err = __sfvwrite_r(ptr, fp, uio);
328 #else /* !INTEGER_ONLY */
329 int __sprint_r (struct _reent *, FILE *, register struct __suio *);
330 #endif /* !INTEGER_ONLY */
333 * Helper function for `fprintf to unbuffered unix file': creates a
334 * temporary buffer. We only work on write-only files; this avoids
335 * worries about ungetc buffers and so forth.
337 * Make sure to avoid inlining when optimizing for size.
340 _DEFUN(__sbprintf, (rptr, fp, fmt, ap),
341 struct _reent *rptr _AND
342 register FILE *fp _AND
343 _CONST char *fmt _AND
348 unsigned char buf[BUFSIZ];
350 /* copy the important variables */
351 fake._flags = fp->_flags & ~__SNBF;
352 fake._flags2 = fp->_flags2;
353 fake._file = fp->_file;
354 fake._cookie = fp->_cookie;
355 fake._write = fp->_write;
357 /* set up the buffer */
358 fake._bf._base = fake._p = buf;
359 fake._bf._size = fake._w = sizeof (buf);
360 fake._lbfsize = 0; /* not actually used, but Just In Case */
361 #ifndef __SINGLE_THREAD__
362 __lock_init_recursive (fake._lock);
365 /* do the work, then copy any error status */
366 ret = _VFPRINTF_R (rptr, &fake, fmt, ap);
367 if (ret >= 0 && _fflush_r (rptr, &fake))
369 if (fake._flags & __SERR)
370 fp->_flags |= __SERR;
372 #ifndef __SINGLE_THREAD__
373 __lock_close_recursive (fake._lock);
377 #endif /* !STRING_ONLY */
380 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
383 #ifdef FLOATING_POINT
386 /* For %La, an exponent of 15 bits occupies the exponent character, a
387 sign, and up to 5 digits. */
393 extern char *_dtoa_r _PARAMS((struct _reent *, double, int,
394 int, int *, int *, char **));
396 # define _PRINTF_FLOAT_TYPE double
397 # define _DTOA_R _dtoa_r
400 # else /* !_NO_LONGDBL */
402 extern char *_ldtoa_r _PARAMS((struct _reent *, _LONG_DOUBLE, int,
403 int, int *, int *, char **));
405 extern int _EXFUN(_ldcheck,(_LONG_DOUBLE *));
407 # define _PRINTF_FLOAT_TYPE _LONG_DOUBLE
408 # define _DTOA_R _ldtoa_r
409 /* FIXME - frexpl is not yet supported; and cvt infloops if (double)f
410 converts a finite value into infinity. */
411 /* # define FREXP frexpl */
412 # define FREXP(f,e) ((_LONG_DOUBLE) frexp ((double)f, e))
413 # endif /* !_NO_LONGDBL */
415 static char *cvt(struct _reent *, _PRINTF_FLOAT_TYPE, int, int, char *, int *,
418 static int exponent(char *, int, int);
420 #endif /* FLOATING_POINT */
422 /* BUF must be big enough for the maximum %#llo (assuming long long is
423 at most 64 bits, this would be 23 characters), the maximum
424 multibyte character %C, and the maximum default precision of %La
425 (assuming long double is at most 128 bits with 113 bits of
426 mantissa, this would be 29 characters). %e, %f, and %g use
427 reentrant storage shared with mprec. All other formats that use
428 buf get by with fewer characters. Making BUF slightly bigger
429 reduces the need for malloc in %.*a and %S, when large precision or
430 long strings are processed.
431 The bigger size of 100 bytes is used on systems which allow number
432 strings using the locale's grouping character. Since that's a multibyte
433 value, we should use a conservative value.
435 #ifdef _WANT_IO_C99_FORMATS
440 #if defined _MB_CAPABLE && MB_LEN_MAX > BUF
442 # define BUF MB_LEN_MAX
446 # define quad_t long long
447 # define u_quad_t unsigned long long
450 # define u_quad_t unsigned long
453 typedef quad_t * quad_ptr_t;
454 typedef _PTR void_ptr_t;
455 typedef char * char_ptr_t;
456 typedef long * long_ptr_t;
457 typedef int * int_ptr_t;
458 typedef short * short_ptr_t;
462 # define MAX_POS_ARGS NL_ARGMAX
464 # define MAX_POS_ARGS 32
475 _LONG_DOUBLE val__LONG_DOUBLE;
476 int_ptr_t val_int_ptr_t;
477 short_ptr_t val_short_ptr_t;
478 long_ptr_t val_long_ptr_t;
479 char_ptr_t val_char_ptr_t;
480 quad_ptr_t val_quad_ptr_t;
481 void_ptr_t val_void_ptr_t;
483 u_quad_t val_u_quad_t;
487 static union arg_val *
488 _EXFUN(get_arg, (struct _reent *data, int n, char *fmt,
489 va_list *ap, int *numargs, union arg_val *args,
490 int *arg_type, char **last_fmt));
491 #endif /* !_NO_POS_ARGS */
494 * Macros for converting digits to letters and vice versa
496 #define to_digit(c) ((c) - '0')
497 #define is_digit(c) ((unsigned)to_digit (c) <= 9)
498 #define to_char(n) ((n) + '0')
501 * Flags used during conversion.
503 #define ALT 0x001 /* alternate form */
504 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
505 #define LADJUST 0x004 /* left adjustment */
506 #define LONGDBL 0x008 /* long double */
507 #define LONGINT 0x010 /* long integer */
509 # define QUADINT 0x020 /* quad integer */
510 #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
511 that %lld behaves the same as %ld, not as %d, as expected if:
512 sizeof (long long) = sizeof long > sizeof int */
513 # define QUADINT LONGINT
515 #define SHORTINT 0x040 /* short integer */
516 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
517 #define FPT 0x100 /* Floating point number */
518 #ifdef _WANT_IO_C99_FORMATS
519 # define CHARINT 0x200 /* char as integer */
520 #else /* define as 0, to make SARG and UARG occupy fewer instructions */
523 #ifdef _WANT_IO_C99_FORMATS
524 # define GROUPING 0x400 /* use grouping ("'" flag) */
527 int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list));
531 _DEFUN(VFPRINTF, (fp, fmt0, ap),
533 _CONST char *fmt0 _AND
537 result = _VFPRINTF_R (_REENT, fp, fmt0, ap);
540 #endif /* STRING_ONLY */
543 _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
544 struct _reent *data _AND
546 _CONST char *fmt0 _AND
549 register char *fmt; /* format string */
550 register int ch; /* character from fmt */
551 register int n, m; /* handy integers (short term usage) */
552 register char *cp; /* handy char pointer (short term usage) */
553 register struct __siov *iovp;/* for PRINT macro */
554 register int flags; /* flags as above */
555 char *fmt_anchor; /* current format spec being processed */
557 int N; /* arg number */
558 int arg_index; /* index into args processed directly */
559 int numargs; /* number of varargs read */
560 char *saved_fmt; /* saved fmt pointer */
561 union arg_val args[MAX_POS_ARGS];
562 int arg_type[MAX_POS_ARGS];
563 int is_pos_arg; /* is current format positional? */
564 int old_is_pos_arg; /* is current format positional? */
566 int ret; /* return value accumulator */
567 int width; /* width from format (%8d), or 0 */
568 int prec; /* precision from format (%.3d), or -1 */
569 char sign; /* sign prefix (' ', '+', '-', or \0) */
570 #ifdef _WANT_IO_C99_FORMATS
571 /* locale specific numeric grouping */
572 char *thousands_sep = NULL;
573 size_t thsnd_len = 0;
574 const char *grouping = NULL;
576 #ifdef FLOATING_POINT
577 char *decimal_point = _localeconv_r (data)->decimal_point;
578 size_t decp_len = strlen (decimal_point);
579 char softsign; /* temporary negative sign for floats */
580 union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
581 # define _fpvalue (_double_.fp)
582 int expt; /* integer value of exponent */
583 int expsize = 0; /* character count for expstr */
584 char expstr[MAXEXPLEN]; /* buffer for exponent string */
585 int lead; /* sig figs before decimal or group sep */
586 #endif /* FLOATING_POINT */
587 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
588 int ndig = 0; /* actual number of digits returned by cvt */
590 #if defined (FLOATING_POINT) && defined (_WANT_IO_C99_FORMATS)
591 int nseps; /* number of group separators with ' */
592 int nrepeats; /* number of repeats of the last group */
594 u_quad_t _uquad; /* integer arguments %[diouxX] */
595 enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
596 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
597 int realsz; /* field size expanded by dprec */
598 int size; /* size of converted field or string */
599 char *xdigs = NULL; /* digits for [xX] conversion */
601 struct __suio uio; /* output information: summary */
602 struct __siov iov[NIOV];/* ... and individual io vectors */
603 char buf[BUF]; /* space for %c, %S, %[diouxX], %[aA] */
604 char ox[2]; /* space for 0x hex-prefix */
607 mbstate_t state; /* mbtowc calls from library must not change state */
609 char *malloc_buf = NULL;/* handy pointer for malloced buffers */
612 * Choose PADSIZE to trade efficiency vs. size. If larger printf
613 * fields occur frequently, increase PADSIZE and make the initialisers
616 #define PADSIZE 16 /* pad chunk size */
617 static _CONST char blanks[PADSIZE] =
618 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
619 static _CONST char zeroes[PADSIZE] =
620 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
623 memset (&state, '\0', sizeof (state));
626 * BEWARE, these `goto error' on error, and PAD uses `n'.
628 #define PRINT(ptr, len) { \
629 iovp->iov_base = (ptr); \
630 iovp->iov_len = (len); \
631 uio.uio_resid += (len); \
633 if (++uio.uio_iovcnt >= NIOV) { \
634 if (__SPRINT(data, fp, &uio)) \
639 #define PAD(howmany, with) { \
640 if ((n = (howmany)) > 0) { \
641 while (n > PADSIZE) { \
642 PRINT (with, PADSIZE); \
648 #define PRINTANDPAD(p, ep, len, with) { \
649 int n = (ep) - (p); \
654 PAD((len) - (n > 0 ? n : 0), (with)); \
657 if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
659 uio.uio_iovcnt = 0; \
663 /* Macros to support positional arguments */
665 # define GET_ARG(n, ap, type) \
668 ? args[n].val_##type \
669 : get_arg (data, n, fmt_anchor, &ap, &numargs, args, \
670 arg_type, &saved_fmt)->val_##type) \
671 : (arg_index++ < numargs \
672 ? args[n].val_##type \
673 : (numargs < MAX_POS_ARGS \
674 ? args[numargs++].val_##type = va_arg (ap, type) \
675 : va_arg (ap, type))))
677 # define GET_ARG(n, ap, type) (va_arg (ap, type))
681 * To extend shorts properly, we need both signed and unsigned
682 * argument extraction methods.
686 (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
687 flags&LONGINT ? GET_ARG (N, ap, long) : \
688 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
689 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
690 (long)GET_ARG (N, ap, int))
692 (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
693 flags&LONGINT ? GET_ARG (N, ap, u_long) : \
694 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
695 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
696 (u_long)GET_ARG (N, ap, u_int))
699 (flags&LONGINT ? GET_ARG (N, ap, long) : \
700 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
701 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
702 (long)GET_ARG (N, ap, int))
704 (flags&LONGINT ? GET_ARG (N, ap, u_long) : \
705 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
706 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
707 (u_long)GET_ARG (N, ap, u_int))
711 /* Initialize std streams if not dealing with sprintf family. */
712 CHECK_INIT (data, fp);
713 _newlib_flockfile_start (fp);
717 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
718 if (cantwrite (data, fp)) {
719 _newlib_flockfile_exit (fp);
723 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
724 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
726 _newlib_flockfile_exit (fp);
727 return (__sbprintf (data, fp, fmt0, ap));
729 #else /* STRING_ONLY */
730 /* Create initial buffer if we are called by asprintf family. */
731 if (fp->_flags & __SMBF && !fp->_bf._base)
733 fp->_bf._base = fp->_p = _malloc_r (data, 64);
736 data->_errno = ENOMEM;
741 #endif /* STRING_ONLY */
744 uio.uio_iov = iovp = iov;
757 * Scan the format for conversions (`%' character).
762 while ((n = __mbtowc (data, &wc, fmt, MB_CUR_MAX,
763 __locale_charset (), &state)) != 0) {
765 /* Wave invalid chars through. */
766 memset (&state, 0, sizeof state);
774 while (*fmt != '\0' && *fmt != '%')
777 if ((m = fmt - cp) != 0) {
789 fmt++; /* skip over '%' */
796 #ifdef FLOATING_POINT
798 #ifdef _WANT_IO_C99_FORMATS
799 nseps = nrepeats = 0;
808 reswitch: switch (ch) {
809 #ifdef _WANT_IO_C99_FORMATS
811 thousands_sep = _localeconv_r (data)->thousands_sep;
812 thsnd_len = strlen (thousands_sep);
813 grouping = _localeconv_r (data)->grouping;
814 if (thsnd_len > 0 && grouping && *grouping)
820 * ``If the space and + flags both appear, the space
821 * flag will be ignored.''
832 /* we must check for positional arg used for dynamic width */
834 old_is_pos_arg = is_pos_arg;
836 if (is_digit (*fmt)) {
842 n = 10 * n + to_digit (ch);
844 } while (is_digit (ch));
847 if (n <= MAX_POS_ARGS) {
859 #endif /* !_NO_POS_ARGS */
862 * ``A negative field width argument is taken as a
863 * - flag followed by a positive field width.''
865 * They don't exclude field widths read from args.
867 width = GET_ARG (n, ap, int);
869 is_pos_arg = old_is_pos_arg;
882 if ((ch = *fmt++) == '*') {
884 /* we must check for positional arg used for dynamic width */
886 old_is_pos_arg = is_pos_arg;
888 if (is_digit (*fmt)) {
894 n = 10 * n + to_digit (ch);
896 } while (is_digit (ch));
899 if (n <= MAX_POS_ARGS) {
911 #endif /* !_NO_POS_ARGS */
912 prec = GET_ARG (n, ap, int);
914 is_pos_arg = old_is_pos_arg;
921 while (is_digit (ch)) {
922 n = 10 * n + to_digit (ch);
925 prec = n < 0 ? -1 : n;
929 * ``Note that 0 is taken as a flag, not as the
930 * beginning of a field width.''
935 case '1': case '2': case '3': case '4':
936 case '5': case '6': case '7': case '8': case '9':
939 n = 10 * n + to_digit (ch);
941 } while (is_digit (ch));
944 if (n <= MAX_POS_ARGS) {
952 #endif /* !_NO_POS_ARGS */
955 #ifdef FLOATING_POINT
961 #ifdef _WANT_IO_C99_FORMATS
970 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
978 case 'q': /* extension */
981 #ifdef _WANT_IO_C99_FORMATS
983 if (sizeof (intmax_t) == sizeof (long))
989 if (sizeof (size_t) < sizeof (int))
990 /* POSIX states size_t is 16 or more bits, as is short. */
992 else if (sizeof (size_t) == sizeof (int))
993 /* no flag needed */;
994 else if (sizeof (size_t) <= sizeof (long))
997 /* POSIX states that at least one programming
998 environment must support size_t no wider than
999 long, but that means other environments can
1000 have size_t as wide as long long. */
1004 if (sizeof (ptrdiff_t) < sizeof (int))
1005 /* POSIX states ptrdiff_t is 16 or more bits, as
1008 else if (sizeof (ptrdiff_t) == sizeof (int))
1009 /* no flag needed */;
1010 else if (sizeof (ptrdiff_t) <= sizeof (long))
1013 /* POSIX states that at least one programming
1014 environment must support ptrdiff_t no wider than
1015 long, but that means other environments can
1016 have ptrdiff_t as wide as long long. */
1020 #endif /* _WANT_IO_C99_FORMATS */
1024 if (ch == 'C' || (flags & LONGINT)) {
1027 memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1028 if ((size = (int)_wcrtomb_r (data, cp,
1029 (wchar_t)GET_ARG (N, ap, wint_t),
1031 fp->_flags |= __SERR;
1036 #endif /* _MB_CAPABLE */
1038 *cp = GET_ARG (N, ap, int);
1043 case 'D': /* extension */
1049 #ifndef _NO_LONGLONG
1050 if ((quad_t)_uquad < 0)
1052 if ((long) _uquad < 0)
1061 #ifdef FLOATING_POINT
1062 # ifdef _WANT_IO_C99_FORMATS
1073 if (flags & LONGDBL) {
1074 _fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE);
1076 _fpvalue = GET_ARG (N, ap, double);
1079 /* do this before tricky precision changes
1081 If the output is infinite or NaN, leading
1082 zeros are not permitted. Otherwise, scanf
1083 could not read what printf wrote.
1085 if (isinf (_fpvalue)) {
1088 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1096 if (isnan (_fpvalue)) {
1097 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1106 # else /* !_NO_LONGDBL */
1108 if (flags & LONGDBL) {
1109 _fpvalue = GET_ARG (N, ap, _LONG_DOUBLE);
1111 _fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double);
1114 /* do this before tricky precision changes */
1115 expt = _ldcheck (&_fpvalue);
1119 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1128 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1136 # endif /* !_NO_LONGDBL */
1138 # ifdef _WANT_IO_C99_FORMATS
1139 if (ch == 'a' || ch == 'A') {
1141 ox[1] = ch == 'a' ? 'x' : 'X';
1146 (char *)_malloc_r (data, prec + 1))
1149 fp->_flags |= __SERR;
1157 # endif /* _WANT_IO_C99_FORMATS */
1160 } else if ((ch == 'g' || ch == 'G') && prec == 0) {
1166 cp = cvt (data, _fpvalue, prec, flags, &softsign,
1167 &expt, ch, &ndig, cp);
1169 if (ch == 'g' || ch == 'G') {
1170 if (expt <= -4 || expt > prec)
1171 ch -= 2; /* 'e' or 'E' */
1175 # ifdef _WANT_IO_C99_FORMATS
1179 if (ch <= 'e') { /* 'a', 'A', 'e', or 'E' fmt */
1181 expsize = exponent (expstr, expt, ch);
1182 size = expsize + ndig;
1183 if (ndig > 1 || flags & ALT)
1185 # ifdef _WANT_IO_C99_FORMATS
1189 if (ch == 'f') { /* f fmt */
1192 if (prec || flags & ALT)
1195 size = (prec || flags & ALT)
1198 } else if (expt >= ndig) { /* fixed g fmt */
1203 size = ndig + (expt > 0 ?
1205 # ifdef _WANT_IO_C99_FORMATS
1206 if ((flags & GROUPING) && expt > 0) {
1207 /* space for thousands' grouping */
1208 nseps = nrepeats = 0;
1210 while (*grouping != CHAR_MAX) {
1211 if (lead <= *grouping)
1220 size += (nseps + nrepeats) * thsnd_len;
1229 #endif /* FLOATING_POINT */
1230 #ifdef _GLIBC_EXTENSION
1231 case 'm': /* extension */
1234 cp = _strerror_r (data, data->_errno, 1, &dummy);
1240 #ifndef _NO_LONGLONG
1241 if (flags & QUADINT)
1242 *GET_ARG (N, ap, quad_ptr_t) = ret;
1245 if (flags & LONGINT)
1246 *GET_ARG (N, ap, long_ptr_t) = ret;
1247 else if (flags & SHORTINT)
1248 *GET_ARG (N, ap, short_ptr_t) = ret;
1249 #ifdef _WANT_IO_C99_FORMATS
1250 else if (flags & CHARINT)
1251 *GET_ARG (N, ap, char_ptr_t) = ret;
1254 *GET_ARG (N, ap, int_ptr_t) = ret;
1255 continue; /* no output */
1256 case 'O': /* extension */
1262 #ifdef _WANT_IO_C99_FORMATS
1268 * ``The argument shall be a pointer to void. The
1269 * value of the pointer is converted to a sequence
1270 * of printable characters, in an implementation-
1275 _uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t);
1277 xdigs = "0123456789abcdef";
1283 #ifdef _WANT_IO_C99_FORMATS
1286 cp = GET_ARG (N, ap, char_ptr_t);
1287 #ifdef _GLIBC_EXTENSION
1291 #ifndef __OPTIMIZE_SIZE__
1292 /* Behavior is undefined if the user passed a
1293 NULL string when precision is not 0.
1294 However, if we are not optimizing for size,
1295 we might as well mirror glibc behavior. */
1298 size = ((unsigned) prec > 6U) ? 6 : prec;
1301 #endif /* __OPTIMIZE_SIZE__ */
1303 if (ch == 'S' || (flags & LONGINT)) {
1305 _CONST wchar_t *wcp;
1307 wcp = (_CONST wchar_t *)cp;
1309 memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1311 /* Count number of bytes needed for multibyte
1312 string that will be produced from widechar
1316 if (wcp[m] == L'\0')
1318 if ((n = (int)_wcrtomb_r (data,
1319 buf, wcp[m], &ps)) == -1) {
1320 fp->_flags |= __SERR;
1323 if (n + size > prec)
1332 if ((size = (int)_wcsrtombs_r (data,
1333 NULL, &wcp, 0, &ps)) == -1) {
1334 fp->_flags |= __SERR;
1337 wcp = (_CONST wchar_t *)cp;
1345 (char *)_malloc_r (data, size + 1))
1347 fp->_flags |= __SERR;
1354 /* Convert widechar string to multibyte string. */
1355 memset ((_PTR)&ps, '\0', sizeof (mbstate_t));
1356 if (_wcsrtombs_r (data, cp, &wcp, size, &ps)
1358 fp->_flags |= __SERR;
1364 #endif /* _MB_CAPABLE */
1367 * can't use strlen; can only look for the
1368 * NUL in the first `prec' characters, and
1369 * strlen () will go further.
1371 char *p = memchr (cp, 0, prec);
1383 case 'U': /* extension */
1391 xdigs = "0123456789ABCDEF";
1394 xdigs = "0123456789abcdef";
1395 hex: _uquad = UARG ();
1397 /* leading 0x/X only if non-zero */
1398 if (flags & ALT && _uquad != 0) {
1404 #ifdef _WANT_IO_C99_FORMATS
1407 /* unsigned conversions */
1408 nosign: sign = '\0';
1410 * ``... diouXx conversions ... if a precision is
1411 * specified, the 0 flag will be ignored.''
1414 number: if ((dprec = prec) >= 0)
1418 * ``The result of converting a zero value with an
1419 * explicit precision of zero is no characters.''
1423 if (_uquad != 0 || prec != 0) {
1425 * Unsigned mod is hard, and unsigned mod
1426 * by a constant is easier than that by
1427 * a variable; hence this switch.
1432 *--cp = to_char (_uquad & 7);
1435 /* handle octal leading 0 */
1436 if (flags & ALT && *cp != '0')
1441 /* many numbers are 1 digit */
1443 *--cp = to_char(_uquad);
1446 #ifdef _WANT_IO_C99_FORMATS
1450 *--cp = to_char (_uquad % 10);
1451 #ifdef _WANT_IO_C99_FORMATS
1453 /* If (*grouping == CHAR_MAX) then no
1455 if ((flags & GROUPING)
1456 && ndig == *grouping
1457 && *grouping != CHAR_MAX
1460 strncpy (cp, thousands_sep,
1463 /* If (grouping[1] == '\0') then we
1464 have to use *grouping character
1465 (last grouping rule) for all
1467 if (grouping[1] != '\0')
1472 } while (_uquad != 0);
1477 *--cp = xdigs[_uquad & 15];
1483 cp = "bug in vfprintf: bad base";
1489 * ...result is to be converted to an 'alternate form'.
1490 * For o conversion, it increases the precision to force
1491 * the first digit of the result to be a zero."
1494 * To demonstrate this case, compile and run:
1495 * printf ("%#.0o",0);
1497 else if (base == OCT && (flags & ALT))
1500 size = buf + BUF - cp;
1503 default: /* "%?" prints ?, unless ? is NUL */
1506 /* pretend it was %c with argument ch */
1515 * All reasonable formats wind up here. At this point, `cp'
1516 * points to a string which (if not flags&LADJUST) should be
1517 * padded out to `width' places. If flags&ZEROPAD, it should
1518 * first be prefixed by any sign or other prefix; otherwise,
1519 * it should be blank padded before the prefix is emitted.
1520 * After any left-hand padding and prefixing, emit zeroes
1521 * required by a decimal [diouxX] precision, then print the
1522 * string proper, then emit zeroes required by any leftover
1523 * floating precision; finally, if LADJUST, pad with blanks.
1524 * If flags&FPT, ch must be in [aAeEfg].
1526 * Compute actual size, so we know how much to pad.
1527 * size excludes decimal prec; realsz includes it.
1529 realsz = dprec > size ? dprec : size;
1532 if (flags & HEXPREFIX)
1535 /* right-adjusting blank padding */
1536 if ((flags & (LADJUST|ZEROPAD)) == 0)
1537 PAD (width - realsz, blanks);
1542 if (flags & HEXPREFIX)
1545 /* right-adjusting zero padding */
1546 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1547 PAD (width - realsz, zeroes);
1549 /* leading zeroes from decimal precision */
1550 PAD (dprec - size, zeroes);
1552 /* the string or number proper */
1553 #ifdef FLOATING_POINT
1554 if ((flags & FPT) == 0) {
1556 } else { /* glue together f_p fragments */
1557 if (ch >= 'f') { /* 'f' or 'g' */
1558 if (_fpvalue == 0) {
1559 /* kludge for __dtoa irregularity */
1561 if (expt < ndig || flags & ALT) {
1562 PRINT (decimal_point, decp_len);
1563 PAD (ndig - 1, zeroes);
1565 } else if (expt <= 0) {
1567 if (expt || ndig || flags & ALT) {
1568 PRINT (decimal_point, decp_len);
1569 PAD (-expt, zeroes);
1574 PRINTANDPAD(cp, convbuf + ndig,
1577 #ifdef _WANT_IO_C99_FORMATS
1578 if (flags & GROUPING) {
1579 while (nseps > 0 || nrepeats > 0) {
1586 PRINT(thousands_sep, thsnd_len);
1587 PRINTANDPAD (cp, convbuf + ndig,
1591 if (cp > convbuf + ndig)
1592 cp = convbuf + ndig;
1595 if (expt < ndig || flags & ALT)
1596 PRINT (decimal_point, decp_len);
1597 PRINTANDPAD (cp, convbuf + ndig,
1598 ndig - expt, zeroes);
1600 } else { /* 'a', 'A', 'e', or 'E' */
1601 if (ndig > 1 || flags & ALT) {
1604 PRINT (decimal_point, decp_len);
1606 PRINT (cp, ndig - 1);
1607 } else /* 0.[0..] */
1608 /* __dtoa irregularity */
1609 PAD (ndig - 1, zeroes);
1612 PRINT (expstr, expsize);
1615 #else /* !FLOATING_POINT */
1618 /* left-adjusting padding (always blank) */
1619 if (flags & LADJUST)
1620 PAD (width - realsz, blanks);
1622 /* finally, adjust ret */
1623 ret += width > realsz ? width : realsz;
1625 FLUSH (); /* copy out the I/O vectors */
1627 if (malloc_buf != NULL) {
1628 _free_r (data, malloc_buf);
1635 if (malloc_buf != NULL)
1636 _free_r (data, malloc_buf);
1638 _newlib_flockfile_end (fp);
1640 return (__sferror (fp) ? EOF : ret);
1644 #ifdef FLOATING_POINT
1646 /* Using reentrant DATA, convert finite VALUE into a string of digits
1647 with no decimal point, using NDIGITS precision and FLAGS as guides
1648 to whether trailing zeros must be included. Set *SIGN to nonzero
1649 if VALUE was negative. Set *DECPT to the exponent plus one. Set
1650 *LENGTH to the length of the returned string. CH must be one of
1651 [aAeEfFgG]; if it is [aA], then the return string lives in BUF,
1652 otherwise the return value shares the mprec reentrant storage. */
1654 cvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags,
1655 char *sign, int *decpt, int ch, int *length, char *buf)
1658 char *digits, *bp, *rve;
1660 union double_union tmp;
1663 if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1668 # else /* !_NO_LONGDBL */
1676 if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
1681 # endif /* !_NO_LONGDBL */
1683 # ifdef _WANT_IO_C99_FORMATS
1684 if (ch == 'a' || ch == 'A') {
1685 /* This code assumes FLT_RADIX is a power of 2. The initial
1686 division ensures the digit before the decimal will be less
1687 than FLT_RADIX (unless it is rounded later). There is no
1688 loss of precision in these calculations. */
1689 value = FREXP (value, decpt) / 8;
1692 digits = ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF";
1698 *bp++ = digits[mode];
1699 } while (ndigits-- && value);
1700 if (value > 0.5 || (value == 0.5 && mode & 1)) {
1703 while (*--rve == digits[0xf]) {
1706 *rve = *rve == '9' ? digits[0xa] : *rve + 1;
1708 while (ndigits-- >= 0) {
1715 # endif /* _WANT_IO_C99_FORMATS */
1716 if (ch == 'f' || ch == 'F') {
1717 mode = 3; /* ndigits after the decimal point */
1719 /* To obtain ndigits after the decimal point for the 'e'
1720 * and 'E' formats, round to ndigits + 1 significant
1723 if (ch == 'e' || ch == 'E') {
1726 mode = 2; /* ndigits significant digits */
1729 digits = _DTOA_R (data, value, mode, ndigits, decpt, &dsgn, &rve);
1731 if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */
1732 bp = digits + ndigits;
1733 if (ch == 'f' || ch == 'F') {
1734 if (*digits == '0' && value)
1735 *decpt = -ndigits + 1;
1738 if (value == 0) /* kludge for __dtoa irregularity */
1743 *length = rve - digits;
1748 exponent(char *p0, int exp, int fmtch)
1750 register char *p, *t;
1751 char expbuf[MAXEXPLEN];
1752 # ifdef _WANT_IO_C99_FORMATS
1753 int isa = fmtch == 'a' || fmtch == 'A';
1759 *p++ = isa ? 'p' - 'a' + fmtch : fmtch;
1766 t = expbuf + MAXEXPLEN;
1769 *--t = to_char (exp % 10);
1770 } while ((exp /= 10) > 9);
1771 *--t = to_char (exp);
1772 for (; t < expbuf + MAXEXPLEN; *p++ = *t++);
1777 *p++ = to_char (exp);
1781 #endif /* FLOATING_POINT */
1784 #ifndef _NO_POS_ARGS
1786 /* Positional argument support.
1787 Written by Jeff Johnston
1789 Copyright (c) 2002 Red Hat Incorporated.
1790 All rights reserved.
1792 Redistribution and use in source and binary forms, with or without
1793 modification, are permitted provided that the following conditions are met:
1795 Redistributions of source code must retain the above copyright
1796 notice, this list of conditions and the following disclaimer.
1798 Redistributions in binary form must reproduce the above copyright
1799 notice, this list of conditions and the following disclaimer in the
1800 documentation and/or other materials provided with the distribution.
1802 The name of Red Hat Incorporated may not be used to endorse
1803 or promote products derived from this software without specific
1804 prior written permission.
1806 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1807 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1808 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1809 DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1810 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1811 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1812 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1813 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1814 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1815 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1817 /* The below constant state tables are shared between all versions of
1818 vfprintf and vfwprintf. They must only be defined once, which we do in
1819 the STRING_ONLY/INTEGER_ONLY versions here. */
1820 #if defined (STRING_ONLY) && defined(INTEGER_ONLY)
1822 _CONST __CH_CLASS __chclass[256] = {
1823 /* 00-07 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1824 /* 08-0f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1825 /* 10-17 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1826 /* 18-1f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1827 /* 20-27 */ FLAG, OTHER, OTHER, FLAG, DOLLAR, OTHER, OTHER, FLAG,
1828 /* 28-2f */ OTHER, OTHER, STAR, FLAG, OTHER, FLAG, DOT, OTHER,
1829 /* 30-37 */ ZERO, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
1830 /* 38-3f */ DIGIT, DIGIT, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1831 /* 40-47 */ OTHER, SPEC, OTHER, SPEC, SPEC, SPEC, SPEC, SPEC,
1832 /* 48-4f */ OTHER, OTHER, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC,
1833 /* 50-57 */ OTHER, OTHER, OTHER, SPEC, OTHER, SPEC, OTHER, OTHER,
1834 /* 58-5f */ SPEC, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1835 /* 60-67 */ OTHER, SPEC, OTHER, SPEC, SPEC, SPEC, SPEC, SPEC,
1836 /* 68-6f */ MODFR, SPEC, MODFR, OTHER, MODFR, OTHER, SPEC, SPEC,
1837 /* 70-77 */ SPEC, MODFR, OTHER, SPEC, MODFR, SPEC, OTHER, OTHER,
1838 /* 78-7f */ SPEC, OTHER, MODFR, OTHER, OTHER, OTHER, OTHER, OTHER,
1839 /* 80-87 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1840 /* 88-8f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1841 /* 90-97 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1842 /* 98-9f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1843 /* a0-a7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1844 /* a8-af */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1845 /* b0-b7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1846 /* b8-bf */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1847 /* c0-c7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1848 /* c8-cf */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1849 /* d0-d7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1850 /* d8-df */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1851 /* e0-e7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1852 /* e8-ef */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1853 /* f0-f7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1854 /* f8-ff */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1857 _CONST __STATE __state_table[MAX_STATE][MAX_CH_CLASS] = {
1858 /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
1859 /* START */ { SFLAG, WDIG, DONE, SMOD, DONE, SDOT, VARW, SFLAG, DONE },
1860 /* SFLAG */ { SFLAG, WDIG, DONE, SMOD, DONE, SDOT, VARW, SFLAG, DONE },
1861 /* WDIG */ { DONE, DONE, WIDTH, SMOD, DONE, SDOT, DONE, DONE, DONE },
1862 /* WIDTH */ { DONE, DONE, DONE, SMOD, DONE, SDOT, DONE, DONE, DONE },
1863 /* SMOD */ { DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE },
1864 /* SDOT */ { SDOT, PREC, DONE, SMOD, DONE, DONE, VARP, DONE, DONE },
1865 /* VARW */ { DONE, VWDIG, DONE, SMOD, DONE, SDOT, DONE, DONE, DONE },
1866 /* VARP */ { DONE, VPDIG, DONE, SMOD, DONE, DONE, DONE, DONE, DONE },
1867 /* PREC */ { DONE, DONE, DONE, SMOD, DONE, DONE, DONE, DONE, DONE },
1868 /* VWDIG */ { DONE, DONE, WIDTH, DONE, DONE, DONE, DONE, DONE, DONE },
1869 /* VPDIG */ { DONE, DONE, PREC, DONE, DONE, DONE, DONE, DONE, DONE },
1872 _CONST __ACTION __action_table[MAX_STATE][MAX_CH_CLASS] = {
1873 /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
1874 /* START */ { NOOP, NUMBER, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1875 /* SFLAG */ { NOOP, NUMBER, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1876 /* WDIG */ { NOOP, NOOP, GETPOS, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1877 /* WIDTH */ { NOOP, NOOP, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1878 /* SMOD */ { NOOP, NOOP, NOOP, NOOP, GETARG, NOOP, NOOP, NOOP, NOOP },
1879 /* SDOT */ { NOOP, SKIPNUM, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1880 /* VARW */ { NOOP, NUMBER, NOOP, GETPW, GETPWB, GETPW, NOOP, NOOP, NOOP },
1881 /* VARP */ { NOOP, NUMBER, NOOP, GETPW, GETPWB, NOOP, NOOP, NOOP, NOOP },
1882 /* PREC */ { NOOP, NOOP, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1883 /* VWDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP },
1884 /* VPDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP },
1887 #endif /* STRING_ONLY && INTEGER_ONLY */
1889 /* function to get positional parameter N where n = N - 1 */
1890 static union arg_val *
1891 _DEFUN(get_arg, (data, n, fmt, ap, numargs_p, args, arg_type, last_fmt),
1892 struct _reent *data _AND
1897 union arg_val *args _AND
1904 int numargs = *numargs_p;
1906 __STATE state, next_state;
1909 int max_pos_arg = n;
1910 /* Only need types that can be reached via vararg promotions. */
1911 enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
1918 /* if this isn't the first call, pick up where we left off last time */
1919 if (*last_fmt != NULL)
1923 memset (&wc_state, '\0', sizeof (wc_state));
1926 /* we need to process either to end of fmt string or until we have actually
1927 read the desired parameter from the vararg list. */
1928 while (*fmt && n >= numargs)
1931 while ((nbytes = __mbtowc (data, &wc, fmt, MB_CUR_MAX,
1932 __locale_charset (), &wc_state)) > 0)
1942 while (*fmt != '\0' && *fmt != '%')
1947 # endif /* ! _MB_CAPABLE */
1954 /* Use state/action table to process format specifiers. We ignore invalid
1955 formats and we are only interested in information that tells us how to
1956 read the vararg list. */
1957 while (state != DONE)
1960 chtype = __chclass[ch];
1961 next_state = __state_table[state][chtype];
1962 action = __action_table[state][chtype];
1967 case GETMOD: /* we have format modifier */
1971 /* No flag needed, since short and char promote to int. */
1979 # ifdef _WANT_IO_C99_FORMATS
1981 if (sizeof (intmax_t) == sizeof (long))
1987 if (sizeof (size_t) <= sizeof (int))
1988 /* no flag needed */;
1989 else if (sizeof (size_t) <= sizeof (long))
1992 /* POSIX states that at least one programming
1993 environment must support size_t no wider than
1994 long, but that means other environments can
1995 have size_t as wide as long long. */
1999 if (sizeof (ptrdiff_t) <= sizeof (int))
2000 /* no flag needed */;
2001 else if (sizeof (ptrdiff_t) <= sizeof (long))
2004 /* POSIX states that at least one programming
2005 environment must support ptrdiff_t no wider than
2006 long, but that means other environments can
2007 have ptrdiff_t as wide as long long. */
2010 # endif /* _WANT_IO_C99_FORMATS */
2013 # if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
2025 case GETARG: /* we have format specifier */
2027 numargs &= (MAX_POS_ARGS - 1);
2028 /* process the specifier and translate it to a type to fetch from varargs */
2037 if (flags & LONGINT)
2038 spec_type = LONG_INT;
2039 # ifndef _NO_LONGLONG
2040 else if (flags & QUADINT)
2041 spec_type = QUAD_INT;
2049 spec_type = LONG_INT;
2051 # ifdef _WANT_IO_C99_FORMATS
2061 # ifndef _NO_LONGDBL
2062 if (flags & LONGDBL)
2063 spec_type = LONG_DOUBLE;
2069 # ifdef _WANT_IO_C99_FORMATS
2074 spec_type = CHAR_PTR;
2077 # ifdef _WANT_IO_C99_FORMATS
2078 if (flags & LONGINT)
2079 spec_type = WIDE_CHAR;
2084 # ifdef _WANT_IO_C99_FORMATS
2086 spec_type = WIDE_CHAR;
2091 /* if we have a positional parameter, just store the type, otherwise
2092 fetch the parameter from the vararg list */
2094 arg_type[pos] = spec_type;
2100 args[numargs++].val_long = va_arg (*ap, long);
2103 args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2106 args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2109 args[numargs++].val_int = va_arg (*ap, int);
2112 args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2115 args[numargs++].val_double = va_arg (*ap, double);
2118 args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2124 case GETPOS: /* we have positional specifier */
2125 if (arg_type[0] == -1)
2126 memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2128 max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos);
2130 case PWPOS: /* we have positional specifier for width or precision */
2131 if (arg_type[0] == -1)
2132 memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2134 arg_type[number] = INT;
2135 max_pos_arg = (max_pos_arg > number ? max_pos_arg : number);
2137 case GETPWB: /* we require format pushback */
2140 case GETPW: /* we have a variable precision or width to acquire */
2141 args[numargs++].val_int = va_arg (*ap, int);
2143 case NUMBER: /* we have a number to process */
2144 number = (ch - '0');
2145 while ((ch = *fmt) != '\0' && is_digit (ch))
2147 number = number * 10 + (ch - '0');
2151 case SKIPNUM: /* we have a number to skip */
2152 while ((ch = *fmt) != '\0' && is_digit (ch))
2157 break; /* do nothing */
2162 /* process all arguments up to at least the one we are looking for and if we
2163 have seen the end of the string, then process up to the max argument needed */
2165 last_arg = max_pos_arg;
2169 while (numargs <= last_arg)
2171 switch (arg_type[numargs])
2174 args[numargs++].val_long = va_arg (*ap, long);
2177 args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2180 args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2183 args[numargs++].val_double = va_arg (*ap, double);
2186 args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2189 args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2193 args[numargs++].val_int = va_arg (*ap, int);
2198 /* alter the global numargs value and keep a reference to the last bit of the fmt
2199 string we processed here because the caller will continue processing where we started */
2200 *numargs_p = numargs;
2204 #endif /* !_NO_POS_ARGS */