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. 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.
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
35 <<vfprintf>>, <<vprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, <<vasnprintf>>---format argument list
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]>,
70 int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
71 char *vasnprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
74 int _vprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
76 int _vfprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
77 const char *<[fmt]>, va_list <[list]>);
78 int _vsprintf_r(struct _reent *<[reent]>, char *<[str]>,
79 const char *<[fmt]>, va_list <[list]>);
80 int _vasprintf_r(struct _reent *<[reent]>, char **<[str]>,
81 const char *<[fmt]>, va_list <[list]>);
82 int _vsnprintf_r(struct _reent *<[reent]>, char *<[str]>,
83 size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
84 char *_vasnprintf_r(struct _reent *<[reent]>, char *<[str]>,
85 size_t *<[size]>, const char *<[fmt]>, va_list <[list]>);
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>>.
96 <<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
97 <<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
101 The return values are consistent with the corresponding functions.
104 ANSI C requires <<vprintf>>, <<vfprintf>>, <<vsprintf>>, and
105 <<vsnprintf>>. The remaining functions are newlib extensions.
107 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
108 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
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 */
117 * Actual printf innards.
119 * This code is large and complicated...
124 # define VFPRINTF vfiprintf
126 # define _VFPRINTF_R _svfiprintf_r
128 # define _VFPRINTF_R _vfiprintf_r
131 # define VFPRINTF vfprintf
133 # define _VFPRINTF_R _svfprintf_r
135 # define _VFPRINTF_R _vfprintf_r
137 # ifndef NO_FLOATING_POINT
138 # define FLOATING_POINT
143 #ifdef _WANT_IO_POS_ARGS
155 #include <sys/lock.h>
158 #include "../stdlib/local.h"
160 #include "vfieeefp.h"
162 /* Currently a test is made to see if long double processing is warranted.
163 This could be changed in the future should the _ldtoa_r code be
164 preferred over _dtoa_r. */
166 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
171 #if defined _WANT_IO_LONG_LONG \
172 && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
178 # ifdef _FVWRITE_IN_STREAMIO
179 # define __SPRINT __ssprint_r
180 int __ssprint_r (struct _reent
*, FILE *, register struct __suio
*);
182 # define __SPRINT __ssputs_r
183 int __ssputs_r (struct _reent
*, FILE *, const char *, size_t);
186 #else /* !STRING_ONLY */
188 # ifdef _FVWRITE_IN_STREAMIO
189 # define __SPRINT __sprint_r
190 int __sprint_r (struct _reent
*, FILE *, register struct __suio
*);
192 # define __SPRINT __sfputs_r
193 int __sfputs_r (struct _reent
*, FILE *, const char *buf
, size_t);
196 #ifdef _UNBUF_STREAM_OPT
198 * Helper function for `fprintf to unbuffered unix file': creates a
199 * temporary buffer. We only work on write-only files; this avoids
200 * worries about ungetc buffers and so forth.
202 * Make sure to avoid inlining.
205 __sbprintf (struct _reent
*rptr
,
212 unsigned char buf
[BUFSIZ
];
214 /* copy the important variables */
215 fake
._flags
= fp
->_flags
& ~__SNBF
;
216 fake
._flags2
= fp
->_flags2
;
217 fake
._file
= fp
->_file
;
218 fake
._cookie
= fp
->_cookie
;
219 fake
._write
= fp
->_write
;
221 /* set up the buffer */
222 fake
._bf
._base
= fake
._p
= buf
;
223 fake
._bf
._size
= fake
._w
= sizeof (buf
);
224 fake
._lbfsize
= 0; /* not actually used, but Just In Case */
225 #ifndef __SINGLE_THREAD__
226 __lock_init_recursive (fake
._lock
);
229 /* do the work, then copy any error status */
230 ret
= _VFPRINTF_R (rptr
, &fake
, fmt
, ap
);
231 if (ret
>= 0 && _fflush_r (rptr
, &fake
))
233 if (fake
._flags
& __SERR
)
234 fp
->_flags
|= __SERR
;
236 #ifndef __SINGLE_THREAD__
237 __lock_close_recursive (fake
._lock
);
241 #endif /* _UNBUF_STREAM_OPT */
242 #endif /* !STRING_ONLY */
245 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
248 #ifdef FLOATING_POINT
251 /* For %La, an exponent of 15 bits occupies the exponent character, a
252 sign, and up to 5 digits. */
258 extern char *_dtoa_r (struct _reent
*, double, int,
259 int, int *, int *, char **);
261 # define _PRINTF_FLOAT_TYPE double
262 # define _DTOA_R _dtoa_r
265 # else /* !_NO_LONGDBL */
267 extern char *_ldtoa_r (struct _reent
*, _LONG_DOUBLE
, int,
268 int, int *, int *, char **);
270 extern int _ldcheck (_LONG_DOUBLE
*);
272 # define _PRINTF_FLOAT_TYPE _LONG_DOUBLE
273 # define _DTOA_R _ldtoa_r
274 # define FREXP frexpl
275 # endif /* !_NO_LONGDBL */
277 static char *cvt(struct _reent
*, _PRINTF_FLOAT_TYPE
, int, int, char *, int *,
280 static int exponent(char *, int, int);
282 #endif /* FLOATING_POINT */
284 /* BUF must be big enough for the maximum %#llo (assuming long long is
285 at most 64 bits, this would be 23 characters), the maximum
286 multibyte character %C, and the maximum default precision of %La
287 (assuming long double is at most 128 bits with 113 bits of
288 mantissa, this would be 29 characters). %e, %f, and %g use
289 reentrant storage shared with mprec. All other formats that use
290 buf get by with fewer characters. Making BUF slightly bigger
291 reduces the need for malloc in %.*a and %S, when large precision or
292 long strings are processed.
293 The bigger size of 100 bytes is used on systems which allow number
294 strings using the locale's grouping character. Since that's a multibyte
295 value, we should use a conservative value.
297 #ifdef _WANT_IO_C99_FORMATS
302 #if defined _MB_CAPABLE && MB_LEN_MAX > BUF
304 # define BUF MB_LEN_MAX
308 # define quad_t long long
309 # define u_quad_t unsigned long long
312 # define u_quad_t unsigned long
315 typedef quad_t
* quad_ptr_t
;
316 typedef void *void_ptr_t
;
317 typedef char * char_ptr_t
;
318 typedef long * long_ptr_t
;
319 typedef int * int_ptr_t
;
320 typedef short * short_ptr_t
;
324 # define MAX_POS_ARGS NL_ARGMAX
326 # define MAX_POS_ARGS 32
337 _LONG_DOUBLE val__LONG_DOUBLE
;
338 int_ptr_t val_int_ptr_t
;
339 short_ptr_t val_short_ptr_t
;
340 long_ptr_t val_long_ptr_t
;
341 char_ptr_t val_char_ptr_t
;
342 quad_ptr_t val_quad_ptr_t
;
343 void_ptr_t val_void_ptr_t
;
345 u_quad_t val_u_quad_t
;
349 static union arg_val
*
350 get_arg (struct _reent
*data
, int n
, char *fmt
,
351 va_list *ap
, int *numargs
, union arg_val
*args
,
352 int *arg_type
, char **last_fmt
);
353 #endif /* !_NO_POS_ARGS */
356 * Macros for converting digits to letters and vice versa
358 #define to_digit(c) ((c) - '0')
359 #define is_digit(c) ((unsigned)to_digit (c) <= 9)
360 #define to_char(n) ((n) + '0')
363 * Flags used during conversion.
365 #define ALT 0x001 /* alternate form */
366 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
367 #define LADJUST 0x004 /* left adjustment */
368 #define LONGDBL 0x008 /* long double */
369 #define LONGINT 0x010 /* long integer */
371 # define QUADINT 0x020 /* quad integer */
372 #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
373 that %lld behaves the same as %ld, not as %d, as expected if:
374 sizeof (long long) = sizeof long > sizeof int */
375 # define QUADINT LONGINT
377 #define SHORTINT 0x040 /* short integer */
378 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
379 #define FPT 0x100 /* Floating point number */
380 #ifdef _WANT_IO_C99_FORMATS
381 # define CHARINT 0x200 /* char as integer */
382 #else /* define as 0, to make SARG and UARG occupy fewer instructions */
385 #ifdef _WANT_IO_C99_FORMATS
386 # define GROUPING 0x400 /* use grouping ("'" flag) */
389 int _VFPRINTF_R (struct _reent
*, FILE *, const char *, va_list);
398 result
= _VFPRINTF_R (_REENT
, fp
, fmt0
, ap
);
401 #endif /* STRING_ONLY */
404 _VFPRINTF_R (struct _reent
*data
,
409 register char *fmt
; /* format string */
410 register int ch
; /* character from fmt */
411 register int n
, m
; /* handy integers (short term usage) */
412 register char *cp
; /* handy char pointer (short term usage) */
413 register int flags
; /* flags as above */
414 char *fmt_anchor
; /* current format spec being processed */
416 int N
; /* arg number */
417 int arg_index
; /* index into args processed directly */
418 int numargs
; /* number of varargs read */
419 char *saved_fmt
; /* saved fmt pointer */
420 union arg_val args
[MAX_POS_ARGS
];
421 int arg_type
[MAX_POS_ARGS
];
422 int is_pos_arg
; /* is current format positional? */
423 int old_is_pos_arg
; /* is current format positional? */
425 int ret
; /* return value accumulator */
426 int width
; /* width from format (%8d), or 0 */
427 int prec
; /* precision from format (%.3d), or -1 */
428 char sign
; /* sign prefix (' ', '+', '-', or \0) */
429 #ifdef _WANT_IO_C99_FORMATS
430 /* locale specific numeric grouping */
431 char *thousands_sep
= NULL
;
432 size_t thsnd_len
= 0;
433 const char *grouping
= NULL
;
435 #ifdef FLOATING_POINT
436 char *decimal_point
= _localeconv_r (data
)->decimal_point
;
437 size_t decp_len
= strlen (decimal_point
);
438 char softsign
; /* temporary negative sign for floats */
439 union { int i
; _PRINTF_FLOAT_TYPE fp
; } _double_
= {0};
440 # define _fpvalue (_double_.fp)
441 int expt
; /* integer value of exponent */
442 int expsize
= 0; /* character count for expstr */
443 char expstr
[MAXEXPLEN
]; /* buffer for exponent string */
444 int lead
; /* sig figs before decimal or group sep */
445 #endif /* FLOATING_POINT */
446 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
447 int ndig
= 0; /* actual number of digits returned by cvt */
449 #if defined (FLOATING_POINT) && defined (_WANT_IO_C99_FORMATS)
450 int nseps
; /* number of group separators with ' */
451 int nrepeats
; /* number of repeats of the last group */
453 u_quad_t _uquad
; /* integer arguments %[diouxX] */
454 enum { OCT
, DEC
, HEX
} base
;/* base for [diouxX] conversion */
455 int dprec
; /* a copy of prec if [diouxX], 0 otherwise */
456 int realsz
; /* field size expanded by dprec */
457 int size
; /* size of converted field or string */
458 char *xdigs
= NULL
; /* digits for [xX] conversion */
459 #ifdef _FVWRITE_IN_STREAMIO
461 struct __suio uio
; /* output information: summary */
462 struct __siov iov
[NIOV
];/* ... and individual io vectors */
463 register struct __siov
*iovp
;/* for PRINT macro */
465 char buf
[BUF
]; /* space for %c, %S, %[diouxX], %[aA] */
466 char ox
[2]; /* space for 0x hex-prefix */
469 mbstate_t state
; /* mbtowc calls from library must not change state */
471 char *malloc_buf
= NULL
;/* handy pointer for malloced buffers */
474 * Choose PADSIZE to trade efficiency vs. size. If larger printf
475 * fields occur frequently, increase PADSIZE and make the initialisers
478 #define PADSIZE 16 /* pad chunk size */
479 static const char blanks
[PADSIZE
] =
480 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
481 static const char zeroes
[PADSIZE
] =
482 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
485 memset (&state
, '\0', sizeof (state
));
488 * BEWARE, these `goto error' on error, and PAD uses `n'.
490 #ifdef _FVWRITE_IN_STREAMIO
491 #define PRINT(ptr, len) { \
492 iovp->iov_base = (ptr); \
493 iovp->iov_len = (len); \
494 uio.uio_resid += (len); \
496 if (++uio.uio_iovcnt >= NIOV) { \
497 if (__SPRINT(data, fp, &uio)) \
502 #define PAD(howmany, with) { \
503 if ((n = (howmany)) > 0) { \
504 while (n > PADSIZE) { \
505 PRINT (with, PADSIZE); \
511 #define PRINTANDPAD(p, ep, len, with) { \
512 int n = (ep) - (p); \
517 PAD((len) - (n > 0 ? n : 0), (with)); \
520 if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
522 uio.uio_iovcnt = 0; \
526 #define PRINT(ptr, len) { \
527 if (__SPRINT (data, fp, (ptr), (len)) == EOF) \
530 #define PAD(howmany, with) { \
531 if ((n = (howmany)) > 0) { \
532 while (n > PADSIZE) { \
533 PRINT (with, PADSIZE); \
539 #define PRINTANDPAD(p, ep, len, with) { \
540 int n = (ep) - (p); \
545 PAD((len) - (n > 0 ? n : 0), (with)); \
550 /* Macros to support positional arguments */
552 # define GET_ARG(n, ap, type) \
555 ? args[n].val_##type \
556 : get_arg (data, n, fmt_anchor, &ap, &numargs, args, \
557 arg_type, &saved_fmt)->val_##type) \
558 : (arg_index++ < numargs \
559 ? args[n].val_##type \
560 : (numargs < MAX_POS_ARGS \
561 ? args[numargs++].val_##type = va_arg (ap, type) \
562 : va_arg (ap, type))))
564 # define GET_ARG(n, ap, type) (va_arg (ap, type))
568 * To extend shorts properly, we need both signed and unsigned
569 * argument extraction methods.
573 (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
574 flags&LONGINT ? GET_ARG (N, ap, long) : \
575 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
576 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
577 (long)GET_ARG (N, ap, int))
579 (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
580 flags&LONGINT ? GET_ARG (N, ap, u_long) : \
581 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
582 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
583 (u_long)GET_ARG (N, ap, u_int))
586 (flags&LONGINT ? GET_ARG (N, ap, long) : \
587 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
588 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
589 (long)GET_ARG (N, ap, int))
591 (flags&LONGINT ? GET_ARG (N, ap, u_long) : \
592 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
593 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
594 (u_long)GET_ARG (N, ap, u_int))
598 /* Initialize std streams if not dealing with sprintf family. */
599 CHECK_INIT (data
, fp
);
600 _newlib_flockfile_start (fp
);
602 if (ORIENT(fp
, -1) != -1) {
603 _newlib_flockfile_exit (fp
);
607 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
608 if (cantwrite (data
, fp
)) {
609 _newlib_flockfile_exit (fp
);
613 #ifdef _UNBUF_STREAM_OPT
614 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
615 if ((fp
->_flags
& (__SNBF
|__SWR
|__SRW
)) == (__SNBF
|__SWR
) &&
617 _newlib_flockfile_exit (fp
);
618 return (__sbprintf (data
, fp
, fmt0
, ap
));
621 #else /* STRING_ONLY */
622 /* Create initial buffer if we are called by asprintf family. */
623 if (fp
->_flags
& __SMBF
&& !fp
->_bf
._base
)
625 fp
->_bf
._base
= fp
->_p
= _malloc_r (data
, 64);
628 _REENT_ERRNO(data
) = ENOMEM
;
633 #endif /* STRING_ONLY */
636 #ifdef _FVWRITE_IN_STREAMIO
637 uio
.uio_iov
= iovp
= iov
;
651 * Scan the format for conversions (`%' character).
656 while ((n
= __MBTOWC (data
, &wc
, fmt
, MB_CUR_MAX
,
659 /* Wave invalid chars through. */
660 memset (&state
, 0, sizeof state
);
668 while (*fmt
!= '\0' && *fmt
!= '%')
671 if ((m
= fmt
- cp
) != 0) {
683 fmt
++; /* skip over '%' */
690 #ifdef FLOATING_POINT
692 #ifdef _WANT_IO_C99_FORMATS
693 nseps
= nrepeats
= 0;
702 reswitch
: switch (ch
) {
703 #ifdef _WANT_IO_C99_FORMATS
705 thousands_sep
= _localeconv_r (data
)->thousands_sep
;
706 thsnd_len
= strlen (thousands_sep
);
707 grouping
= _localeconv_r (data
)->grouping
;
708 if (thsnd_len
> 0 && grouping
&& *grouping
)
714 * ``If the space and + flags both appear, the space
715 * flag will be ignored.''
726 /* we must check for positional arg used for dynamic width */
728 old_is_pos_arg
= is_pos_arg
;
730 if (is_digit (*fmt
)) {
736 n
= 10 * n
+ to_digit (ch
);
738 } while (is_digit (ch
));
741 if (n
<= MAX_POS_ARGS
) {
753 #endif /* !_NO_POS_ARGS */
756 * ``A negative field width argument is taken as a
757 * - flag followed by a positive field width.''
759 * They don't exclude field widths read from args.
761 width
= GET_ARG (n
, ap
, int);
763 is_pos_arg
= old_is_pos_arg
;
776 if ((ch
= *fmt
++) == '*') {
778 /* we must check for positional arg used for dynamic width */
780 old_is_pos_arg
= is_pos_arg
;
782 if (is_digit (*fmt
)) {
788 n
= 10 * n
+ to_digit (ch
);
790 } while (is_digit (ch
));
793 if (n
<= MAX_POS_ARGS
) {
805 #endif /* !_NO_POS_ARGS */
806 prec
= GET_ARG (n
, ap
, int);
808 is_pos_arg
= old_is_pos_arg
;
815 while (is_digit (ch
)) {
816 n
= 10 * n
+ to_digit (ch
);
819 prec
= n
< 0 ? -1 : n
;
823 * ``Note that 0 is taken as a flag, not as the
824 * beginning of a field width.''
829 case '1': case '2': case '3': case '4':
830 case '5': case '6': case '7': case '8': case '9':
833 n
= 10 * n
+ to_digit (ch
);
835 } while (is_digit (ch
));
838 if (n
<= MAX_POS_ARGS
) {
846 #endif /* !_NO_POS_ARGS */
849 #ifdef FLOATING_POINT
855 #ifdef _WANT_IO_C99_FORMATS
864 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
872 case 'q': /* extension */
875 #ifdef _WANT_IO_C99_FORMATS
877 if (sizeof (intmax_t) == sizeof (long))
883 if (sizeof (size_t) < sizeof (int))
884 /* POSIX states size_t is 16 or more bits, as is short. */
886 else if (sizeof (size_t) == sizeof (int))
887 /* no flag needed */;
888 else if (sizeof (size_t) <= sizeof (long))
891 /* POSIX states that at least one programming
892 environment must support size_t no wider than
893 long, but that means other environments can
894 have size_t as wide as long long. */
898 if (sizeof (ptrdiff_t) < sizeof (int))
899 /* POSIX states ptrdiff_t is 16 or more bits, as
902 else if (sizeof (ptrdiff_t) == sizeof (int))
903 /* no flag needed */;
904 else if (sizeof (ptrdiff_t) <= sizeof (long))
907 /* POSIX states that at least one programming
908 environment must support ptrdiff_t no wider than
909 long, but that means other environments can
910 have ptrdiff_t as wide as long long. */
914 #endif /* _WANT_IO_C99_FORMATS */
918 if (ch
== 'C' || (flags
& LONGINT
)) {
921 memset ((void *)&ps
, '\0', sizeof (mbstate_t));
922 if ((size
= (int)_wcrtomb_r (data
, cp
,
923 (wchar_t)GET_ARG (N
, ap
, wint_t),
925 fp
->_flags
|= __SERR
;
930 #endif /* _MB_CAPABLE */
932 *cp
= GET_ARG (N
, ap
, int);
937 case 'D': /* extension */
944 if ((quad_t
)_uquad
< 0)
946 if ((long) _uquad
< 0)
955 #ifdef FLOATING_POINT
956 # ifdef _WANT_IO_C99_FORMATS
967 if (flags
& LONGDBL
) {
968 _fpvalue
= (double) GET_ARG (N
, ap
, _LONG_DOUBLE
);
970 _fpvalue
= GET_ARG (N
, ap
, double);
973 /* do this before tricky precision changes
975 If the output is infinite or NaN, leading
976 zeros are not permitted. Otherwise, scanf
977 could not read what printf wrote.
979 if (isinf (_fpvalue
)) {
982 if (ch
<= 'G') /* 'A', 'E', 'F', or 'G' */
990 if (isnan (_fpvalue
)) {
991 if (signbit (_fpvalue
))
993 if (ch
<= 'G') /* 'A', 'E', 'F', or 'G' */
1002 # else /* !_NO_LONGDBL */
1004 if (flags
& LONGDBL
) {
1005 _fpvalue
= GET_ARG (N
, ap
, _LONG_DOUBLE
);
1007 _fpvalue
= (_LONG_DOUBLE
)GET_ARG (N
, ap
, double);
1010 /* do this before tricky precision changes */
1011 expt
= _ldcheck (&_fpvalue
);
1015 if (ch
<= 'G') /* 'A', 'E', 'F', or 'G' */
1024 if (signbit (_fpvalue
))
1026 if (ch
<= 'G') /* 'A', 'E', 'F', or 'G' */
1034 # endif /* !_NO_LONGDBL */
1036 # ifdef _WANT_IO_C99_FORMATS
1037 if (ch
== 'a' || ch
== 'A') {
1039 ox
[1] = ch
== 'a' ? 'x' : 'X';
1044 (char *)_malloc_r (data
, prec
+ 1))
1047 fp
->_flags
|= __SERR
;
1055 # endif /* _WANT_IO_C99_FORMATS */
1058 } else if ((ch
== 'g' || ch
== 'G') && prec
== 0) {
1064 cp
= cvt (data
, _fpvalue
, prec
, flags
, &softsign
,
1065 &expt
, ch
, &ndig
, cp
);
1067 if (ch
== 'g' || ch
== 'G') {
1068 if (expt
<= -4 || expt
> prec
)
1069 ch
-= 2; /* 'e' or 'E' */
1073 # ifdef _WANT_IO_C99_FORMATS
1077 if (ch
<= 'e') { /* 'a', 'A', 'e', or 'E' fmt */
1079 expsize
= exponent (expstr
, expt
, ch
);
1080 size
= expsize
+ ndig
;
1081 if (ndig
> 1 || flags
& ALT
)
1083 # ifdef _WANT_IO_C99_FORMATS
1087 if (ch
== 'f') { /* f fmt */
1090 if (prec
|| flags
& ALT
)
1091 size
+= prec
+ decp_len
;
1093 size
= (prec
|| flags
& ALT
)
1094 ? prec
+ 1 + decp_len
1096 } else if (expt
>= ndig
) { /* fixed g fmt */
1101 size
= ndig
+ decp_len
;
1105 # ifdef _WANT_IO_C99_FORMATS
1106 if ((flags
& GROUPING
) && expt
> 0) {
1107 /* space for thousands' grouping */
1108 nseps
= nrepeats
= 0;
1110 while (*grouping
!= CHAR_MAX
) {
1111 if (lead
<= *grouping
)
1120 size
+= (nseps
+ nrepeats
) * thsnd_len
;
1129 #endif /* FLOATING_POINT */
1130 #ifdef _GLIBC_EXTENSION
1131 case 'm': /* extension */
1134 cp
= _strerror_r (data
, _REENT_ERRNO(data
), 1, &dummy
);
1140 #ifndef _NO_LONGLONG
1141 if (flags
& QUADINT
)
1142 *GET_ARG (N
, ap
, quad_ptr_t
) = ret
;
1145 if (flags
& LONGINT
)
1146 *GET_ARG (N
, ap
, long_ptr_t
) = ret
;
1147 else if (flags
& SHORTINT
)
1148 *GET_ARG (N
, ap
, short_ptr_t
) = ret
;
1149 #ifdef _WANT_IO_C99_FORMATS
1150 else if (flags
& CHARINT
)
1151 *GET_ARG (N
, ap
, char_ptr_t
) = ret
;
1154 *GET_ARG (N
, ap
, int_ptr_t
) = ret
;
1155 continue; /* no output */
1156 case 'O': /* extension */
1162 #ifdef _WANT_IO_C99_FORMATS
1168 * ``The argument shall be a pointer to void. The
1169 * value of the pointer is converted to a sequence
1170 * of printable characters, in an implementation-
1175 _uquad
= (uintptr_t) GET_ARG (N
, ap
, void_ptr_t
);
1177 xdigs
= "0123456789abcdef";
1183 #ifdef _WANT_IO_C99_FORMATS
1186 cp
= GET_ARG (N
, ap
, char_ptr_t
);
1187 #ifdef _GLIBC_EXTENSION
1191 #ifndef __OPTIMIZE_SIZE__
1192 /* Behavior is undefined if the user passed a
1193 NULL string when precision is not 0.
1194 However, if we are not optimizing for size,
1195 we might as well mirror glibc behavior. */
1198 size
= ((unsigned) prec
> 6U) ? 6 : prec
;
1201 #endif /* __OPTIMIZE_SIZE__ */
1203 if (ch
== 'S' || (flags
& LONGINT
)) {
1207 wcp
= (const wchar_t *)cp
;
1209 memset ((void *)&ps
, '\0', sizeof (mbstate_t));
1211 /* Count number of bytes needed for multibyte
1212 string that will be produced from widechar
1216 if (wcp
[m
] == L
'\0')
1218 if ((n
= (int)_wcrtomb_r (data
,
1219 buf
, wcp
[m
], &ps
)) == -1) {
1220 fp
->_flags
|= __SERR
;
1223 if (n
+ size
> prec
)
1232 if ((size
= (int)_wcsrtombs_r (data
,
1233 NULL
, &wcp
, 0, &ps
)) == -1) {
1234 fp
->_flags
|= __SERR
;
1237 wcp
= (const wchar_t *)cp
;
1245 (char *)_malloc_r (data
, size
+ 1))
1247 fp
->_flags
|= __SERR
;
1254 /* Convert widechar string to multibyte string. */
1255 memset ((void *)&ps
, '\0', sizeof (mbstate_t));
1256 if (_wcsrtombs_r (data
, cp
, &wcp
, size
, &ps
)
1258 fp
->_flags
|= __SERR
;
1264 #endif /* _MB_CAPABLE */
1267 * can't use strlen; can only look for the
1268 * NUL in the first `prec' characters, and
1269 * strlen () will go further.
1271 char *p
= memchr (cp
, 0, prec
);
1281 case 'U': /* extension */
1289 xdigs
= "0123456789ABCDEF";
1292 xdigs
= "0123456789abcdef";
1293 hex
: _uquad
= UARG ();
1295 /* leading 0x/X only if non-zero */
1296 if (flags
& ALT
&& _uquad
!= 0) {
1302 #ifdef _WANT_IO_C99_FORMATS
1305 /* unsigned conversions */
1306 nosign
: sign
= '\0';
1308 * ``... diouXx conversions ... if a precision is
1309 * specified, the 0 flag will be ignored.''
1312 number
: if ((dprec
= prec
) >= 0)
1316 * ``The result of converting a zero value with an
1317 * explicit precision of zero is no characters.''
1321 if (_uquad
!= 0 || prec
!= 0) {
1323 * Unsigned mod is hard, and unsigned mod
1324 * by a constant is easier than that by
1325 * a variable; hence this switch.
1330 *--cp
= to_char (_uquad
& 7);
1333 /* handle octal leading 0 */
1334 if (flags
& ALT
&& *cp
!= '0')
1339 /* many numbers are 1 digit */
1341 *--cp
= to_char(_uquad
);
1344 #ifdef _WANT_IO_C99_FORMATS
1348 *--cp
= to_char (_uquad
% 10);
1349 #ifdef _WANT_IO_C99_FORMATS
1351 /* If (*grouping == CHAR_MAX) then no
1353 if ((flags
& GROUPING
)
1354 && ndig
== *grouping
1355 && *grouping
!= CHAR_MAX
1358 strncpy (cp
, thousands_sep
,
1361 /* If (grouping[1] == '\0') then we
1362 have to use *grouping character
1363 (last grouping rule) for all
1365 if (grouping
[1] != '\0')
1370 } while (_uquad
!= 0);
1375 *--cp
= xdigs
[_uquad
& 15];
1381 cp
= "bug in vfprintf: bad base";
1387 * ...result is to be converted to an 'alternate form'.
1388 * For o conversion, it increases the precision to force
1389 * the first digit of the result to be a zero."
1392 * To demonstrate this case, compile and run:
1393 * printf ("%#.0o",0);
1395 else if (base
== OCT
&& (flags
& ALT
))
1398 size
= buf
+ BUF
- cp
;
1401 default: /* "%?" prints ?, unless ? is NUL */
1404 /* pretend it was %c with argument ch */
1413 * All reasonable formats wind up here. At this point, `cp'
1414 * points to a string which (if not flags&LADJUST) should be
1415 * padded out to `width' places. If flags&ZEROPAD, it should
1416 * first be prefixed by any sign or other prefix; otherwise,
1417 * it should be blank padded before the prefix is emitted.
1418 * After any left-hand padding and prefixing, emit zeroes
1419 * required by a decimal [diouxX] precision, then print the
1420 * string proper, then emit zeroes required by any leftover
1421 * floating precision; finally, if LADJUST, pad with blanks.
1422 * If flags&FPT, ch must be in [aAeEfg].
1424 * Compute actual size, so we know how much to pad.
1425 * size excludes decimal prec; realsz includes it.
1427 realsz
= dprec
> size
? dprec
: size
;
1430 if (flags
& HEXPREFIX
)
1433 /* right-adjusting blank padding */
1434 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
1435 PAD (width
- realsz
, blanks
);
1440 if (flags
& HEXPREFIX
)
1443 /* right-adjusting zero padding */
1444 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
1445 PAD (width
- realsz
, zeroes
);
1447 /* leading zeroes from decimal precision */
1448 PAD (dprec
- size
, zeroes
);
1450 /* the string or number proper */
1451 #ifdef FLOATING_POINT
1452 if ((flags
& FPT
) == 0) {
1454 } else { /* glue together f_p fragments */
1455 if (ch
>= 'f') { /* 'f' or 'g' */
1456 if (_fpvalue
== 0) {
1457 /* kludge for __dtoa irregularity */
1459 if (expt
< ndig
|| flags
& ALT
) {
1460 PRINT (decimal_point
, decp_len
);
1461 PAD (ndig
- 1, zeroes
);
1463 } else if (expt
<= 0) {
1465 if (expt
|| ndig
|| flags
& ALT
) {
1466 PRINT (decimal_point
, decp_len
);
1467 PAD (-expt
, zeroes
);
1472 PRINTANDPAD(cp
, convbuf
+ ndig
,
1475 #ifdef _WANT_IO_C99_FORMATS
1476 if (flags
& GROUPING
) {
1477 while (nseps
> 0 || nrepeats
> 0) {
1484 PRINT(thousands_sep
, thsnd_len
);
1485 PRINTANDPAD (cp
, convbuf
+ ndig
,
1489 if (cp
> convbuf
+ ndig
)
1490 cp
= convbuf
+ ndig
;
1493 if (expt
< ndig
|| flags
& ALT
)
1494 PRINT (decimal_point
, decp_len
);
1495 PRINTANDPAD (cp
, convbuf
+ ndig
,
1496 ndig
- expt
, zeroes
);
1498 } else { /* 'a', 'A', 'e', or 'E' */
1499 if (ndig
> 1 || flags
& ALT
) {
1502 PRINT (decimal_point
, decp_len
);
1504 PRINT (cp
, ndig
- 1);
1505 } else /* 0.[0..] */
1506 /* __dtoa irregularity */
1507 PAD (ndig
- 1, zeroes
);
1510 PRINT (expstr
, expsize
);
1513 #else /* !FLOATING_POINT */
1516 /* left-adjusting padding (always blank) */
1517 if (flags
& LADJUST
)
1518 PAD (width
- realsz
, blanks
);
1520 /* finally, adjust ret */
1521 ret
+= width
> realsz
? width
: realsz
;
1523 FLUSH (); /* copy out the I/O vectors */
1525 if (malloc_buf
!= NULL
) {
1526 _free_r (data
, malloc_buf
);
1533 if (malloc_buf
!= NULL
)
1534 _free_r (data
, malloc_buf
);
1536 _newlib_flockfile_end (fp
);
1538 return (__sferror (fp
) ? EOF
: ret
);
1542 #ifdef FLOATING_POINT
1544 /* Using reentrant DATA, convert finite VALUE into a string of digits
1545 with no decimal point, using NDIGITS precision and FLAGS as guides
1546 to whether trailing zeros must be included. Set *SIGN to nonzero
1547 if VALUE was negative. Set *DECPT to the exponent plus one. Set
1548 *LENGTH to the length of the returned string. CH must be one of
1549 [aAeEfFgG]; if it is [aA], then the return string lives in BUF,
1550 otherwise the return value shares the mprec reentrant storage. */
1552 cvt(struct _reent
*data
, _PRINTF_FLOAT_TYPE value
, int ndigits
, int flags
,
1553 char *sign
, int *decpt
, int ch
, int *length
, char *buf
)
1556 char *digits
, *bp
, *rve
;
1558 union double_union tmp
;
1561 if (word0 (tmp
) & Sign_bit
) { /* this will check for < 0 and -0.0 */
1566 # else /* !_NO_LONGDBL */
1574 if (ld
.ieee
.sign
) { /* this will check for < 0 and -0.0 */
1579 # endif /* !_NO_LONGDBL */
1581 # ifdef _WANT_IO_C99_FORMATS
1582 if (ch
== 'a' || ch
== 'A') {
1583 /* This code assumes FLT_RADIX is a power of 2. The initial
1584 division ensures the digit before the decimal will be less
1585 than FLT_RADIX (unless it is rounded later). There is no
1586 loss of precision in these calculations. */
1587 value
= FREXP (value
, decpt
) / 8;
1590 digits
= ch
== 'a' ? "0123456789abcdef" : "0123456789ABCDEF";
1596 *bp
++ = digits
[mode
];
1597 } while (ndigits
-- && value
);
1598 if (value
> 0.5 || (value
== 0.5 && mode
& 1)) {
1601 while (*--rve
== digits
[0xf]) {
1604 *rve
= *rve
== '9' ? digits
[0xa] : *rve
+ 1;
1606 while (ndigits
-- >= 0) {
1613 # endif /* _WANT_IO_C99_FORMATS */
1614 if (ch
== 'f' || ch
== 'F') {
1615 mode
= 3; /* ndigits after the decimal point */
1617 /* To obtain ndigits after the decimal point for the 'e'
1618 * and 'E' formats, round to ndigits + 1 significant
1621 if (ch
== 'e' || ch
== 'E') {
1624 mode
= 2; /* ndigits significant digits */
1627 digits
= _DTOA_R (data
, value
, mode
, ndigits
, decpt
, &dsgn
, &rve
);
1629 if ((ch
!= 'g' && ch
!= 'G') || flags
& ALT
) { /* Print trailing zeros */
1630 bp
= digits
+ ndigits
;
1631 if (ch
== 'f' || ch
== 'F') {
1632 if (*digits
== '0' && value
)
1633 *decpt
= -ndigits
+ 1;
1636 if (value
== 0) /* kludge for __dtoa irregularity */
1641 *length
= rve
- digits
;
1646 exponent(char *p0
, int exp
, int fmtch
)
1648 register char *p
, *t
;
1649 char expbuf
[MAXEXPLEN
];
1650 # ifdef _WANT_IO_C99_FORMATS
1651 int isa
= fmtch
== 'a' || fmtch
== 'A';
1657 *p
++ = isa
? 'p' - 'a' + fmtch
: fmtch
;
1664 t
= expbuf
+ MAXEXPLEN
;
1667 *--t
= to_char (exp
% 10);
1668 } while ((exp
/= 10) > 9);
1669 *--t
= to_char (exp
);
1670 for (; t
< expbuf
+ MAXEXPLEN
; *p
++ = *t
++);
1675 *p
++ = to_char (exp
);
1679 #endif /* FLOATING_POINT */
1682 #ifndef _NO_POS_ARGS
1684 /* Positional argument support.
1685 Written by Jeff Johnston
1687 Copyright (c) 2002 Red Hat Incorporated.
1688 All rights reserved.
1690 Redistribution and use in source and binary forms, with or without
1691 modification, are permitted provided that the following conditions are met:
1693 Redistributions of source code must retain the above copyright
1694 notice, this list of conditions and the following disclaimer.
1696 Redistributions in binary form must reproduce the above copyright
1697 notice, this list of conditions and the following disclaimer in the
1698 documentation and/or other materials provided with the distribution.
1700 The name of Red Hat Incorporated may not be used to endorse
1701 or promote products derived from this software without specific
1702 prior written permission.
1704 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1705 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1706 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1707 DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1708 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1709 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1710 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1711 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1712 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1713 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1715 /* The below constant state tables are shared between all versions of
1716 vfprintf and vfwprintf. They must only be defined once, which we do in
1717 the STRING_ONLY/INTEGER_ONLY versions here. */
1718 #if defined (STRING_ONLY) && defined(INTEGER_ONLY)
1720 const __CH_CLASS __chclass
[256] = {
1721 /* 00-07 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1722 /* 08-0f */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1723 /* 10-17 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1724 /* 18-1f */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1725 /* 20-27 */ FLAG
, OTHER
, OTHER
, FLAG
, DOLLAR
, OTHER
, OTHER
, FLAG
,
1726 /* 28-2f */ OTHER
, OTHER
, STAR
, FLAG
, OTHER
, FLAG
, DOT
, OTHER
,
1727 /* 30-37 */ ZERO
, DIGIT
, DIGIT
, DIGIT
, DIGIT
, DIGIT
, DIGIT
, DIGIT
,
1728 /* 38-3f */ DIGIT
, DIGIT
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1729 /* 40-47 */ OTHER
, SPEC
, OTHER
, SPEC
, SPEC
, SPEC
, SPEC
, SPEC
,
1730 /* 48-4f */ OTHER
, OTHER
, OTHER
, OTHER
, MODFR
, OTHER
, OTHER
, SPEC
,
1731 /* 50-57 */ OTHER
, OTHER
, OTHER
, SPEC
, OTHER
, SPEC
, OTHER
, OTHER
,
1732 /* 58-5f */ SPEC
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1733 /* 60-67 */ OTHER
, SPEC
, OTHER
, SPEC
, SPEC
, SPEC
, SPEC
, SPEC
,
1734 /* 68-6f */ MODFR
, SPEC
, MODFR
, OTHER
, MODFR
, OTHER
, SPEC
, SPEC
,
1735 /* 70-77 */ SPEC
, MODFR
, OTHER
, SPEC
, MODFR
, SPEC
, OTHER
, OTHER
,
1736 /* 78-7f */ SPEC
, OTHER
, MODFR
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1737 /* 80-87 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1738 /* 88-8f */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1739 /* 90-97 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1740 /* 98-9f */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1741 /* a0-a7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1742 /* a8-af */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1743 /* b0-b7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1744 /* b8-bf */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1745 /* c0-c7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1746 /* c8-cf */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1747 /* d0-d7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1748 /* d8-df */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1749 /* e0-e7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1750 /* e8-ef */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1751 /* f0-f7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1752 /* f8-ff */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1755 const __STATE __state_table
[MAX_STATE
][MAX_CH_CLASS
] = {
1756 /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
1757 /* START */ { SFLAG
, WDIG
, DONE
, SMOD
, DONE
, SDOT
, VARW
, SFLAG
, DONE
},
1758 /* SFLAG */ { SFLAG
, WDIG
, DONE
, SMOD
, DONE
, SDOT
, VARW
, SFLAG
, DONE
},
1759 /* WDIG */ { DONE
, DONE
, WIDTH
, SMOD
, DONE
, SDOT
, DONE
, DONE
, DONE
},
1760 /* WIDTH */ { DONE
, DONE
, DONE
, SMOD
, DONE
, SDOT
, DONE
, DONE
, DONE
},
1761 /* SMOD */ { DONE
, DONE
, DONE
, DONE
, DONE
, DONE
, DONE
, DONE
, DONE
},
1762 /* SDOT */ { SDOT
, PREC
, DONE
, SMOD
, DONE
, DONE
, VARP
, DONE
, DONE
},
1763 /* VARW */ { DONE
, VWDIG
, DONE
, SMOD
, DONE
, SDOT
, DONE
, DONE
, DONE
},
1764 /* VARP */ { DONE
, VPDIG
, DONE
, SMOD
, DONE
, DONE
, DONE
, DONE
, DONE
},
1765 /* PREC */ { DONE
, DONE
, DONE
, SMOD
, DONE
, DONE
, DONE
, DONE
, DONE
},
1766 /* VWDIG */ { DONE
, DONE
, WIDTH
, DONE
, DONE
, DONE
, DONE
, DONE
, DONE
},
1767 /* VPDIG */ { DONE
, DONE
, PREC
, DONE
, DONE
, DONE
, DONE
, DONE
, DONE
},
1770 const __ACTION __action_table
[MAX_STATE
][MAX_CH_CLASS
] = {
1771 /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
1772 /* START */ { NOOP
, NUMBER
, NOOP
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
1773 /* SFLAG */ { NOOP
, NUMBER
, NOOP
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
1774 /* WDIG */ { NOOP
, NOOP
, GETPOS
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
1775 /* WIDTH */ { NOOP
, NOOP
, NOOP
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
1776 /* SMOD */ { NOOP
, NOOP
, NOOP
, NOOP
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
1777 /* SDOT */ { NOOP
, SKIPNUM
, NOOP
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
1778 /* VARW */ { NOOP
, NUMBER
, NOOP
, GETPW
, GETPWB
, GETPW
, NOOP
, NOOP
, NOOP
},
1779 /* VARP */ { NOOP
, NUMBER
, NOOP
, GETPW
, GETPWB
, NOOP
, NOOP
, NOOP
, NOOP
},
1780 /* PREC */ { NOOP
, NOOP
, NOOP
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
1781 /* VWDIG */ { NOOP
, NOOP
, PWPOS
, NOOP
, NOOP
, NOOP
, NOOP
, NOOP
, NOOP
},
1782 /* VPDIG */ { NOOP
, NOOP
, PWPOS
, NOOP
, NOOP
, NOOP
, NOOP
, NOOP
, NOOP
},
1785 #endif /* STRING_ONLY && INTEGER_ONLY */
1787 /* function to get positional parameter N where n = N - 1 */
1788 static union arg_val
*
1789 get_arg (struct _reent
*data
,
1794 union arg_val
*args
,
1801 int numargs
= *numargs_p
;
1803 __STATE state
, next_state
;
1806 int max_pos_arg
= n
;
1807 /* Only need types that can be reached via vararg promotions. */
1808 enum types
{ INT
, LONG_INT
, QUAD_INT
, CHAR_PTR
, DOUBLE
, LONG_DOUBLE
, WIDE_CHAR
};
1815 /* if this isn't the first call, pick up where we left off last time */
1816 if (*last_fmt
!= NULL
)
1820 memset (&wc_state
, '\0', sizeof (wc_state
));
1823 /* we need to process either to end of fmt string or until we have actually
1824 read the desired parameter from the vararg list. */
1825 while (*fmt
&& n
>= numargs
)
1828 while ((nbytes
= __MBTOWC (data
, &wc
, fmt
, MB_CUR_MAX
, &wc_state
)) > 0)
1838 while (*fmt
!= '\0' && *fmt
!= '%')
1845 # endif /* ! _MB_CAPABLE */
1852 /* Use state/action table to process format specifiers. We ignore invalid
1853 formats and we are only interested in information that tells us how to
1854 read the vararg list. */
1855 while (state
!= DONE
)
1858 chtype
= __chclass
[ch
];
1859 next_state
= __state_table
[state
][chtype
];
1860 action
= __action_table
[state
][chtype
];
1865 case GETMOD
: /* we have format modifier */
1869 /* No flag needed, since short and char promote to int. */
1877 # ifdef _WANT_IO_C99_FORMATS
1879 if (sizeof (intmax_t) == sizeof (long))
1885 if (sizeof (size_t) <= sizeof (int))
1886 /* no flag needed */;
1887 else if (sizeof (size_t) <= sizeof (long))
1890 /* POSIX states that at least one programming
1891 environment must support size_t no wider than
1892 long, but that means other environments can
1893 have size_t as wide as long long. */
1897 if (sizeof (ptrdiff_t) <= sizeof (int))
1898 /* no flag needed */;
1899 else if (sizeof (ptrdiff_t) <= sizeof (long))
1902 /* POSIX states that at least one programming
1903 environment must support ptrdiff_t no wider than
1904 long, but that means other environments can
1905 have ptrdiff_t as wide as long long. */
1908 # endif /* _WANT_IO_C99_FORMATS */
1911 # if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
1923 case GETARG
: /* we have format specifier */
1925 numargs
&= (MAX_POS_ARGS
- 1);
1926 /* process the specifier and translate it to a type to fetch from varargs */
1935 if (flags
& LONGINT
)
1936 spec_type
= LONG_INT
;
1937 # ifndef _NO_LONGLONG
1938 else if (flags
& QUADINT
)
1939 spec_type
= QUAD_INT
;
1947 spec_type
= LONG_INT
;
1949 # ifdef _WANT_IO_C99_FORMATS
1959 # ifndef _NO_LONGDBL
1960 if (flags
& LONGDBL
)
1961 spec_type
= LONG_DOUBLE
;
1967 # ifdef _WANT_IO_C99_FORMATS
1972 spec_type
= CHAR_PTR
;
1975 # ifdef _WANT_IO_C99_FORMATS
1976 if (flags
& LONGINT
)
1977 spec_type
= WIDE_CHAR
;
1982 # ifdef _WANT_IO_C99_FORMATS
1984 spec_type
= WIDE_CHAR
;
1989 /* if we have a positional parameter, just store the type, otherwise
1990 fetch the parameter from the vararg list */
1992 arg_type
[pos
] = spec_type
;
1998 args
[numargs
++].val_long
= va_arg (*ap
, long);
2001 args
[numargs
++].val_quad_t
= va_arg (*ap
, quad_t
);
2004 args
[numargs
++].val_wint_t
= va_arg (*ap
, wint_t);
2007 args
[numargs
++].val_int
= va_arg (*ap
, int);
2010 args
[numargs
++].val_char_ptr_t
= va_arg (*ap
, char *);
2013 args
[numargs
++].val_double
= va_arg (*ap
, double);
2016 args
[numargs
++].val__LONG_DOUBLE
= va_arg (*ap
, _LONG_DOUBLE
);
2022 case GETPOS
: /* we have positional specifier */
2023 if (arg_type
[0] == -1)
2024 memset (arg_type
, 0, sizeof (int) * MAX_POS_ARGS
);
2026 max_pos_arg
= (max_pos_arg
> pos
? max_pos_arg
: pos
);
2028 case PWPOS
: /* we have positional specifier for width or precision */
2029 if (arg_type
[0] == -1)
2030 memset (arg_type
, 0, sizeof (int) * MAX_POS_ARGS
);
2032 arg_type
[number
] = INT
;
2033 max_pos_arg
= (max_pos_arg
> number
? max_pos_arg
: number
);
2035 case GETPWB
: /* we require format pushback */
2038 case GETPW
: /* we have a variable precision or width to acquire */
2039 args
[numargs
++].val_int
= va_arg (*ap
, int);
2041 case NUMBER
: /* we have a number to process */
2042 number
= (ch
- '0');
2043 while ((ch
= *fmt
) != '\0' && is_digit (ch
))
2045 number
= number
* 10 + (ch
- '0');
2049 case SKIPNUM
: /* we have a number to skip */
2050 while ((ch
= *fmt
) != '\0' && is_digit (ch
))
2055 break; /* do nothing */
2060 /* process all arguments up to at least the one we are looking for and if we
2061 have seen the end of the string, then process up to the max argument needed */
2063 last_arg
= max_pos_arg
;
2067 while (numargs
<= last_arg
)
2069 switch (arg_type
[numargs
])
2072 args
[numargs
++].val_long
= va_arg (*ap
, long);
2075 args
[numargs
++].val_quad_t
= va_arg (*ap
, quad_t
);
2078 args
[numargs
++].val_char_ptr_t
= va_arg (*ap
, char *);
2081 args
[numargs
++].val_double
= va_arg (*ap
, double);
2084 args
[numargs
++].val__LONG_DOUBLE
= va_arg (*ap
, _LONG_DOUBLE
);
2087 args
[numargs
++].val_wint_t
= va_arg (*ap
, wint_t);
2091 args
[numargs
++].val_int
= va_arg (*ap
, int);
2096 /* alter the global numargs value and keep a reference to the last bit of the fmt
2097 string we processed here because the caller will continue processing where we started */
2098 *numargs_p
= numargs
;
2102 #endif /* !_NO_POS_ARGS */