1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
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.
19 *
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.
31 */
32
33 /*
34 FUNCTION
35 <<vfprintf>>, <<vprintf>>, <<vsprintf>>, <<vsnprintf>>, <<vasprintf>>, <<vasnprintf>>---format argument list
36
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
61
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]>);
73
74 int vprintf( const char *<[fmt]>,
75 va_list <[list]>);
76 int vfprintf( FILE *<[fp]>,
77 const char *<[fmt]>, va_list <[list]>);
78 int vsprintf( char *<[str]>,
79 const char *<[fmt]>, va_list <[list]>);
80 int vasprintf( char **<[str]>,
81 const char *<[fmt]>, va_list <[list]>);
82 int vsnprintf( char *<[str]>,
83 size_t <[size]>, const char *<[fmt]>, va_list <[list]>);
84 char *vasnprintf( char *<[str]>,
85 size_t *<[size]>, const char *<[fmt]>, va_list <[list]>);
86
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>>.
95
96 <<_vprintf_r>>, <<_vfprintf_r>>, <<_vasprintf_r>>, <<_vsprintf_r>>,
97 <<_vsnprintf_r>>, and <<_vasnprintf_r>> are reentrant versions of the
98 above.
99
100 RETURNS
101 The return values are consistent with the corresponding functions.
102
103 PORTABILITY
104 ANSI C requires <<vprintf>>, <<vfprintf>>, <<vsprintf>>, and
105 <<vsnprintf>>. The remaining functions are newlib extensions.
106
107 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
108 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
109 */
110
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 */
115
116 /*
117 * Actual printf innards.
118 *
119 * This code is large and complicated...
120 */
121 #define _DEFAULT_SOURCE
122 #include <newlib.h>
123
124 #ifdef INTEGER_ONLY
125 # ifdef STRING_ONLY
126 # define VFPRINTF svfiprintf
127 # else
128 # define VFPRINTF vfiprintf
129 # endif
130 #else
131 # ifdef STRING_ONLY
132 # define VFPRINTF svfprintf
133 # else
134 # define VFPRINTF vfprintf
135 # endif
136 # ifndef NO_FLOATING_POINT
137 # define FLOATING_POINT
138 # endif
139 #endif
140
141 #define _NO_POS_ARGS
142 #ifdef _WANT_IO_POS_ARGS
143 # undef _NO_POS_ARGS
144 #endif
145
146 #define _DEFAULT_SOURCE
147 #include <_ansi.h>
148 #include <stdio.h>
149 #include <stdlib.h>
150 #include <string.h>
151 #include <limits.h>
152 #include <stdint.h>
153 #include <wchar.h>
154 #include <sys/lock.h>
155 #include <stdarg.h>
156 #include "local.h"
157 #include "../stdlib/local.h"
158 #include "fvwrite.h"
159 #include "vfieeefp.h"
160
161 /* Currently a test is made to see if long double processing is warranted.
162 This could be changed in the future should the __ldtoa code be
163 preferred over __dtoa. */
164 #define _NO_LONGDBL
165 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
166 #undef _NO_LONGDBL
167 #endif
168
169 #define _NO_LONGLONG
170 #if defined _WANT_IO_LONG_LONG \
171 && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
172 # undef _NO_LONGLONG
173 #endif
174
175 #ifdef STRING_ONLY
176 # ifdef _FVWRITE_IN_STREAMIO
177 # define __SPRINT _ssprint
178 # else
179 # define __SPRINT _ssputs
180 # endif
181 #else
182 # ifdef _FVWRITE_IN_STREAMIO
183 # define __SPRINT _sprint
184 # else
185 # define __SPRINT _sfputs
186 # endif
187 #endif
188
189 /* The __sprint_r/__ssprint_r functions are shared between all versions of
190 vfprintf and vfwprintf. They must only be defined once, which we do in
191 the INTEGER_ONLY versions here. */
192 #ifdef STRING_ONLY
193 #ifdef INTEGER_ONLY
194 #ifndef _FVWRITE_IN_STREAMIO
195 int
_ssputs(FILE * fp,const char * buf,size_t len)196 _ssputs (
197 FILE *fp,
198 const char *buf,
199 size_t len)
200 {
201 register int w;
202
203 w = fp->_w;
204 if (len >= (size_t) w && fp->_flags & (__SMBF | __SOPT)) {
205 /* must be asprintf family */
206 unsigned char *str;
207 int curpos = (fp->_p - fp->_bf._base);
208 /* Choose a geometric growth factor to avoid
209 * quadratic realloc behavior, but use a rate less
210 * than (1+sqrt(5))/2 to accomodate malloc
211 * overhead. asprintf EXPECTS us to overallocate, so
212 * that it can add a trailing \0 without
213 * reallocating. The new allocation should thus be
214 * max(prev_size*1.5, curpos+len+1). */
215 int newsize = fp->_bf._size * 3 / 2;
216 if ((size_t) newsize < curpos + len + 1)
217 newsize = curpos + len + 1;
218 if (fp->_flags & __SOPT)
219 {
220 /* asnprintf leaves original buffer alone. */
221 str = (unsigned char *)malloc (newsize);
222 if (!str)
223 {
224 _REENT_ERRNO(ptr) = ENOMEM;
225 goto err;
226 }
227 memcpy (str, fp->_bf._base, curpos);
228 fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
229 }
230 else
231 {
232 str = (unsigned char *)realloc (fp->_bf._base,
233 newsize);
234 if (!str) {
235 /* Free unneeded buffer. */
236 free (fp->_bf._base);
237 /* Ensure correct errno, even if free
238 * changed it. */
239 _REENT_ERRNO(ptr) = ENOMEM;
240 goto err;
241 }
242 }
243 fp->_bf._base = str;
244 fp->_p = str + curpos;
245 fp->_bf._size = newsize;
246 w = len;
247 fp->_w = newsize - curpos;
248 }
249 if (len < (size_t) w)
250 w = len;
251 (void)memmove ((void *) fp->_p, (void *) buf, (size_t) (w));
252 fp->_w -= w;
253 fp->_p += w;
254
255 return 0;
256
257 err:
258 fp->_flags |= __SERR;
259 return EOF;
260 }
261 #endif
262
263 int
_ssprint(FILE * fp,register struct __suio * uio)264 _ssprint (
265 FILE *fp,
266 register struct __suio *uio)
267 {
268 register size_t len;
269 register int w;
270 register struct __siov *iov;
271 register const char *p = NULL;
272
273 iov = uio->uio_iov;
274 len = 0;
275
276 if (uio->uio_resid == 0) {
277 uio->uio_iovcnt = 0;
278 return (0);
279 }
280
281 do {
282 while (len == 0) {
283 p = iov->iov_base;
284 len = iov->iov_len;
285 iov++;
286 }
287 w = fp->_w;
288 if (len >= (size_t) w && fp->_flags & (__SMBF | __SOPT)) {
289 /* must be asprintf family */
290 unsigned char *str;
291 int curpos = (fp->_p - fp->_bf._base);
292 /* Choose a geometric growth factor to avoid
293 * quadratic realloc behavior, but use a rate less
294 * than (1+sqrt(5))/2 to accomodate malloc
295 * overhead. asprintf EXPECTS us to overallocate, so
296 * that it can add a trailing \0 without
297 * reallocating. The new allocation should thus be
298 * max(prev_size*1.5, curpos+len+1). */
299 int newsize = fp->_bf._size * 3 / 2;
300 if ((size_t) newsize < curpos + len + 1)
301 newsize = curpos + len + 1;
302 if (fp->_flags & __SOPT)
303 {
304 /* asnprintf leaves original buffer alone. */
305 str = (unsigned char *)malloc (newsize);
306 if (!str)
307 {
308 _REENT_ERRNO(ptr) = ENOMEM;
309 goto err;
310 }
311 memcpy (str, fp->_bf._base, curpos);
312 fp->_flags = (fp->_flags & ~__SOPT) | __SMBF;
313 }
314 else
315 {
316 str = (unsigned char *)realloc (fp->_bf._base,
317 newsize);
318 if (!str) {
319 /* Free unneeded buffer. */
320 free (fp->_bf._base);
321 /* Ensure correct errno, even if free
322 * changed it. */
323 _REENT_ERRNO(ptr) = ENOMEM;
324 goto err;
325 }
326 }
327 fp->_bf._base = str;
328 fp->_p = str + curpos;
329 fp->_bf._size = newsize;
330 w = len;
331 fp->_w = newsize - curpos;
332 }
333 if (len < (size_t) w)
334 w = len;
335 (void)memmove ((void *) fp->_p, (void *) p, (size_t) (w));
336 fp->_w -= w;
337 fp->_p += w;
338 w = len; /* pretend we copied all */
339 p += w;
340 len -= w;
341 } while ((uio->uio_resid -= w) != 0);
342
343 uio->uio_resid = 0;
344 uio->uio_iovcnt = 0;
345 return 0;
346
347 err:
348 fp->_flags |= __SERR;
349 uio->uio_resid = 0;
350 uio->uio_iovcnt = 0;
351 return EOF;
352 }
353 #else /* !INTEGER_ONLY */
354 #ifndef _FVWRITE_IN_STREAMIO
355 int _ssputs ( FILE *, const char *, size_t);
356 #endif
357 int _ssprint ( FILE *, register struct __suio *);
358 #endif /* !INTEGER_ONLY */
359
360 #else /* !STRING_ONLY */
361 #ifdef INTEGER_ONLY
362
363 #ifndef _FVWRITE_IN_STREAMIO
364 int
_sfputs(FILE * fp,const char * buf,size_t len)365 _sfputs (
366 FILE *fp,
367 const char *buf,
368 size_t len)
369 {
370 register int i;
371
372 #if defined _WIDE_ORIENT && (!defined _ELIX_LEVEL || _ELIX_LEVEL >= 4)
373 if (fp->_flags2 & __SWID) {
374 wchar_t *p;
375
376 p = (wchar_t *) buf;
377 for (i = 0; i < (len / sizeof (wchar_t)); i++) {
378 if (fputwc ( p[i], fp) == WEOF)
379 return -1;
380 }
381 } else {
382 #else
383 {
384 #endif
385 for (i = 0; (size_t) i < len; i++) {
386 if (fputc ( buf[i], fp) == EOF)
387 return -1;
388 }
389 }
390 return (0);
391 }
392 #endif
393 /*
394 * Flush out all the vectors defined by the given uio,
395 * then reset it so that it can be reused.
396 */
397 int
398 _sprint (
399 FILE *fp,
400 register struct __suio *uio)
401 {
402 register int err = 0;
403
404 if (uio->uio_resid == 0) {
405 uio->uio_iovcnt = 0;
406 return (0);
407 }
408 #if defined _WIDE_ORIENT && (!defined _ELIX_LEVEL || _ELIX_LEVEL >= 4)
409 if (fp->_flags2 & __SWID) {
410 struct __siov *iov;
411 wchar_t *p;
412 int i, len;
413
414 iov = uio->uio_iov;
415 for (; uio->uio_resid != 0;
416 uio->uio_resid -= len * sizeof (wchar_t), iov++) {
417 p = (wchar_t *) iov->iov_base;
418 len = iov->iov_len / sizeof (wchar_t);
419 for (i = 0; i < len; i++) {
420 if (fputwc ( p[i], fp) == WEOF) {
421 err = -1;
422 goto out;
423 }
424 }
425 }
426 out:
427 ;
428 } else
429 #endif
430 err = _sfvwrite( fp, uio);
431 uio->uio_resid = 0;
432 uio->uio_iovcnt = 0;
433 return (err);
434 }
435 #else /* !INTEGER_ONLY */
436 #ifndef _FVWRITE_IN_STREAMIO
437 int _sfputs ( FILE *, const char *buf, size_t);
438 #endif
439 int _sprint ( FILE *, register struct __suio *);
440 #endif /* !INTEGER_ONLY */
441
442 #ifdef _UNBUF_STREAM_OPT
443 /*
444 * Helper function for `fprintf to unbuffered unix file': creates a
445 * temporary buffer. We only work on write-only files; this avoids
446 * worries about ungetc buffers and so forth.
447 *
448 * Make sure to avoid inlining.
449 */
450 _NOINLINE_STATIC int
451 __sbprintf (struct _reent *rptr,
452 register FILE *fp,
453 const char *fmt,
454 va_list ap)
455 {
456 int ret;
457 FILE fake;
458 unsigned char buf[BUFSIZ];
459
460 /* copy the important variables */
461 fake._flags = fp->_flags & ~__SNBF;
462 fake._flags2 = fp->_flags2;
463 fake._file = fp->_file;
464 fake._cookie = fp->_cookie;
465 fake._write = fp->_write;
466
467 /* set up the buffer */
468 fake._bf._base = fake._p = buf;
469 fake._bf._size = fake._w = sizeof (buf);
470 fake._lbfsize = 0; /* not actually used, but Just In Case */
471 #ifndef __SINGLE_THREAD__
472 __lock_init_recursive (fake._lock);
473 #endif
474
475 /* do the work, then copy any error status */
476 ret = VFPRINTF (&fake, fmt, ap);
477 if (ret >= 0 && fflush ( &fake))
478 ret = EOF;
479 if (fake._flags & __SERR)
480 fp->_flags |= __SERR;
481
482 #ifndef __SINGLE_THREAD__
483 __lock_close_recursive (fake._lock);
484 #endif
485 return (ret);
486 }
487 #endif /* _UNBUF_STREAM_OPT */
488 #endif /* !STRING_ONLY */
489
490
491 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
492 # include <locale.h>
493 #endif
494 #ifdef FLOATING_POINT
495 # include <math.h>
496
497 /* For %La, an exponent of 15 bits occupies the exponent character, a
498 sign, and up to 5 digits. */
499 # define MAXEXPLEN 7
500 # define DEFPREC 6
501
502 # ifdef _NO_LONGDBL
503
504 # define _PRINTF_FLOAT_TYPE double
505 # define _DTOA __dtoa
506 # define FREXP frexp
507
508 # else /* !_NO_LONGDBL */
509
510 extern int _ldcheck (_LONG_DOUBLE *);
511
512 # define _PRINTF_FLOAT_TYPE _LONG_DOUBLE
513 # define _DTOA __ldtoa
514 # define FREXP frexpl
515 # endif /* !_NO_LONGDBL */
516
517 static char *cvt(_PRINTF_FLOAT_TYPE, int, int, char *, int *,
518 int, int *, char *);
519
520 static int exponent(char *, int, int);
521
522 #endif /* FLOATING_POINT */
523
524 /* BUF must be big enough for the maximum %#llo (assuming long long is
525 at most 64 bits, this would be 23 characters), the maximum
526 multibyte character %C, and the maximum default precision of %La
527 (assuming long double is at most 128 bits with 113 bits of
528 mantissa, this would be 29 characters). %e, %f, and %g use
529 reentrant storage shared with mprec. All other formats that use
530 buf get by with fewer characters. Making BUF slightly bigger
531 reduces the need for malloc in %.*a and %S, when large precision or
532 long strings are processed.
533 The bigger size of 100 bytes is used on systems which allow number
534 strings using the locale's grouping character. Since that's a multibyte
535 value, we should use a conservative value.
536 */
537 #ifdef _WANT_IO_C99_FORMATS
538 #define BUF 100
539 #else
540 #define BUF 40
541 #endif
542 #if defined _MB_CAPABLE && MB_LEN_MAX > BUF
543 # undef BUF
544 # define BUF MB_LEN_MAX
545 #endif
546
547 #ifndef _NO_LONGLONG
548 # define quad_t long long
549 # define u_quad_t unsigned long long
550 #else
551 # define quad_t long
552 # define u_quad_t unsigned long
553 #endif
554
555 typedef quad_t * quad_ptr_t;
556 typedef void *void_ptr_t;
557 typedef char * char_ptr_t;
558 typedef long * long_ptr_t;
559 typedef int * int_ptr_t;
560 typedef short * short_ptr_t;
561
562 #ifndef _NO_POS_ARGS
563 # ifdef NL_ARGMAX
564 # define MAX_POS_ARGS NL_ARGMAX
565 # else
566 # define MAX_POS_ARGS 32
567 # endif
568
569 union arg_val
570 {
571 int val_int;
572 u_int val_u_int;
573 long val_long;
574 u_long val_u_long;
575 float val_float;
576 double val_double;
577 _LONG_DOUBLE val__LONG_DOUBLE;
578 int_ptr_t val_int_ptr_t;
579 short_ptr_t val_short_ptr_t;
580 long_ptr_t val_long_ptr_t;
581 char_ptr_t val_char_ptr_t;
582 quad_ptr_t val_quad_ptr_t;
583 void_ptr_t val_void_ptr_t;
584 quad_t val_quad_t;
585 u_quad_t val_u_quad_t;
586 wint_t val_wint_t;
587 };
588
589 static union arg_val *
590 get_arg (struct _reent *data, int n, char *fmt,
591 va_list *ap, int *numargs, union arg_val *args,
592 int *arg_type, char **last_fmt);
593 #endif /* !_NO_POS_ARGS */
594
595 /*
596 * Macros for converting digits to letters and vice versa
597 */
598 #define to_digit(c) ((c) - '0')
599 #define is_digit(c) ((unsigned)to_digit (c) <= 9)
600 #define to_char(n) ((n) + '0')
601
602 /*
603 * Flags used during conversion.
604 */
605 #define ALT 0x001 /* alternate form */
606 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
607 #define LADJUST 0x004 /* left adjustment */
608 #define LONGDBL 0x008 /* long double */
609 #define LONGINT 0x010 /* long integer */
610 #ifndef _NO_LONGLONG
611 # define QUADINT 0x020 /* quad integer */
612 #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
613 that %lld behaves the same as %ld, not as %d, as expected if:
614 sizeof (long long) = sizeof long > sizeof int */
615 # define QUADINT LONGINT
616 #endif
617 #define SHORTINT 0x040 /* short integer */
618 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
619 #define FPT 0x100 /* Floating point number */
620 #ifdef _WANT_IO_C99_FORMATS
621 # define CHARINT 0x200 /* char as integer */
622 #else /* define as 0, to make SARG and UARG occupy fewer instructions */
623 # define CHARINT 0
624 #endif
625 #ifdef _WANT_IO_C99_FORMATS
626 # define GROUPING 0x400 /* use grouping ("'" flag) */
627 #endif
628
629 int
630 VFPRINTF (
631 FILE * fp,
632 const char *fmt0,
633 va_list ap)
634 {
635 register char *fmt; /* format string */
636 register int ch; /* character from fmt */
637 register int n, m; /* handy integers (short term usage) */
638 register char *cp; /* handy char pointer (short term usage) */
639 register int flags; /* flags as above */
640 #ifndef _NO_POS_ARGS
641 char *fmt_anchor; /* current format spec being processed */
642 int N; /* arg number */
643 int arg_index; /* index into args processed directly */
644 int numargs; /* number of varargs read */
645 char *saved_fmt; /* saved fmt pointer */
646 union arg_val args[MAX_POS_ARGS];
647 int arg_type[MAX_POS_ARGS];
648 int is_pos_arg; /* is current format positional? */
649 int old_is_pos_arg; /* is current format positional? */
650 #endif
651 int ret; /* return value accumulator */
652 int width; /* width from format (%8d), or 0 */
653 int prec; /* precision from format (%.3d), or -1 */
654 char sign; /* sign prefix (' ', '+', '-', or \0) */
655 #ifdef _WANT_IO_C99_FORMATS
656 /* locale specific numeric grouping */
657 char *thousands_sep = NULL;
658 size_t thsnd_len = 0;
659 const char *grouping = NULL;
660 #endif
661 #ifdef FLOATING_POINT
662 char *decimal_point = localeconv ()->decimal_point;
663 size_t decp_len = strlen (decimal_point);
664 char softsign; /* temporary negative sign for floats */
665 union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
666 # define _fpvalue (_double_.fp)
667 int expt; /* integer value of exponent */
668 int expsize = 0; /* character count for expstr */
669 char expstr[MAXEXPLEN]; /* buffer for exponent string */
670 int lead; /* sig figs before decimal or group sep */
671 #endif /* FLOATING_POINT */
672 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
673 int ndig = 0; /* actual number of digits returned by cvt */
674 #endif
675 #if defined (FLOATING_POINT) && defined (_WANT_IO_C99_FORMATS)
676 int nseps; /* number of group separators with ' */
677 int nrepeats; /* number of repeats of the last group */
678 #endif
679 u_quad_t _uquad; /* integer arguments %[diouxX] */
680 enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
681 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
682 int realsz; /* field size expanded by dprec */
683 int size; /* size of converted field or string */
684 char *xdigs = NULL; /* digits for [xX] conversion */
685 #ifdef _FVWRITE_IN_STREAMIO
686 #define NIOV 8
687 struct __suio uio; /* output information: summary */
688 struct __siov iov[NIOV];/* ... and individual io vectors */
689 register struct __siov *iovp;/* for PRINT macro */
690 #endif
691 char buf[BUF]; /* space for %c, %S, %[diouxX], %[aA] */
692 char ox[2] = {0}; /* space for 0x hex-prefix */
693 #ifdef _MB_CAPABLE
694 wchar_t wc;
695 mbstate_t state; /* mbtowc calls from library must not change state */
696 #endif
697 char *malloc_buf = NULL;/* handy pointer for malloced buffers */
698
699 /*
700 * Choose PADSIZE to trade efficiency vs. size. If larger printf
701 * fields occur frequently, increase PADSIZE and make the initialisers
702 * below longer.
703 */
704 #define PADSIZE 16 /* pad chunk size */
705 static const char blanks[PADSIZE] =
706 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
707 static const char zeroes[PADSIZE] =
708 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
709
710 #ifdef _MB_CAPABLE
711 memset (&state, '\0', sizeof (state));
712 #endif
713 /*
714 * BEWARE, these `goto error' on error, and PAD uses `n'.
715 */
716 #ifdef _FVWRITE_IN_STREAMIO
717 #define PRINT(ptr, len) { \
718 iovp->iov_base = (ptr); \
719 iovp->iov_len = (len); \
720 uio.uio_resid += (len); \
721 iovp++; \
722 if (++uio.uio_iovcnt >= NIOV) { \
723 if (__SPRINT(fp, &uio)) \
724 goto error; \
725 iovp = iov; \
726 } \
727 }
728 #define PAD(howmany, with) { \
729 if ((n = (howmany)) > 0) { \
730 while (n > PADSIZE) { \
731 PRINT (with, PADSIZE); \
732 n -= PADSIZE; \
733 } \
734 PRINT (with, n); \
735 } \
736 }
737 #define PRINTANDPAD(p, ep, len, with) { \
738 int n = (ep) - (p); \
739 if (n > (len)) \
740 n = (len); \
741 if (n > 0) \
742 PRINT((p), n); \
743 PAD((len) - (n > 0 ? n : 0), (with)); \
744 }
745 #define FLUSH() { \
746 if (uio.uio_resid && __SPRINT(fp, &uio)) \
747 goto error; \
748 uio.uio_iovcnt = 0; \
749 iovp = iov; \
750 }
751 #else
752 #define PRINT(ptr, len) { \
753 if (__SPRINT (fp, (ptr), (len)) == EOF) \
754 goto error; \
755 }
756 #define PAD(howmany, with) { \
757 if ((n = (howmany)) > 0) { \
758 while (n > PADSIZE) { \
759 PRINT (with, PADSIZE); \
760 n -= PADSIZE; \
761 } \
762 PRINT (with, n); \
763 } \
764 }
765 #define PRINTANDPAD(p, ep, len, with) { \
766 int n = (ep) - (p); \
767 if (n > (len)) \
768 n = (len); \
769 if (n > 0) \
770 PRINT((p), n); \
771 PAD((len) - (n > 0 ? n : 0), (with)); \
772 }
773 #define FLUSH()
774 #endif
775
776 /* Macros to support positional arguments */
777 #ifndef _NO_POS_ARGS
778 # define GET_ARG(n, ap, type) \
779 (is_pos_arg \
780 ? (n < numargs \
781 ? args[n].val_##type \
782 : get_arg (data, n, fmt_anchor, &ap, &numargs, args, \
783 arg_type, &saved_fmt)->val_##type) \
784 : (arg_index++ < numargs \
785 ? args[n].val_##type \
786 : (numargs < MAX_POS_ARGS \
787 ? args[numargs++].val_##type = va_arg (ap, type) \
788 : va_arg (ap, type))))
789 #else
790 # define GET_ARG(n, ap, type) (va_arg (ap, type))
791 #endif
792
793 /*
794 * To extend shorts properly, we need both signed and unsigned
795 * argument extraction methods.
796 */
797 #ifndef _NO_LONGLONG
798 #define SARG() \
799 (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
800 flags&LONGINT ? GET_ARG (N, ap, long) : \
801 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
802 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
803 (long)GET_ARG (N, ap, int))
804 #define UARG() \
805 (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
806 flags&LONGINT ? GET_ARG (N, ap, u_long) : \
807 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
808 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
809 (u_long)GET_ARG (N, ap, u_int))
810 #else
811 #define SARG() \
812 (flags&LONGINT ? GET_ARG (N, ap, long) : \
813 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
814 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
815 (long)GET_ARG (N, ap, int))
816 #define UARG() \
817 (flags&LONGINT ? GET_ARG (N, ap, u_long) : \
818 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
819 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
820 (u_long)GET_ARG (N, ap, u_int))
821 #endif
822
823 #ifndef STRING_ONLY
824 /* Initialize std streams if not dealing with sprintf family. */
825 CHECK_INIT (data, fp);
826 _newlib_flockfile_start (fp);
827
828 ORIENT(fp, -1);
829
830 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
831 if (cantwrite (data, fp)) {
832 _newlib_flockfile_exit (fp);
833 return (EOF);
834 }
835
836 #ifdef _UNBUF_STREAM_OPT
837 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
838 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
839 fp->_file >= 0) {
840 _newlib_flockfile_exit (fp);
841 return (__sbprintf (data, fp, fmt0, ap));
842 }
843 #endif
844 #else /* STRING_ONLY */
845 /* Create initial buffer if we are called by asprintf family. */
846 if (fp->_flags & __SMBF && !fp->_bf._base)
847 {
848 fp->_bf._base = fp->_p = malloc (64);
849 if (!fp->_p)
850 {
851 _REENT_ERRNO(data) = ENOMEM;
852 return EOF;
853 }
854 fp->_bf._size = 64;
855 }
856 #endif /* STRING_ONLY */
857
858 fmt = (char *)fmt0;
859 #ifdef _FVWRITE_IN_STREAMIO
860 uio.uio_iov = iovp = iov;
861 uio.uio_resid = 0;
862 uio.uio_iovcnt = 0;
863 #endif
864 ret = 0;
865 #ifndef _NO_POS_ARGS
866 arg_index = 0;
867 saved_fmt = NULL;
868 arg_type[0] = -1;
869 numargs = 0;
870 is_pos_arg = 0;
871 #endif
872
873 /*
874 * Scan the format for conversions (`%' character).
875 */
876 for (;;) {
877 cp = fmt;
878 #ifdef _MB_CAPABLE
879 while ((n = __MBTOWC (&wc, fmt, MB_CUR_MAX,
880 &state)) != 0) {
881 if (n < 0) {
882 /* Wave invalid chars through. */
883 memset (&state, 0, sizeof state);
884 n = 1;
885 }
886 else if (wc == '%')
887 break;
888 fmt += n;
889 }
890 #else
891 while (*fmt != '\0' && *fmt != '%')
892 fmt += 1;
893 #endif
894 if ((m = fmt - cp) != 0) {
895 PRINT (cp, m);
896 ret += m;
897 }
898 #ifdef _MB_CAPABLE
899 if (n <= 0)
900 goto done;
901 #else
902 if (*fmt == '\0')
903 goto done;
904 #endif
905 #ifndef _NO_POS_ARGS
906 fmt_anchor = fmt;
907 #endif
908 fmt++; /* skip over '%' */
909
910 flags = 0;
911 dprec = 0;
912 width = 0;
913 prec = -1;
914 sign = '\0';
915 #ifdef FLOATING_POINT
916 lead = 0;
917 #ifdef _WANT_IO_C99_FORMATS
918 nseps = nrepeats = 0;
919 #endif
920 #endif
921 #ifndef _NO_POS_ARGS
922 N = arg_index;
923 is_pos_arg = 0;
924 #endif
925
926 rflag: ch = *fmt++;
927 reswitch: switch (ch) {
928 #ifdef _WANT_IO_C99_FORMATS
929 case '\'':
930 thousands_sep = localeconv ()->thousands_sep;
931 thsnd_len = strlen (thousands_sep);
932 grouping = localeconv ()->grouping;
933 if (thsnd_len > 0 && grouping && *grouping)
934 flags |= GROUPING;
935 goto rflag;
936 #endif
937 case ' ':
938 /*
939 * ``If the space and + flags both appear, the space
940 * flag will be ignored.''
941 * -- ANSI X3J11
942 */
943 if (!sign)
944 sign = ' ';
945 goto rflag;
946 case '#':
947 flags |= ALT;
948 goto rflag;
949 case '*':
950 #ifndef _NO_POS_ARGS
951 /* we must check for positional arg used for dynamic width */
952 n = N;
953 old_is_pos_arg = is_pos_arg;
954 is_pos_arg = 0;
955 if (is_digit (*fmt)) {
956 char *old_fmt = fmt;
957
958 n = 0;
959 ch = *fmt++;
960 do {
961 n = 10 * n + to_digit (ch);
962 ch = *fmt++;
963 } while (is_digit (ch));
964
965 if (ch == '$') {
966 if (n <= MAX_POS_ARGS) {
967 n -= 1;
968 is_pos_arg = 1;
969 }
970 else
971 goto error;
972 }
973 else {
974 fmt = old_fmt;
975 goto rflag;
976 }
977 }
978 #endif /* !_NO_POS_ARGS */
979
980 /*
981 * ``A negative field width argument is taken as a
982 * - flag followed by a positive field width.''
983 * -- ANSI X3J11
984 * They don't exclude field widths read from args.
985 */
986 width = GET_ARG (n, ap, int);
987 #ifndef _NO_POS_ARGS
988 is_pos_arg = old_is_pos_arg;
989 #endif
990 if (width >= 0)
991 goto rflag;
992 width = -width;
993 FALLTHROUGH;
994 case '-':
995 flags |= LADJUST;
996 goto rflag;
997 case '+':
998 sign = '+';
999 goto rflag;
1000 case '.':
1001 if ((ch = *fmt++) == '*') {
1002 #ifndef _NO_POS_ARGS
1003 /* we must check for positional arg used for dynamic width */
1004 n = N;
1005 old_is_pos_arg = is_pos_arg;
1006 is_pos_arg = 0;
1007 if (is_digit (*fmt)) {
1008 char *old_fmt = fmt;
1009
1010 n = 0;
1011 ch = *fmt++;
1012 do {
1013 n = 10 * n + to_digit (ch);
1014 ch = *fmt++;
1015 } while (is_digit (ch));
1016
1017 if (ch == '$') {
1018 if (n <= MAX_POS_ARGS) {
1019 n -= 1;
1020 is_pos_arg = 1;
1021 }
1022 else
1023 goto error;
1024 }
1025 else {
1026 fmt = old_fmt;
1027 goto rflag;
1028 }
1029 }
1030 #endif /* !_NO_POS_ARGS */
1031 prec = GET_ARG (n, ap, int);
1032 #ifndef _NO_POS_ARGS
1033 is_pos_arg = old_is_pos_arg;
1034 #endif
1035 if (prec < 0)
1036 prec = -1;
1037 goto rflag;
1038 }
1039 n = 0;
1040 while (is_digit (ch)) {
1041 n = 10 * n + to_digit (ch);
1042 ch = *fmt++;
1043 }
1044 prec = n < 0 ? -1 : n;
1045 goto reswitch;
1046 case '0':
1047 /*
1048 * ``Note that 0 is taken as a flag, not as the
1049 * beginning of a field width.''
1050 * -- ANSI X3J11
1051 */
1052 flags |= ZEROPAD;
1053 goto rflag;
1054 case '1': case '2': case '3': case '4':
1055 case '5': case '6': case '7': case '8': case '9':
1056 n = 0;
1057 do {
1058 n = 10 * n + to_digit (ch);
1059 ch = *fmt++;
1060 } while (is_digit (ch));
1061 #ifndef _NO_POS_ARGS
1062 if (ch == '$') {
1063 if (n <= MAX_POS_ARGS) {
1064 N = n - 1;
1065 is_pos_arg = 1;
1066 goto rflag;
1067 }
1068 else
1069 goto error;
1070 }
1071 #endif /* !_NO_POS_ARGS */
1072 width = n;
1073 goto reswitch;
1074 #ifdef FLOATING_POINT
1075 case 'L':
1076 flags |= LONGDBL;
1077 goto rflag;
1078 #endif
1079 case 'h':
1080 #ifdef _WANT_IO_C99_FORMATS
1081 if (*fmt == 'h') {
1082 fmt++;
1083 flags |= CHARINT;
1084 } else
1085 #endif
1086 flags |= SHORTINT;
1087 goto rflag;
1088 case 'l':
1089 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
1090 if (*fmt == 'l') {
1091 fmt++;
1092 flags |= QUADINT;
1093 } else
1094 #endif
1095 flags |= LONGINT;
1096 goto rflag;
1097 case 'q': /* extension */
1098 flags |= QUADINT;
1099 goto rflag;
1100 #ifdef _WANT_IO_C99_FORMATS
1101 case 'j':
1102 if (sizeof (intmax_t) == sizeof (long))
1103 flags |= LONGINT;
1104 else
1105 flags |= QUADINT;
1106 goto rflag;
1107 case 'z':
1108 if (sizeof (size_t) < sizeof (int))
1109 /* POSIX states size_t is 16 or more bits, as is short. */
1110 flags |= SHORTINT;
1111 else if (sizeof (size_t) == sizeof (int))
1112 /* no flag needed */;
1113 else if (sizeof (size_t) <= sizeof (long))
1114 flags |= LONGINT;
1115 else
1116 /* POSIX states that at least one programming
1117 environment must support size_t no wider than
1118 long, but that means other environments can
1119 have size_t as wide as long long. */
1120 flags |= QUADINT;
1121 goto rflag;
1122 case 't':
1123 if (sizeof (ptrdiff_t) < sizeof (int))
1124 /* POSIX states ptrdiff_t is 16 or more bits, as
1125 is short. */
1126 flags |= SHORTINT;
1127 else if (sizeof (ptrdiff_t) == sizeof (int))
1128 /* no flag needed */;
1129 else if (sizeof (ptrdiff_t) <= sizeof (long))
1130 flags |= LONGINT;
1131 else
1132 /* POSIX states that at least one programming
1133 environment must support ptrdiff_t no wider than
1134 long, but that means other environments can
1135 have ptrdiff_t as wide as long long. */
1136 flags |= QUADINT;
1137 goto rflag;
1138 case 'C':
1139 #endif /* _WANT_IO_C99_FORMATS */
1140 case 'c':
1141 cp = buf;
1142 #ifdef _MB_CAPABLE
1143 if (ch == 'C' || (flags & LONGINT)) {
1144 mbstate_t ps;
1145
1146 memset ((void *)&ps, '\0', sizeof (mbstate_t));
1147 if ((size = (int)wcrtomb (cp,
1148 (wchar_t)GET_ARG (N, ap, wint_t),
1149 &ps)) == -1) {
1150 fp->_flags |= __SERR;
1151 goto error;
1152 }
1153 }
1154 else
1155 #endif /* _MB_CAPABLE */
1156 {
1157 *cp = GET_ARG (N, ap, int);
1158 size = 1;
1159 }
1160 sign = '\0';
1161 break;
1162 case 'D': /* extension */
1163 flags |= LONGINT;
1164 FALLTHROUGH;
1165 case 'd':
1166 case 'i':
1167 _uquad = SARG ();
1168 #ifndef _NO_LONGLONG
1169 if ((quad_t)_uquad < 0)
1170 #else
1171 if ((long) _uquad < 0)
1172 #endif
1173 {
1174
1175 _uquad = -_uquad;
1176 sign = '-';
1177 }
1178 base = DEC;
1179 goto number;
1180 #ifdef FLOATING_POINT
1181 # ifdef _WANT_IO_C99_FORMATS
1182 case 'a':
1183 case 'A':
1184 case 'F':
1185 # endif
1186 case 'e':
1187 case 'E':
1188 case 'f':
1189 case 'g':
1190 case 'G':
1191 # ifdef _NO_LONGDBL
1192 if (flags & LONGDBL) {
1193 _fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE);
1194 } else {
1195 _fpvalue = GET_ARG (N, ap, double);
1196 }
1197
1198 /* do this before tricky precision changes
1199
1200 If the output is infinite or NaN, leading
1201 zeros are not permitted. Otherwise, scanf
1202 could not read what printf wrote.
1203 */
1204 if (isinf (_fpvalue)) {
1205 if (_fpvalue < 0)
1206 sign = '-';
1207 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1208 cp = "INF";
1209 else
1210 cp = "inf";
1211 size = 3;
1212 flags &= ~ZEROPAD;
1213 break;
1214 }
1215 if (isnan (_fpvalue)) {
1216 if (signbit (_fpvalue))
1217 sign = '-';
1218 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1219 cp = "NAN";
1220 else
1221 cp = "nan";
1222 size = 3;
1223 flags &= ~ZEROPAD;
1224 break;
1225 }
1226
1227 # else /* !_NO_LONGDBL */
1228
1229 if (flags & LONGDBL) {
1230 _fpvalue = GET_ARG (N, ap, _LONG_DOUBLE);
1231 } else {
1232 _fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double);
1233 }
1234
1235 /* do this before tricky precision changes */
1236 expt = _ldcheck (&_fpvalue);
1237 if (expt == 2) {
1238 if (_fpvalue < 0)
1239 sign = '-';
1240 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1241 cp = "INF";
1242 else
1243 cp = "inf";
1244 size = 3;
1245 flags &= ~ZEROPAD;
1246 break;
1247 }
1248 if (expt == 1) {
1249 if (signbit (_fpvalue))
1250 sign = '-';
1251 if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */
1252 cp = "NAN";
1253 else
1254 cp = "nan";
1255 size = 3;
1256 flags &= ~ZEROPAD;
1257 break;
1258 }
1259 # endif /* !_NO_LONGDBL */
1260
1261 # ifdef _WANT_IO_C99_FORMATS
1262 if (ch == 'a' || ch == 'A') {
1263 ox[0] = '0';
1264 ox[1] = ch == 'a' ? 'x' : 'X';
1265 flags |= HEXPREFIX;
1266 if (prec >= BUF)
1267 {
1268 if ((malloc_buf =
1269 (char *)malloc (prec + 1))
1270 == NULL)
1271 {
1272 fp->_flags |= __SERR;
1273 goto error;
1274 }
1275 cp = malloc_buf;
1276 }
1277 else
1278 cp = buf;
1279 } else
1280 # endif /* _WANT_IO_C99_FORMATS */
1281 if (prec == -1) {
1282 prec = DEFPREC;
1283 } else if ((ch == 'g' || ch == 'G') && prec == 0) {
1284 prec = 1;
1285 }
1286
1287 flags |= FPT;
1288
1289 cp = cvt (_fpvalue, prec, flags, &softsign,
1290 &expt, ch, &ndig, cp);
1291 if (!cp)
1292 goto error;
1293
1294 if (ch == 'g' || ch == 'G') {
1295 if (expt <= -4 || expt > prec)
1296 ch -= 2; /* 'e' or 'E' */
1297 else
1298 ch = 'g';
1299 }
1300 # ifdef _WANT_IO_C99_FORMATS
1301 else if (ch == 'F')
1302 ch = 'f';
1303 # endif
1304 if (ch <= 'e') { /* 'a', 'A', 'e', or 'E' fmt */
1305 --expt;
1306 expsize = exponent (expstr, expt, ch);
1307 size = expsize + ndig;
1308 if (ndig > 1 || flags & ALT)
1309 size += decp_len;
1310 # ifdef _WANT_IO_C99_FORMATS
1311 flags &= ~GROUPING;
1312 # endif
1313 } else {
1314 if (ch == 'f') { /* f fmt */
1315 if (expt > 0) {
1316 size = expt;
1317 if (prec || flags & ALT)
1318 size += prec + decp_len;
1319 } else /* "0.X" */
1320 size = (prec || flags & ALT)
1321 ? prec + 1 + decp_len
1322 : 1;
1323 } else if (expt >= ndig) { /* fixed g fmt */
1324 size = expt;
1325 if (flags & ALT)
1326 size += decp_len;
1327 } else {
1328 size = ndig + decp_len;
1329 if (expt <= 0)
1330 size += 1 - expt;
1331 }
1332 # ifdef _WANT_IO_C99_FORMATS
1333 if ((flags & GROUPING) && expt > 0) {
1334 /* space for thousands' grouping */
1335 nseps = nrepeats = 0;
1336 lead = expt;
1337 while (*grouping != CHAR_MAX) {
1338 if (lead <= *grouping)
1339 break;
1340 lead -= *grouping;
1341 if (grouping[1]) {
1342 nseps++;
1343 grouping++;
1344 } else
1345 nrepeats++;
1346 }
1347 size += (nseps + nrepeats) * thsnd_len;
1348 } else
1349 # endif
1350 lead = expt;
1351 }
1352
1353 if (softsign)
1354 sign = '-';
1355 break;
1356 #endif /* FLOATING_POINT */
1357 #ifdef _GLIBC_EXTENSION
1358 case 'm': /* extension */
1359 {
1360 int dummy;
1361 cp = strerror ( _REENT_ERRNO(data), 1, &dummy);
1362 }
1363 flags &= ~LONGINT;
1364 goto string;
1365 #endif
1366 case 'n':
1367 #ifndef _NO_LONGLONG
1368 if (flags & QUADINT)
1369 *GET_ARG (N, ap, quad_ptr_t) = ret;
1370 else
1371 #endif
1372 if (flags & LONGINT)
1373 *GET_ARG (N, ap, long_ptr_t) = ret;
1374 else if (flags & SHORTINT)
1375 *GET_ARG (N, ap, short_ptr_t) = ret;
1376 #ifdef _WANT_IO_C99_FORMATS
1377 else if (flags & CHARINT)
1378 *GET_ARG (N, ap, char_ptr_t) = ret;
1379 #endif
1380 else
1381 *GET_ARG (N, ap, int_ptr_t) = ret;
1382 continue; /* no output */
1383 case 'O': /* extension */
1384 flags |= LONGINT;
1385 FALLTHROUGH;
1386 case 'o':
1387 _uquad = UARG ();
1388 base = OCT;
1389 #ifdef _WANT_IO_C99_FORMATS
1390 flags &= ~GROUPING;
1391 #endif
1392 goto nosign;
1393 case 'p':
1394 /*
1395 * ``The argument shall be a pointer to void. The
1396 * value of the pointer is converted to a sequence
1397 * of printable characters, in an implementation-
1398 * defined manner.''
1399 * -- ANSI X3J11
1400 */
1401 /* NOSTRICT */
1402 _uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t);
1403 base = HEX;
1404 xdigs = "0123456789abcdef";
1405 flags |= HEXPREFIX;
1406 ox[0] = '0';
1407 ox[1] = ch = 'x';
1408 goto nosign;
1409 case 's':
1410 #ifdef _WANT_IO_C99_FORMATS
1411 case 'S':
1412 #endif
1413 cp = GET_ARG (N, ap, char_ptr_t);
1414 #ifdef _GLIBC_EXTENSION
1415 string:
1416 #endif
1417 sign = '\0';
1418 /* Behavior is undefined if the user passed a
1419 NULL string when precision is not 0.
1420 However, we might as well mirror glibc behavior. */
1421 if (cp == NULL) {
1422 cp = "(null)";
1423 size = ((unsigned) prec > 6U) ? 6 : prec;
1424 }
1425 else
1426 #ifdef _MB_CAPABLE
1427 if (ch == 'S' || (flags & LONGINT)) {
1428 mbstate_t ps;
1429 const wchar_t *wcp;
1430
1431 wcp = (const wchar_t *)cp;
1432 size = m = 0;
1433 memset ((void *)&ps, '\0', sizeof (mbstate_t));
1434
1435 /* Count number of bytes needed for multibyte
1436 string that will be produced from widechar
1437 string. */
1438 if (prec >= 0) {
1439 while (1) {
1440 if (wcp[m] == L'\0')
1441 break;
1442 if ((n = (int)wcrtomb (
1443 buf, wcp[m], &ps)) == -1) {
1444 fp->_flags |= __SERR;
1445 goto error;
1446 }
1447 if (n + size > prec)
1448 break;
1449 m += 1;
1450 size += n;
1451 if (size == prec)
1452 break;
1453 }
1454 }
1455 else {
1456 if ((size = (int)wcsrtombs (
1457 NULL, &wcp, 0, &ps)) == -1) {
1458 fp->_flags |= __SERR;
1459 goto error;
1460 }
1461 wcp = (const wchar_t *)cp;
1462 }
1463
1464 if (size == 0)
1465 break;
1466
1467 if (size >= BUF) {
1468 if ((malloc_buf =
1469 (char *)malloc (size + 1))
1470 == NULL) {
1471 fp->_flags |= __SERR;
1472 goto error;
1473 }
1474 cp = malloc_buf;
1475 } else
1476 cp = buf;
1477
1478 /* Convert widechar string to multibyte string. */
1479 memset ((void *)&ps, '\0', sizeof (mbstate_t));
1480 if (wcsrtombs (cp, &wcp, size, &ps)
1481 != size) {
1482 fp->_flags |= __SERR;
1483 goto error;
1484 }
1485 cp[size] = '\0';
1486 }
1487 else
1488 #endif /* _MB_CAPABLE */
1489 if (prec >= 0) {
1490 /*
1491 * can't use strlen; can only look for the
1492 * NUL in the first `prec' characters, and
1493 * strlen () will go further.
1494 */
1495 char *p = memchr (cp, 0, prec);
1496
1497 if (p != NULL)
1498 size = p - cp;
1499 else
1500 size = prec;
1501 } else
1502 size = strlen (cp);
1503
1504 break;
1505 case 'U': /* extension */
1506 flags |= LONGINT;
1507 FALLTHROUGH;
1508 case 'u':
1509 _uquad = UARG ();
1510 base = DEC;
1511 goto nosign;
1512 case 'X':
1513 xdigs = "0123456789ABCDEF";
1514 goto hex;
1515 case 'x':
1516 xdigs = "0123456789abcdef";
1517 hex: _uquad = UARG ();
1518 base = HEX;
1519 /* leading 0x/X only if non-zero */
1520 if (flags & ALT && _uquad != 0) {
1521 ox[0] = '0';
1522 ox[1] = ch;
1523 flags |= HEXPREFIX;
1524 }
1525
1526 #ifdef _WANT_IO_C99_FORMATS
1527 flags &= ~GROUPING;
1528 #endif
1529 /* unsigned conversions */
1530 nosign: sign = '\0';
1531 /*
1532 * ``... diouXx conversions ... if a precision is
1533 * specified, the 0 flag will be ignored.''
1534 * -- ANSI X3J11
1535 */
1536 number: if ((dprec = prec) >= 0)
1537 flags &= ~ZEROPAD;
1538
1539 /*
1540 * ``The result of converting a zero value with an
1541 * explicit precision of zero is no characters.''
1542 * -- ANSI X3J11
1543 */
1544 cp = buf + BUF;
1545 if (_uquad != 0 || prec != 0) {
1546 /*
1547 * Unsigned mod is hard, and unsigned mod
1548 * by a constant is easier than that by
1549 * a variable; hence this switch.
1550 */
1551 switch (base) {
1552 case OCT:
1553 do {
1554 *--cp = to_char (_uquad & 7);
1555 _uquad >>= 3;
1556 } while (_uquad);
1557 /* handle octal leading 0 */
1558 if (flags & ALT && *cp != '0')
1559 *--cp = '0';
1560 break;
1561
1562 case DEC:
1563 /* many numbers are 1 digit */
1564 if (_uquad < 10) {
1565 *--cp = to_char(_uquad);
1566 break;
1567 }
1568 #ifdef _WANT_IO_C99_FORMATS
1569 ndig = 0;
1570 #endif
1571 do {
1572 *--cp = to_char (_uquad % 10);
1573 #ifdef _WANT_IO_C99_FORMATS
1574 ndig++;
1575 /* If (*grouping == CHAR_MAX) then no
1576 more grouping */
1577 if ((flags & GROUPING)
1578 && ndig == *grouping
1579 && *grouping != CHAR_MAX
1580 && _uquad > 9) {
1581 cp -= thsnd_len;
1582 strncpy (cp, thousands_sep,
1583 thsnd_len);
1584 ndig = 0;
1585 /* If (grouping[1] == '\0') then we
1586 have to use *grouping character
1587 (last grouping rule) for all
1588 next cases. */
1589 if (grouping[1] != '\0')
1590 grouping++;
1591 }
1592 #endif
1593 _uquad /= 10;
1594 } while (_uquad != 0);
1595 break;
1596
1597 case HEX:
1598 do {
1599 *--cp = xdigs[_uquad & 15];
1600 _uquad >>= 4;
1601 } while (_uquad);
1602 break;
1603
1604 default:
1605 cp = "bug in vfprintf: bad base";
1606 size = strlen (cp);
1607 goto skipsize;
1608 }
1609 }
1610 /*
1611 * ...result is to be converted to an 'alternate form'.
1612 * For o conversion, it increases the precision to force
1613 * the first digit of the result to be a zero."
1614 * -- ANSI X3J11
1615 *
1616 * To demonstrate this case, compile and run:
1617 * printf ("%#.0o",0);
1618 */
1619 else if (base == OCT && (flags & ALT))
1620 *--cp = '0';
1621
1622 size = buf + BUF - cp;
1623 skipsize:
1624 break;
1625 default: /* "%?" prints ?, unless ? is NUL */
1626 if (ch == '\0')
1627 goto done;
1628 /* pretend it was %c with argument ch */
1629 cp = buf;
1630 *cp = ch;
1631 size = 1;
1632 sign = '\0';
1633 break;
1634 }
1635
1636 /*
1637 * All reasonable formats wind up here. At this point, `cp'
1638 * points to a string which (if not flags&LADJUST) should be
1639 * padded out to `width' places. If flags&ZEROPAD, it should
1640 * first be prefixed by any sign or other prefix; otherwise,
1641 * it should be blank padded before the prefix is emitted.
1642 * After any left-hand padding and prefixing, emit zeroes
1643 * required by a decimal [diouxX] precision, then print the
1644 * string proper, then emit zeroes required by any leftover
1645 * floating precision; finally, if LADJUST, pad with blanks.
1646 * If flags&FPT, ch must be in [aAeEfg].
1647 *
1648 * Compute actual size, so we know how much to pad.
1649 * size excludes decimal prec; realsz includes it.
1650 */
1651 realsz = dprec > size ? dprec : size;
1652 if (sign)
1653 realsz++;
1654 if (flags & HEXPREFIX)
1655 realsz+= 2;
1656
1657 /* right-adjusting blank padding */
1658 if ((flags & (LADJUST|ZEROPAD)) == 0)
1659 PAD (width - realsz, blanks);
1660
1661 /* prefix */
1662 if (sign)
1663 PRINT (&sign, 1);
1664 if (flags & HEXPREFIX)
1665 PRINT (ox, 2);
1666
1667 /* right-adjusting zero padding */
1668 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1669 PAD (width - realsz, zeroes);
1670
1671 /* leading zeroes from decimal precision */
1672 PAD (dprec - size, zeroes);
1673
1674 /* the string or number proper */
1675 #ifdef FLOATING_POINT
1676 if ((flags & FPT) == 0) {
1677 PRINT (cp, size);
1678 } else { /* glue together f_p fragments */
1679 if (ch >= 'f') { /* 'f' or 'g' */
1680 if (_fpvalue == 0) {
1681 /* kludge for __dtoa irregularity */
1682 PRINT ("0", 1);
1683 if (expt < ndig || flags & ALT) {
1684 PRINT (decimal_point, decp_len);
1685 PAD (ndig - 1, zeroes);
1686 }
1687 } else if (expt <= 0) {
1688 PRINT ("0", 1);
1689 if (expt || ndig || flags & ALT) {
1690 PRINT (decimal_point, decp_len);
1691 PAD (-expt, zeroes);
1692 PRINT (cp, ndig);
1693 }
1694 } else {
1695 char *convbuf = cp;
1696 PRINTANDPAD(cp, convbuf + ndig,
1697 lead, zeroes);
1698 cp += lead;
1699 #ifdef _WANT_IO_C99_FORMATS
1700 if (flags & GROUPING) {
1701 while (nseps > 0 || nrepeats > 0) {
1702 if (nrepeats > 0)
1703 nrepeats--;
1704 else {
1705 grouping--;
1706 nseps--;
1707 }
1708 PRINT(thousands_sep, thsnd_len);
1709 PRINTANDPAD (cp, convbuf + ndig,
1710 *grouping, zeroes);
1711 cp += *grouping;
1712 }
1713 if (cp > convbuf + ndig)
1714 cp = convbuf + ndig;
1715 }
1716 #endif
1717 if (expt < ndig || flags & ALT)
1718 PRINT (decimal_point, decp_len);
1719 PRINTANDPAD (cp, convbuf + ndig,
1720 ndig - expt, zeroes);
1721 }
1722 } else { /* 'a', 'A', 'e', or 'E' */
1723 if (ndig > 1 || flags & ALT) {
1724 PRINT (cp, 1);
1725 cp++;
1726 PRINT (decimal_point, decp_len);
1727 if (_fpvalue) {
1728 PRINT (cp, ndig - 1);
1729 } else /* 0.[0..] */
1730 /* __dtoa irregularity */
1731 PAD (ndig - 1, zeroes);
1732 } else /* XeYYY */
1733 PRINT (cp, 1);
1734 PRINT (expstr, expsize);
1735 }
1736 }
1737 #else /* !FLOATING_POINT */
1738 PRINT (cp, size);
1739 #endif
1740 /* left-adjusting padding (always blank) */
1741 if (flags & LADJUST)
1742 PAD (width - realsz, blanks);
1743
1744 /* finally, adjust ret */
1745 ret += width > realsz ? width : realsz;
1746
1747 FLUSH (); /* copy out the I/O vectors */
1748
1749 if (malloc_buf != NULL) {
1750 free (malloc_buf);
1751 malloc_buf = NULL;
1752 }
1753 }
1754 done:
1755 FLUSH ();
1756 error:
1757 if (malloc_buf != NULL)
1758 free (malloc_buf);
1759 #ifndef STRING_ONLY
1760 _newlib_flockfile_end (fp);
1761 #endif
1762 return (__sferror (fp) ? EOF : ret);
1763 /* NOTREACHED */
1764 }
1765
1766 #ifdef FLOATING_POINT
1767
1768 /* Using reentrant DATA, convert finite VALUE into a string of digits
1769 with no decimal point, using NDIGITS precision and FLAGS as guides
1770 to whether trailing zeros must be included. Set *SIGN to nonzero
1771 if VALUE was negative. Set *DECPT to the exponent plus one. Set
1772 *LENGTH to the length of the returned string. CH must be one of
1773 [aAeEfFgG]; if it is [aA], then the return string lives in BUF,
1774 otherwise the return value shares the mprec reentrant storage. */
1775 static char *
1776 cvt(_PRINTF_FLOAT_TYPE value, int ndigits, int flags,
1777 char *sign, int *decpt, int ch, int *length, char *buf)
1778 {
1779 int mode, dsgn;
1780 char *digits, *bp, *rve;
1781 # ifdef _NO_LONGDBL
1782 union double_union tmp;
1783
1784 tmp.d = value;
1785 if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1786 value = -value;
1787 *sign = '-';
1788 } else
1789 *sign = '\000';
1790 # else /* !_NO_LONGDBL */
1791 union
1792 {
1793 struct ldieee ieee;
1794 _LONG_DOUBLE val;
1795 } ld;
1796
1797 ld.val = value;
1798 if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
1799 value = -value;
1800 *sign = '-';
1801 } else
1802 *sign = '\000';
1803 # endif /* !_NO_LONGDBL */
1804
1805 # ifdef _WANT_IO_C99_FORMATS
1806 if (ch == 'a' || ch == 'A') {
1807 /* This code assumes FLT_RADIX is a power of 2. The initial
1808 division ensures the digit before the decimal will be less
1809 than FLT_RADIX (unless it is rounded later). There is no
1810 loss of precision in these calculations. */
1811 value = FREXP (value, decpt) / 8;
1812 if (!value)
1813 *decpt = 1;
1814 digits = ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF";
1815 bp = buf;
1816 do {
1817 value *= 16;
1818 mode = (int) value;
1819 value -= mode;
1820 *bp++ = digits[mode];
1821 } while (ndigits-- && value);
1822 if (value > (_PRINTF_FLOAT_TYPE) 0.5 || (value == (_PRINTF_FLOAT_TYPE) 0.5 && mode & 1)) {
1823 /* round to even */
1824 rve = bp;
1825 while (*--rve == digits[0xf]) {
1826 *rve = '0';
1827 }
1828 *rve = *rve == '9' ? digits[0xa] : *rve + 1;
1829 } else {
1830 while (ndigits-- >= 0) {
1831 *bp++ = '0';
1832 }
1833 }
1834 *length = bp - buf;
1835 return buf;
1836 }
1837 # endif /* _WANT_IO_C99_FORMATS */
1838 if (ch == 'f' || ch == 'F') {
1839 mode = 3; /* ndigits after the decimal point */
1840 } else {
1841 /* To obtain ndigits after the decimal point for the 'e'
1842 * and 'E' formats, round to ndigits + 1 significant
1843 * figures.
1844 */
1845 if (ch == 'e' || ch == 'E') {
1846 ndigits++;
1847 }
1848 mode = 2; /* ndigits significant digits */
1849 }
1850
1851 digits = _DTOA (value, mode, ndigits, decpt, &dsgn, &rve);
1852 if (!digits)
1853 return NULL;
1854
1855 if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */
1856 bp = digits + ndigits;
1857 if (ch == 'f' || ch == 'F') {
1858 if (*digits == '0' && value)
1859 *decpt = -ndigits + 1;
1860 bp += *decpt;
1861 }
1862 if (value == 0) /* kludge for __dtoa irregularity */
1863 rve = bp;
1864 while (rve < bp)
1865 *rve++ = '0';
1866 }
1867 *length = rve - digits;
1868 return (digits);
1869 }
1870
1871 static int
1872 exponent(char *p0, int exp, int fmtch)
1873 {
1874 register char *p, *t;
1875 char expbuf[MAXEXPLEN];
1876 # ifdef _WANT_IO_C99_FORMATS
1877 int isa = fmtch == 'a' || fmtch == 'A';
1878 # else
1879 # define isa 0
1880 # endif
1881
1882 p = p0;
1883 *p++ = isa ? 'p' - 'a' + fmtch : fmtch;
1884 if (exp < 0) {
1885 exp = -exp;
1886 *p++ = '-';
1887 }
1888 else
1889 *p++ = '+';
1890 t = expbuf + MAXEXPLEN;
1891 if (exp > 9) {
1892 do {
1893 *--t = to_char (exp % 10);
1894 } while ((exp /= 10) > 9);
1895 *--t = to_char (exp);
1896 for (; t < expbuf + MAXEXPLEN; *p++ = *t++);
1897 }
1898 else {
1899 if (!isa)
1900 *p++ = '0';
1901 *p++ = to_char (exp);
1902 }
1903 return (p - p0);
1904 }
1905 #endif /* FLOATING_POINT */
1906
1907
1908 #ifndef _NO_POS_ARGS
1909
1910 /* Positional argument support.
1911 Written by Jeff Johnston
1912
1913 Copyright (c) 2002 Red Hat Incorporated.
1914 All rights reserved.
1915
1916 Redistribution and use in source and binary forms, with or without
1917 modification, are permitted provided that the following conditions are met:
1918
1919 Redistributions of source code must retain the above copyright
1920 notice, this list of conditions and the following disclaimer.
1921
1922 Redistributions in binary form must reproduce the above copyright
1923 notice, this list of conditions and the following disclaimer in the
1924 documentation and/or other materials provided with the distribution.
1925
1926 The name of Red Hat Incorporated may not be used to endorse
1927 or promote products derived from this software without specific
1928 prior written permission.
1929
1930 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1931 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1932 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1933 DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1934 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1935 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1936 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1937 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1938 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1939 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1940
1941 /* The below constant state tables are shared between all versions of
1942 vfprintf and vfwprintf. They must only be defined once, which we do in
1943 the STRING_ONLY/INTEGER_ONLY versions here. */
1944 #if defined (STRING_ONLY) && defined(INTEGER_ONLY)
1945
1946 const __CH_CLASS __chclass[256] = {
1947 /* 00-07 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1948 /* 08-0f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1949 /* 10-17 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1950 /* 18-1f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1951 /* 20-27 */ FLAG, OTHER, OTHER, FLAG, DOLLAR, OTHER, OTHER, FLAG,
1952 /* 28-2f */ OTHER, OTHER, STAR, FLAG, OTHER, FLAG, DOT, OTHER,
1953 /* 30-37 */ ZERO, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
1954 /* 38-3f */ DIGIT, DIGIT, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1955 /* 40-47 */ OTHER, SPEC, OTHER, SPEC, SPEC, SPEC, SPEC, SPEC,
1956 /* 48-4f */ OTHER, OTHER, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC,
1957 /* 50-57 */ OTHER, OTHER, OTHER, SPEC, OTHER, SPEC, OTHER, OTHER,
1958 /* 58-5f */ SPEC, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1959 /* 60-67 */ OTHER, SPEC, OTHER, SPEC, SPEC, SPEC, SPEC, SPEC,
1960 /* 68-6f */ MODFR, SPEC, MODFR, OTHER, MODFR, OTHER, SPEC, SPEC,
1961 /* 70-77 */ SPEC, MODFR, OTHER, SPEC, MODFR, SPEC, OTHER, OTHER,
1962 /* 78-7f */ SPEC, OTHER, MODFR, OTHER, OTHER, OTHER, OTHER, OTHER,
1963 /* 80-87 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1964 /* 88-8f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1965 /* 90-97 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1966 /* 98-9f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1967 /* a0-a7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1968 /* a8-af */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1969 /* b0-b7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1970 /* b8-bf */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1971 /* c0-c7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1972 /* c8-cf */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1973 /* d0-d7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1974 /* d8-df */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1975 /* e0-e7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1976 /* e8-ef */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1977 /* f0-f7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1978 /* f8-ff */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,
1979 };
1980
1981 const __STATE __state_table[MAX_STATE][MAX_CH_CLASS] = {
1982 /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
1983 /* START */ { SFLAG, WDIG, DONE, SMOD, DONE, SDOT, VARW, SFLAG, DONE },
1984 /* SFLAG */ { SFLAG, WDIG, DONE, SMOD, DONE, SDOT, VARW, SFLAG, DONE },
1985 /* WDIG */ { DONE, DONE, WIDTH, SMOD, DONE, SDOT, DONE, DONE, DONE },
1986 /* WIDTH */ { DONE, DONE, DONE, SMOD, DONE, SDOT, DONE, DONE, DONE },
1987 /* SMOD */ { DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE },
1988 /* SDOT */ { SDOT, PREC, DONE, SMOD, DONE, DONE, VARP, DONE, DONE },
1989 /* VARW */ { DONE, VWDIG, DONE, SMOD, DONE, SDOT, DONE, DONE, DONE },
1990 /* VARP */ { DONE, VPDIG, DONE, SMOD, DONE, DONE, DONE, DONE, DONE },
1991 /* PREC */ { DONE, DONE, DONE, SMOD, DONE, DONE, DONE, DONE, DONE },
1992 /* VWDIG */ { DONE, DONE, WIDTH, DONE, DONE, DONE, DONE, DONE, DONE },
1993 /* VPDIG */ { DONE, DONE, PREC, DONE, DONE, DONE, DONE, DONE, DONE },
1994 };
1995
1996 const __ACTION __action_table[MAX_STATE][MAX_CH_CLASS] = {
1997 /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */
1998 /* START */ { NOOP, NUMBER, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
1999 /* SFLAG */ { NOOP, NUMBER, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
2000 /* WDIG */ { NOOP, NOOP, GETPOS, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
2001 /* WIDTH */ { NOOP, NOOP, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
2002 /* SMOD */ { NOOP, NOOP, NOOP, NOOP, GETARG, NOOP, NOOP, NOOP, NOOP },
2003 /* SDOT */ { NOOP, SKIPNUM, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
2004 /* VARW */ { NOOP, NUMBER, NOOP, GETPW, GETPWB, GETPW, NOOP, NOOP, NOOP },
2005 /* VARP */ { NOOP, NUMBER, NOOP, GETPW, GETPWB, NOOP, NOOP, NOOP, NOOP },
2006 /* PREC */ { NOOP, NOOP, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP },
2007 /* VWDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP },
2008 /* VPDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP },
2009 };
2010
2011 #endif /* STRING_ONLY && INTEGER_ONLY */
2012
2013 /* function to get positional parameter N where n = N - 1 */
2014 static union arg_val *
2015 get_arg (struct _reent *data,
2016 int n,
2017 char *fmt,
2018 va_list *ap,
2019 int *numargs_p,
2020 union arg_val *args,
2021 int *arg_type,
2022 char **last_fmt)
2023 {
2024 int ch;
2025 int number, flags;
2026 int spec_type;
2027 int numargs = *numargs_p;
2028 __CH_CLASS chtype;
2029 __STATE state, next_state;
2030 __ACTION action;
2031 int pos, last_arg;
2032 int max_pos_arg = n;
2033 /* Only need types that can be reached via vararg promotions. */
2034 enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
2035 # ifdef _MB_CAPABLE
2036 wchar_t wc;
2037 mbstate_t wc_state;
2038 int nbytes;
2039 # endif
2040
2041 /* if this isn't the first call, pick up where we left off last time */
2042 if (*last_fmt != NULL)
2043 fmt = *last_fmt;
2044
2045 # ifdef _MB_CAPABLE
2046 memset (&wc_state, '\0', sizeof (wc_state));
2047 # endif
2048
2049 /* we need to process either to end of fmt string or until we have actually
2050 read the desired parameter from the vararg list. */
2051 while (*fmt && n >= numargs)
2052 {
2053 # ifdef _MB_CAPABLE
2054 while ((nbytes = __MBTOWC (data, &wc, fmt, MB_CUR_MAX, &wc_state)) > 0)
2055 {
2056 fmt += nbytes;
2057 if (wc == '%')
2058 break;
2059 }
2060
2061 if (nbytes <= 0)
2062 break;
2063 # else
2064 while (*fmt != '\0' && *fmt != '%')
2065 fmt += 1;
2066
2067 if (*fmt == '\0')
2068 break;
2069
2070 fmt++;
2071 # endif /* ! _MB_CAPABLE */
2072 state = START;
2073 flags = 0;
2074 pos = -1;
2075 number = 0;
2076 spec_type = INT;
2077
2078 /* Use state/action table to process format specifiers. We ignore invalid
2079 formats and we are only interested in information that tells us how to
2080 read the vararg list. */
2081 while (state != DONE)
2082 {
2083 ch = *fmt++;
2084 chtype = __chclass[ch];
2085 next_state = __state_table[state][chtype];
2086 action = __action_table[state][chtype];
2087 state = next_state;
2088
2089 switch (action)
2090 {
2091 case GETMOD: /* we have format modifier */
2092 switch (ch)
2093 {
2094 case 'h':
2095 /* No flag needed, since short and char promote to int. */
2096 break;
2097 case 'L':
2098 flags |= LONGDBL;
2099 break;
2100 case 'q':
2101 flags |= QUADINT;
2102 break;
2103 # ifdef _WANT_IO_C99_FORMATS
2104 case 'j':
2105 if (sizeof (intmax_t) == sizeof (long))
2106 flags |= LONGINT;
2107 else
2108 flags |= QUADINT;
2109 break;
2110 case 'z':
2111 if (sizeof (size_t) <= sizeof (int))
2112 /* no flag needed */;
2113 else if (sizeof (size_t) <= sizeof (long))
2114 flags |= LONGINT;
2115 else
2116 /* POSIX states that at least one programming
2117 environment must support size_t no wider than
2118 long, but that means other environments can
2119 have size_t as wide as long long. */
2120 flags |= QUADINT;
2121 break;
2122 case 't':
2123 if (sizeof (ptrdiff_t) <= sizeof (int))
2124 /* no flag needed */;
2125 else if (sizeof (ptrdiff_t) <= sizeof (long))
2126 flags |= LONGINT;
2127 else
2128 /* POSIX states that at least one programming
2129 environment must support ptrdiff_t no wider than
2130 long, but that means other environments can
2131 have ptrdiff_t as wide as long long. */
2132 flags |= QUADINT;
2133 break;
2134 # endif /* _WANT_IO_C99_FORMATS */
2135 case 'l':
2136 default:
2137 # if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
2138 if (*fmt == 'l')
2139 {
2140 flags |= QUADINT;
2141 ++fmt;
2142 }
2143 else
2144 # endif
2145 flags |= LONGINT;
2146 break;
2147 }
2148 break;
2149 case GETARG: /* we have format specifier */
2150 {
2151 numargs &= (MAX_POS_ARGS - 1);
2152 /* process the specifier and translate it to a type to fetch from varargs */
2153 switch (ch)
2154 {
2155 case 'd':
2156 case 'i':
2157 case 'o':
2158 case 'x':
2159 case 'X':
2160 case 'u':
2161 if (flags & LONGINT)
2162 spec_type = LONG_INT;
2163 # ifndef _NO_LONGLONG
2164 else if (flags & QUADINT)
2165 spec_type = QUAD_INT;
2166 # endif
2167 else
2168 spec_type = INT;
2169 break;
2170 case 'D':
2171 case 'U':
2172 case 'O':
2173 spec_type = LONG_INT;
2174 break;
2175 # ifdef _WANT_IO_C99_FORMATS
2176 case 'a':
2177 case 'A':
2178 case 'F':
2179 # endif
2180 case 'f':
2181 case 'g':
2182 case 'G':
2183 case 'E':
2184 case 'e':
2185 # ifndef _NO_LONGDBL
2186 if (flags & LONGDBL)
2187 spec_type = LONG_DOUBLE;
2188 else
2189 # endif
2190 spec_type = DOUBLE;
2191 break;
2192 case 's':
2193 # ifdef _WANT_IO_C99_FORMATS
2194 case 'S':
2195 # endif
2196 case 'p':
2197 case 'n':
2198 spec_type = CHAR_PTR;
2199 break;
2200 case 'c':
2201 # ifdef _WANT_IO_C99_FORMATS
2202 if (flags & LONGINT)
2203 spec_type = WIDE_CHAR;
2204 else
2205 # endif
2206 spec_type = INT;
2207 break;
2208 # ifdef _WANT_IO_C99_FORMATS
2209 case 'C':
2210 spec_type = WIDE_CHAR;
2211 break;
2212 # endif
2213 }
2214
2215 /* if we have a positional parameter, just store the type, otherwise
2216 fetch the parameter from the vararg list */
2217 if (pos != -1)
2218 arg_type[pos] = spec_type;
2219 else
2220 {
2221 switch (spec_type)
2222 {
2223 case LONG_INT:
2224 args[numargs++].val_long = va_arg (*ap, long);
2225 break;
2226 case QUAD_INT:
2227 args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2228 break;
2229 case WIDE_CHAR:
2230 args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2231 break;
2232 case INT:
2233 args[numargs++].val_int = va_arg (*ap, int);
2234 break;
2235 case CHAR_PTR:
2236 args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2237 break;
2238 case DOUBLE:
2239 args[numargs++].val_double = va_arg (*ap, double);
2240 break;
2241 case LONG_DOUBLE:
2242 args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2243 break;
2244 }
2245 }
2246 }
2247 break;
2248 case GETPOS: /* we have positional specifier */
2249 if (arg_type[0] == -1)
2250 memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2251 pos = number - 1;
2252 max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos);
2253 break;
2254 case PWPOS: /* we have positional specifier for width or precision */
2255 if (arg_type[0] == -1)
2256 memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
2257 number -= 1;
2258 arg_type[number] = INT;
2259 max_pos_arg = (max_pos_arg > number ? max_pos_arg : number);
2260 break;
2261 case GETPWB: /* we require format pushback */
2262 --fmt;
2263 FALLTHROUGH;
2264 case GETPW: /* we have a variable precision or width to acquire */
2265 args[numargs++].val_int = va_arg (*ap, int);
2266 break;
2267 case NUMBER: /* we have a number to process */
2268 number = (ch - '0');
2269 while ((ch = *fmt) != '\0' && is_digit (ch))
2270 {
2271 number = number * 10 + (ch - '0');
2272 ++fmt;
2273 }
2274 break;
2275 case SKIPNUM: /* we have a number to skip */
2276 while ((ch = *fmt) != '\0' && is_digit (ch))
2277 ++fmt;
2278 break;
2279 case NOOP:
2280 default:
2281 break; /* do nothing */
2282 }
2283 }
2284 }
2285
2286 /* process all arguments up to at least the one we are looking for and if we
2287 have seen the end of the string, then process up to the max argument needed */
2288 if (*fmt == '\0')
2289 last_arg = max_pos_arg;
2290 else
2291 last_arg = n;
2292
2293 while (numargs <= last_arg)
2294 {
2295 switch (arg_type[numargs])
2296 {
2297 case LONG_INT:
2298 args[numargs++].val_long = va_arg (*ap, long);
2299 break;
2300 case QUAD_INT:
2301 args[numargs++].val_quad_t = va_arg (*ap, quad_t);
2302 break;
2303 case CHAR_PTR:
2304 args[numargs++].val_char_ptr_t = va_arg (*ap, char *);
2305 break;
2306 case DOUBLE:
2307 args[numargs++].val_double = va_arg (*ap, double);
2308 break;
2309 case LONG_DOUBLE:
2310 args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2311 break;
2312 case WIDE_CHAR:
2313 args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2314 break;
2315 case INT:
2316 default:
2317 args[numargs++].val_int = va_arg (*ap, int);
2318 break;
2319 }
2320 }
2321
2322 /* alter the global numargs value and keep a reference to the last bit of the fmt
2323 string we processed here because the caller will continue processing where we started */
2324 *numargs_p = numargs;
2325 *last_fmt = fmt;
2326 return &args[n];
2327 }
2328 #endif /* !_NO_POS_ARGS */
2329