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 * 4. 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 <<vfwprintf>>, <<vwprintf>>, <<vswprintf>>---wide character format argument list
54 int vwprintf(const wchar_t *__restrict <[fmt]>, va_list <[list]>);
55 int vfwprintf(FILE *__restrict <[fp]>,
56 const wchar_t *__restrict <[fmt]>, va_list <[list]>);
57 int vswprintf(wchar_t * __restrict <[str]>, size_t <[size]>,
58 const wchar_t *__ restrict <[fmt]>, va_list <[list]>);
60 int _vwprintf_r(struct _reent *<[reent]>, const wchar_t *<[fmt]>,
62 int _vfwprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
63 const wchar_t *<[fmt]>, va_list <[list]>);
64 int _vswprintf_r(struct _reent *<[reent]>, wchar_t *<[str]>,
65 size_t <[size]>, const wchar_t *<[fmt]>, va_list <[list]>);
68 <<vwprintf>>, <<vfwprintf>> and <<vswprintf>> are (respectively) variants
69 of <<wprintf>>, <<fwprintf>> and <<swprintf>>. They differ only in allowing
70 their caller to pass the variable argument list as a <<va_list>> object
71 (initialized by <<va_start>>) rather than directly accepting a variable
72 number of arguments. The caller is responsible for calling <<va_end>>.
74 <<_vwprintf_r>>, <<_vfwprintf_r>> and <<_vswprintf_r>> are reentrant
75 versions of the above.
78 The return values are consistent with the corresponding functions.
81 POSIX-1.2008 with extensions; C99 (compliant except for POSIX extensions).
83 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
84 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
87 <<wprintf>>, <<fwprintf>> and <<swprintf>>.
91 * Actual wprintf innards.
93 * This code is large and complicated...
98 # define VFWPRINTF vfiwprintf
100 # define _VFWPRINTF_R _svfiwprintf_r
102 # define _VFWPRINTF_R _vfiwprintf_r
105 # define VFWPRINTF vfwprintf
107 # define _VFWPRINTF_R _svfwprintf_r
109 # define _VFWPRINTF_R _vfwprintf_r
111 # ifndef NO_FLOATING_POINT
112 # define FLOATING_POINT
117 #ifdef _WANT_IO_POS_ARGS
129 #include <sys/lock.h>
133 #include "vfieeefp.h"
134 #ifdef __HAVE_LOCALE_INFO_EXTENDED__
135 #include "../locale/setlocale.h"
138 /* Currently a test is made to see if long double processing is warranted.
139 This could be changed in the future should the _ldtoa_r code be
140 preferred over _dtoa_r. */
142 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
147 #if defined _WANT_IO_LONG_LONG \
148 && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
152 int _VFWPRINTF_R (struct _reent
*, FILE *, const wchar_t *, va_list);
153 /* Defined in vfprintf.c. */
154 #ifdef _FVWRITE_IN_STREAMIO
156 # define __SPRINT __sswprint_r
158 # define __SPRINT __swprint_r
160 int __SPRINT (struct _reent
*, FILE *, register struct __suio
*);
163 # define __SPRINT __ssputws_r
165 # define __SPRINT __sfputws_r
167 int __SPRINT (struct _reent
*, FILE *, const wchar_t *, size_t);
170 #ifdef _UNBUF_STREAM_OPT
172 * Helper function for `fprintf to unbuffered unix file': creates a
173 * temporary buffer. We only work on write-only files; this avoids
174 * worries about ungetc buffers and so forth.
177 __sbwprintf (struct _reent
*rptr
,
184 unsigned char buf
[BUFSIZ
];
186 /* copy the important variables */
187 fake
._flags
= fp
->_flags
& ~__SNBF
;
188 fake
._flags2
= fp
->_flags2
;
189 fake
._file
= fp
->_file
;
190 fake
._cookie
= fp
->_cookie
;
191 fake
._write
= fp
->_write
;
193 /* set up the buffer */
194 fake
._bf
._base
= fake
._p
= buf
;
195 fake
._bf
._size
= fake
._w
= sizeof (buf
);
196 fake
._lbfsize
= 0; /* not actually used, but Just In Case */
197 #ifndef __SINGLE_THREAD__
198 __lock_init_recursive (fake
._lock
);
201 /* do the work, then copy any error status */
202 ret
= _VFWPRINTF_R (rptr
, &fake
, fmt
, ap
);
203 if (ret
>= 0 && _fflush_r (rptr
, &fake
))
205 if (fake
._flags
& __SERR
)
206 fp
->_flags
|= __SERR
;
208 #ifndef __SINGLE_THREAD__
209 __lock_close_recursive (fake
._lock
);
213 #endif /* _UNBUF_STREAM_OPT */
214 #endif /* !STRING_ONLY */
217 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
220 #ifdef FLOATING_POINT
223 /* For %La, an exponent of 15 bits occupies the exponent character, a
224 sign, and up to 5 digits. */
230 extern char *_dtoa_r (struct _reent
*, double, int,
231 int, int *, int *, char **);
233 # define _PRINTF_FLOAT_TYPE double
234 # define _DTOA_R _dtoa_r
237 # else /* !_NO_LONGDBL */
239 extern char *_ldtoa_r (struct _reent
*, _LONG_DOUBLE
, int,
240 int, int *, int *, char **);
242 extern int _ldcheck (_LONG_DOUBLE
*);
244 # define _PRINTF_FLOAT_TYPE _LONG_DOUBLE
245 # define _DTOA_R _ldtoa_r
246 # define FREXP frexpl
247 # endif /* !_NO_LONGDBL */
249 static wchar_t *wcvt(struct _reent
*, _PRINTF_FLOAT_TYPE
, int, int, wchar_t *,
250 int *, int, int *, wchar_t *, int);
252 static int wexponent(wchar_t *, int, int);
254 #endif /* FLOATING_POINT */
256 /* BUF must be big enough for the maximum %#llo (assuming long long is
257 at most 64 bits, this would be 23 characters), the maximum
258 multibyte character %C, and the maximum default precision of %La
259 (assuming long double is at most 128 bits with 113 bits of
260 mantissa, this would be 29 characters). %e, %f, and %g use
261 reentrant storage shared with mprec. All other formats that use
262 buf get by with fewer characters. Making BUF slightly bigger
263 reduces the need for malloc in %.*a and %ls/%S, when large precision or
264 long strings are processed.
265 The bigger size of 100 bytes is used on systems which allow number
266 strings using the locale's grouping character. Since that's a multibyte
267 value, we should use a conservative value.
269 #ifdef _WANT_IO_C99_FORMATS
274 #if defined _MB_CAPABLE && MB_LEN_MAX > BUF
276 # define BUF MB_LEN_MAX
280 # define quad_t long long
281 # define u_quad_t unsigned long long
284 # define u_quad_t unsigned long
287 typedef quad_t
* quad_ptr_t
;
288 typedef void *void_ptr_t
;
289 typedef char * char_ptr_t
;
290 typedef wchar_t* wchar_ptr_t
;
291 typedef long * long_ptr_t
;
292 typedef int * int_ptr_t
;
293 typedef short * short_ptr_t
;
297 # define MAX_POS_ARGS NL_ARGMAX
299 # define MAX_POS_ARGS 32
310 _LONG_DOUBLE val__LONG_DOUBLE
;
311 int_ptr_t val_int_ptr_t
;
312 short_ptr_t val_short_ptr_t
;
313 long_ptr_t val_long_ptr_t
;
314 char_ptr_t val_char_ptr_t
;
315 wchar_ptr_t val_wchar_ptr_t
;
316 quad_ptr_t val_quad_ptr_t
;
317 void_ptr_t val_void_ptr_t
;
319 u_quad_t val_u_quad_t
;
323 static union arg_val
*
324 get_arg (struct _reent
*data
, int n
, wchar_t *fmt
,
325 va_list *ap
, int *numargs
, union arg_val
*args
,
326 int *arg_type
, wchar_t **last_fmt
);
327 #endif /* !_NO_POS_ARGS */
330 * Macros for converting digits to letters and vice versa
332 #define to_digit(c) ((c) - L'0')
333 #define is_digit(c) ((unsigned)to_digit (c) <= 9)
334 #define to_char(n) ((n) + L'0')
337 * Flags used during conversion.
339 #define ALT 0x001 /* alternate form */
340 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
341 #define LADJUST 0x004 /* left adjustment */
342 #define LONGDBL 0x008 /* long double */
343 #define LONGINT 0x010 /* long integer */
345 # define QUADINT 0x020 /* quad integer */
346 #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
347 that %lld behaves the same as %ld, not as %d, as expected if:
348 sizeof (long long) = sizeof long > sizeof int */
349 # define QUADINT LONGINT
351 #define SHORTINT 0x040 /* short integer */
352 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
353 #define FPT 0x100 /* Floating point number */
354 #ifdef _WANT_IO_C99_FORMATS
355 # define CHARINT 0x200 /* char as integer */
356 #else /* define as 0, to make SARG and UARG occupy fewer instructions */
359 #ifdef _WANT_IO_C99_FORMATS
360 # define GROUPING 0x400 /* use grouping ("'" flag) */
365 VFWPRINTF (FILE *__restrict fp
,
366 const wchar_t *__restrict fmt0
,
370 result
= _VFWPRINTF_R (_REENT
, fp
, fmt0
, ap
);
373 #endif /* STRING_ONLY */
376 _VFWPRINTF_R (struct _reent
*data
,
381 register wchar_t *fmt
; /* format string */
382 register wint_t ch
; /* character from fmt */
383 register int n
, m
; /* handy integers (short term usage) */
384 register wchar_t *cp
; /* handy char pointer (short term usage) */
385 register int flags
; /* flags as above */
386 wchar_t *fmt_anchor
; /* current format spec being processed */
388 int N
; /* arg number */
389 int arg_index
; /* index into args processed directly */
390 int numargs
; /* number of varargs read */
391 wchar_t *saved_fmt
; /* saved fmt pointer */
392 union arg_val args
[MAX_POS_ARGS
];
393 int arg_type
[MAX_POS_ARGS
];
394 int is_pos_arg
; /* is current format positional? */
395 int old_is_pos_arg
; /* is current format positional? */
397 int ret
; /* return value accumulator */
398 int width
; /* width from format (%8d), or 0 */
399 int prec
; /* precision from format (%.3d), or -1 */
400 wchar_t sign
; /* sign prefix (' ', '+', '-', or \0) */
401 #ifdef _WANT_IO_C99_FORMATS
402 /* locale specific numeric grouping */
403 wchar_t thousands_sep
= L
'\0';
404 const char *grouping
= NULL
;
406 #if defined (_MB_CAPABLE) && !defined (__HAVE_LOCALE_INFO_EXTENDED__) \
407 && (defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS))
408 mbstate_t state
; /* mbtowc calls from library must not change state */
410 #ifdef FLOATING_POINT
411 wchar_t decimal_point
;
412 wchar_t softsign
; /* temporary negative sign for floats */
413 union { int i
; _PRINTF_FLOAT_TYPE fp
; } _double_
= {0};
414 # define _fpvalue (_double_.fp)
415 int expt
; /* integer value of exponent */
416 int expsize
= 0; /* character count for expstr */
417 wchar_t expstr
[MAXEXPLEN
]; /* buffer for exponent string */
418 int lead
; /* sig figs before decimal or group sep */
419 #endif /* FLOATING_POINT */
420 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
421 int ndig
= 0; /* actual number of digits returned by cvt */
423 #if defined (FLOATING_POINT) && defined (_WANT_IO_C99_FORMATS)
424 int nseps
; /* number of group separators with ' */
425 int nrepeats
; /* number of repeats of the last group */
427 u_quad_t _uquad
; /* integer arguments %[diouxX] */
428 enum { OCT
, DEC
, HEX
} base
;/* base for [diouxX] conversion */
429 int dprec
; /* a copy of prec if [diouxX], 0 otherwise */
430 int realsz
; /* field size expanded by dprec */
431 int size
= 0; /* size of converted field or string */
432 wchar_t *xdigs
= NULL
; /* digits for [xX] conversion */
433 #ifdef _FVWRITE_IN_STREAMIO
435 struct __suio uio
; /* output information: summary */
436 struct __siov iov
[NIOV
];/* ... and individual io vectors */
437 register struct __siov
*iovp
;/* for PRINT macro */
439 wchar_t buf
[BUF
]; /* space for %c, %ls/%S, %[diouxX], %[aA] */
440 wchar_t ox
[2]; /* space for 0x hex-prefix */
441 wchar_t *malloc_buf
= NULL
;/* handy pointer for malloced buffers */
444 * Choose PADSIZE to trade efficiency vs. size. If larger printf
445 * fields occur frequently, increase PADSIZE and make the initialisers
448 #define PADSIZE 16 /* pad chunk size */
449 static const wchar_t blanks
[PADSIZE
] =
450 {L
' ',L
' ',L
' ',L
' ',L
' ',L
' ',L
' ',L
' ',
451 L
' ',L
' ',L
' ',L
' ',L
' ',L
' ',L
' ',L
' '};
452 static const wchar_t zeroes
[PADSIZE
] =
453 {L
'0',L
'0',L
'0',L
'0',L
'0',L
'0',L
'0',L
'0',
454 L
'0',L
'0',L
'0',L
'0',L
'0',L
'0',L
'0',L
'0'};
456 #ifdef FLOATING_POINT
458 #ifdef __HAVE_LOCALE_INFO_EXTENDED__
459 decimal_point
= *__get_current_numeric_locale ()->wdecimal_point
;
464 memset (&state
, '\0', sizeof (state
));
465 nconv
= _mbrtowc_r (data
, &decimal_point
,
466 _localeconv_r (data
)->decimal_point
,
468 if (nconv
== (size_t) -1 || nconv
== (size_t) -2)
469 decimal_point
= L
'.';
473 decimal_point
= (wchar_t) *_localeconv_r (data
)->decimal_point
;
477 * BEWARE, these `goto error' on error, and PAD uses `n'.
479 #ifdef _FVWRITE_IN_STREAMIO
480 #define PRINT(ptr, len) { \
481 iovp->iov_base = (char *) (ptr); \
482 iovp->iov_len = (len); \
483 uio.uio_resid += iovp->iov_len; \
485 if (++uio.uio_iovcnt >= NIOV) { \
486 if (__SPRINT(data, fp, &uio)) \
491 #define PAD(howmany, with) { \
492 if ((n = (howmany)) > 0) { \
493 while (n > PADSIZE) { \
494 PRINT (with, PADSIZE); \
500 #define PRINTANDPAD(p, ep, len, with) { \
501 int n = (ep) - (p); \
506 PAD((len) - (n > 0 ? n : 0), (with)); \
509 if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
511 uio.uio_iovcnt = 0; \
515 #define PRINT(ptr, len) { \
516 if (__SPRINT (data, fp, (ptr), (len)) == EOF) \
519 #define PAD(howmany, with) { \
520 if ((n = (howmany)) > 0) { \
521 while (n > PADSIZE) { \
522 PRINT (with, PADSIZE); \
528 #define PRINTANDPAD(p, ep, len, with) { \
529 int n = (ep) - (p); \
534 PAD((len) - (n > 0 ? n : 0), (with)); \
539 /* Macros to support positional arguments */
541 # define GET_ARG(n, ap, type) \
544 ? args[n].val_##type \
545 : get_arg (data, n, fmt_anchor, &ap, &numargs, args, \
546 arg_type, &saved_fmt)->val_##type) \
547 : (arg_index++ < numargs \
548 ? args[n].val_##type \
549 : (numargs < MAX_POS_ARGS \
550 ? args[numargs++].val_##type = va_arg (ap, type) \
551 : va_arg (ap, type))))
553 # define GET_ARG(n, ap, type) (va_arg (ap, type))
557 * To extend shorts properly, we need both signed and unsigned
558 * argument extraction methods.
562 (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
563 flags&LONGINT ? GET_ARG (N, ap, long) : \
564 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
565 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
566 (long)GET_ARG (N, ap, int))
568 (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
569 flags&LONGINT ? GET_ARG (N, ap, u_long) : \
570 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
571 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
572 (u_long)GET_ARG (N, ap, u_int))
575 (flags&LONGINT ? GET_ARG (N, ap, long) : \
576 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
577 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
578 (long)GET_ARG (N, ap, int))
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))
587 /* Initialize std streams if not dealing with sprintf family. */
588 CHECK_INIT (data
, fp
);
589 _newlib_flockfile_start (fp
);
591 if (ORIENT(fp
, 1) != 1) {
592 _newlib_flockfile_exit (fp
);
596 /* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */
597 if (cantwrite (data
, fp
)) {
598 _newlib_flockfile_exit (fp
);
602 #ifdef _UNBUF_STREAM_OPT
603 /* optimise fwprintf(stderr) (and other unbuffered Unix files) */
604 if ((fp
->_flags
& (__SNBF
|__SWR
|__SRW
)) == (__SNBF
|__SWR
) &&
606 _newlib_flockfile_exit (fp
);
607 return (__sbwprintf (data
, fp
, fmt0
, ap
));
610 #else /* STRING_ONLY */
611 /* Create initial buffer if we are called by asprintf family. */
612 if (fp
->_flags
& __SMBF
&& !fp
->_bf
._base
)
614 fp
->_bf
._base
= fp
->_p
= _malloc_r (data
, 64);
617 _REENT_ERRNO(data
) = ENOMEM
;
622 #endif /* STRING_ONLY */
624 fmt
= (wchar_t *)fmt0
;
625 #ifdef _FVWRITE_IN_STREAMIO
626 uio
.uio_iov
= iovp
= iov
;
640 * Scan the format for conversions (`%' character).
644 while (*fmt
!= L
'\0' && *fmt
!= L
'%')
646 if ((m
= fmt
- cp
) != 0) {
653 fmt
++; /* skip over '%' */
660 #ifdef FLOATING_POINT
662 #ifdef _WANT_IO_C99_FORMATS
663 nseps
= nrepeats
= 0;
672 reswitch
: switch (ch
) {
673 #ifdef _WANT_IO_C99_FORMATS
676 #ifdef __HAVE_LOCALE_INFO_EXTENDED__
677 thousands_sep
= *__get_current_numeric_locale ()->wthousands_sep
;
682 memset (&state
, '\0', sizeof (state
));
683 nconv
= _mbrtowc_r (data
, &thousands_sep
,
684 _localeconv_r (data
)->thousands_sep
,
686 if (nconv
== (size_t) -1 || nconv
== (size_t) -2)
687 thousands_sep
= L
'\0';
691 thousands_sep
= (wchar_t) *_localeconv_r(data
)->thousands_sep
;
693 grouping
= _localeconv_r (data
)->grouping
;
694 if (thousands_sep
&& grouping
&& *grouping
)
700 * ``If the space and + flags both appear, the space
701 * flag will be ignored.''
712 /* we must check for positional arg used for dynamic width */
714 old_is_pos_arg
= is_pos_arg
;
716 if (is_digit (*fmt
)) {
717 wchar_t *old_fmt
= fmt
;
722 n
= 10 * n
+ to_digit (ch
);
724 } while (is_digit (ch
));
727 if (n
<= MAX_POS_ARGS
) {
739 #endif /* !_NO_POS_ARGS */
742 * ``A negative field width argument is taken as a
743 * - flag followed by a positive field width.''
745 * They don't exclude field widths read from args.
747 width
= GET_ARG (n
, ap
, int);
749 is_pos_arg
= old_is_pos_arg
;
762 if ((ch
= *fmt
++) == L
'*') {
764 /* we must check for positional arg used for dynamic width */
766 old_is_pos_arg
= is_pos_arg
;
768 if (is_digit (*fmt
)) {
769 wchar_t *old_fmt
= fmt
;
774 n
= 10 * n
+ to_digit (ch
);
776 } while (is_digit (ch
));
779 if (n
<= MAX_POS_ARGS
) {
791 #endif /* !_NO_POS_ARGS */
792 prec
= GET_ARG (n
, ap
, int);
794 is_pos_arg
= old_is_pos_arg
;
801 while (is_digit (ch
)) {
802 n
= 10 * n
+ to_digit (ch
);
805 prec
= n
< 0 ? -1 : n
;
809 * ``Note that 0 is taken as a flag, not as the
810 * beginning of a field width.''
815 case L
'1': case L
'2': case L
'3': case L
'4':
816 case L
'5': case L
'6': case L
'7': case L
'8': case L
'9':
819 n
= 10 * n
+ to_digit (ch
);
821 } while (is_digit (ch
));
824 if (n
<= MAX_POS_ARGS
) {
832 #endif /* !_NO_POS_ARGS */
835 #ifdef FLOATING_POINT
841 #ifdef _WANT_IO_C99_FORMATS
850 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
858 case L
'q': /* GNU extension */
861 #ifdef _WANT_IO_C99_FORMATS
863 if (sizeof (intmax_t) == sizeof (long))
869 if (sizeof (size_t) < sizeof (int))
870 /* POSIX states size_t is 16 or more bits, as is short. */
872 else if (sizeof (size_t) == sizeof (int))
873 /* no flag needed */;
874 else if (sizeof (size_t) <= sizeof (long))
877 /* POSIX states that at least one programming
878 environment must support size_t no wider than
879 long, but that means other environments can
880 have size_t as wide as long long. */
884 if (sizeof (ptrdiff_t) < sizeof (int))
885 /* POSIX states ptrdiff_t is 16 or more bits, as
888 else if (sizeof (ptrdiff_t) == sizeof (int))
889 /* no flag needed */;
890 else if (sizeof (ptrdiff_t) <= sizeof (long))
893 /* POSIX states that at least one programming
894 environment must support ptrdiff_t no wider than
895 long, but that means other environments can
896 have ptrdiff_t as wide as long long. */
899 case L
'C': /* POSIX extension */
900 #endif /* _WANT_IO_C99_FORMATS */
903 if (ch
== L
'c' && !(flags
& LONGINT
)) {
904 wint_t wc
= btowc ((int) GET_ARG (N
, ap
, int));
906 fp
->_flags
|= __SERR
;
909 cp
[0] = (wchar_t) wc
;
913 cp
[0] = GET_ARG (N
, ap
, int);
923 if ((quad_t
)_uquad
< 0)
925 if ((long) _uquad
< 0)
934 #ifdef FLOATING_POINT
935 # ifdef _WANT_IO_C99_FORMATS
946 if (flags
& LONGDBL
) {
947 _fpvalue
= (double) GET_ARG (N
, ap
, _LONG_DOUBLE
);
949 _fpvalue
= GET_ARG (N
, ap
, double);
952 /* do this before tricky precision changes
954 If the output is infinite or NaN, leading
955 zeros are not permitted. Otherwise, scanf
956 could not read what printf wrote.
958 if (isinf (_fpvalue
)) {
961 if (ch
<= L
'G') /* 'A', 'E', 'F', or 'G' */
969 if (isnan (_fpvalue
)) {
970 if (signbit (_fpvalue
))
972 if (ch
<= L
'G') /* 'A', 'E', 'F', or 'G' */
981 # else /* !_NO_LONGDBL */
983 if (flags
& LONGDBL
) {
984 _fpvalue
= GET_ARG (N
, ap
, _LONG_DOUBLE
);
986 _fpvalue
= (_LONG_DOUBLE
)GET_ARG (N
, ap
, double);
989 /* do this before tricky precision changes */
990 expt
= _ldcheck (&_fpvalue
);
994 if (ch
<= L
'G') /* 'A', 'E', 'F', or 'G' */
1003 if (signbit (_fpvalue
))
1005 if (ch
<= L
'G') /* 'A', 'E', 'F', or 'G' */
1013 # endif /* !_NO_LONGDBL */
1016 # ifdef _WANT_IO_C99_FORMATS
1017 if (ch
== L
'a' || ch
== L
'A') {
1019 ox
[1] = ch
== L
'a' ? L
'x' : L
'X';
1024 (wchar_t *)_malloc_r (data
, (prec
+ 1) * sizeof (wchar_t)))
1027 fp
->_flags
|= __SERR
;
1033 # endif /* _WANT_IO_C99_FORMATS */
1036 } else if ((ch
== L
'g' || ch
== L
'G') && prec
== 0) {
1042 cp
= wcvt (data
, _fpvalue
, prec
, flags
, &softsign
,
1043 &expt
, ch
, &ndig
, cp
, BUF
);
1045 /* If buf is not large enough for the converted wchar_t
1046 sequence, call wcvt again with a malloced new buffer.
1047 This should happen fairly rarely.
1049 if (cp
== buf
&& ndig
> BUF
&& malloc_buf
== NULL
) {
1051 (wchar_t *)_malloc_r (data
, ndig
* sizeof (wchar_t)))
1054 fp
->_flags
|= __SERR
;
1057 cp
= wcvt (data
, _fpvalue
, prec
, flags
, &softsign
,
1058 &expt
, ch
, &ndig
, malloc_buf
, ndig
);
1061 if (ch
== L
'g' || ch
== L
'G') {
1062 if (expt
<= -4 || expt
> prec
)
1063 ch
-= 2; /* 'e' or 'E' */
1067 # ifdef _WANT_IO_C99_FORMATS
1068 else if (ch
== L
'F')
1071 if (ch
<= L
'e') { /* 'a', 'A', 'e', or 'E' fmt */
1073 expsize
= wexponent (expstr
, expt
, ch
);
1074 size
= expsize
+ ndig
;
1075 if (ndig
> 1 || flags
& ALT
)
1077 # ifdef _WANT_IO_C99_FORMATS
1081 if (ch
== L
'f') { /* f fmt */
1084 if (prec
|| flags
& ALT
)
1087 size
= (prec
|| flags
& ALT
)
1090 } else if (expt
>= ndig
) { /* fixed g fmt */
1095 size
= ndig
+ (expt
> 0 ?
1097 # ifdef _WANT_IO_C99_FORMATS
1098 if ((flags
& GROUPING
) && expt
> 0) {
1099 /* space for thousands' grouping */
1100 nseps
= nrepeats
= 0;
1102 while (*grouping
!= CHAR_MAX
) {
1103 if (lead
<= *grouping
)
1112 size
+= nseps
+ nrepeats
;
1120 #endif /* FLOATING_POINT */
1121 #ifdef _GLIBC_EXTENSION
1122 case L
'm': /* GNU extension */
1125 cp
= (wchar_t *) _strerror_r (data
, _REENT_ERRNO(data
), 1, &dummy
);
1131 #ifndef _NO_LONGLONG
1132 if (flags
& QUADINT
)
1133 *GET_ARG (N
, ap
, quad_ptr_t
) = ret
;
1136 if (flags
& LONGINT
)
1137 *GET_ARG (N
, ap
, long_ptr_t
) = ret
;
1138 else if (flags
& SHORTINT
)
1139 *GET_ARG (N
, ap
, short_ptr_t
) = ret
;
1140 #ifdef _WANT_IO_C99_FORMATS
1141 else if (flags
& CHARINT
)
1142 *GET_ARG (N
, ap
, char_ptr_t
) = ret
;
1145 *GET_ARG (N
, ap
, int_ptr_t
) = ret
;
1146 continue; /* no output */
1150 #ifdef _WANT_IO_C99_FORMATS
1156 * ``The argument shall be a pointer to void. The
1157 * value of the pointer is converted to a sequence
1158 * of printable characters, in an implementation-
1163 _uquad
= (uintptr_t) GET_ARG (N
, ap
, void_ptr_t
);
1165 xdigs
= L
"0123456789abcdef";
1171 #ifdef _WANT_IO_C99_FORMATS
1172 case L
'S': /* POSIX extension */
1174 cp
= GET_ARG (N
, ap
, wchar_ptr_t
);
1175 #ifdef _GLIBC_EXTENSION
1179 #ifndef __OPTIMIZE_SIZE__
1180 /* Behavior is undefined if the user passed a
1181 NULL string when precision is not 0.
1182 However, if we are not optimizing for size,
1183 we might as well mirror glibc behavior. */
1186 size
= ((unsigned) prec
> 6U) ? 6 : prec
;
1189 #endif /* __OPTIMIZE_SIZE__ */
1191 if (ch
!= L
'S' && !(flags
& LONGINT
)) {
1192 char *arg
= (char *) cp
;
1193 size_t insize
= 0, nchars
= 0, nconv
= 0;
1199 memset ((void *)&ps
, '\0', sizeof (mbstate_t));
1200 while (nchars
< (size_t)prec
) {
1201 nconv
= mbrlen (p
, MB_CUR_MAX
, &ps
);
1202 if (nconv
== 0 || nconv
== (size_t)-1 ||
1203 nconv
== (size_t)-2)
1209 if (nconv
== (size_t) -1 || nconv
== (size_t) -2) {
1210 fp
->_flags
|= __SERR
;
1214 insize
= strlen(arg
);
1215 if (insize
>= BUF
) {
1216 if ((malloc_buf
= (wchar_t *) _malloc_r (data
, (insize
+ 1) * sizeof (wchar_t)))
1218 fp
->_flags
|= __SERR
;
1224 memset ((void *)&ps
, '\0', sizeof (mbstate_t));
1226 while (insize
!= 0) {
1227 nconv
= _mbrtowc_r (data
, p
, arg
, insize
, &ps
);
1228 if (nconv
== 0 || nconv
== (size_t)-1 || nconv
== (size_t)-2)
1234 if (nconv
== (size_t) -1 || nconv
== (size_t) -2) {
1235 fp
->_flags
|= __SERR
;
1242 if (ch
!= L
'S' && !(flags
& LONGINT
)) {
1243 char *arg
= (char *) cp
;
1247 char *p
= memchr (arg
, '\0', prec
);
1248 insize
= p
? p
- arg
: prec
;
1250 insize
= strlen (arg
);
1251 if (insize
>= BUF
) {
1252 if ((malloc_buf
= (wchar_t *) _malloc_r (data
, (insize
+ 1) * sizeof (wchar_t)))
1254 fp
->_flags
|= __SERR
;
1260 for (size
= 0; size
< insize
; ++size
)
1261 cp
[size
] = arg
[size
];
1264 #endif /* _MB_CAPABLE */
1265 else if (prec
>= 0) {
1267 * can't use wcslen; can only look for the
1268 * NUL in the first `prec' characters, and
1269 * strlen () will go further.
1271 wchar_t *p
= wmemchr (cp
, L
'\0', prec
);
1288 xdigs
= L
"0123456789ABCDEF";
1291 xdigs
= L
"0123456789abcdef";
1292 hex
: _uquad
= UARG ();
1294 /* leading 0x/X only if non-zero */
1295 if (flags
& ALT
&& _uquad
!= 0) {
1301 #ifdef _WANT_IO_C99_FORMATS
1304 /* unsigned conversions */
1305 nosign
: sign
= L
'\0';
1307 * ``... diouXx conversions ... if a precision is
1308 * specified, the 0 flag will be ignored.''
1311 number
: if ((dprec
= prec
) >= 0)
1315 * ``The result of converting a zero value with an
1316 * explicit precision of zero is no characters.''
1320 if (_uquad
!= 0 || prec
!= 0) {
1322 * Unsigned mod is hard, and unsigned mod
1323 * by a constant is easier than that by
1324 * a variable; hence this switch.
1329 *--cp
= to_char (_uquad
& 7);
1332 /* handle octal leading 0 */
1333 if (flags
& ALT
&& *cp
!= L
'0')
1338 /* many numbers are 1 digit */
1340 *--cp
= to_char(_uquad
);
1343 #ifdef _WANT_IO_C99_FORMATS
1347 *--cp
= to_char (_uquad
% 10);
1348 #ifdef _WANT_IO_C99_FORMATS
1350 /* If (*grouping == CHAR_MAX) then no
1352 if ((flags
& GROUPING
)
1353 && ndig
== *grouping
1354 && *grouping
!= CHAR_MAX
1356 *--cp
= thousands_sep
;
1358 /* If (grouping[1] == '\0') then we
1359 have to use *grouping character
1360 (last grouping rule) for all
1362 if (grouping
[1] != '\0')
1367 } while (_uquad
!= 0);
1372 *--cp
= xdigs
[_uquad
& 15];
1378 cp
= L
"bug in vfprintf: bad base";
1384 * ...result is to be converted to an 'alternate form'.
1385 * For o conversion, it increases the precision to force
1386 * the first digit of the result to be a zero."
1389 * To demonstrate this case, compile and run:
1390 * printf ("%#.0o",0);
1392 else if (base
== OCT
&& (flags
& ALT
))
1395 size
= buf
+ BUF
- cp
;
1398 default: /* "%?" prints ?, unless ? is NUL */
1401 /* pretend it was %c with argument ch */
1410 * All reasonable formats wind up here. At this point, `cp'
1411 * points to a string which (if not flags&LADJUST) should be
1412 * padded out to `width' places. If flags&ZEROPAD, it should
1413 * first be prefixed by any sign or other prefix; otherwise,
1414 * it should be blank padded before the prefix is emitted.
1415 * After any left-hand padding and prefixing, emit zeroes
1416 * required by a decimal [diouxX] precision, then print the
1417 * string proper, then emit zeroes required by any leftover
1418 * floating precision; finally, if LADJUST, pad with blanks.
1419 * If flags&FPT, ch must be in [aAeEfg].
1421 * Compute actual size, so we know how much to pad.
1422 * size excludes decimal prec; realsz includes it.
1424 realsz
= dprec
> size
? dprec
: size
;
1427 if (flags
& HEXPREFIX
)
1430 /* right-adjusting blank padding */
1431 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
1432 PAD (width
- realsz
, blanks
);
1437 if (flags
& HEXPREFIX
)
1440 /* right-adjusting zero padding */
1441 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
1442 PAD (width
- realsz
, zeroes
);
1444 /* leading zeroes from decimal precision */
1445 PAD (dprec
- size
, zeroes
);
1447 /* the string or number proper */
1448 #ifdef FLOATING_POINT
1449 if ((flags
& FPT
) == 0) {
1451 } else { /* glue together f_p fragments */
1452 if (ch
>= L
'f') { /* 'f' or 'g' */
1453 if (_fpvalue
== 0) {
1454 /* kludge for __dtoa irregularity */
1456 if (expt
< ndig
|| flags
& ALT
) {
1457 PRINT (&decimal_point
, 1);
1458 PAD (ndig
- 1, zeroes
);
1460 } else if (expt
<= 0) {
1462 if (expt
|| ndig
|| flags
& ALT
) {
1463 PRINT (&decimal_point
, 1);
1464 PAD (-expt
, zeroes
);
1468 wchar_t *convbuf
= cp
;
1469 PRINTANDPAD(cp
, convbuf
+ ndig
,
1472 #ifdef _WANT_IO_C99_FORMATS
1473 if (flags
& GROUPING
) {
1474 while (nseps
> 0 || nrepeats
> 0) {
1481 PRINT (&thousands_sep
, 1);
1482 PRINTANDPAD (cp
, convbuf
+ ndig
,
1486 if (cp
> convbuf
+ ndig
)
1487 cp
= convbuf
+ ndig
;
1490 if (expt
< ndig
|| flags
& ALT
)
1491 PRINT (&decimal_point
, 1);
1492 PRINTANDPAD (cp
, convbuf
+ ndig
,
1493 ndig
- expt
, zeroes
);
1496 } else { /* 'a', 'A', 'e', or 'E' */
1497 if (ndig
> 1 || flags
& ALT
) {
1500 PRINT (&decimal_point
, 1);
1502 PRINT (cp
, ndig
- 1);
1503 } else /* 0.[0..] */
1504 /* __dtoa irregularity */
1505 PAD (ndig
- 1, zeroes
);
1508 PRINT (expstr
, expsize
);
1511 #else /* !FLOATING_POINT */
1514 /* left-adjusting padding (always blank) */
1515 if (flags
& LADJUST
)
1516 PAD (width
- realsz
, blanks
);
1518 /* finally, adjust ret */
1519 ret
+= width
> realsz
? width
: realsz
;
1521 FLUSH (); /* copy out the I/O vectors */
1523 if (malloc_buf
!= NULL
) {
1524 _free_r (data
, malloc_buf
);
1531 if (malloc_buf
!= NULL
)
1532 _free_r (data
, malloc_buf
);
1534 _newlib_flockfile_end (fp
);
1536 return (__sferror (fp
) ? EOF
: ret
);
1540 #ifdef FLOATING_POINT
1542 /* Using reentrant DATA, convert finite VALUE into a string of digits
1543 with no decimal point, using NDIGITS precision and FLAGS as guides
1544 to whether trailing zeros must be included. Set *SIGN to nonzero
1545 if VALUE was negative. Set *DECPT to the exponent plus one. Set
1546 *LENGTH to the length of the returned string. CH must be one of
1547 [aAeEfFgG]; different from vfprintf.c:cvt(), the return string
1548 lives in BUF regardless of CH. LEN is the length of BUF, except
1549 when CH is [aA], in which case LEN is not in use. If BUF is not
1550 large enough for the converted string, only the first LEN number
1551 of characters will be returned in BUF, but *LENGTH will be set to
1552 the full length of the string before the truncation. */
1554 wcvt(struct _reent
*data
, _PRINTF_FLOAT_TYPE value
, int ndigits
, int flags
,
1555 wchar_t *sign
, int *decpt
, int ch
, int *length
, wchar_t *buf
, int len
)
1559 union double_union tmp
;
1562 if (word0 (tmp
) & Sign_bit
) { /* this will check for < 0 and -0.0 */
1567 # else /* !_NO_LONGDBL */
1575 if (ld
.ieee
.sign
) { /* this will check for < 0 and -0.0 */
1580 # endif /* !_NO_LONGDBL */
1582 # ifdef _WANT_IO_C99_FORMATS
1583 if (ch
== L
'a' || ch
== L
'A') {
1584 wchar_t *digits
, *bp
, *rve
;
1585 /* This code assumes FLT_RADIX is a power of 2. The initial
1586 division ensures the digit before the decimal will be less
1587 than FLT_RADIX (unless it is rounded later). There is no
1588 loss of precision in these calculations. */
1589 value
= FREXP (value
, decpt
) / 8;
1592 digits
= ch
== L
'a' ? L
"0123456789abcdef" : L
"0123456789ABCDEF";
1598 *bp
++ = digits
[mode
];
1599 } while (ndigits
-- && value
);
1600 if (value
> 0.5 || (value
== 0.5 && mode
& 1)) {
1603 while (*--rve
== digits
[0xf]) {
1606 *rve
= *rve
== L
'9' ? digits
[0xa] : *rve
+ 1;
1608 while (ndigits
-- >= 0) {
1615 # endif /* _WANT_IO_C99_FORMATS */
1616 if (ch
== L
'f' || ch
== L
'F') {
1617 mode
= 3; /* ndigits after the decimal point */
1619 /* To obtain ndigits after the decimal point for the 'e'
1620 * and 'E' formats, round to ndigits + 1 significant
1623 if (ch
== L
'e' || ch
== L
'E') {
1626 mode
= 2; /* ndigits significant digits */
1630 char *digits
, *bp
, *rve
;
1635 digits
= _DTOA_R (data
, value
, mode
, ndigits
, decpt
, &dsgn
, &rve
);
1637 if ((ch
!= L
'g' && ch
!= L
'G') || flags
& ALT
) { /* Print trailing zeros */
1638 bp
= digits
+ ndigits
;
1639 if (ch
== L
'f' || ch
== L
'F') {
1640 if (*digits
== L
'0' && value
)
1641 *decpt
= -ndigits
+ 1;
1644 if (value
== 0) /* kludge for __dtoa irregularity */
1650 *length
= rve
- digits
; /* full length of the string */
1652 _mbsnrtowcs_r (data
, buf
, (const char **) &digits
, *length
,
1655 for (i
= 0; i
< *length
&& i
< len
; ++i
)
1656 buf
[i
] = (wchar_t) digits
[i
];
1663 wexponent(wchar_t *p0
, int exp
, int fmtch
)
1665 register wchar_t *p
, *t
;
1666 wchar_t expbuf
[MAXEXPLEN
];
1667 # ifdef _WANT_IO_C99_FORMATS
1668 int isa
= fmtch
== L
'a' || fmtch
== L
'A';
1674 *p
++ = isa
? L
'p' - L
'a' + fmtch
: fmtch
;
1681 t
= expbuf
+ MAXEXPLEN
;
1684 *--t
= to_char (exp
% 10);
1685 } while ((exp
/= 10) > 9);
1686 *--t
= to_char (exp
);
1687 for (; t
< expbuf
+ MAXEXPLEN
; *p
++ = *t
++);
1692 *p
++ = to_char (exp
);
1696 #endif /* FLOATING_POINT */
1699 #ifndef _NO_POS_ARGS
1701 /* Positional argument support.
1702 Written by Jeff Johnston
1704 Copyright (c) 2002 Red Hat Incorporated.
1705 All rights reserved.
1707 Redistribution and use in source and binary forms, with or without
1708 modification, are permitted provided that the following conditions are met:
1710 Redistributions of source code must retain the above copyright
1711 notice, this list of conditions and the following disclaimer.
1713 Redistributions in binary form must reproduce the above copyright
1714 notice, this list of conditions and the following disclaimer in the
1715 documentation and/or other materials provided with the distribution.
1717 The name of Red Hat Incorporated may not be used to endorse
1718 or promote products derived from this software without specific
1719 prior written permission.
1721 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1722 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1723 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1724 DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1725 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1726 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1727 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1728 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1729 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1730 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1732 /* function to get positional parameter N where n = N - 1 */
1733 static union arg_val
*
1734 get_arg (struct _reent
*data
,
1739 union arg_val
*args
,
1746 int numargs
= *numargs_p
;
1748 __STATE state
, next_state
;
1751 int max_pos_arg
= n
;
1752 /* Only need types that can be reached via vararg promotions. */
1753 enum types
{ INT
, LONG_INT
, QUAD_INT
, CHAR_PTR
, DOUBLE
, LONG_DOUBLE
, WIDE_CHAR
};
1755 /* if this isn't the first call, pick up where we left off last time */
1756 if (*last_fmt
!= NULL
)
1759 /* we need to process either to end of fmt string or until we have actually
1760 read the desired parameter from the vararg list. */
1761 while (*fmt
&& n
>= numargs
)
1763 while (*fmt
!= L
'\0' && *fmt
!= L
'%')
1774 /* Use state/action table to process format specifiers. We ignore invalid
1775 formats and we are only interested in information that tells us how to
1776 read the vararg list. */
1777 while (state
!= DONE
)
1780 chtype
= ch
< (wchar_t) 256 ? __chclass
[ch
] : OTHER
;
1781 next_state
= __state_table
[state
][chtype
];
1782 action
= __action_table
[state
][chtype
];
1787 case GETMOD
: /* we have format modifier */
1791 /* No flag needed, since short and char promote to int. */
1799 # ifdef _WANT_IO_C99_FORMATS
1801 if (sizeof (intmax_t) == sizeof (long))
1807 if (sizeof (size_t) <= sizeof (int))
1808 /* no flag needed */;
1809 else if (sizeof (size_t) <= sizeof (long))
1812 /* POSIX states that at least one programming
1813 environment must support size_t no wider than
1814 long, but that means other environments can
1815 have size_t as wide as long long. */
1819 if (sizeof (ptrdiff_t) <= sizeof (int))
1820 /* no flag needed */;
1821 else if (sizeof (ptrdiff_t) <= sizeof (long))
1824 /* POSIX states that at least one programming
1825 environment must support ptrdiff_t no wider than
1826 long, but that means other environments can
1827 have ptrdiff_t as wide as long long. */
1830 # endif /* _WANT_IO_C99_FORMATS */
1833 # if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
1845 case GETARG
: /* we have format specifier */
1847 numargs
&= (MAX_POS_ARGS
- 1);
1848 /* process the specifier and translate it to a type to fetch from varargs */
1857 if (flags
& LONGINT
)
1858 spec_type
= LONG_INT
;
1859 # ifndef _NO_LONGLONG
1860 else if (flags
& QUADINT
)
1861 spec_type
= QUAD_INT
;
1866 # ifdef _WANT_IO_C99_FORMATS
1876 # ifndef _NO_LONGDBL
1877 if (flags
& LONGDBL
)
1878 spec_type
= LONG_DOUBLE
;
1884 # ifdef _WANT_IO_C99_FORMATS
1885 case L
'S': /* POSIX extension */
1889 spec_type
= CHAR_PTR
;
1892 # ifdef _WANT_IO_C99_FORMATS
1893 if (flags
& LONGINT
)
1894 spec_type
= WIDE_CHAR
;
1899 # ifdef _WANT_IO_C99_FORMATS
1900 case L
'C': /* POSIX extension */
1901 spec_type
= WIDE_CHAR
;
1906 /* if we have a positional parameter, just store the type, otherwise
1907 fetch the parameter from the vararg list */
1909 arg_type
[pos
] = spec_type
;
1915 args
[numargs
++].val_long
= va_arg (*ap
, long);
1918 args
[numargs
++].val_quad_t
= va_arg (*ap
, quad_t
);
1921 args
[numargs
++].val_wint_t
= va_arg (*ap
, wint_t);
1924 args
[numargs
++].val_int
= va_arg (*ap
, int);
1927 args
[numargs
++].val_wchar_ptr_t
= va_arg (*ap
, wchar_t *);
1930 args
[numargs
++].val_double
= va_arg (*ap
, double);
1933 args
[numargs
++].val__LONG_DOUBLE
= va_arg (*ap
, _LONG_DOUBLE
);
1939 case GETPOS
: /* we have positional specifier */
1940 if (arg_type
[0] == -1)
1941 memset (arg_type
, 0, sizeof (int) * MAX_POS_ARGS
);
1943 max_pos_arg
= (max_pos_arg
> pos
? max_pos_arg
: pos
);
1945 case PWPOS
: /* we have positional specifier for width or precision */
1946 if (arg_type
[0] == -1)
1947 memset (arg_type
, 0, sizeof (int) * MAX_POS_ARGS
);
1949 arg_type
[number
] = INT
;
1950 max_pos_arg
= (max_pos_arg
> number
? max_pos_arg
: number
);
1952 case GETPWB
: /* we require format pushback */
1955 case GETPW
: /* we have a variable precision or width to acquire */
1956 args
[numargs
++].val_int
= va_arg (*ap
, int);
1958 case NUMBER
: /* we have a number to process */
1959 number
= (ch
- '0');
1960 while ((ch
= *fmt
) != '\0' && is_digit (ch
))
1962 number
= number
* 10 + (ch
- '0');
1966 case SKIPNUM
: /* we have a number to skip */
1967 while ((ch
= *fmt
) != '\0' && is_digit (ch
))
1972 break; /* do nothing */
1977 /* process all arguments up to at least the one we are looking for and if we
1978 have seen the end of the string, then process up to the max argument needed */
1980 last_arg
= max_pos_arg
;
1984 while (numargs
<= last_arg
)
1986 switch (arg_type
[numargs
])
1989 args
[numargs
++].val_long
= va_arg (*ap
, long);
1992 args
[numargs
++].val_quad_t
= va_arg (*ap
, quad_t
);
1995 args
[numargs
++].val_wchar_ptr_t
= va_arg (*ap
, wchar_t *);
1998 args
[numargs
++].val_double
= va_arg (*ap
, double);
2001 args
[numargs
++].val__LONG_DOUBLE
= va_arg (*ap
, _LONG_DOUBLE
);
2004 args
[numargs
++].val_wint_t
= va_arg (*ap
, wint_t);
2008 args
[numargs
++].val_int
= va_arg (*ap
, int);
2013 /* alter the global numargs value and keep a reference to the last bit of the fmt
2014 string we processed here because the caller will continue processing where we started */
2015 *numargs_p
= numargs
;
2019 #endif /* !_NO_POS_ARGS */