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