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)
177 # ifdef _FVWRITE_IN_STREAMIO
178 # define __SPRINT __ssprint_r
180 # define __SPRINT __ssputs_r
183 # ifdef _FVWRITE_IN_STREAMIO
184 # define __SPRINT __sprint_r
186 # define __SPRINT __sfputs_r
190 /* The __sprint_r/__ssprint_r functions are shared between all versions of
191 vfprintf and vfwprintf. They must only be defined once, which we do in
192 the INTEGER_ONLY versions here. */
195 #ifndef _FVWRITE_IN_STREAMIO
197 __ssputs_r (struct _reent
*ptr
,
205 if (len
>= w
&& fp
->_flags
& (__SMBF
| __SOPT
)) {
206 /* must be asprintf family */
208 int curpos
= (fp
->_p
- fp
->_bf
._base
);
209 /* Choose a geometric growth factor to avoid
210 * quadratic realloc behavior, but use a rate less
211 * than (1+sqrt(5))/2 to accomodate malloc
212 * overhead. asprintf EXPECTS us to overallocate, so
213 * that it can add a trailing \0 without
214 * reallocating. The new allocation should thus be
215 * max(prev_size*1.5, curpos+len+1). */
216 int newsize
= fp
->_bf
._size
* 3 / 2;
217 if (newsize
< curpos
+ len
+ 1)
218 newsize
= curpos
+ len
+ 1;
219 if (fp
->_flags
& __SOPT
)
221 /* asnprintf leaves original buffer alone. */
222 str
= (unsigned char *)_malloc_r (ptr
, newsize
);
225 _REENT_ERRNO(ptr
) = ENOMEM
;
228 memcpy (str
, fp
->_bf
._base
, curpos
);
229 fp
->_flags
= (fp
->_flags
& ~__SOPT
) | __SMBF
;
233 str
= (unsigned char *)_realloc_r (ptr
, fp
->_bf
._base
,
236 /* Free unneeded buffer. */
237 _free_r (ptr
, fp
->_bf
._base
);
238 /* Ensure correct errno, even if free
240 _REENT_ERRNO(ptr
) = ENOMEM
;
245 fp
->_p
= str
+ curpos
;
246 fp
->_bf
._size
= newsize
;
248 fp
->_w
= newsize
- curpos
;
252 (void)memmove ((void *) fp
->_p
, (void *) buf
, (size_t) (w
));
259 fp
->_flags
|= __SERR
;
265 __ssprint_r (struct _reent
*ptr
,
267 register struct __suio
*uio
)
271 register struct __siov
*iov
;
272 register const char *p
= NULL
;
277 if (uio
->uio_resid
== 0) {
289 if (len
>= w
&& fp
->_flags
& (__SMBF
| __SOPT
)) {
290 /* must be asprintf family */
292 int curpos
= (fp
->_p
- fp
->_bf
._base
);
293 /* Choose a geometric growth factor to avoid
294 * quadratic realloc behavior, but use a rate less
295 * than (1+sqrt(5))/2 to accomodate malloc
296 * overhead. asprintf EXPECTS us to overallocate, so
297 * that it can add a trailing \0 without
298 * reallocating. The new allocation should thus be
299 * max(prev_size*1.5, curpos+len+1). */
300 int newsize
= fp
->_bf
._size
* 3 / 2;
301 if (newsize
< curpos
+ len
+ 1)
302 newsize
= curpos
+ len
+ 1;
303 if (fp
->_flags
& __SOPT
)
305 /* asnprintf leaves original buffer alone. */
306 str
= (unsigned char *)_malloc_r (ptr
, newsize
);
309 _REENT_ERRNO(ptr
) = ENOMEM
;
312 memcpy (str
, fp
->_bf
._base
, curpos
);
313 fp
->_flags
= (fp
->_flags
& ~__SOPT
) | __SMBF
;
317 str
= (unsigned char *)_realloc_r (ptr
, fp
->_bf
._base
,
320 /* Free unneeded buffer. */
321 _free_r (ptr
, fp
->_bf
._base
);
322 /* Ensure correct errno, even if free
324 _REENT_ERRNO(ptr
) = ENOMEM
;
329 fp
->_p
= str
+ curpos
;
330 fp
->_bf
._size
= newsize
;
332 fp
->_w
= newsize
- curpos
;
336 (void)memmove ((void *) fp
->_p
, (void *) p
, (size_t) (w
));
339 w
= len
; /* pretend we copied all */
342 } while ((uio
->uio_resid
-= w
) != 0);
349 fp
->_flags
|= __SERR
;
354 #else /* !INTEGER_ONLY */
355 #ifndef _FVWRITE_IN_STREAMIO
356 int __ssputs_r (struct _reent
*, FILE *, const char *, size_t);
358 int __ssprint_r (struct _reent
*, FILE *, register struct __suio
*);
359 #endif /* !INTEGER_ONLY */
361 #else /* !STRING_ONLY */
364 #ifndef _FVWRITE_IN_STREAMIO
366 __sfputs_r (struct _reent
*ptr
,
373 #if defined _WIDE_ORIENT && (!defined _ELIX_LEVEL || _ELIX_LEVEL >= 4)
374 if (fp
->_flags2
& __SWID
) {
378 for (i
= 0; i
< (len
/ sizeof (wchar_t)); i
++) {
379 if (_fputwc_r (ptr
, p
[i
], fp
) == WEOF
)
386 for (i
= 0; i
< len
; i
++) {
387 if (_fputc_r (ptr
, buf
[i
], fp
) == EOF
)
395 * Flush out all the vectors defined by the given uio,
396 * then reset it so that it can be reused.
399 __sprint_r (struct _reent
*ptr
,
401 register struct __suio
*uio
)
403 register int err
= 0;
405 if (uio
->uio_resid
== 0) {
409 #if defined _WIDE_ORIENT && (!defined _ELIX_LEVEL || _ELIX_LEVEL >= 4)
410 if (fp
->_flags2
& __SWID
) {
416 for (; uio
->uio_resid
!= 0;
417 uio
->uio_resid
-= len
* sizeof (wchar_t), iov
++) {
418 p
= (wchar_t *) iov
->iov_base
;
419 len
= iov
->iov_len
/ sizeof (wchar_t);
420 for (i
= 0; i
< len
; i
++) {
421 if (_fputwc_r (ptr
, p
[i
], fp
) == WEOF
) {
429 err
= __sfvwrite_r(ptr
, fp
, uio
);
435 #else /* !INTEGER_ONLY */
436 #ifndef _FVWRITE_IN_STREAMIO
437 int __sfputs_r (struct _reent
*, FILE *, const char *buf
, size_t);
439 int __sprint_r (struct _reent
*, FILE *, register struct __suio
*);
440 #endif /* !INTEGER_ONLY */
442 #ifdef _UNBUF_STREAM_OPT
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.
448 * Make sure to avoid inlining.
451 __sbprintf (struct _reent
*rptr
,
458 unsigned char buf
[BUFSIZ
];
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
;
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
);
475 /* do the work, then copy any error status */
476 ret
= _VFPRINTF_R (rptr
, &fake
, fmt
, ap
);
477 if (ret
>= 0 && _fflush_r (rptr
, &fake
))
479 if (fake
._flags
& __SERR
)
480 fp
->_flags
|= __SERR
;
482 #ifndef __SINGLE_THREAD__
483 __lock_close_recursive (fake
._lock
);
487 #endif /* _UNBUF_STREAM_OPT */
488 #endif /* !STRING_ONLY */
491 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
494 #ifdef FLOATING_POINT
497 /* For %La, an exponent of 15 bits occupies the exponent character, a
498 sign, and up to 5 digits. */
504 extern char *_dtoa_r (struct _reent
*, double, int,
505 int, int *, int *, char **);
507 # define _PRINTF_FLOAT_TYPE double
508 # define _DTOA_R _dtoa_r
511 # else /* !_NO_LONGDBL */
513 extern char *_ldtoa_r (struct _reent
*, _LONG_DOUBLE
, int,
514 int, int *, int *, char **);
516 extern int _ldcheck (_LONG_DOUBLE
*);
518 # define _PRINTF_FLOAT_TYPE _LONG_DOUBLE
519 # define _DTOA_R _ldtoa_r
520 # define FREXP frexpl
521 # endif /* !_NO_LONGDBL */
523 static char *cvt(struct _reent
*, _PRINTF_FLOAT_TYPE
, int, int, char *, int *,
526 static int exponent(char *, int, int);
528 #endif /* FLOATING_POINT */
530 /* BUF must be big enough for the maximum %#llo (assuming long long is
531 at most 64 bits, this would be 23 characters), the maximum
532 multibyte character %C, and the maximum default precision of %La
533 (assuming long double is at most 128 bits with 113 bits of
534 mantissa, this would be 29 characters). %e, %f, and %g use
535 reentrant storage shared with mprec. All other formats that use
536 buf get by with fewer characters. Making BUF slightly bigger
537 reduces the need for malloc in %.*a and %S, when large precision or
538 long strings are processed.
539 The bigger size of 100 bytes is used on systems which allow number
540 strings using the locale's grouping character. Since that's a multibyte
541 value, we should use a conservative value.
543 #ifdef _WANT_IO_C99_FORMATS
548 #if defined _MB_CAPABLE && MB_LEN_MAX > BUF
550 # define BUF MB_LEN_MAX
554 # define quad_t long long
555 # define u_quad_t unsigned long long
558 # define u_quad_t unsigned long
561 typedef quad_t
* quad_ptr_t
;
562 typedef void *void_ptr_t
;
563 typedef char * char_ptr_t
;
564 typedef long * long_ptr_t
;
565 typedef int * int_ptr_t
;
566 typedef short * short_ptr_t
;
570 # define MAX_POS_ARGS NL_ARGMAX
572 # define MAX_POS_ARGS 32
583 _LONG_DOUBLE val__LONG_DOUBLE
;
584 int_ptr_t val_int_ptr_t
;
585 short_ptr_t val_short_ptr_t
;
586 long_ptr_t val_long_ptr_t
;
587 char_ptr_t val_char_ptr_t
;
588 quad_ptr_t val_quad_ptr_t
;
589 void_ptr_t val_void_ptr_t
;
591 u_quad_t val_u_quad_t
;
595 static union arg_val
*
596 get_arg (struct _reent
*data
, int n
, char *fmt
,
597 va_list *ap
, int *numargs
, union arg_val
*args
,
598 int *arg_type
, char **last_fmt
);
599 #endif /* !_NO_POS_ARGS */
602 * Macros for converting digits to letters and vice versa
604 #define to_digit(c) ((c) - '0')
605 #define is_digit(c) ((unsigned)to_digit (c) <= 9)
606 #define to_char(n) ((n) + '0')
609 * Flags used during conversion.
611 #define ALT 0x001 /* alternate form */
612 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
613 #define LADJUST 0x004 /* left adjustment */
614 #define LONGDBL 0x008 /* long double */
615 #define LONGINT 0x010 /* long integer */
617 # define QUADINT 0x020 /* quad integer */
618 #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
619 that %lld behaves the same as %ld, not as %d, as expected if:
620 sizeof (long long) = sizeof long > sizeof int */
621 # define QUADINT LONGINT
623 #define SHORTINT 0x040 /* short integer */
624 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
625 #define FPT 0x100 /* Floating point number */
626 #ifdef _WANT_IO_C99_FORMATS
627 # define CHARINT 0x200 /* char as integer */
628 #else /* define as 0, to make SARG and UARG occupy fewer instructions */
631 #ifdef _WANT_IO_C99_FORMATS
632 # define GROUPING 0x400 /* use grouping ("'" flag) */
635 int _VFPRINTF_R (struct _reent
*, FILE *, const char *, va_list);
644 result
= _VFPRINTF_R (_REENT
, fp
, fmt0
, ap
);
647 #endif /* STRING_ONLY */
650 _VFPRINTF_R (struct _reent
*data
,
655 register char *fmt
; /* format string */
656 register int ch
; /* character from fmt */
657 register int n
, m
; /* handy integers (short term usage) */
658 register char *cp
; /* handy char pointer (short term usage) */
659 register int flags
; /* flags as above */
660 char *fmt_anchor
; /* current format spec being processed */
662 int N
; /* arg number */
663 int arg_index
; /* index into args processed directly */
664 int numargs
; /* number of varargs read */
665 char *saved_fmt
; /* saved fmt pointer */
666 union arg_val args
[MAX_POS_ARGS
];
667 int arg_type
[MAX_POS_ARGS
];
668 int is_pos_arg
; /* is current format positional? */
669 int old_is_pos_arg
; /* is current format positional? */
671 int ret
; /* return value accumulator */
672 int width
; /* width from format (%8d), or 0 */
673 int prec
; /* precision from format (%.3d), or -1 */
674 char sign
; /* sign prefix (' ', '+', '-', or \0) */
675 #ifdef _WANT_IO_C99_FORMATS
676 /* locale specific numeric grouping */
677 char *thousands_sep
= NULL
;
678 size_t thsnd_len
= 0;
679 const char *grouping
= NULL
;
681 #ifdef FLOATING_POINT
682 char *decimal_point
= _localeconv_r (data
)->decimal_point
;
683 size_t decp_len
= strlen (decimal_point
);
684 char softsign
; /* temporary negative sign for floats */
685 union { int i
; _PRINTF_FLOAT_TYPE fp
; } _double_
= {0};
686 # define _fpvalue (_double_.fp)
687 int expt
; /* integer value of exponent */
688 int expsize
= 0; /* character count for expstr */
689 char expstr
[MAXEXPLEN
]; /* buffer for exponent string */
690 int lead
; /* sig figs before decimal or group sep */
691 #endif /* FLOATING_POINT */
692 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
693 int ndig
= 0; /* actual number of digits returned by cvt */
695 #if defined (FLOATING_POINT) && defined (_WANT_IO_C99_FORMATS)
696 int nseps
; /* number of group separators with ' */
697 int nrepeats
; /* number of repeats of the last group */
699 u_quad_t _uquad
; /* integer arguments %[diouxX] */
700 enum { OCT
, DEC
, HEX
} base
;/* base for [diouxX] conversion */
701 int dprec
; /* a copy of prec if [diouxX], 0 otherwise */
702 int realsz
; /* field size expanded by dprec */
703 int size
; /* size of converted field or string */
704 char *xdigs
= NULL
; /* digits for [xX] conversion */
705 #ifdef _FVWRITE_IN_STREAMIO
707 struct __suio uio
; /* output information: summary */
708 struct __siov iov
[NIOV
];/* ... and individual io vectors */
709 register struct __siov
*iovp
;/* for PRINT macro */
711 char buf
[BUF
]; /* space for %c, %S, %[diouxX], %[aA] */
712 char ox
[2]; /* space for 0x hex-prefix */
715 mbstate_t state
; /* mbtowc calls from library must not change state */
717 char *malloc_buf
= NULL
;/* handy pointer for malloced buffers */
720 * Choose PADSIZE to trade efficiency vs. size. If larger printf
721 * fields occur frequently, increase PADSIZE and make the initialisers
724 #define PADSIZE 16 /* pad chunk size */
725 static const char blanks
[PADSIZE
] =
726 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
727 static const char zeroes
[PADSIZE
] =
728 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
731 memset (&state
, '\0', sizeof (state
));
734 * BEWARE, these `goto error' on error, and PAD uses `n'.
736 #ifdef _FVWRITE_IN_STREAMIO
737 #define PRINT(ptr, len) { \
738 iovp->iov_base = (ptr); \
739 iovp->iov_len = (len); \
740 uio.uio_resid += (len); \
742 if (++uio.uio_iovcnt >= NIOV) { \
743 if (__SPRINT(data, fp, &uio)) \
748 #define PAD(howmany, with) { \
749 if ((n = (howmany)) > 0) { \
750 while (n > PADSIZE) { \
751 PRINT (with, PADSIZE); \
757 #define PRINTANDPAD(p, ep, len, with) { \
758 int n = (ep) - (p); \
763 PAD((len) - (n > 0 ? n : 0), (with)); \
766 if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
768 uio.uio_iovcnt = 0; \
772 #define PRINT(ptr, len) { \
773 if (__SPRINT (data, fp, (ptr), (len)) == EOF) \
776 #define PAD(howmany, with) { \
777 if ((n = (howmany)) > 0) { \
778 while (n > PADSIZE) { \
779 PRINT (with, PADSIZE); \
785 #define PRINTANDPAD(p, ep, len, with) { \
786 int n = (ep) - (p); \
791 PAD((len) - (n > 0 ? n : 0), (with)); \
796 /* Macros to support positional arguments */
798 # define GET_ARG(n, ap, type) \
801 ? args[n].val_##type \
802 : get_arg (data, n, fmt_anchor, &ap, &numargs, args, \
803 arg_type, &saved_fmt)->val_##type) \
804 : (arg_index++ < numargs \
805 ? args[n].val_##type \
806 : (numargs < MAX_POS_ARGS \
807 ? args[numargs++].val_##type = va_arg (ap, type) \
808 : va_arg (ap, type))))
810 # define GET_ARG(n, ap, type) (va_arg (ap, type))
814 * To extend shorts properly, we need both signed and unsigned
815 * argument extraction methods.
819 (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
820 flags&LONGINT ? GET_ARG (N, ap, long) : \
821 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
822 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
823 (long)GET_ARG (N, ap, int))
825 (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
826 flags&LONGINT ? GET_ARG (N, ap, u_long) : \
827 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
828 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
829 (u_long)GET_ARG (N, ap, u_int))
832 (flags&LONGINT ? GET_ARG (N, ap, long) : \
833 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
834 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
835 (long)GET_ARG (N, ap, int))
837 (flags&LONGINT ? GET_ARG (N, ap, u_long) : \
838 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
839 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
840 (u_long)GET_ARG (N, ap, u_int))
844 /* Initialize std streams if not dealing with sprintf family. */
845 CHECK_INIT (data
, fp
);
846 _newlib_flockfile_start (fp
);
850 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
851 if (cantwrite (data
, fp
)) {
852 _newlib_flockfile_exit (fp
);
856 #ifdef _UNBUF_STREAM_OPT
857 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
858 if ((fp
->_flags
& (__SNBF
|__SWR
|__SRW
)) == (__SNBF
|__SWR
) &&
860 _newlib_flockfile_exit (fp
);
861 return (__sbprintf (data
, fp
, fmt0
, ap
));
864 #else /* STRING_ONLY */
865 /* Create initial buffer if we are called by asprintf family. */
866 if (fp
->_flags
& __SMBF
&& !fp
->_bf
._base
)
868 fp
->_bf
._base
= fp
->_p
= _malloc_r (data
, 64);
871 _REENT_ERRNO(data
) = ENOMEM
;
876 #endif /* STRING_ONLY */
879 #ifdef _FVWRITE_IN_STREAMIO
880 uio
.uio_iov
= iovp
= iov
;
894 * Scan the format for conversions (`%' character).
899 while ((n
= __MBTOWC (data
, &wc
, fmt
, MB_CUR_MAX
,
902 /* Wave invalid chars through. */
903 memset (&state
, 0, sizeof state
);
911 while (*fmt
!= '\0' && *fmt
!= '%')
914 if ((m
= fmt
- cp
) != 0) {
926 fmt
++; /* skip over '%' */
933 #ifdef FLOATING_POINT
935 #ifdef _WANT_IO_C99_FORMATS
936 nseps
= nrepeats
= 0;
945 reswitch
: switch (ch
) {
946 #ifdef _WANT_IO_C99_FORMATS
948 thousands_sep
= _localeconv_r (data
)->thousands_sep
;
949 thsnd_len
= strlen (thousands_sep
);
950 grouping
= _localeconv_r (data
)->grouping
;
951 if (thsnd_len
> 0 && grouping
&& *grouping
)
957 * ``If the space and + flags both appear, the space
958 * flag will be ignored.''
969 /* we must check for positional arg used for dynamic width */
971 old_is_pos_arg
= is_pos_arg
;
973 if (is_digit (*fmt
)) {
979 n
= 10 * n
+ to_digit (ch
);
981 } while (is_digit (ch
));
984 if (n
<= MAX_POS_ARGS
) {
996 #endif /* !_NO_POS_ARGS */
999 * ``A negative field width argument is taken as a
1000 * - flag followed by a positive field width.''
1002 * They don't exclude field widths read from args.
1004 width
= GET_ARG (n
, ap
, int);
1005 #ifndef _NO_POS_ARGS
1006 is_pos_arg
= old_is_pos_arg
;
1019 if ((ch
= *fmt
++) == '*') {
1020 #ifndef _NO_POS_ARGS
1021 /* we must check for positional arg used for dynamic width */
1023 old_is_pos_arg
= is_pos_arg
;
1025 if (is_digit (*fmt
)) {
1026 char *old_fmt
= fmt
;
1031 n
= 10 * n
+ to_digit (ch
);
1033 } while (is_digit (ch
));
1036 if (n
<= MAX_POS_ARGS
) {
1048 #endif /* !_NO_POS_ARGS */
1049 prec
= GET_ARG (n
, ap
, int);
1050 #ifndef _NO_POS_ARGS
1051 is_pos_arg
= old_is_pos_arg
;
1058 while (is_digit (ch
)) {
1059 n
= 10 * n
+ to_digit (ch
);
1062 prec
= n
< 0 ? -1 : n
;
1066 * ``Note that 0 is taken as a flag, not as the
1067 * beginning of a field width.''
1072 case '1': case '2': case '3': case '4':
1073 case '5': case '6': case '7': case '8': case '9':
1076 n
= 10 * n
+ to_digit (ch
);
1078 } while (is_digit (ch
));
1079 #ifndef _NO_POS_ARGS
1081 if (n
<= MAX_POS_ARGS
) {
1089 #endif /* !_NO_POS_ARGS */
1092 #ifdef FLOATING_POINT
1098 #ifdef _WANT_IO_C99_FORMATS
1107 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
1115 case 'q': /* extension */
1118 #ifdef _WANT_IO_C99_FORMATS
1120 if (sizeof (intmax_t) == sizeof (long))
1126 if (sizeof (size_t) < sizeof (int))
1127 /* POSIX states size_t is 16 or more bits, as is short. */
1129 else if (sizeof (size_t) == sizeof (int))
1130 /* no flag needed */;
1131 else if (sizeof (size_t) <= sizeof (long))
1134 /* POSIX states that at least one programming
1135 environment must support size_t no wider than
1136 long, but that means other environments can
1137 have size_t as wide as long long. */
1141 if (sizeof (ptrdiff_t) < sizeof (int))
1142 /* POSIX states ptrdiff_t is 16 or more bits, as
1145 else if (sizeof (ptrdiff_t) == sizeof (int))
1146 /* no flag needed */;
1147 else if (sizeof (ptrdiff_t) <= sizeof (long))
1150 /* POSIX states that at least one programming
1151 environment must support ptrdiff_t no wider than
1152 long, but that means other environments can
1153 have ptrdiff_t as wide as long long. */
1157 #endif /* _WANT_IO_C99_FORMATS */
1161 if (ch
== 'C' || (flags
& LONGINT
)) {
1164 memset ((void *)&ps
, '\0', sizeof (mbstate_t));
1165 if ((size
= (int)_wcrtomb_r (data
, cp
,
1166 (wchar_t)GET_ARG (N
, ap
, wint_t),
1168 fp
->_flags
|= __SERR
;
1173 #endif /* _MB_CAPABLE */
1175 *cp
= GET_ARG (N
, ap
, int);
1180 case 'D': /* extension */
1186 #ifndef _NO_LONGLONG
1187 if ((quad_t
)_uquad
< 0)
1189 if ((long) _uquad
< 0)
1198 #ifdef FLOATING_POINT
1199 # ifdef _WANT_IO_C99_FORMATS
1210 if (flags
& LONGDBL
) {
1211 _fpvalue
= (double) GET_ARG (N
, ap
, _LONG_DOUBLE
);
1213 _fpvalue
= GET_ARG (N
, ap
, double);
1216 /* do this before tricky precision changes
1218 If the output is infinite or NaN, leading
1219 zeros are not permitted. Otherwise, scanf
1220 could not read what printf wrote.
1222 if (isinf (_fpvalue
)) {
1225 if (ch
<= 'G') /* 'A', 'E', 'F', or 'G' */
1233 if (isnan (_fpvalue
)) {
1234 if (signbit (_fpvalue
))
1236 if (ch
<= 'G') /* 'A', 'E', 'F', or 'G' */
1245 # else /* !_NO_LONGDBL */
1247 if (flags
& LONGDBL
) {
1248 _fpvalue
= GET_ARG (N
, ap
, _LONG_DOUBLE
);
1250 _fpvalue
= (_LONG_DOUBLE
)GET_ARG (N
, ap
, double);
1253 /* do this before tricky precision changes */
1254 expt
= _ldcheck (&_fpvalue
);
1258 if (ch
<= 'G') /* 'A', 'E', 'F', or 'G' */
1267 if (signbit (_fpvalue
))
1269 if (ch
<= 'G') /* 'A', 'E', 'F', or 'G' */
1277 # endif /* !_NO_LONGDBL */
1279 # ifdef _WANT_IO_C99_FORMATS
1280 if (ch
== 'a' || ch
== 'A') {
1282 ox
[1] = ch
== 'a' ? 'x' : 'X';
1287 (char *)_malloc_r (data
, prec
+ 1))
1290 fp
->_flags
|= __SERR
;
1298 # endif /* _WANT_IO_C99_FORMATS */
1301 } else if ((ch
== 'g' || ch
== 'G') && prec
== 0) {
1307 cp
= cvt (data
, _fpvalue
, prec
, flags
, &softsign
,
1308 &expt
, ch
, &ndig
, cp
);
1310 if (ch
== 'g' || ch
== 'G') {
1311 if (expt
<= -4 || expt
> prec
)
1312 ch
-= 2; /* 'e' or 'E' */
1316 # ifdef _WANT_IO_C99_FORMATS
1320 if (ch
<= 'e') { /* 'a', 'A', 'e', or 'E' fmt */
1322 expsize
= exponent (expstr
, expt
, ch
);
1323 size
= expsize
+ ndig
;
1324 if (ndig
> 1 || flags
& ALT
)
1326 # ifdef _WANT_IO_C99_FORMATS
1330 if (ch
== 'f') { /* f fmt */
1333 if (prec
|| flags
& ALT
)
1334 size
+= prec
+ decp_len
;
1336 size
= (prec
|| flags
& ALT
)
1337 ? prec
+ 1 + decp_len
1339 } else if (expt
>= ndig
) { /* fixed g fmt */
1344 size
= ndig
+ decp_len
;
1348 # ifdef _WANT_IO_C99_FORMATS
1349 if ((flags
& GROUPING
) && expt
> 0) {
1350 /* space for thousands' grouping */
1351 nseps
= nrepeats
= 0;
1353 while (*grouping
!= CHAR_MAX
) {
1354 if (lead
<= *grouping
)
1363 size
+= (nseps
+ nrepeats
) * thsnd_len
;
1372 #endif /* FLOATING_POINT */
1373 #ifdef _GLIBC_EXTENSION
1374 case 'm': /* extension */
1377 cp
= _strerror_r (data
, _REENT_ERRNO(data
), 1, &dummy
);
1383 #ifndef _NO_LONGLONG
1384 if (flags
& QUADINT
)
1385 *GET_ARG (N
, ap
, quad_ptr_t
) = ret
;
1388 if (flags
& LONGINT
)
1389 *GET_ARG (N
, ap
, long_ptr_t
) = ret
;
1390 else if (flags
& SHORTINT
)
1391 *GET_ARG (N
, ap
, short_ptr_t
) = ret
;
1392 #ifdef _WANT_IO_C99_FORMATS
1393 else if (flags
& CHARINT
)
1394 *GET_ARG (N
, ap
, char_ptr_t
) = ret
;
1397 *GET_ARG (N
, ap
, int_ptr_t
) = ret
;
1398 continue; /* no output */
1399 case 'O': /* extension */
1405 #ifdef _WANT_IO_C99_FORMATS
1411 * ``The argument shall be a pointer to void. The
1412 * value of the pointer is converted to a sequence
1413 * of printable characters, in an implementation-
1418 _uquad
= (uintptr_t) GET_ARG (N
, ap
, void_ptr_t
);
1420 xdigs
= "0123456789abcdef";
1426 #ifdef _WANT_IO_C99_FORMATS
1429 cp
= GET_ARG (N
, ap
, char_ptr_t
);
1430 #ifdef _GLIBC_EXTENSION
1434 #ifndef __OPTIMIZE_SIZE__
1435 /* Behavior is undefined if the user passed a
1436 NULL string when precision is not 0.
1437 However, if we are not optimizing for size,
1438 we might as well mirror glibc behavior. */
1441 size
= ((unsigned) prec
> 6U) ? 6 : prec
;
1444 #endif /* __OPTIMIZE_SIZE__ */
1446 if (ch
== 'S' || (flags
& LONGINT
)) {
1450 wcp
= (const wchar_t *)cp
;
1452 memset ((void *)&ps
, '\0', sizeof (mbstate_t));
1454 /* Count number of bytes needed for multibyte
1455 string that will be produced from widechar
1459 if (wcp
[m
] == L
'\0')
1461 if ((n
= (int)_wcrtomb_r (data
,
1462 buf
, wcp
[m
], &ps
)) == -1) {
1463 fp
->_flags
|= __SERR
;
1466 if (n
+ size
> prec
)
1475 if ((size
= (int)_wcsrtombs_r (data
,
1476 NULL
, &wcp
, 0, &ps
)) == -1) {
1477 fp
->_flags
|= __SERR
;
1480 wcp
= (const wchar_t *)cp
;
1488 (char *)_malloc_r (data
, size
+ 1))
1490 fp
->_flags
|= __SERR
;
1497 /* Convert widechar string to multibyte string. */
1498 memset ((void *)&ps
, '\0', sizeof (mbstate_t));
1499 if (_wcsrtombs_r (data
, cp
, &wcp
, size
, &ps
)
1501 fp
->_flags
|= __SERR
;
1507 #endif /* _MB_CAPABLE */
1510 * can't use strlen; can only look for the
1511 * NUL in the first `prec' characters, and
1512 * strlen () will go further.
1514 char *p
= memchr (cp
, 0, prec
);
1524 case 'U': /* extension */
1532 xdigs
= "0123456789ABCDEF";
1535 xdigs
= "0123456789abcdef";
1536 hex
: _uquad
= UARG ();
1538 /* leading 0x/X only if non-zero */
1539 if (flags
& ALT
&& _uquad
!= 0) {
1545 #ifdef _WANT_IO_C99_FORMATS
1548 /* unsigned conversions */
1549 nosign
: sign
= '\0';
1551 * ``... diouXx conversions ... if a precision is
1552 * specified, the 0 flag will be ignored.''
1555 number
: if ((dprec
= prec
) >= 0)
1559 * ``The result of converting a zero value with an
1560 * explicit precision of zero is no characters.''
1564 if (_uquad
!= 0 || prec
!= 0) {
1566 * Unsigned mod is hard, and unsigned mod
1567 * by a constant is easier than that by
1568 * a variable; hence this switch.
1573 *--cp
= to_char (_uquad
& 7);
1576 /* handle octal leading 0 */
1577 if (flags
& ALT
&& *cp
!= '0')
1582 /* many numbers are 1 digit */
1584 *--cp
= to_char(_uquad
);
1587 #ifdef _WANT_IO_C99_FORMATS
1591 *--cp
= to_char (_uquad
% 10);
1592 #ifdef _WANT_IO_C99_FORMATS
1594 /* If (*grouping == CHAR_MAX) then no
1596 if ((flags
& GROUPING
)
1597 && ndig
== *grouping
1598 && *grouping
!= CHAR_MAX
1601 strncpy (cp
, thousands_sep
,
1604 /* If (grouping[1] == '\0') then we
1605 have to use *grouping character
1606 (last grouping rule) for all
1608 if (grouping
[1] != '\0')
1613 } while (_uquad
!= 0);
1618 *--cp
= xdigs
[_uquad
& 15];
1624 cp
= "bug in vfprintf: bad base";
1630 * ...result is to be converted to an 'alternate form'.
1631 * For o conversion, it increases the precision to force
1632 * the first digit of the result to be a zero."
1635 * To demonstrate this case, compile and run:
1636 * printf ("%#.0o",0);
1638 else if (base
== OCT
&& (flags
& ALT
))
1641 size
= buf
+ BUF
- cp
;
1644 default: /* "%?" prints ?, unless ? is NUL */
1647 /* pretend it was %c with argument ch */
1656 * All reasonable formats wind up here. At this point, `cp'
1657 * points to a string which (if not flags&LADJUST) should be
1658 * padded out to `width' places. If flags&ZEROPAD, it should
1659 * first be prefixed by any sign or other prefix; otherwise,
1660 * it should be blank padded before the prefix is emitted.
1661 * After any left-hand padding and prefixing, emit zeroes
1662 * required by a decimal [diouxX] precision, then print the
1663 * string proper, then emit zeroes required by any leftover
1664 * floating precision; finally, if LADJUST, pad with blanks.
1665 * If flags&FPT, ch must be in [aAeEfg].
1667 * Compute actual size, so we know how much to pad.
1668 * size excludes decimal prec; realsz includes it.
1670 realsz
= dprec
> size
? dprec
: size
;
1673 if (flags
& HEXPREFIX
)
1676 /* right-adjusting blank padding */
1677 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
1678 PAD (width
- realsz
, blanks
);
1683 if (flags
& HEXPREFIX
)
1686 /* right-adjusting zero padding */
1687 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
1688 PAD (width
- realsz
, zeroes
);
1690 /* leading zeroes from decimal precision */
1691 PAD (dprec
- size
, zeroes
);
1693 /* the string or number proper */
1694 #ifdef FLOATING_POINT
1695 if ((flags
& FPT
) == 0) {
1697 } else { /* glue together f_p fragments */
1698 if (ch
>= 'f') { /* 'f' or 'g' */
1699 if (_fpvalue
== 0) {
1700 /* kludge for __dtoa irregularity */
1702 if (expt
< ndig
|| flags
& ALT
) {
1703 PRINT (decimal_point
, decp_len
);
1704 PAD (ndig
- 1, zeroes
);
1706 } else if (expt
<= 0) {
1708 if (expt
|| ndig
|| flags
& ALT
) {
1709 PRINT (decimal_point
, decp_len
);
1710 PAD (-expt
, zeroes
);
1715 PRINTANDPAD(cp
, convbuf
+ ndig
,
1718 #ifdef _WANT_IO_C99_FORMATS
1719 if (flags
& GROUPING
) {
1720 while (nseps
> 0 || nrepeats
> 0) {
1727 PRINT(thousands_sep
, thsnd_len
);
1728 PRINTANDPAD (cp
, convbuf
+ ndig
,
1732 if (cp
> convbuf
+ ndig
)
1733 cp
= convbuf
+ ndig
;
1736 if (expt
< ndig
|| flags
& ALT
)
1737 PRINT (decimal_point
, decp_len
);
1738 PRINTANDPAD (cp
, convbuf
+ ndig
,
1739 ndig
- expt
, zeroes
);
1741 } else { /* 'a', 'A', 'e', or 'E' */
1742 if (ndig
> 1 || flags
& ALT
) {
1745 PRINT (decimal_point
, decp_len
);
1747 PRINT (cp
, ndig
- 1);
1748 } else /* 0.[0..] */
1749 /* __dtoa irregularity */
1750 PAD (ndig
- 1, zeroes
);
1753 PRINT (expstr
, expsize
);
1756 #else /* !FLOATING_POINT */
1759 /* left-adjusting padding (always blank) */
1760 if (flags
& LADJUST
)
1761 PAD (width
- realsz
, blanks
);
1763 /* finally, adjust ret */
1764 ret
+= width
> realsz
? width
: realsz
;
1766 FLUSH (); /* copy out the I/O vectors */
1768 if (malloc_buf
!= NULL
) {
1769 _free_r (data
, malloc_buf
);
1776 if (malloc_buf
!= NULL
)
1777 _free_r (data
, malloc_buf
);
1779 _newlib_flockfile_end (fp
);
1781 return (__sferror (fp
) ? EOF
: ret
);
1785 #ifdef FLOATING_POINT
1787 /* Using reentrant DATA, convert finite VALUE into a string of digits
1788 with no decimal point, using NDIGITS precision and FLAGS as guides
1789 to whether trailing zeros must be included. Set *SIGN to nonzero
1790 if VALUE was negative. Set *DECPT to the exponent plus one. Set
1791 *LENGTH to the length of the returned string. CH must be one of
1792 [aAeEfFgG]; if it is [aA], then the return string lives in BUF,
1793 otherwise the return value shares the mprec reentrant storage. */
1795 cvt(struct _reent
*data
, _PRINTF_FLOAT_TYPE value
, int ndigits
, int flags
,
1796 char *sign
, int *decpt
, int ch
, int *length
, char *buf
)
1799 char *digits
, *bp
, *rve
;
1801 union double_union tmp
;
1804 if (word0 (tmp
) & Sign_bit
) { /* this will check for < 0 and -0.0 */
1809 # else /* !_NO_LONGDBL */
1817 if (ld
.ieee
.sign
) { /* this will check for < 0 and -0.0 */
1822 # endif /* !_NO_LONGDBL */
1824 # ifdef _WANT_IO_C99_FORMATS
1825 if (ch
== 'a' || ch
== 'A') {
1826 /* This code assumes FLT_RADIX is a power of 2. The initial
1827 division ensures the digit before the decimal will be less
1828 than FLT_RADIX (unless it is rounded later). There is no
1829 loss of precision in these calculations. */
1830 value
= FREXP (value
, decpt
) / 8;
1833 digits
= ch
== 'a' ? "0123456789abcdef" : "0123456789ABCDEF";
1839 *bp
++ = digits
[mode
];
1840 } while (ndigits
-- && value
);
1841 if (value
> 0.5 || (value
== 0.5 && mode
& 1)) {
1844 while (*--rve
== digits
[0xf]) {
1847 *rve
= *rve
== '9' ? digits
[0xa] : *rve
+ 1;
1849 while (ndigits
-- >= 0) {
1856 # endif /* _WANT_IO_C99_FORMATS */
1857 if (ch
== 'f' || ch
== 'F') {
1858 mode
= 3; /* ndigits after the decimal point */
1860 /* To obtain ndigits after the decimal point for the 'e'
1861 * and 'E' formats, round to ndigits + 1 significant
1864 if (ch
== 'e' || ch
== 'E') {
1867 mode
= 2; /* ndigits significant digits */
1870 digits
= _DTOA_R (data
, value
, mode
, ndigits
, decpt
, &dsgn
, &rve
);
1872 if ((ch
!= 'g' && ch
!= 'G') || flags
& ALT
) { /* Print trailing zeros */
1873 bp
= digits
+ ndigits
;
1874 if (ch
== 'f' || ch
== 'F') {
1875 if (*digits
== '0' && value
)
1876 *decpt
= -ndigits
+ 1;
1879 if (value
== 0) /* kludge for __dtoa irregularity */
1884 *length
= rve
- digits
;
1889 exponent(char *p0
, int exp
, int fmtch
)
1891 register char *p
, *t
;
1892 char expbuf
[MAXEXPLEN
];
1893 # ifdef _WANT_IO_C99_FORMATS
1894 int isa
= fmtch
== 'a' || fmtch
== 'A';
1900 *p
++ = isa
? 'p' - 'a' + fmtch
: fmtch
;
1907 t
= expbuf
+ MAXEXPLEN
;
1910 *--t
= to_char (exp
% 10);
1911 } while ((exp
/= 10) > 9);
1912 *--t
= to_char (exp
);
1913 for (; t
< expbuf
+ MAXEXPLEN
; *p
++ = *t
++);
1918 *p
++ = to_char (exp
);
1922 #endif /* FLOATING_POINT */
1925 #ifndef _NO_POS_ARGS
1927 /* Positional argument support.
1928 Written by Jeff Johnston
1930 Copyright (c) 2002 Red Hat Incorporated.
1931 All rights reserved.
1933 Redistribution and use in source and binary forms, with or without
1934 modification, are permitted provided that the following conditions are met:
1936 Redistributions of source code must retain the above copyright
1937 notice, this list of conditions and the following disclaimer.
1939 Redistributions in binary form must reproduce the above copyright
1940 notice, this list of conditions and the following disclaimer in the
1941 documentation and/or other materials provided with the distribution.
1943 The name of Red Hat Incorporated may not be used to endorse
1944 or promote products derived from this software without specific
1945 prior written permission.
1947 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1948 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1949 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1950 DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1951 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1952 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1953 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1954 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1955 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1956 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1958 /* The below constant state tables are shared between all versions of
1959 vfprintf and vfwprintf. They must only be defined once, which we do in
1960 the STRING_ONLY/INTEGER_ONLY versions here. */
1961 #if defined (STRING_ONLY) && defined(INTEGER_ONLY)
1963 const __CH_CLASS __chclass
[256] = {
1964 /* 00-07 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1965 /* 08-0f */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1966 /* 10-17 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1967 /* 18-1f */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1968 /* 20-27 */ FLAG
, OTHER
, OTHER
, FLAG
, DOLLAR
, OTHER
, OTHER
, FLAG
,
1969 /* 28-2f */ OTHER
, OTHER
, STAR
, FLAG
, OTHER
, FLAG
, DOT
, OTHER
,
1970 /* 30-37 */ ZERO
, DIGIT
, DIGIT
, DIGIT
, DIGIT
, DIGIT
, DIGIT
, DIGIT
,
1971 /* 38-3f */ DIGIT
, DIGIT
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1972 /* 40-47 */ OTHER
, SPEC
, OTHER
, SPEC
, SPEC
, SPEC
, SPEC
, SPEC
,
1973 /* 48-4f */ OTHER
, OTHER
, OTHER
, OTHER
, MODFR
, OTHER
, OTHER
, SPEC
,
1974 /* 50-57 */ OTHER
, OTHER
, OTHER
, SPEC
, OTHER
, SPEC
, OTHER
, OTHER
,
1975 /* 58-5f */ SPEC
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1976 /* 60-67 */ OTHER
, SPEC
, OTHER
, SPEC
, SPEC
, SPEC
, SPEC
, SPEC
,
1977 /* 68-6f */ MODFR
, SPEC
, MODFR
, OTHER
, MODFR
, OTHER
, SPEC
, SPEC
,
1978 /* 70-77 */ SPEC
, MODFR
, OTHER
, SPEC
, MODFR
, SPEC
, OTHER
, OTHER
,
1979 /* 78-7f */ SPEC
, OTHER
, MODFR
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1980 /* 80-87 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1981 /* 88-8f */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1982 /* 90-97 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1983 /* 98-9f */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1984 /* a0-a7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1985 /* a8-af */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1986 /* b0-b7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1987 /* b8-bf */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1988 /* c0-c7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1989 /* c8-cf */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1990 /* d0-d7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1991 /* d8-df */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1992 /* e0-e7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1993 /* e8-ef */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1994 /* f0-f7 */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1995 /* f8-ff */ OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
, OTHER
,
1998 const __STATE __state_table
[MAX_STATE
][MAX_CH_CLASS
] = {
1999 /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
2000 /* START */ { SFLAG
, WDIG
, DONE
, SMOD
, DONE
, SDOT
, VARW
, SFLAG
, DONE
},
2001 /* SFLAG */ { SFLAG
, WDIG
, DONE
, SMOD
, DONE
, SDOT
, VARW
, SFLAG
, DONE
},
2002 /* WDIG */ { DONE
, DONE
, WIDTH
, SMOD
, DONE
, SDOT
, DONE
, DONE
, DONE
},
2003 /* WIDTH */ { DONE
, DONE
, DONE
, SMOD
, DONE
, SDOT
, DONE
, DONE
, DONE
},
2004 /* SMOD */ { DONE
, DONE
, DONE
, DONE
, DONE
, DONE
, DONE
, DONE
, DONE
},
2005 /* SDOT */ { SDOT
, PREC
, DONE
, SMOD
, DONE
, DONE
, VARP
, DONE
, DONE
},
2006 /* VARW */ { DONE
, VWDIG
, DONE
, SMOD
, DONE
, SDOT
, DONE
, DONE
, DONE
},
2007 /* VARP */ { DONE
, VPDIG
, DONE
, SMOD
, DONE
, DONE
, DONE
, DONE
, DONE
},
2008 /* PREC */ { DONE
, DONE
, DONE
, SMOD
, DONE
, DONE
, DONE
, DONE
, DONE
},
2009 /* VWDIG */ { DONE
, DONE
, WIDTH
, DONE
, DONE
, DONE
, DONE
, DONE
, DONE
},
2010 /* VPDIG */ { DONE
, DONE
, PREC
, DONE
, DONE
, DONE
, DONE
, DONE
, DONE
},
2013 const __ACTION __action_table
[MAX_STATE
][MAX_CH_CLASS
] = {
2014 /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
2015 /* START */ { NOOP
, NUMBER
, NOOP
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
2016 /* SFLAG */ { NOOP
, NUMBER
, NOOP
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
2017 /* WDIG */ { NOOP
, NOOP
, GETPOS
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
2018 /* WIDTH */ { NOOP
, NOOP
, NOOP
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
2019 /* SMOD */ { NOOP
, NOOP
, NOOP
, NOOP
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
2020 /* SDOT */ { NOOP
, SKIPNUM
, NOOP
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
2021 /* VARW */ { NOOP
, NUMBER
, NOOP
, GETPW
, GETPWB
, GETPW
, NOOP
, NOOP
, NOOP
},
2022 /* VARP */ { NOOP
, NUMBER
, NOOP
, GETPW
, GETPWB
, NOOP
, NOOP
, NOOP
, NOOP
},
2023 /* PREC */ { NOOP
, NOOP
, NOOP
, GETMOD
, GETARG
, NOOP
, NOOP
, NOOP
, NOOP
},
2024 /* VWDIG */ { NOOP
, NOOP
, PWPOS
, NOOP
, NOOP
, NOOP
, NOOP
, NOOP
, NOOP
},
2025 /* VPDIG */ { NOOP
, NOOP
, PWPOS
, NOOP
, NOOP
, NOOP
, NOOP
, NOOP
, NOOP
},
2028 #endif /* STRING_ONLY && INTEGER_ONLY */
2030 /* function to get positional parameter N where n = N - 1 */
2031 static union arg_val
*
2032 get_arg (struct _reent
*data
,
2037 union arg_val
*args
,
2044 int numargs
= *numargs_p
;
2046 __STATE state
, next_state
;
2049 int max_pos_arg
= n
;
2050 /* Only need types that can be reached via vararg promotions. */
2051 enum types
{ INT
, LONG_INT
, QUAD_INT
, CHAR_PTR
, DOUBLE
, LONG_DOUBLE
, WIDE_CHAR
};
2058 /* if this isn't the first call, pick up where we left off last time */
2059 if (*last_fmt
!= NULL
)
2063 memset (&wc_state
, '\0', sizeof (wc_state
));
2066 /* we need to process either to end of fmt string or until we have actually
2067 read the desired parameter from the vararg list. */
2068 while (*fmt
&& n
>= numargs
)
2071 while ((nbytes
= __MBTOWC (data
, &wc
, fmt
, MB_CUR_MAX
, &wc_state
)) > 0)
2081 while (*fmt
!= '\0' && *fmt
!= '%')
2088 # endif /* ! _MB_CAPABLE */
2095 /* Use state/action table to process format specifiers. We ignore invalid
2096 formats and we are only interested in information that tells us how to
2097 read the vararg list. */
2098 while (state
!= DONE
)
2101 chtype
= __chclass
[ch
];
2102 next_state
= __state_table
[state
][chtype
];
2103 action
= __action_table
[state
][chtype
];
2108 case GETMOD
: /* we have format modifier */
2112 /* No flag needed, since short and char promote to int. */
2120 # ifdef _WANT_IO_C99_FORMATS
2122 if (sizeof (intmax_t) == sizeof (long))
2128 if (sizeof (size_t) <= sizeof (int))
2129 /* no flag needed */;
2130 else if (sizeof (size_t) <= sizeof (long))
2133 /* POSIX states that at least one programming
2134 environment must support size_t no wider than
2135 long, but that means other environments can
2136 have size_t as wide as long long. */
2140 if (sizeof (ptrdiff_t) <= sizeof (int))
2141 /* no flag needed */;
2142 else if (sizeof (ptrdiff_t) <= sizeof (long))
2145 /* POSIX states that at least one programming
2146 environment must support ptrdiff_t no wider than
2147 long, but that means other environments can
2148 have ptrdiff_t as wide as long long. */
2151 # endif /* _WANT_IO_C99_FORMATS */
2154 # if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
2166 case GETARG
: /* we have format specifier */
2168 numargs
&= (MAX_POS_ARGS
- 1);
2169 /* process the specifier and translate it to a type to fetch from varargs */
2178 if (flags
& LONGINT
)
2179 spec_type
= LONG_INT
;
2180 # ifndef _NO_LONGLONG
2181 else if (flags
& QUADINT
)
2182 spec_type
= QUAD_INT
;
2190 spec_type
= LONG_INT
;
2192 # ifdef _WANT_IO_C99_FORMATS
2202 # ifndef _NO_LONGDBL
2203 if (flags
& LONGDBL
)
2204 spec_type
= LONG_DOUBLE
;
2210 # ifdef _WANT_IO_C99_FORMATS
2215 spec_type
= CHAR_PTR
;
2218 # ifdef _WANT_IO_C99_FORMATS
2219 if (flags
& LONGINT
)
2220 spec_type
= WIDE_CHAR
;
2225 # ifdef _WANT_IO_C99_FORMATS
2227 spec_type
= WIDE_CHAR
;
2232 /* if we have a positional parameter, just store the type, otherwise
2233 fetch the parameter from the vararg list */
2235 arg_type
[pos
] = spec_type
;
2241 args
[numargs
++].val_long
= va_arg (*ap
, long);
2244 args
[numargs
++].val_quad_t
= va_arg (*ap
, quad_t
);
2247 args
[numargs
++].val_wint_t
= va_arg (*ap
, wint_t);
2250 args
[numargs
++].val_int
= va_arg (*ap
, int);
2253 args
[numargs
++].val_char_ptr_t
= va_arg (*ap
, char *);
2256 args
[numargs
++].val_double
= va_arg (*ap
, double);
2259 args
[numargs
++].val__LONG_DOUBLE
= va_arg (*ap
, _LONG_DOUBLE
);
2265 case GETPOS
: /* we have positional specifier */
2266 if (arg_type
[0] == -1)
2267 memset (arg_type
, 0, sizeof (int) * MAX_POS_ARGS
);
2269 max_pos_arg
= (max_pos_arg
> pos
? max_pos_arg
: pos
);
2271 case PWPOS
: /* we have positional specifier for width or precision */
2272 if (arg_type
[0] == -1)
2273 memset (arg_type
, 0, sizeof (int) * MAX_POS_ARGS
);
2275 arg_type
[number
] = INT
;
2276 max_pos_arg
= (max_pos_arg
> number
? max_pos_arg
: number
);
2278 case GETPWB
: /* we require format pushback */
2281 case GETPW
: /* we have a variable precision or width to acquire */
2282 args
[numargs
++].val_int
= va_arg (*ap
, int);
2284 case NUMBER
: /* we have a number to process */
2285 number
= (ch
- '0');
2286 while ((ch
= *fmt
) != '\0' && is_digit (ch
))
2288 number
= number
* 10 + (ch
- '0');
2292 case SKIPNUM
: /* we have a number to skip */
2293 while ((ch
= *fmt
) != '\0' && is_digit (ch
))
2298 break; /* do nothing */
2303 /* process all arguments up to at least the one we are looking for and if we
2304 have seen the end of the string, then process up to the max argument needed */
2306 last_arg
= max_pos_arg
;
2310 while (numargs
<= last_arg
)
2312 switch (arg_type
[numargs
])
2315 args
[numargs
++].val_long
= va_arg (*ap
, long);
2318 args
[numargs
++].val_quad_t
= va_arg (*ap
, quad_t
);
2321 args
[numargs
++].val_char_ptr_t
= va_arg (*ap
, char *);
2324 args
[numargs
++].val_double
= va_arg (*ap
, double);
2327 args
[numargs
++].val__LONG_DOUBLE
= va_arg (*ap
, _LONG_DOUBLE
);
2330 args
[numargs
++].val_wint_t
= va_arg (*ap
, wint_t);
2334 args
[numargs
++].val_int
= va_arg (*ap
, int);
2339 /* alter the global numargs value and keep a reference to the last bit of the fmt
2340 string we processed here because the caller will continue processing where we started */
2341 *numargs_p
= numargs
;
2345 #endif /* !_NO_POS_ARGS */