Cygwin: mmap: allow remapping part of an existing anonymous mapping
[newlib-cygwin.git] / newlib / libc / stdio / vfprintf.c
blobfeb1fab560633f51a0f54a3b67c84151a2593aa8
1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
34 FUNCTION
35 <<vfprintf>>, <<vprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, <<vasnprintf>>---format argument list
37 INDEX
38 vfprintf
39 INDEX
40 _vfprintf_r
41 INDEX
42 vprintf
43 INDEX
44 _vprintf_r
45 INDEX
46 vsprintf
47 INDEX
48 _vsprintf_r
49 INDEX
50 vsnprintf
51 INDEX
52 _vsnprintf_r
53 INDEX
54 vasprintf
55 INDEX
56 _vasprintf_r
57 INDEX
58 vasnprintf
59 INDEX
60 _vasnprintf_r
62 SYNOPSIS
63 #include <stdio.h>
64 #include <stdarg.h>
65 int vprintf(const char *<[fmt]>, va_list <[list]>);
66 int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
67 int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
68 int vsnprintf(char *<[str]>, size_t <[size]>, const char *<[fmt]>,
69 va_list <[list]>);
70 int vasprintf(char **<[strp]>, const char *<[fmt]>, va_list <[list]>);
71 char *vasnprintf(char *<[str]>, size_t *<[size]>, const char *<[fmt]>,
72 va_list <[list]>);
74 int _vprintf_r(struct _reent *<[reent]>, const char *<[fmt]>,
75 va_list <[list]>);
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]>);
87 DESCRIPTION
88 <<vprintf>>, <<vfprintf>>, <<vasprintf>>, <<vsprintf>>, <<vsnprintf>>,
89 and <<vasnprintf>> are (respectively) variants of <<printf>>,
90 <<fprintf>>, <<asprintf>>, <<sprintf>>, <<snprintf>>, and
91 <<asnprintf>>. They differ only in allowing their caller to pass the
92 variable argument list as a <<va_list>> object (initialized by
93 <<va_start>>) rather than directly accepting a variable number of
94 arguments. The caller is responsible for calling <<va_end>>.
96 <<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
97 <<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
98 above.
100 RETURNS
101 The return values are consistent with the corresponding functions.
103 PORTABILITY
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...
121 #include <newlib.h>
123 #ifdef INTEGER_ONLY
124 # define VFPRINTF vfiprintf
125 # ifdef STRING_ONLY
126 # define _VFPRINTF_R _svfiprintf_r
127 # else
128 # define _VFPRINTF_R _vfiprintf_r
129 # endif
130 #else
131 # define VFPRINTF vfprintf
132 # ifdef STRING_ONLY
133 # define _VFPRINTF_R _svfprintf_r
134 # else
135 # define _VFPRINTF_R _vfprintf_r
136 # endif
137 # ifndef NO_FLOATING_POINT
138 # define FLOATING_POINT
139 # endif
140 #endif
142 #define _NO_POS_ARGS
143 #ifdef _WANT_IO_POS_ARGS
144 # undef _NO_POS_ARGS
145 #endif
147 #include <_ansi.h>
148 #include <reent.h>
149 #include <stdio.h>
150 #include <stdlib.h>
151 #include <string.h>
152 #include <limits.h>
153 #include <stdint.h>
154 #include <wchar.h>
155 #include <sys/lock.h>
156 #include <stdarg.h>
157 #include "local.h"
158 #include "../stdlib/local.h"
159 #include "fvwrite.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. */
165 #define _NO_LONGDBL
166 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
167 #undef _NO_LONGDBL
168 #endif
170 #define _NO_LONGLONG
171 #if defined _WANT_IO_LONG_LONG \
172 && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
173 # undef _NO_LONGLONG
174 #endif
176 #ifdef STRING_ONLY
178 # ifdef _FVWRITE_IN_STREAMIO
179 # define __SPRINT __ssprint_r
180 int __ssprint_r (struct _reent *, FILE *, register struct __suio *);
181 # else
182 # define __SPRINT __ssputs_r
183 int __ssputs_r (struct _reent *, FILE *, const char *, size_t);
184 # endif
186 #else /* !STRING_ONLY */
188 # ifdef _FVWRITE_IN_STREAMIO
189 # define __SPRINT __sprint_r
190 int __sprint_r (struct _reent *, FILE *, register struct __suio *);
191 # else
192 # define __SPRINT __sfputs_r
193 int __sfputs_r (struct _reent *, FILE *, const char *buf, size_t);
194 # endif
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.
204 _NOINLINE_STATIC int
205 __sbprintf (struct _reent *rptr,
206 register FILE *fp,
207 const char *fmt,
208 va_list ap)
210 int ret;
211 FILE fake;
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);
227 #endif
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))
232 ret = EOF;
233 if (fake._flags & __SERR)
234 fp->_flags |= __SERR;
236 #ifndef __SINGLE_THREAD__
237 __lock_close_recursive (fake._lock);
238 #endif
239 return (ret);
241 #endif /* _UNBUF_STREAM_OPT */
242 #endif /* !STRING_ONLY */
245 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
246 # include <locale.h>
247 #endif
248 #ifdef FLOATING_POINT
249 # include <math.h>
251 /* For %La, an exponent of 15 bits occupies the exponent character, a
252 sign, and up to 5 digits. */
253 # define MAXEXPLEN 7
254 # define DEFPREC 6
256 # ifdef _NO_LONGDBL
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
263 # define FREXP frexp
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 *,
278 int, int *, char *);
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
298 #define BUF 100
299 #else
300 #define BUF 40
301 #endif
302 #if defined _MB_CAPABLE && MB_LEN_MAX > BUF
303 # undef BUF
304 # define BUF MB_LEN_MAX
305 #endif
307 #ifndef _NO_LONGLONG
308 # define quad_t long long
309 # define u_quad_t unsigned long long
310 #else
311 # define quad_t long
312 # define u_quad_t unsigned long
313 #endif
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;
322 #ifndef _NO_POS_ARGS
323 # ifdef NL_ARGMAX
324 # define MAX_POS_ARGS NL_ARGMAX
325 # else
326 # define MAX_POS_ARGS 32
327 # endif
329 union arg_val
331 int val_int;
332 u_int val_u_int;
333 long val_long;
334 u_long val_u_long;
335 float val_float;
336 double val_double;
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;
344 quad_t val_quad_t;
345 u_quad_t val_u_quad_t;
346 wint_t val_wint_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 */
370 #ifndef _NO_LONGLONG
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
376 #endif
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 */
383 # define CHARINT 0
384 #endif
385 #ifdef _WANT_IO_C99_FORMATS
386 # define GROUPING 0x400 /* use grouping ("'" flag) */
387 #endif
389 int _VFPRINTF_R (struct _reent *, FILE *, const char *, va_list);
391 #ifndef STRING_ONLY
393 VFPRINTF (FILE * fp,
394 const char *fmt0,
395 va_list ap)
397 int result;
398 result = _VFPRINTF_R (_REENT, fp, fmt0, ap);
399 return result;
401 #endif /* STRING_ONLY */
404 _VFPRINTF_R (struct _reent *data,
405 FILE * fp,
406 const char *fmt0,
407 va_list ap)
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 */
415 #ifndef _NO_POS_ARGS
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? */
424 #endif
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;
434 #endif
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 */
448 #endif
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 */
452 #endif
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
460 #define NIOV 8
461 struct __suio uio; /* output information: summary */
462 struct __siov iov[NIOV];/* ... and individual io vectors */
463 register struct __siov *iovp;/* for PRINT macro */
464 #endif
465 char buf[BUF]; /* space for %c, %S, %[diouxX], %[aA] */
466 char ox[2]; /* space for 0x hex-prefix */
467 #ifdef _MB_CAPABLE
468 wchar_t wc;
469 mbstate_t state; /* mbtowc calls from library must not change state */
470 #endif
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
476 * below longer.
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'};
484 #ifdef _MB_CAPABLE
485 memset (&state, '\0', sizeof (state));
486 #endif
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); \
495 iovp++; \
496 if (++uio.uio_iovcnt >= NIOV) { \
497 if (__SPRINT(data, fp, &uio)) \
498 goto error; \
499 iovp = iov; \
502 #define PAD(howmany, with) { \
503 if ((n = (howmany)) > 0) { \
504 while (n > PADSIZE) { \
505 PRINT (with, PADSIZE); \
506 n -= PADSIZE; \
508 PRINT (with, n); \
511 #define PRINTANDPAD(p, ep, len, with) { \
512 int n = (ep) - (p); \
513 if (n > (len)) \
514 n = (len); \
515 if (n > 0) \
516 PRINT((p), n); \
517 PAD((len) - (n > 0 ? n : 0), (with)); \
519 #define FLUSH() { \
520 if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
521 goto error; \
522 uio.uio_iovcnt = 0; \
523 iovp = iov; \
525 #else
526 #define PRINT(ptr, len) { \
527 if (__SPRINT (data, fp, (ptr), (len)) == EOF) \
528 goto error; \
530 #define PAD(howmany, with) { \
531 if ((n = (howmany)) > 0) { \
532 while (n > PADSIZE) { \
533 PRINT (with, PADSIZE); \
534 n -= PADSIZE; \
536 PRINT (with, n); \
539 #define PRINTANDPAD(p, ep, len, with) { \
540 int n = (ep) - (p); \
541 if (n > (len)) \
542 n = (len); \
543 if (n > 0) \
544 PRINT((p), n); \
545 PAD((len) - (n > 0 ? n : 0), (with)); \
547 #define FLUSH()
548 #endif
550 /* Macros to support positional arguments */
551 #ifndef _NO_POS_ARGS
552 # define GET_ARG(n, ap, type) \
553 (is_pos_arg \
554 ? (n < numargs \
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))))
563 #else
564 # define GET_ARG(n, ap, type) (va_arg (ap, type))
565 #endif
568 * To extend shorts properly, we need both signed and unsigned
569 * argument extraction methods.
571 #ifndef _NO_LONGLONG
572 #define SARG() \
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))
578 #define UARG() \
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))
584 #else
585 #define SARG() \
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))
590 #define UARG() \
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))
595 #endif
597 #ifndef STRING_ONLY
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);
604 return (EOF);
607 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
608 if (cantwrite (data, fp)) {
609 _newlib_flockfile_exit (fp);
610 return (EOF);
613 #ifdef _UNBUF_STREAM_OPT
614 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
615 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
616 fp->_file >= 0) {
617 _newlib_flockfile_exit (fp);
618 return (__sbprintf (data, fp, fmt0, ap));
620 #endif
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);
626 if (!fp->_p)
628 _REENT_ERRNO(data) = ENOMEM;
629 return EOF;
631 fp->_bf._size = 64;
633 #endif /* STRING_ONLY */
635 fmt = (char *)fmt0;
636 #ifdef _FVWRITE_IN_STREAMIO
637 uio.uio_iov = iovp = iov;
638 uio.uio_resid = 0;
639 uio.uio_iovcnt = 0;
640 #endif
641 ret = 0;
642 #ifndef _NO_POS_ARGS
643 arg_index = 0;
644 saved_fmt = NULL;
645 arg_type[0] = -1;
646 numargs = 0;
647 is_pos_arg = 0;
648 #endif
651 * Scan the format for conversions (`%' character).
653 for (;;) {
654 cp = fmt;
655 #ifdef _MB_CAPABLE
656 while ((n = __MBTOWC (data, &wc, fmt, MB_CUR_MAX,
657 &state)) != 0) {
658 if (n < 0) {
659 /* Wave invalid chars through. */
660 memset (&state, 0, sizeof state);
661 n = 1;
663 else if (wc == '%')
664 break;
665 fmt += n;
667 #else
668 while (*fmt != '\0' && *fmt != '%')
669 fmt += 1;
670 #endif
671 if ((m = fmt - cp) != 0) {
672 PRINT (cp, m);
673 ret += m;
675 #ifdef _MB_CAPABLE
676 if (n <= 0)
677 goto done;
678 #else
679 if (*fmt == '\0')
680 goto done;
681 #endif
682 fmt_anchor = fmt;
683 fmt++; /* skip over '%' */
685 flags = 0;
686 dprec = 0;
687 width = 0;
688 prec = -1;
689 sign = '\0';
690 #ifdef FLOATING_POINT
691 lead = 0;
692 #ifdef _WANT_IO_C99_FORMATS
693 nseps = nrepeats = 0;
694 #endif
695 #endif
696 #ifndef _NO_POS_ARGS
697 N = arg_index;
698 is_pos_arg = 0;
699 #endif
701 rflag: ch = *fmt++;
702 reswitch: switch (ch) {
703 #ifdef _WANT_IO_C99_FORMATS
704 case '\'':
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)
709 flags |= GROUPING;
710 goto rflag;
711 #endif
712 case ' ':
714 * ``If the space and + flags both appear, the space
715 * flag will be ignored.''
716 * -- ANSI X3J11
718 if (!sign)
719 sign = ' ';
720 goto rflag;
721 case '#':
722 flags |= ALT;
723 goto rflag;
724 case '*':
725 #ifndef _NO_POS_ARGS
726 /* we must check for positional arg used for dynamic width */
727 n = N;
728 old_is_pos_arg = is_pos_arg;
729 is_pos_arg = 0;
730 if (is_digit (*fmt)) {
731 char *old_fmt = fmt;
733 n = 0;
734 ch = *fmt++;
735 do {
736 n = 10 * n + to_digit (ch);
737 ch = *fmt++;
738 } while (is_digit (ch));
740 if (ch == '$') {
741 if (n <= MAX_POS_ARGS) {
742 n -= 1;
743 is_pos_arg = 1;
745 else
746 goto error;
748 else {
749 fmt = old_fmt;
750 goto rflag;
753 #endif /* !_NO_POS_ARGS */
756 * ``A negative field width argument is taken as a
757 * - flag followed by a positive field width.''
758 * -- ANSI X3J11
759 * They don't exclude field widths read from args.
761 width = GET_ARG (n, ap, int);
762 #ifndef _NO_POS_ARGS
763 is_pos_arg = old_is_pos_arg;
764 #endif
765 if (width >= 0)
766 goto rflag;
767 width = -width;
768 /* FALLTHROUGH */
769 case '-':
770 flags |= LADJUST;
771 goto rflag;
772 case '+':
773 sign = '+';
774 goto rflag;
775 case '.':
776 if ((ch = *fmt++) == '*') {
777 #ifndef _NO_POS_ARGS
778 /* we must check for positional arg used for dynamic width */
779 n = N;
780 old_is_pos_arg = is_pos_arg;
781 is_pos_arg = 0;
782 if (is_digit (*fmt)) {
783 char *old_fmt = fmt;
785 n = 0;
786 ch = *fmt++;
787 do {
788 n = 10 * n + to_digit (ch);
789 ch = *fmt++;
790 } while (is_digit (ch));
792 if (ch == '$') {
793 if (n <= MAX_POS_ARGS) {
794 n -= 1;
795 is_pos_arg = 1;
797 else
798 goto error;
800 else {
801 fmt = old_fmt;
802 goto rflag;
805 #endif /* !_NO_POS_ARGS */
806 prec = GET_ARG (n, ap, int);
807 #ifndef _NO_POS_ARGS
808 is_pos_arg = old_is_pos_arg;
809 #endif
810 if (prec < 0)
811 prec = -1;
812 goto rflag;
814 n = 0;
815 while (is_digit (ch)) {
816 n = 10 * n + to_digit (ch);
817 ch = *fmt++;
819 prec = n < 0 ? -1 : n;
820 goto reswitch;
821 case '0':
823 * ``Note that 0 is taken as a flag, not as the
824 * beginning of a field width.''
825 * -- ANSI X3J11
827 flags |= ZEROPAD;
828 goto rflag;
829 case '1': case '2': case '3': case '4':
830 case '5': case '6': case '7': case '8': case '9':
831 n = 0;
832 do {
833 n = 10 * n + to_digit (ch);
834 ch = *fmt++;
835 } while (is_digit (ch));
836 #ifndef _NO_POS_ARGS
837 if (ch == '$') {
838 if (n <= MAX_POS_ARGS) {
839 N = n - 1;
840 is_pos_arg = 1;
841 goto rflag;
843 else
844 goto error;
846 #endif /* !_NO_POS_ARGS */
847 width = n;
848 goto reswitch;
849 #ifdef FLOATING_POINT
850 case 'L':
851 flags |= LONGDBL;
852 goto rflag;
853 #endif
854 case 'h':
855 #ifdef _WANT_IO_C99_FORMATS
856 if (*fmt == 'h') {
857 fmt++;
858 flags |= CHARINT;
859 } else
860 #endif
861 flags |= SHORTINT;
862 goto rflag;
863 case 'l':
864 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
865 if (*fmt == 'l') {
866 fmt++;
867 flags |= QUADINT;
868 } else
869 #endif
870 flags |= LONGINT;
871 goto rflag;
872 case 'q': /* extension */
873 flags |= QUADINT;
874 goto rflag;
875 #ifdef _WANT_IO_C99_FORMATS
876 case 'j':
877 if (sizeof (intmax_t) == sizeof (long))
878 flags |= LONGINT;
879 else
880 flags |= QUADINT;
881 goto rflag;
882 case 'z':
883 if (sizeof (size_t) < sizeof (int))
884 /* POSIX states size_t is 16 or more bits, as is short. */
885 flags |= SHORTINT;
886 else if (sizeof (size_t) == sizeof (int))
887 /* no flag needed */;
888 else if (sizeof (size_t) <= sizeof (long))
889 flags |= LONGINT;
890 else
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. */
895 flags |= QUADINT;
896 goto rflag;
897 case 't':
898 if (sizeof (ptrdiff_t) < sizeof (int))
899 /* POSIX states ptrdiff_t is 16 or more bits, as
900 is short. */
901 flags |= SHORTINT;
902 else if (sizeof (ptrdiff_t) == sizeof (int))
903 /* no flag needed */;
904 else if (sizeof (ptrdiff_t) <= sizeof (long))
905 flags |= LONGINT;
906 else
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. */
911 flags |= QUADINT;
912 goto rflag;
913 case 'C':
914 #endif /* _WANT_IO_C99_FORMATS */
915 case 'c':
916 cp = buf;
917 #ifdef _MB_CAPABLE
918 if (ch == 'C' || (flags & LONGINT)) {
919 mbstate_t ps;
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),
924 &ps)) == -1) {
925 fp->_flags |= __SERR;
926 goto error;
929 else
930 #endif /* _MB_CAPABLE */
932 *cp = GET_ARG (N, ap, int);
933 size = 1;
935 sign = '\0';
936 break;
937 case 'D': /* extension */
938 flags |= LONGINT;
939 /*FALLTHROUGH*/
940 case 'd':
941 case 'i':
942 _uquad = SARG ();
943 #ifndef _NO_LONGLONG
944 if ((quad_t)_uquad < 0)
945 #else
946 if ((long) _uquad < 0)
947 #endif
950 _uquad = -_uquad;
951 sign = '-';
953 base = DEC;
954 goto number;
955 #ifdef FLOATING_POINT
956 # ifdef _WANT_IO_C99_FORMATS
957 case 'a':
958 case 'A':
959 case 'F':
960 # endif
961 case 'e':
962 case 'E':
963 case 'f':
964 case 'g':
965 case 'G':
966 # ifdef _NO_LONGDBL
967 if (flags & LONGDBL) {
968 _fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE);
969 } else {
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)) {
980 if (_fpvalue < 0)
981 sign = '-';
982 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
983 cp = "INF";
984 else
985 cp = "inf";
986 size = 3;
987 flags &= ~ZEROPAD;
988 break;
990 if (isnan (_fpvalue)) {
991 if (signbit (_fpvalue))
992 sign = '-';
993 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
994 cp = "NAN";
995 else
996 cp = "nan";
997 size = 3;
998 flags &= ~ZEROPAD;
999 break;
1002 # else /* !_NO_LONGDBL */
1004 if (flags & LONGDBL) {
1005 _fpvalue = GET_ARG (N, ap, _LONG_DOUBLE);
1006 } else {
1007 _fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double);
1010 /* do this before tricky precision changes */
1011 expt = _ldcheck (&_fpvalue);
1012 if (expt == 2) {
1013 if (_fpvalue < 0)
1014 sign = '-';
1015 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1016 cp = "INF";
1017 else
1018 cp = "inf";
1019 size = 3;
1020 flags &= ~ZEROPAD;
1021 break;
1023 if (expt == 1) {
1024 if (signbit (_fpvalue))
1025 sign = '-';
1026 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1027 cp = "NAN";
1028 else
1029 cp = "nan";
1030 size = 3;
1031 flags &= ~ZEROPAD;
1032 break;
1034 # endif /* !_NO_LONGDBL */
1036 # ifdef _WANT_IO_C99_FORMATS
1037 if (ch == 'a' || ch == 'A') {
1038 ox[0] = '0';
1039 ox[1] = ch == 'a' ? 'x' : 'X';
1040 flags |= HEXPREFIX;
1041 if (prec >= BUF)
1043 if ((malloc_buf =
1044 (char *)_malloc_r (data, prec + 1))
1045 == NULL)
1047 fp->_flags |= __SERR;
1048 goto error;
1050 cp = malloc_buf;
1052 else
1053 cp = buf;
1054 } else
1055 # endif /* _WANT_IO_C99_FORMATS */
1056 if (prec == -1) {
1057 prec = DEFPREC;
1058 } else if ((ch == 'g' || ch == 'G') && prec == 0) {
1059 prec = 1;
1062 flags |= FPT;
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' */
1070 else
1071 ch = 'g';
1073 # ifdef _WANT_IO_C99_FORMATS
1074 else if (ch == 'F')
1075 ch = 'f';
1076 # endif
1077 if (ch <= 'e') { /* 'a', 'A', 'e', or 'E' fmt */
1078 --expt;
1079 expsize = exponent (expstr, expt, ch);
1080 size = expsize + ndig;
1081 if (ndig > 1 || flags & ALT)
1082 size += decp_len;
1083 # ifdef _WANT_IO_C99_FORMATS
1084 flags &= ~GROUPING;
1085 # endif
1086 } else {
1087 if (ch == 'f') { /* f fmt */
1088 if (expt > 0) {
1089 size = expt;
1090 if (prec || flags & ALT)
1091 size += prec + decp_len;
1092 } else /* "0.X" */
1093 size = (prec || flags & ALT)
1094 ? prec + 1 + decp_len
1095 : 1;
1096 } else if (expt >= ndig) { /* fixed g fmt */
1097 size = expt;
1098 if (flags & ALT)
1099 size += decp_len;
1100 } else {
1101 size = ndig + decp_len;
1102 if (expt <= 0)
1103 size += 1 - expt;
1105 # ifdef _WANT_IO_C99_FORMATS
1106 if ((flags & GROUPING) && expt > 0) {
1107 /* space for thousands' grouping */
1108 nseps = nrepeats = 0;
1109 lead = expt;
1110 while (*grouping != CHAR_MAX) {
1111 if (lead <= *grouping)
1112 break;
1113 lead -= *grouping;
1114 if (grouping[1]) {
1115 nseps++;
1116 grouping++;
1117 } else
1118 nrepeats++;
1120 size += (nseps + nrepeats) * thsnd_len;
1121 } else
1122 # endif
1123 lead = expt;
1126 if (softsign)
1127 sign = '-';
1128 break;
1129 #endif /* FLOATING_POINT */
1130 #ifdef _GLIBC_EXTENSION
1131 case 'm': /* extension */
1133 int dummy;
1134 cp = _strerror_r (data, _REENT_ERRNO(data), 1, &dummy);
1136 flags &= ~LONGINT;
1137 goto string;
1138 #endif
1139 case 'n':
1140 #ifndef _NO_LONGLONG
1141 if (flags & QUADINT)
1142 *GET_ARG (N, ap, quad_ptr_t) = ret;
1143 else
1144 #endif
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;
1152 #endif
1153 else
1154 *GET_ARG (N, ap, int_ptr_t) = ret;
1155 continue; /* no output */
1156 case 'O': /* extension */
1157 flags |= LONGINT;
1158 /*FALLTHROUGH*/
1159 case 'o':
1160 _uquad = UARG ();
1161 base = OCT;
1162 #ifdef _WANT_IO_C99_FORMATS
1163 flags &= ~GROUPING;
1164 #endif
1165 goto nosign;
1166 case 'p':
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-
1171 * defined manner.''
1172 * -- ANSI X3J11
1174 /* NOSTRICT */
1175 _uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t);
1176 base = HEX;
1177 xdigs = "0123456789abcdef";
1178 flags |= HEXPREFIX;
1179 ox[0] = '0';
1180 ox[1] = ch = 'x';
1181 goto nosign;
1182 case 's':
1183 #ifdef _WANT_IO_C99_FORMATS
1184 case 'S':
1185 #endif
1186 cp = GET_ARG (N, ap, char_ptr_t);
1187 #ifdef _GLIBC_EXTENSION
1188 string:
1189 #endif
1190 sign = '\0';
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. */
1196 if (cp == NULL) {
1197 cp = "(null)";
1198 size = ((unsigned) prec > 6U) ? 6 : prec;
1200 else
1201 #endif /* __OPTIMIZE_SIZE__ */
1202 #ifdef _MB_CAPABLE
1203 if (ch == 'S' || (flags & LONGINT)) {
1204 mbstate_t ps;
1205 const wchar_t *wcp;
1207 wcp = (const wchar_t *)cp;
1208 size = m = 0;
1209 memset ((void *)&ps, '\0', sizeof (mbstate_t));
1211 /* Count number of bytes needed for multibyte
1212 string that will be produced from widechar
1213 string. */
1214 if (prec >= 0) {
1215 while (1) {
1216 if (wcp[m] == L'\0')
1217 break;
1218 if ((n = (int)_wcrtomb_r (data,
1219 buf, wcp[m], &ps)) == -1) {
1220 fp->_flags |= __SERR;
1221 goto error;
1223 if (n + size > prec)
1224 break;
1225 m += 1;
1226 size += n;
1227 if (size == prec)
1228 break;
1231 else {
1232 if ((size = (int)_wcsrtombs_r (data,
1233 NULL, &wcp, 0, &ps)) == -1) {
1234 fp->_flags |= __SERR;
1235 goto error;
1237 wcp = (const wchar_t *)cp;
1240 if (size == 0)
1241 break;
1243 if (size >= BUF) {
1244 if ((malloc_buf =
1245 (char *)_malloc_r (data, size + 1))
1246 == NULL) {
1247 fp->_flags |= __SERR;
1248 goto error;
1250 cp = malloc_buf;
1251 } else
1252 cp = buf;
1254 /* Convert widechar string to multibyte string. */
1255 memset ((void *)&ps, '\0', sizeof (mbstate_t));
1256 if (_wcsrtombs_r (data, cp, &wcp, size, &ps)
1257 != size) {
1258 fp->_flags |= __SERR;
1259 goto error;
1261 cp[size] = '\0';
1263 else
1264 #endif /* _MB_CAPABLE */
1265 if (prec >= 0) {
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);
1273 if (p != NULL)
1274 size = p - cp;
1275 else
1276 size = prec;
1277 } else
1278 size = strlen (cp);
1280 break;
1281 case 'U': /* extension */
1282 flags |= LONGINT;
1283 /*FALLTHROUGH*/
1284 case 'u':
1285 _uquad = UARG ();
1286 base = DEC;
1287 goto nosign;
1288 case 'X':
1289 xdigs = "0123456789ABCDEF";
1290 goto hex;
1291 case 'x':
1292 xdigs = "0123456789abcdef";
1293 hex: _uquad = UARG ();
1294 base = HEX;
1295 /* leading 0x/X only if non-zero */
1296 if (flags & ALT && _uquad != 0) {
1297 ox[0] = '0';
1298 ox[1] = ch;
1299 flags |= HEXPREFIX;
1302 #ifdef _WANT_IO_C99_FORMATS
1303 flags &= ~GROUPING;
1304 #endif
1305 /* unsigned conversions */
1306 nosign: sign = '\0';
1308 * ``... diouXx conversions ... if a precision is
1309 * specified, the 0 flag will be ignored.''
1310 * -- ANSI X3J11
1312 number: if ((dprec = prec) >= 0)
1313 flags &= ~ZEROPAD;
1316 * ``The result of converting a zero value with an
1317 * explicit precision of zero is no characters.''
1318 * -- ANSI X3J11
1320 cp = buf + BUF;
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.
1327 switch (base) {
1328 case OCT:
1329 do {
1330 *--cp = to_char (_uquad & 7);
1331 _uquad >>= 3;
1332 } while (_uquad);
1333 /* handle octal leading 0 */
1334 if (flags & ALT && *cp != '0')
1335 *--cp = '0';
1336 break;
1338 case DEC:
1339 /* many numbers are 1 digit */
1340 if (_uquad < 10) {
1341 *--cp = to_char(_uquad);
1342 break;
1344 #ifdef _WANT_IO_C99_FORMATS
1345 ndig = 0;
1346 #endif
1347 do {
1348 *--cp = to_char (_uquad % 10);
1349 #ifdef _WANT_IO_C99_FORMATS
1350 ndig++;
1351 /* If (*grouping == CHAR_MAX) then no
1352 more grouping */
1353 if ((flags & GROUPING)
1354 && ndig == *grouping
1355 && *grouping != CHAR_MAX
1356 && _uquad > 9) {
1357 cp -= thsnd_len;
1358 strncpy (cp, thousands_sep,
1359 thsnd_len);
1360 ndig = 0;
1361 /* If (grouping[1] == '\0') then we
1362 have to use *grouping character
1363 (last grouping rule) for all
1364 next cases. */
1365 if (grouping[1] != '\0')
1366 grouping++;
1368 #endif
1369 _uquad /= 10;
1370 } while (_uquad != 0);
1371 break;
1373 case HEX:
1374 do {
1375 *--cp = xdigs[_uquad & 15];
1376 _uquad >>= 4;
1377 } while (_uquad);
1378 break;
1380 default:
1381 cp = "bug in vfprintf: bad base";
1382 size = strlen (cp);
1383 goto skipsize;
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."
1390 * -- ANSI X3J11
1392 * To demonstrate this case, compile and run:
1393 * printf ("%#.0o",0);
1395 else if (base == OCT && (flags & ALT))
1396 *--cp = '0';
1398 size = buf + BUF - cp;
1399 skipsize:
1400 break;
1401 default: /* "%?" prints ?, unless ? is NUL */
1402 if (ch == '\0')
1403 goto done;
1404 /* pretend it was %c with argument ch */
1405 cp = buf;
1406 *cp = ch;
1407 size = 1;
1408 sign = '\0';
1409 break;
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;
1428 if (sign)
1429 realsz++;
1430 if (flags & HEXPREFIX)
1431 realsz+= 2;
1433 /* right-adjusting blank padding */
1434 if ((flags & (LADJUST|ZEROPAD)) == 0)
1435 PAD (width - realsz, blanks);
1437 /* prefix */
1438 if (sign)
1439 PRINT (&sign, 1);
1440 if (flags & HEXPREFIX)
1441 PRINT (ox, 2);
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) {
1453 PRINT (cp, size);
1454 } else { /* glue together f_p fragments */
1455 if (ch >= 'f') { /* 'f' or 'g' */
1456 if (_fpvalue == 0) {
1457 /* kludge for __dtoa irregularity */
1458 PRINT ("0", 1);
1459 if (expt < ndig || flags & ALT) {
1460 PRINT (decimal_point, decp_len);
1461 PAD (ndig - 1, zeroes);
1463 } else if (expt <= 0) {
1464 PRINT ("0", 1);
1465 if (expt || ndig || flags & ALT) {
1466 PRINT (decimal_point, decp_len);
1467 PAD (-expt, zeroes);
1468 PRINT (cp, ndig);
1470 } else {
1471 char *convbuf = cp;
1472 PRINTANDPAD(cp, convbuf + ndig,
1473 lead, zeroes);
1474 cp += lead;
1475 #ifdef _WANT_IO_C99_FORMATS
1476 if (flags & GROUPING) {
1477 while (nseps > 0 || nrepeats > 0) {
1478 if (nrepeats > 0)
1479 nrepeats--;
1480 else {
1481 grouping--;
1482 nseps--;
1484 PRINT(thousands_sep, thsnd_len);
1485 PRINTANDPAD (cp, convbuf + ndig,
1486 *grouping, zeroes);
1487 cp += *grouping;
1489 if (cp > convbuf + ndig)
1490 cp = convbuf + ndig;
1492 #endif
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) {
1500 PRINT (cp, 1);
1501 cp++;
1502 PRINT (decimal_point, decp_len);
1503 if (_fpvalue) {
1504 PRINT (cp, ndig - 1);
1505 } else /* 0.[0..] */
1506 /* __dtoa irregularity */
1507 PAD (ndig - 1, zeroes);
1508 } else /* XeYYY */
1509 PRINT (cp, 1);
1510 PRINT (expstr, expsize);
1513 #else /* !FLOATING_POINT */
1514 PRINT (cp, size);
1515 #endif
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);
1527 malloc_buf = NULL;
1530 done:
1531 FLUSH ();
1532 error:
1533 if (malloc_buf != NULL)
1534 _free_r (data, malloc_buf);
1535 #ifndef STRING_ONLY
1536 _newlib_flockfile_end (fp);
1537 #endif
1538 return (__sferror (fp) ? EOF : ret);
1539 /* NOTREACHED */
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. */
1551 static char *
1552 cvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags,
1553 char *sign, int *decpt, int ch, int *length, char *buf)
1555 int mode, dsgn;
1556 char *digits, *bp, *rve;
1557 # ifdef _NO_LONGDBL
1558 union double_union tmp;
1560 tmp.d = value;
1561 if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1562 value = -value;
1563 *sign = '-';
1564 } else
1565 *sign = '\000';
1566 # else /* !_NO_LONGDBL */
1567 union
1569 struct ldieee ieee;
1570 _LONG_DOUBLE val;
1571 } ld;
1573 ld.val = value;
1574 if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
1575 value = -value;
1576 *sign = '-';
1577 } else
1578 *sign = '\000';
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;
1588 if (!value)
1589 *decpt = 1;
1590 digits = ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF";
1591 bp = buf;
1592 do {
1593 value *= 16;
1594 mode = (int) value;
1595 value -= mode;
1596 *bp++ = digits[mode];
1597 } while (ndigits-- && value);
1598 if (value > 0.5 || (value == 0.5 && mode & 1)) {
1599 /* round to even */
1600 rve = bp;
1601 while (*--rve == digits[0xf]) {
1602 *rve = '0';
1604 *rve = *rve == '9' ? digits[0xa] : *rve + 1;
1605 } else {
1606 while (ndigits-- >= 0) {
1607 *bp++ = '0';
1610 *length = bp - buf;
1611 return buf;
1613 # endif /* _WANT_IO_C99_FORMATS */
1614 if (ch == 'f' || ch == 'F') {
1615 mode = 3; /* ndigits after the decimal point */
1616 } else {
1617 /* To obtain ndigits after the decimal point for the 'e'
1618 * and 'E' formats, round to ndigits + 1 significant
1619 * figures.
1621 if (ch == 'e' || ch == 'E') {
1622 ndigits++;
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;
1634 bp += *decpt;
1636 if (value == 0) /* kludge for __dtoa irregularity */
1637 rve = bp;
1638 while (rve < bp)
1639 *rve++ = '0';
1641 *length = rve - digits;
1642 return (digits);
1645 static int
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';
1652 # else
1653 # define isa 0
1654 # endif
1656 p = p0;
1657 *p++ = isa ? 'p' - 'a' + fmtch : fmtch;
1658 if (exp < 0) {
1659 exp = -exp;
1660 *p++ = '-';
1662 else
1663 *p++ = '+';
1664 t = expbuf + MAXEXPLEN;
1665 if (exp > 9) {
1666 do {
1667 *--t = to_char (exp % 10);
1668 } while ((exp /= 10) > 9);
1669 *--t = to_char (exp);
1670 for (; t < expbuf + MAXEXPLEN; *p++ = *t++);
1672 else {
1673 if (!isa)
1674 *p++ = '0';
1675 *p++ = to_char (exp);
1677 return (p - p0);
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,
1790 int n,
1791 char *fmt,
1792 va_list *ap,
1793 int *numargs_p,
1794 union arg_val *args,
1795 int *arg_type,
1796 char **last_fmt)
1798 int ch;
1799 int number, flags;
1800 int spec_type;
1801 int numargs = *numargs_p;
1802 __CH_CLASS chtype;
1803 __STATE state, next_state;
1804 __ACTION action;
1805 int pos, last_arg;
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 };
1809 # ifdef _MB_CAPABLE
1810 wchar_t wc;
1811 mbstate_t wc_state;
1812 int nbytes;
1813 # endif
1815 /* if this isn't the first call, pick up where we left off last time */
1816 if (*last_fmt != NULL)
1817 fmt = *last_fmt;
1819 # ifdef _MB_CAPABLE
1820 memset (&wc_state, '\0', sizeof (wc_state));
1821 # endif
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)
1827 # ifdef _MB_CAPABLE
1828 while ((nbytes = __MBTOWC (data, &wc, fmt, MB_CUR_MAX, &wc_state)) > 0)
1830 fmt += nbytes;
1831 if (wc == '%')
1832 break;
1835 if (nbytes <= 0)
1836 break;
1837 # else
1838 while (*fmt != '\0' && *fmt != '%')
1839 fmt += 1;
1841 if (*fmt == '\0')
1842 break;
1844 fmt++;
1845 # endif /* ! _MB_CAPABLE */
1846 state = START;
1847 flags = 0;
1848 pos = -1;
1849 number = 0;
1850 spec_type = INT;
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)
1857 ch = *fmt++;
1858 chtype = __chclass[ch];
1859 next_state = __state_table[state][chtype];
1860 action = __action_table[state][chtype];
1861 state = next_state;
1863 switch (action)
1865 case GETMOD: /* we have format modifier */
1866 switch (ch)
1868 case 'h':
1869 /* No flag needed, since short and char promote to int. */
1870 break;
1871 case 'L':
1872 flags |= LONGDBL;
1873 break;
1874 case 'q':
1875 flags |= QUADINT;
1876 break;
1877 # ifdef _WANT_IO_C99_FORMATS
1878 case 'j':
1879 if (sizeof (intmax_t) == sizeof (long))
1880 flags |= LONGINT;
1881 else
1882 flags |= QUADINT;
1883 break;
1884 case 'z':
1885 if (sizeof (size_t) <= sizeof (int))
1886 /* no flag needed */;
1887 else if (sizeof (size_t) <= sizeof (long))
1888 flags |= LONGINT;
1889 else
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. */
1894 flags |= QUADINT;
1895 break;
1896 case 't':
1897 if (sizeof (ptrdiff_t) <= sizeof (int))
1898 /* no flag needed */;
1899 else if (sizeof (ptrdiff_t) <= sizeof (long))
1900 flags |= LONGINT;
1901 else
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. */
1906 flags |= QUADINT;
1907 break;
1908 # endif /* _WANT_IO_C99_FORMATS */
1909 case 'l':
1910 default:
1911 # if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
1912 if (*fmt == 'l')
1914 flags |= QUADINT;
1915 ++fmt;
1917 else
1918 # endif
1919 flags |= LONGINT;
1920 break;
1922 break;
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 */
1927 switch (ch)
1929 case 'd':
1930 case 'i':
1931 case 'o':
1932 case 'x':
1933 case 'X':
1934 case 'u':
1935 if (flags & LONGINT)
1936 spec_type = LONG_INT;
1937 # ifndef _NO_LONGLONG
1938 else if (flags & QUADINT)
1939 spec_type = QUAD_INT;
1940 # endif
1941 else
1942 spec_type = INT;
1943 break;
1944 case 'D':
1945 case 'U':
1946 case 'O':
1947 spec_type = LONG_INT;
1948 break;
1949 # ifdef _WANT_IO_C99_FORMATS
1950 case 'a':
1951 case 'A':
1952 case 'F':
1953 # endif
1954 case 'f':
1955 case 'g':
1956 case 'G':
1957 case 'E':
1958 case 'e':
1959 # ifndef _NO_LONGDBL
1960 if (flags & LONGDBL)
1961 spec_type = LONG_DOUBLE;
1962 else
1963 # endif
1964 spec_type = DOUBLE;
1965 break;
1966 case 's':
1967 # ifdef _WANT_IO_C99_FORMATS
1968 case 'S':
1969 # endif
1970 case 'p':
1971 case 'n':
1972 spec_type = CHAR_PTR;
1973 break;
1974 case 'c':
1975 # ifdef _WANT_IO_C99_FORMATS
1976 if (flags & LONGINT)
1977 spec_type = WIDE_CHAR;
1978 else
1979 # endif
1980 spec_type = INT;
1981 break;
1982 # ifdef _WANT_IO_C99_FORMATS
1983 case 'C':
1984 spec_type = WIDE_CHAR;
1985 break;
1986 # endif
1989 /* if we have a positional parameter, just store the type, otherwise
1990 fetch the parameter from the vararg list */
1991 if (pos != -1)
1992 arg_type[pos] = spec_type;
1993 else
1995 switch (spec_type)
1997 case LONG_INT:
1998 args[numargs++].val_long = va_arg (*ap, long);
1999 break;
2000 case QUAD_INT:
2001 args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2002 break;
2003 case WIDE_CHAR:
2004 args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2005 break;
2006 case INT:
2007 args[numargs++].val_int = va_arg (*ap, int);
2008 break;
2009 case CHAR_PTR:
2010 args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2011 break;
2012 case DOUBLE:
2013 args[numargs++].val_double = va_arg (*ap, double);
2014 break;
2015 case LONG_DOUBLE:
2016 args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2017 break;
2021 break;
2022 case GETPOS: /* we have positional specifier */
2023 if (arg_type[0] == -1)
2024 memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2025 pos = number - 1;
2026 max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos);
2027 break;
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);
2031 number -= 1;
2032 arg_type[number] = INT;
2033 max_pos_arg = (max_pos_arg > number ? max_pos_arg : number);
2034 break;
2035 case GETPWB: /* we require format pushback */
2036 --fmt;
2037 /* fallthrough */
2038 case GETPW: /* we have a variable precision or width to acquire */
2039 args[numargs++].val_int = va_arg (*ap, int);
2040 break;
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');
2046 ++fmt;
2048 break;
2049 case SKIPNUM: /* we have a number to skip */
2050 while ((ch = *fmt) != '\0' && is_digit (ch))
2051 ++fmt;
2052 break;
2053 case NOOP:
2054 default:
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 */
2062 if (*fmt == '\0')
2063 last_arg = max_pos_arg;
2064 else
2065 last_arg = n;
2067 while (numargs <= last_arg)
2069 switch (arg_type[numargs])
2071 case LONG_INT:
2072 args[numargs++].val_long = va_arg (*ap, long);
2073 break;
2074 case QUAD_INT:
2075 args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2076 break;
2077 case CHAR_PTR:
2078 args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2079 break;
2080 case DOUBLE:
2081 args[numargs++].val_double = va_arg (*ap, double);
2082 break;
2083 case LONG_DOUBLE:
2084 args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2085 break;
2086 case WIDE_CHAR:
2087 args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2088 break;
2089 case INT:
2090 default:
2091 args[numargs++].val_int = va_arg (*ap, int);
2092 break;
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;
2099 *last_fmt = fmt;
2100 return &args[n];
2102 #endif /* !_NO_POS_ARGS */