Cygwin: mmap: allow remapping part of an existing anonymous mapping
[newlib-cygwin.git] / newlib / libc / stdio / vfwprintf.c
blob5a5c368298d2ca3f6944edd394614d652e7fe84d
1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
34 FUNCTION
35 <<vfwprintf>>, <<vwprintf>>, <<vswprintf>>---wide character format argument list
37 INDEX
38 vfwprintf
39 INDEX
40 _vfwprintf_r
41 INDEX
42 vwprintf
43 INDEX
44 _vwprintf_r
45 INDEX
46 vswprintf
47 INDEX
48 _vswprintf_r
50 SYNOPSIS
51 #include <stdio.h>
52 #include <stdarg.h>
53 #include <wchar.h>
54 int vwprintf(const wchar_t *__restrict <[fmt]>, va_list <[list]>);
55 int vfwprintf(FILE *__restrict <[fp]>,
56 const wchar_t *__restrict <[fmt]>, va_list <[list]>);
57 int vswprintf(wchar_t * __restrict <[str]>, size_t <[size]>,
58 const wchar_t *__ restrict <[fmt]>, va_list <[list]>);
60 int _vwprintf_r(struct _reent *<[reent]>, const wchar_t *<[fmt]>,
61 va_list <[list]>);
62 int _vfwprintf_r(struct _reent *<[reent]>, FILE *<[fp]>,
63 const wchar_t *<[fmt]>, va_list <[list]>);
64 int _vswprintf_r(struct _reent *<[reent]>, wchar_t *<[str]>,
65 size_t <[size]>, const wchar_t *<[fmt]>, va_list <[list]>);
67 DESCRIPTION
68 <<vwprintf>>, <<vfwprintf>> and <<vswprintf>> are (respectively) variants
69 of <<wprintf>>, <<fwprintf>> and <<swprintf>>. They differ only in allowing
70 their caller to pass the variable argument list as a <<va_list>> object
71 (initialized by <<va_start>>) rather than directly accepting a variable
72 number of arguments. The caller is responsible for calling <<va_end>>.
74 <<_vwprintf_r>>, <<_vfwprintf_r>> and <<_vswprintf_r>> are reentrant
75 versions of the above.
77 RETURNS
78 The return values are consistent with the corresponding functions.
80 PORTABILITY
81 POSIX-1.2008 with extensions; C99 (compliant except for POSIX extensions).
83 Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
84 <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
86 SEEALSO
87 <<wprintf>>, <<fwprintf>> and <<swprintf>>.
91 * Actual wprintf innards.
93 * This code is large and complicated...
95 #include <newlib.h>
97 #ifdef INTEGER_ONLY
98 # define VFWPRINTF vfiwprintf
99 # ifdef STRING_ONLY
100 # define _VFWPRINTF_R _svfiwprintf_r
101 # else
102 # define _VFWPRINTF_R _vfiwprintf_r
103 # endif
104 #else
105 # define VFWPRINTF vfwprintf
106 # ifdef STRING_ONLY
107 # define _VFWPRINTF_R _svfwprintf_r
108 # else
109 # define _VFWPRINTF_R _vfwprintf_r
110 # endif
111 # ifndef NO_FLOATING_POINT
112 # define FLOATING_POINT
113 # endif
114 #endif
116 #define _NO_POS_ARGS
117 #ifdef _WANT_IO_POS_ARGS
118 # undef _NO_POS_ARGS
119 #endif
121 #include <_ansi.h>
122 #include <reent.h>
123 #include <stdio.h>
124 #include <stdlib.h>
125 #include <string.h>
126 #include <limits.h>
127 #include <stdint.h>
128 #include <wchar.h>
129 #include <sys/lock.h>
130 #include <stdarg.h>
131 #include "local.h"
132 #include "fvwrite.h"
133 #include "vfieeefp.h"
134 #ifdef __HAVE_LOCALE_INFO_EXTENDED__
135 #include "../locale/setlocale.h"
136 #endif
138 /* Currently a test is made to see if long double processing is warranted.
139 This could be changed in the future should the _ldtoa_r code be
140 preferred over _dtoa_r. */
141 #define _NO_LONGDBL
142 #if defined _WANT_IO_LONG_DOUBLE && (LDBL_MANT_DIG > DBL_MANT_DIG)
143 #undef _NO_LONGDBL
144 #endif
146 #define _NO_LONGLONG
147 #if defined _WANT_IO_LONG_LONG \
148 && (defined __GNUC__ || __STDC_VERSION__ >= 199901L)
149 # undef _NO_LONGLONG
150 #endif
152 int _VFWPRINTF_R (struct _reent *, FILE *, const wchar_t *, va_list);
153 /* Defined in vfprintf.c. */
154 #ifdef _FVWRITE_IN_STREAMIO
155 # ifdef STRING_ONLY
156 # define __SPRINT __sswprint_r
157 # else
158 # define __SPRINT __swprint_r
159 # endif
160 int __SPRINT (struct _reent *, FILE *, register struct __suio *);
161 #else
162 # ifdef STRING_ONLY
163 # define __SPRINT __ssputws_r
164 # else
165 # define __SPRINT __sfputws_r
166 # endif
167 int __SPRINT (struct _reent *, FILE *, const wchar_t *, size_t);
168 #endif
169 #ifndef STRING_ONLY
170 #ifdef _UNBUF_STREAM_OPT
172 * Helper function for `fprintf to unbuffered unix file': creates a
173 * temporary buffer. We only work on write-only files; this avoids
174 * worries about ungetc buffers and so forth.
176 static int
177 __sbwprintf (struct _reent *rptr,
178 register FILE *fp,
179 const wchar_t *fmt,
180 va_list ap)
182 int ret;
183 FILE fake;
184 unsigned char buf[BUFSIZ];
186 /* copy the important variables */
187 fake._flags = fp->_flags & ~__SNBF;
188 fake._flags2 = fp->_flags2;
189 fake._file = fp->_file;
190 fake._cookie = fp->_cookie;
191 fake._write = fp->_write;
193 /* set up the buffer */
194 fake._bf._base = fake._p = buf;
195 fake._bf._size = fake._w = sizeof (buf);
196 fake._lbfsize = 0; /* not actually used, but Just In Case */
197 #ifndef __SINGLE_THREAD__
198 __lock_init_recursive (fake._lock);
199 #endif
201 /* do the work, then copy any error status */
202 ret = _VFWPRINTF_R (rptr, &fake, fmt, ap);
203 if (ret >= 0 && _fflush_r (rptr, &fake))
204 ret = EOF;
205 if (fake._flags & __SERR)
206 fp->_flags |= __SERR;
208 #ifndef __SINGLE_THREAD__
209 __lock_close_recursive (fake._lock);
210 #endif
211 return (ret);
213 #endif /* _UNBUF_STREAM_OPT */
214 #endif /* !STRING_ONLY */
217 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
218 # include <locale.h>
219 #endif
220 #ifdef FLOATING_POINT
221 # include <math.h>
223 /* For %La, an exponent of 15 bits occupies the exponent character, a
224 sign, and up to 5 digits. */
225 # define MAXEXPLEN 7
226 # define DEFPREC 6
228 # ifdef _NO_LONGDBL
230 extern char *_dtoa_r (struct _reent *, double, int,
231 int, int *, int *, char **);
233 # define _PRINTF_FLOAT_TYPE double
234 # define _DTOA_R _dtoa_r
235 # define FREXP frexp
237 # else /* !_NO_LONGDBL */
239 extern char *_ldtoa_r (struct _reent *, _LONG_DOUBLE, int,
240 int, int *, int *, char **);
242 extern int _ldcheck (_LONG_DOUBLE *);
244 # define _PRINTF_FLOAT_TYPE _LONG_DOUBLE
245 # define _DTOA_R _ldtoa_r
246 # define FREXP frexpl
247 # endif /* !_NO_LONGDBL */
249 static wchar_t *wcvt(struct _reent *, _PRINTF_FLOAT_TYPE, int, int, wchar_t *,
250 int *, int, int *, wchar_t *, int);
252 static int wexponent(wchar_t *, int, int);
254 #endif /* FLOATING_POINT */
256 /* BUF must be big enough for the maximum %#llo (assuming long long is
257 at most 64 bits, this would be 23 characters), the maximum
258 multibyte character %C, and the maximum default precision of %La
259 (assuming long double is at most 128 bits with 113 bits of
260 mantissa, this would be 29 characters). %e, %f, and %g use
261 reentrant storage shared with mprec. All other formats that use
262 buf get by with fewer characters. Making BUF slightly bigger
263 reduces the need for malloc in %.*a and %ls/%S, when large precision or
264 long strings are processed.
265 The bigger size of 100 bytes is used on systems which allow number
266 strings using the locale's grouping character. Since that's a multibyte
267 value, we should use a conservative value.
269 #ifdef _WANT_IO_C99_FORMATS
270 #define BUF 100
271 #else
272 #define BUF 40
273 #endif
274 #if defined _MB_CAPABLE && MB_LEN_MAX > BUF
275 # undef BUF
276 # define BUF MB_LEN_MAX
277 #endif
279 #ifndef _NO_LONGLONG
280 # define quad_t long long
281 # define u_quad_t unsigned long long
282 #else
283 # define quad_t long
284 # define u_quad_t unsigned long
285 #endif
287 typedef quad_t * quad_ptr_t;
288 typedef void *void_ptr_t;
289 typedef char * char_ptr_t;
290 typedef wchar_t* wchar_ptr_t;
291 typedef long * long_ptr_t;
292 typedef int * int_ptr_t;
293 typedef short * short_ptr_t;
295 #ifndef _NO_POS_ARGS
296 # ifdef NL_ARGMAX
297 # define MAX_POS_ARGS NL_ARGMAX
298 # else
299 # define MAX_POS_ARGS 32
300 # endif
302 union arg_val
304 int val_int;
305 u_int val_u_int;
306 long val_long;
307 u_long val_u_long;
308 float val_float;
309 double val_double;
310 _LONG_DOUBLE val__LONG_DOUBLE;
311 int_ptr_t val_int_ptr_t;
312 short_ptr_t val_short_ptr_t;
313 long_ptr_t val_long_ptr_t;
314 char_ptr_t val_char_ptr_t;
315 wchar_ptr_t val_wchar_ptr_t;
316 quad_ptr_t val_quad_ptr_t;
317 void_ptr_t val_void_ptr_t;
318 quad_t val_quad_t;
319 u_quad_t val_u_quad_t;
320 wint_t val_wint_t;
323 static union arg_val *
324 get_arg (struct _reent *data, int n, wchar_t *fmt,
325 va_list *ap, int *numargs, union arg_val *args,
326 int *arg_type, wchar_t **last_fmt);
327 #endif /* !_NO_POS_ARGS */
330 * Macros for converting digits to letters and vice versa
332 #define to_digit(c) ((c) - L'0')
333 #define is_digit(c) ((unsigned)to_digit (c) <= 9)
334 #define to_char(n) ((n) + L'0')
337 * Flags used during conversion.
339 #define ALT 0x001 /* alternate form */
340 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
341 #define LADJUST 0x004 /* left adjustment */
342 #define LONGDBL 0x008 /* long double */
343 #define LONGINT 0x010 /* long integer */
344 #ifndef _NO_LONGLONG
345 # define QUADINT 0x020 /* quad integer */
346 #else /* ifdef _NO_LONGLONG, make QUADINT equivalent to LONGINT, so
347 that %lld behaves the same as %ld, not as %d, as expected if:
348 sizeof (long long) = sizeof long > sizeof int */
349 # define QUADINT LONGINT
350 #endif
351 #define SHORTINT 0x040 /* short integer */
352 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
353 #define FPT 0x100 /* Floating point number */
354 #ifdef _WANT_IO_C99_FORMATS
355 # define CHARINT 0x200 /* char as integer */
356 #else /* define as 0, to make SARG and UARG occupy fewer instructions */
357 # define CHARINT 0
358 #endif
359 #ifdef _WANT_IO_C99_FORMATS
360 # define GROUPING 0x400 /* use grouping ("'" flag) */
361 #endif
363 #ifndef STRING_ONLY
365 VFWPRINTF (FILE *__restrict fp,
366 const wchar_t *__restrict fmt0,
367 va_list ap)
369 int result;
370 result = _VFWPRINTF_R (_REENT, fp, fmt0, ap);
371 return result;
373 #endif /* STRING_ONLY */
376 _VFWPRINTF_R (struct _reent *data,
377 FILE * fp,
378 const wchar_t *fmt0,
379 va_list ap)
381 register wchar_t *fmt; /* format string */
382 register wint_t ch; /* character from fmt */
383 register int n, m; /* handy integers (short term usage) */
384 register wchar_t *cp; /* handy char pointer (short term usage) */
385 register int flags; /* flags as above */
386 wchar_t *fmt_anchor; /* current format spec being processed */
387 #ifndef _NO_POS_ARGS
388 int N; /* arg number */
389 int arg_index; /* index into args processed directly */
390 int numargs; /* number of varargs read */
391 wchar_t *saved_fmt; /* saved fmt pointer */
392 union arg_val args[MAX_POS_ARGS];
393 int arg_type[MAX_POS_ARGS];
394 int is_pos_arg; /* is current format positional? */
395 int old_is_pos_arg; /* is current format positional? */
396 #endif
397 int ret; /* return value accumulator */
398 int width; /* width from format (%8d), or 0 */
399 int prec; /* precision from format (%.3d), or -1 */
400 wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */
401 #ifdef _WANT_IO_C99_FORMATS
402 /* locale specific numeric grouping */
403 wchar_t thousands_sep = L'\0';
404 const char *grouping = NULL;
405 #endif
406 #if defined (_MB_CAPABLE) && !defined (__HAVE_LOCALE_INFO_EXTENDED__) \
407 && (defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS))
408 mbstate_t state; /* mbtowc calls from library must not change state */
409 #endif
410 #ifdef FLOATING_POINT
411 wchar_t decimal_point;
412 wchar_t softsign; /* temporary negative sign for floats */
413 union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
414 # define _fpvalue (_double_.fp)
415 int expt; /* integer value of exponent */
416 int expsize = 0; /* character count for expstr */
417 wchar_t expstr[MAXEXPLEN]; /* buffer for exponent string */
418 int lead; /* sig figs before decimal or group sep */
419 #endif /* FLOATING_POINT */
420 #if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
421 int ndig = 0; /* actual number of digits returned by cvt */
422 #endif
423 #if defined (FLOATING_POINT) && defined (_WANT_IO_C99_FORMATS)
424 int nseps; /* number of group separators with ' */
425 int nrepeats; /* number of repeats of the last group */
426 #endif
427 u_quad_t _uquad; /* integer arguments %[diouxX] */
428 enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
429 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
430 int realsz; /* field size expanded by dprec */
431 int size = 0; /* size of converted field or string */
432 wchar_t *xdigs = NULL; /* digits for [xX] conversion */
433 #ifdef _FVWRITE_IN_STREAMIO
434 #define NIOV 8
435 struct __suio uio; /* output information: summary */
436 struct __siov iov[NIOV];/* ... and individual io vectors */
437 register struct __siov *iovp;/* for PRINT macro */
438 #endif
439 wchar_t buf[BUF]; /* space for %c, %ls/%S, %[diouxX], %[aA] */
440 wchar_t ox[2]; /* space for 0x hex-prefix */
441 wchar_t *malloc_buf = NULL;/* handy pointer for malloced buffers */
444 * Choose PADSIZE to trade efficiency vs. size. If larger printf
445 * fields occur frequently, increase PADSIZE and make the initialisers
446 * below longer.
448 #define PADSIZE 16 /* pad chunk size */
449 static const wchar_t blanks[PADSIZE] =
450 {L' ',L' ',L' ',L' ',L' ',L' ',L' ',L' ',
451 L' ',L' ',L' ',L' ',L' ',L' ',L' ',L' '};
452 static const wchar_t zeroes[PADSIZE] =
453 {L'0',L'0',L'0',L'0',L'0',L'0',L'0',L'0',
454 L'0',L'0',L'0',L'0',L'0',L'0',L'0',L'0'};
456 #ifdef FLOATING_POINT
457 #ifdef _MB_CAPABLE
458 #ifdef __HAVE_LOCALE_INFO_EXTENDED__
459 decimal_point = *__get_current_numeric_locale ()->wdecimal_point;
460 #else
462 size_t nconv;
464 memset (&state, '\0', sizeof (state));
465 nconv = _mbrtowc_r (data, &decimal_point,
466 _localeconv_r (data)->decimal_point,
467 MB_CUR_MAX, &state);
468 if (nconv == (size_t) -1 || nconv == (size_t) -2)
469 decimal_point = L'.';
471 #endif
472 #else
473 decimal_point = (wchar_t) *_localeconv_r (data)->decimal_point;
474 #endif
475 #endif
477 * BEWARE, these `goto error' on error, and PAD uses `n'.
479 #ifdef _FVWRITE_IN_STREAMIO
480 #define PRINT(ptr, len) { \
481 iovp->iov_base = (char *) (ptr); \
482 iovp->iov_len = (len); \
483 uio.uio_resid += iovp->iov_len; \
484 iovp++; \
485 if (++uio.uio_iovcnt >= NIOV) { \
486 if (__SPRINT(data, fp, &uio)) \
487 goto error; \
488 iovp = iov; \
491 #define PAD(howmany, with) { \
492 if ((n = (howmany)) > 0) { \
493 while (n > PADSIZE) { \
494 PRINT (with, PADSIZE); \
495 n -= PADSIZE; \
497 PRINT (with, n); \
500 #define PRINTANDPAD(p, ep, len, with) { \
501 int n = (ep) - (p); \
502 if (n > (len)) \
503 n = (len); \
504 if (n > 0) \
505 PRINT((p), n); \
506 PAD((len) - (n > 0 ? n : 0), (with)); \
508 #define FLUSH() { \
509 if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
510 goto error; \
511 uio.uio_iovcnt = 0; \
512 iovp = iov; \
514 #else
515 #define PRINT(ptr, len) { \
516 if (__SPRINT (data, fp, (ptr), (len)) == EOF) \
517 goto error; \
519 #define PAD(howmany, with) { \
520 if ((n = (howmany)) > 0) { \
521 while (n > PADSIZE) { \
522 PRINT (with, PADSIZE); \
523 n -= PADSIZE; \
525 PRINT (with, n); \
528 #define PRINTANDPAD(p, ep, len, with) { \
529 int n = (ep) - (p); \
530 if (n > (len)) \
531 n = (len); \
532 if (n > 0) \
533 PRINT((p), n); \
534 PAD((len) - (n > 0 ? n : 0), (with)); \
536 #define FLUSH()
537 #endif
539 /* Macros to support positional arguments */
540 #ifndef _NO_POS_ARGS
541 # define GET_ARG(n, ap, type) \
542 (is_pos_arg \
543 ? (n < numargs \
544 ? args[n].val_##type \
545 : get_arg (data, n, fmt_anchor, &ap, &numargs, args, \
546 arg_type, &saved_fmt)->val_##type) \
547 : (arg_index++ < numargs \
548 ? args[n].val_##type \
549 : (numargs < MAX_POS_ARGS \
550 ? args[numargs++].val_##type = va_arg (ap, type) \
551 : va_arg (ap, type))))
552 #else
553 # define GET_ARG(n, ap, type) (va_arg (ap, type))
554 #endif
557 * To extend shorts properly, we need both signed and unsigned
558 * argument extraction methods.
560 #ifndef _NO_LONGLONG
561 #define SARG() \
562 (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \
563 flags&LONGINT ? GET_ARG (N, ap, long) : \
564 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
565 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
566 (long)GET_ARG (N, ap, int))
567 #define UARG() \
568 (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \
569 flags&LONGINT ? GET_ARG (N, ap, u_long) : \
570 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
571 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
572 (u_long)GET_ARG (N, ap, u_int))
573 #else
574 #define SARG() \
575 (flags&LONGINT ? GET_ARG (N, ap, long) : \
576 flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \
577 flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \
578 (long)GET_ARG (N, ap, int))
579 #define UARG() \
580 (flags&LONGINT ? GET_ARG (N, ap, u_long) : \
581 flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \
582 flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \
583 (u_long)GET_ARG (N, ap, u_int))
584 #endif
586 #ifndef STRING_ONLY
587 /* Initialize std streams if not dealing with sprintf family. */
588 CHECK_INIT (data, fp);
589 _newlib_flockfile_start (fp);
591 if (ORIENT(fp, 1) != 1) {
592 _newlib_flockfile_exit (fp);
593 return (EOF);
596 /* sorry, fwprintf(read_only_file, "") returns EOF, not 0 */
597 if (cantwrite (data, fp)) {
598 _newlib_flockfile_exit (fp);
599 return (EOF);
602 #ifdef _UNBUF_STREAM_OPT
603 /* optimise fwprintf(stderr) (and other unbuffered Unix files) */
604 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
605 fp->_file >= 0) {
606 _newlib_flockfile_exit (fp);
607 return (__sbwprintf (data, fp, fmt0, ap));
609 #endif
610 #else /* STRING_ONLY */
611 /* Create initial buffer if we are called by asprintf family. */
612 if (fp->_flags & __SMBF && !fp->_bf._base)
614 fp->_bf._base = fp->_p = _malloc_r (data, 64);
615 if (!fp->_p)
617 _REENT_ERRNO(data) = ENOMEM;
618 return EOF;
620 fp->_bf._size = 64;
622 #endif /* STRING_ONLY */
624 fmt = (wchar_t *)fmt0;
625 #ifdef _FVWRITE_IN_STREAMIO
626 uio.uio_iov = iovp = iov;
627 uio.uio_resid = 0;
628 uio.uio_iovcnt = 0;
629 #endif
630 ret = 0;
631 #ifndef _NO_POS_ARGS
632 arg_index = 0;
633 saved_fmt = NULL;
634 arg_type[0] = -1;
635 numargs = 0;
636 is_pos_arg = 0;
637 #endif
640 * Scan the format for conversions (`%' character).
642 for (;;) {
643 cp = fmt;
644 while (*fmt != L'\0' && *fmt != L'%')
645 ++fmt;
646 if ((m = fmt - cp) != 0) {
647 PRINT (cp, m);
648 ret += m;
650 if (*fmt == L'\0')
651 goto done;
652 fmt_anchor = fmt;
653 fmt++; /* skip over '%' */
655 flags = 0;
656 dprec = 0;
657 width = 0;
658 prec = -1;
659 sign = L'\0';
660 #ifdef FLOATING_POINT
661 lead = 0;
662 #ifdef _WANT_IO_C99_FORMATS
663 nseps = nrepeats = 0;
664 #endif
665 #endif
666 #ifndef _NO_POS_ARGS
667 N = arg_index;
668 is_pos_arg = 0;
669 #endif
671 rflag: ch = *fmt++;
672 reswitch: switch (ch) {
673 #ifdef _WANT_IO_C99_FORMATS
674 case L'\'':
675 #ifdef _MB_CAPABLE
676 #ifdef __HAVE_LOCALE_INFO_EXTENDED__
677 thousands_sep = *__get_current_numeric_locale ()->wthousands_sep;
678 #else
680 size_t nconv;
682 memset (&state, '\0', sizeof (state));
683 nconv = _mbrtowc_r (data, &thousands_sep,
684 _localeconv_r (data)->thousands_sep,
685 MB_CUR_MAX, &state);
686 if (nconv == (size_t) -1 || nconv == (size_t) -2)
687 thousands_sep = L'\0';
689 #endif
690 #else
691 thousands_sep = (wchar_t) *_localeconv_r(data)->thousands_sep;
692 #endif
693 grouping = _localeconv_r (data)->grouping;
694 if (thousands_sep && grouping && *grouping)
695 flags |= GROUPING;
696 goto rflag;
697 #endif
698 case L' ':
700 * ``If the space and + flags both appear, the space
701 * flag will be ignored.''
702 * -- ANSI X3J11
704 if (!sign)
705 sign = L' ';
706 goto rflag;
707 case L'#':
708 flags |= ALT;
709 goto rflag;
710 case L'*':
711 #ifndef _NO_POS_ARGS
712 /* we must check for positional arg used for dynamic width */
713 n = N;
714 old_is_pos_arg = is_pos_arg;
715 is_pos_arg = 0;
716 if (is_digit (*fmt)) {
717 wchar_t *old_fmt = fmt;
719 n = 0;
720 ch = *fmt++;
721 do {
722 n = 10 * n + to_digit (ch);
723 ch = *fmt++;
724 } while (is_digit (ch));
726 if (ch == L'$') {
727 if (n <= MAX_POS_ARGS) {
728 n -= 1;
729 is_pos_arg = 1;
731 else
732 goto error;
734 else {
735 fmt = old_fmt;
736 goto rflag;
739 #endif /* !_NO_POS_ARGS */
742 * ``A negative field width argument is taken as a
743 * - flag followed by a positive field width.''
744 * -- ANSI X3J11
745 * They don't exclude field widths read from args.
747 width = GET_ARG (n, ap, int);
748 #ifndef _NO_POS_ARGS
749 is_pos_arg = old_is_pos_arg;
750 #endif
751 if (width >= 0)
752 goto rflag;
753 width = -width;
754 /* FALLTHROUGH */
755 case L'-':
756 flags |= LADJUST;
757 goto rflag;
758 case L'+':
759 sign = L'+';
760 goto rflag;
761 case L'.':
762 if ((ch = *fmt++) == L'*') {
763 #ifndef _NO_POS_ARGS
764 /* we must check for positional arg used for dynamic width */
765 n = N;
766 old_is_pos_arg = is_pos_arg;
767 is_pos_arg = 0;
768 if (is_digit (*fmt)) {
769 wchar_t *old_fmt = fmt;
771 n = 0;
772 ch = *fmt++;
773 do {
774 n = 10 * n + to_digit (ch);
775 ch = *fmt++;
776 } while (is_digit (ch));
778 if (ch == L'$') {
779 if (n <= MAX_POS_ARGS) {
780 n -= 1;
781 is_pos_arg = 1;
783 else
784 goto error;
786 else {
787 fmt = old_fmt;
788 goto rflag;
791 #endif /* !_NO_POS_ARGS */
792 prec = GET_ARG (n, ap, int);
793 #ifndef _NO_POS_ARGS
794 is_pos_arg = old_is_pos_arg;
795 #endif
796 if (prec < 0)
797 prec = -1;
798 goto rflag;
800 n = 0;
801 while (is_digit (ch)) {
802 n = 10 * n + to_digit (ch);
803 ch = *fmt++;
805 prec = n < 0 ? -1 : n;
806 goto reswitch;
807 case L'0':
809 * ``Note that 0 is taken as a flag, not as the
810 * beginning of a field width.''
811 * -- ANSI X3J11
813 flags |= ZEROPAD;
814 goto rflag;
815 case L'1': case L'2': case L'3': case L'4':
816 case L'5': case L'6': case L'7': case L'8': case L'9':
817 n = 0;
818 do {
819 n = 10 * n + to_digit (ch);
820 ch = *fmt++;
821 } while (is_digit (ch));
822 #ifndef _NO_POS_ARGS
823 if (ch == L'$') {
824 if (n <= MAX_POS_ARGS) {
825 N = n - 1;
826 is_pos_arg = 1;
827 goto rflag;
829 else
830 goto error;
832 #endif /* !_NO_POS_ARGS */
833 width = n;
834 goto reswitch;
835 #ifdef FLOATING_POINT
836 case L'L':
837 flags |= LONGDBL;
838 goto rflag;
839 #endif
840 case L'h':
841 #ifdef _WANT_IO_C99_FORMATS
842 if (*fmt == L'h') {
843 fmt++;
844 flags |= CHARINT;
845 } else
846 #endif
847 flags |= SHORTINT;
848 goto rflag;
849 case L'l':
850 #if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
851 if (*fmt == L'l') {
852 fmt++;
853 flags |= QUADINT;
854 } else
855 #endif
856 flags |= LONGINT;
857 goto rflag;
858 case L'q': /* GNU extension */
859 flags |= QUADINT;
860 goto rflag;
861 #ifdef _WANT_IO_C99_FORMATS
862 case L'j':
863 if (sizeof (intmax_t) == sizeof (long))
864 flags |= LONGINT;
865 else
866 flags |= QUADINT;
867 goto rflag;
868 case L'z':
869 if (sizeof (size_t) < sizeof (int))
870 /* POSIX states size_t is 16 or more bits, as is short. */
871 flags |= SHORTINT;
872 else if (sizeof (size_t) == sizeof (int))
873 /* no flag needed */;
874 else if (sizeof (size_t) <= sizeof (long))
875 flags |= LONGINT;
876 else
877 /* POSIX states that at least one programming
878 environment must support size_t no wider than
879 long, but that means other environments can
880 have size_t as wide as long long. */
881 flags |= QUADINT;
882 goto rflag;
883 case L't':
884 if (sizeof (ptrdiff_t) < sizeof (int))
885 /* POSIX states ptrdiff_t is 16 or more bits, as
886 is short. */
887 flags |= SHORTINT;
888 else if (sizeof (ptrdiff_t) == sizeof (int))
889 /* no flag needed */;
890 else if (sizeof (ptrdiff_t) <= sizeof (long))
891 flags |= LONGINT;
892 else
893 /* POSIX states that at least one programming
894 environment must support ptrdiff_t no wider than
895 long, but that means other environments can
896 have ptrdiff_t as wide as long long. */
897 flags |= QUADINT;
898 goto rflag;
899 case L'C': /* POSIX extension */
900 #endif /* _WANT_IO_C99_FORMATS */
901 case L'c':
902 cp = buf;
903 if (ch == L'c' && !(flags & LONGINT)) {
904 wint_t wc = btowc ((int) GET_ARG (N, ap, int));
905 if (wc == WEOF) {
906 fp->_flags |= __SERR;
907 goto error;
909 cp[0] = (wchar_t) wc;
911 else
913 cp[0] = GET_ARG (N, ap, int);
915 cp[1] = L'\0';
916 size = 1;
917 sign = L'\0';
918 break;
919 case L'd':
920 case L'i':
921 _uquad = SARG ();
922 #ifndef _NO_LONGLONG
923 if ((quad_t)_uquad < 0)
924 #else
925 if ((long) _uquad < 0)
926 #endif
929 _uquad = -_uquad;
930 sign = L'-';
932 base = DEC;
933 goto number;
934 #ifdef FLOATING_POINT
935 # ifdef _WANT_IO_C99_FORMATS
936 case L'a':
937 case L'A':
938 case L'F':
939 # endif
940 case L'e':
941 case L'E':
942 case L'f':
943 case L'g':
944 case L'G':
945 # ifdef _NO_LONGDBL
946 if (flags & LONGDBL) {
947 _fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE);
948 } else {
949 _fpvalue = GET_ARG (N, ap, double);
952 /* do this before tricky precision changes
954 If the output is infinite or NaN, leading
955 zeros are not permitted. Otherwise, scanf
956 could not read what printf wrote.
958 if (isinf (_fpvalue)) {
959 if (_fpvalue < 0)
960 sign = '-';
961 if (ch <= L'G') /* 'A', 'E', 'F', or 'G' */
962 cp = L"INF";
963 else
964 cp = L"inf";
965 size = 3;
966 flags &= ~ZEROPAD;
967 break;
969 if (isnan (_fpvalue)) {
970 if (signbit (_fpvalue))
971 sign = L'-';
972 if (ch <= L'G') /* 'A', 'E', 'F', or 'G' */
973 cp = L"NAN";
974 else
975 cp = L"nan";
976 size = 3;
977 flags &= ~ZEROPAD;
978 break;
981 # else /* !_NO_LONGDBL */
983 if (flags & LONGDBL) {
984 _fpvalue = GET_ARG (N, ap, _LONG_DOUBLE);
985 } else {
986 _fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double);
989 /* do this before tricky precision changes */
990 expt = _ldcheck (&_fpvalue);
991 if (expt == 2) {
992 if (_fpvalue < 0)
993 sign = L'-';
994 if (ch <= L'G') /* 'A', 'E', 'F', or 'G' */
995 cp = L"INF";
996 else
997 cp = L"inf";
998 size = 3;
999 flags &= ~ZEROPAD;
1000 break;
1002 if (expt == 1) {
1003 if (signbit (_fpvalue))
1004 sign = L'-';
1005 if (ch <= L'G') /* 'A', 'E', 'F', or 'G' */
1006 cp = L"NAN";
1007 else
1008 cp = L"nan";
1009 size = 3;
1010 flags &= ~ZEROPAD;
1011 break;
1013 # endif /* !_NO_LONGDBL */
1015 cp = buf;
1016 # ifdef _WANT_IO_C99_FORMATS
1017 if (ch == L'a' || ch == L'A') {
1018 ox[0] = L'0';
1019 ox[1] = ch == L'a' ? L'x' : L'X';
1020 flags |= HEXPREFIX;
1021 if (prec >= BUF)
1023 if ((malloc_buf =
1024 (wchar_t *)_malloc_r (data, (prec + 1) * sizeof (wchar_t)))
1025 == NULL)
1027 fp->_flags |= __SERR;
1028 goto error;
1030 cp = malloc_buf;
1032 } else
1033 # endif /* _WANT_IO_C99_FORMATS */
1034 if (prec == -1) {
1035 prec = DEFPREC;
1036 } else if ((ch == L'g' || ch == L'G') && prec == 0) {
1037 prec = 1;
1040 flags |= FPT;
1042 cp = wcvt (data, _fpvalue, prec, flags, &softsign,
1043 &expt, ch, &ndig, cp, BUF);
1045 /* If buf is not large enough for the converted wchar_t
1046 sequence, call wcvt again with a malloced new buffer.
1047 This should happen fairly rarely.
1049 if (cp == buf && ndig > BUF && malloc_buf == NULL) {
1050 if ((malloc_buf =
1051 (wchar_t *)_malloc_r (data, ndig * sizeof (wchar_t)))
1052 == NULL)
1054 fp->_flags |= __SERR;
1055 goto error;
1057 cp = wcvt (data, _fpvalue, prec, flags, &softsign,
1058 &expt, ch, &ndig, malloc_buf, ndig);
1061 if (ch == L'g' || ch == L'G') {
1062 if (expt <= -4 || expt > prec)
1063 ch -= 2; /* 'e' or 'E' */
1064 else
1065 ch = L'g';
1067 # ifdef _WANT_IO_C99_FORMATS
1068 else if (ch == L'F')
1069 ch = L'f';
1070 # endif
1071 if (ch <= L'e') { /* 'a', 'A', 'e', or 'E' fmt */
1072 --expt;
1073 expsize = wexponent (expstr, expt, ch);
1074 size = expsize + ndig;
1075 if (ndig > 1 || flags & ALT)
1076 ++size;
1077 # ifdef _WANT_IO_C99_FORMATS
1078 flags &= ~GROUPING;
1079 # endif
1080 } else {
1081 if (ch == L'f') { /* f fmt */
1082 if (expt > 0) {
1083 size = expt;
1084 if (prec || flags & ALT)
1085 size += prec + 1;
1086 } else /* "0.X" */
1087 size = (prec || flags & ALT)
1088 ? prec + 2
1089 : 1;
1090 } else if (expt >= ndig) { /* fixed g fmt */
1091 size = expt;
1092 if (flags & ALT)
1093 ++size;
1094 } else
1095 size = ndig + (expt > 0 ?
1096 1 : 2 - expt);
1097 # ifdef _WANT_IO_C99_FORMATS
1098 if ((flags & GROUPING) && expt > 0) {
1099 /* space for thousands' grouping */
1100 nseps = nrepeats = 0;
1101 lead = expt;
1102 while (*grouping != CHAR_MAX) {
1103 if (lead <= *grouping)
1104 break;
1105 lead -= *grouping;
1106 if (grouping[1]) {
1107 nseps++;
1108 grouping++;
1109 } else
1110 nrepeats++;
1112 size += nseps + nrepeats;
1113 } else
1114 # endif
1115 lead = expt;
1117 if (softsign)
1118 sign = L'-';
1119 break;
1120 #endif /* FLOATING_POINT */
1121 #ifdef _GLIBC_EXTENSION
1122 case L'm': /* GNU extension */
1124 int dummy;
1125 cp = (wchar_t *) _strerror_r (data, _REENT_ERRNO(data), 1, &dummy);
1127 flags &= ~LONGINT;
1128 goto string;
1129 #endif
1130 case L'n':
1131 #ifndef _NO_LONGLONG
1132 if (flags & QUADINT)
1133 *GET_ARG (N, ap, quad_ptr_t) = ret;
1134 else
1135 #endif
1136 if (flags & LONGINT)
1137 *GET_ARG (N, ap, long_ptr_t) = ret;
1138 else if (flags & SHORTINT)
1139 *GET_ARG (N, ap, short_ptr_t) = ret;
1140 #ifdef _WANT_IO_C99_FORMATS
1141 else if (flags & CHARINT)
1142 *GET_ARG (N, ap, char_ptr_t) = ret;
1143 #endif
1144 else
1145 *GET_ARG (N, ap, int_ptr_t) = ret;
1146 continue; /* no output */
1147 case L'o':
1148 _uquad = UARG ();
1149 base = OCT;
1150 #ifdef _WANT_IO_C99_FORMATS
1151 flags &= ~GROUPING;
1152 #endif
1153 goto nosign;
1154 case L'p':
1156 * ``The argument shall be a pointer to void. The
1157 * value of the pointer is converted to a sequence
1158 * of printable characters, in an implementation-
1159 * defined manner.''
1160 * -- ANSI X3J11
1162 /* NOSTRICT */
1163 _uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t);
1164 base = HEX;
1165 xdigs = L"0123456789abcdef";
1166 flags |= HEXPREFIX;
1167 ox[0] = L'0';
1168 ox[1] = ch = L'x';
1169 goto nosign;
1170 case L's':
1171 #ifdef _WANT_IO_C99_FORMATS
1172 case L'S': /* POSIX extension */
1173 #endif
1174 cp = GET_ARG (N, ap, wchar_ptr_t);
1175 #ifdef _GLIBC_EXTENSION
1176 string:
1177 #endif
1178 sign = '\0';
1179 #ifndef __OPTIMIZE_SIZE__
1180 /* Behavior is undefined if the user passed a
1181 NULL string when precision is not 0.
1182 However, if we are not optimizing for size,
1183 we might as well mirror glibc behavior. */
1184 if (cp == NULL) {
1185 cp = L"(null)";
1186 size = ((unsigned) prec > 6U) ? 6 : prec;
1188 else
1189 #endif /* __OPTIMIZE_SIZE__ */
1190 #ifdef _MB_CAPABLE
1191 if (ch != L'S' && !(flags & LONGINT)) {
1192 char *arg = (char *) cp;
1193 size_t insize = 0, nchars = 0, nconv = 0;
1194 mbstate_t ps;
1195 wchar_t *p;
1197 if (prec >= 0) {
1198 char *p = arg;
1199 memset ((void *)&ps, '\0', sizeof (mbstate_t));
1200 while (nchars < (size_t)prec) {
1201 nconv = mbrlen (p, MB_CUR_MAX, &ps);
1202 if (nconv == 0 || nconv == (size_t)-1 ||
1203 nconv == (size_t)-2)
1204 break;
1205 p += nconv;
1206 ++nchars;
1207 insize += nconv;
1209 if (nconv == (size_t) -1 || nconv == (size_t) -2) {
1210 fp->_flags |= __SERR;
1211 goto error;
1213 } else
1214 insize = strlen(arg);
1215 if (insize >= BUF) {
1216 if ((malloc_buf = (wchar_t *) _malloc_r (data, (insize + 1) * sizeof (wchar_t)))
1217 == NULL) {
1218 fp->_flags |= __SERR;
1219 goto error;
1221 cp = malloc_buf;
1222 } else
1223 cp = buf;
1224 memset ((void *)&ps, '\0', sizeof (mbstate_t));
1225 p = cp;
1226 while (insize != 0) {
1227 nconv = _mbrtowc_r (data, p, arg, insize, &ps);
1228 if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
1229 break;
1230 ++p;
1231 arg += nconv;
1232 insize -= nconv;
1234 if (nconv == (size_t) -1 || nconv == (size_t) -2) {
1235 fp->_flags |= __SERR;
1236 goto error;
1238 *p = L'\0';
1239 size = p - cp;
1241 #else
1242 if (ch != L'S' && !(flags & LONGINT)) {
1243 char *arg = (char *) cp;
1244 size_t insize = 0;
1246 if (prec >= 0) {
1247 char *p = memchr (arg, '\0', prec);
1248 insize = p ? p - arg : prec;
1249 } else
1250 insize = strlen (arg);
1251 if (insize >= BUF) {
1252 if ((malloc_buf = (wchar_t *) _malloc_r (data, (insize + 1) * sizeof (wchar_t)))
1253 == NULL) {
1254 fp->_flags |= __SERR;
1255 goto error;
1257 cp = malloc_buf;
1258 } else
1259 cp = buf;
1260 for (size = 0; size < insize; ++size)
1261 cp[size] = arg[size];
1262 cp[size] = L'\0';
1264 #endif /* _MB_CAPABLE */
1265 else if (prec >= 0) {
1267 * can't use wcslen; can only look for the
1268 * NUL in the first `prec' characters, and
1269 * strlen () will go further.
1271 wchar_t *p = wmemchr (cp, L'\0', prec);
1273 if (p != NULL) {
1274 size = p - cp;
1275 if (size > prec)
1276 size = prec;
1277 } else
1278 size = prec;
1279 } else
1280 size = wcslen (cp);
1282 break;
1283 case L'u':
1284 _uquad = UARG ();
1285 base = DEC;
1286 goto nosign;
1287 case L'X':
1288 xdigs = L"0123456789ABCDEF";
1289 goto hex;
1290 case L'x':
1291 xdigs = L"0123456789abcdef";
1292 hex: _uquad = UARG ();
1293 base = HEX;
1294 /* leading 0x/X only if non-zero */
1295 if (flags & ALT && _uquad != 0) {
1296 ox[0] = L'0';
1297 ox[1] = ch;
1298 flags |= HEXPREFIX;
1301 #ifdef _WANT_IO_C99_FORMATS
1302 flags &= ~GROUPING;
1303 #endif
1304 /* unsigned conversions */
1305 nosign: sign = L'\0';
1307 * ``... diouXx conversions ... if a precision is
1308 * specified, the 0 flag will be ignored.''
1309 * -- ANSI X3J11
1311 number: if ((dprec = prec) >= 0)
1312 flags &= ~ZEROPAD;
1315 * ``The result of converting a zero value with an
1316 * explicit precision of zero is no characters.''
1317 * -- ANSI X3J11
1319 cp = buf + BUF;
1320 if (_uquad != 0 || prec != 0) {
1322 * Unsigned mod is hard, and unsigned mod
1323 * by a constant is easier than that by
1324 * a variable; hence this switch.
1326 switch (base) {
1327 case OCT:
1328 do {
1329 *--cp = to_char (_uquad & 7);
1330 _uquad >>= 3;
1331 } while (_uquad);
1332 /* handle octal leading 0 */
1333 if (flags & ALT && *cp != L'0')
1334 *--cp = L'0';
1335 break;
1337 case DEC:
1338 /* many numbers are 1 digit */
1339 if (_uquad < 10) {
1340 *--cp = to_char(_uquad);
1341 break;
1343 #ifdef _WANT_IO_C99_FORMATS
1344 ndig = 0;
1345 #endif
1346 do {
1347 *--cp = to_char (_uquad % 10);
1348 #ifdef _WANT_IO_C99_FORMATS
1349 ndig++;
1350 /* If (*grouping == CHAR_MAX) then no
1351 more grouping */
1352 if ((flags & GROUPING)
1353 && ndig == *grouping
1354 && *grouping != CHAR_MAX
1355 && _uquad > 9) {
1356 *--cp = thousands_sep;
1357 ndig = 0;
1358 /* If (grouping[1] == '\0') then we
1359 have to use *grouping character
1360 (last grouping rule) for all
1361 next cases. */
1362 if (grouping[1] != '\0')
1363 grouping++;
1365 #endif
1366 _uquad /= 10;
1367 } while (_uquad != 0);
1368 break;
1370 case HEX:
1371 do {
1372 *--cp = xdigs[_uquad & 15];
1373 _uquad >>= 4;
1374 } while (_uquad);
1375 break;
1377 default:
1378 cp = L"bug in vfprintf: bad base";
1379 size = wcslen (cp);
1380 goto skipsize;
1384 * ...result is to be converted to an 'alternate form'.
1385 * For o conversion, it increases the precision to force
1386 * the first digit of the result to be a zero."
1387 * -- ANSI X3J11
1389 * To demonstrate this case, compile and run:
1390 * printf ("%#.0o",0);
1392 else if (base == OCT && (flags & ALT))
1393 *--cp = L'0';
1395 size = buf + BUF - cp;
1396 skipsize:
1397 break;
1398 default: /* "%?" prints ?, unless ? is NUL */
1399 if (ch == L'\0')
1400 goto done;
1401 /* pretend it was %c with argument ch */
1402 cp = buf;
1403 *cp = ch;
1404 size = 1;
1405 sign = L'\0';
1406 break;
1410 * All reasonable formats wind up here. At this point, `cp'
1411 * points to a string which (if not flags&LADJUST) should be
1412 * padded out to `width' places. If flags&ZEROPAD, it should
1413 * first be prefixed by any sign or other prefix; otherwise,
1414 * it should be blank padded before the prefix is emitted.
1415 * After any left-hand padding and prefixing, emit zeroes
1416 * required by a decimal [diouxX] precision, then print the
1417 * string proper, then emit zeroes required by any leftover
1418 * floating precision; finally, if LADJUST, pad with blanks.
1419 * If flags&FPT, ch must be in [aAeEfg].
1421 * Compute actual size, so we know how much to pad.
1422 * size excludes decimal prec; realsz includes it.
1424 realsz = dprec > size ? dprec : size;
1425 if (sign)
1426 realsz++;
1427 if (flags & HEXPREFIX)
1428 realsz+= 2;
1430 /* right-adjusting blank padding */
1431 if ((flags & (LADJUST|ZEROPAD)) == 0)
1432 PAD (width - realsz, blanks);
1434 /* prefix */
1435 if (sign)
1436 PRINT (&sign, 1);
1437 if (flags & HEXPREFIX)
1438 PRINT (ox, 2);
1440 /* right-adjusting zero padding */
1441 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1442 PAD (width - realsz, zeroes);
1444 /* leading zeroes from decimal precision */
1445 PAD (dprec - size, zeroes);
1447 /* the string or number proper */
1448 #ifdef FLOATING_POINT
1449 if ((flags & FPT) == 0) {
1450 PRINT (cp, size);
1451 } else { /* glue together f_p fragments */
1452 if (ch >= L'f') { /* 'f' or 'g' */
1453 if (_fpvalue == 0) {
1454 /* kludge for __dtoa irregularity */
1455 PRINT (L"0", 1);
1456 if (expt < ndig || flags & ALT) {
1457 PRINT (&decimal_point, 1);
1458 PAD (ndig - 1, zeroes);
1460 } else if (expt <= 0) {
1461 PRINT (L"0", 1);
1462 if (expt || ndig || flags & ALT) {
1463 PRINT (&decimal_point, 1);
1464 PAD (-expt, zeroes);
1465 PRINT (cp, ndig);
1467 } else {
1468 wchar_t *convbuf = cp;
1469 PRINTANDPAD(cp, convbuf + ndig,
1470 lead, zeroes);
1471 cp += lead;
1472 #ifdef _WANT_IO_C99_FORMATS
1473 if (flags & GROUPING) {
1474 while (nseps > 0 || nrepeats > 0) {
1475 if (nrepeats > 0)
1476 nrepeats--;
1477 else {
1478 grouping--;
1479 nseps--;
1481 PRINT (&thousands_sep, 1);
1482 PRINTANDPAD (cp, convbuf + ndig,
1483 *grouping, zeroes);
1484 cp += *grouping;
1486 if (cp > convbuf + ndig)
1487 cp = convbuf + ndig;
1489 #endif
1490 if (expt < ndig || flags & ALT)
1491 PRINT (&decimal_point, 1);
1492 PRINTANDPAD (cp, convbuf + ndig,
1493 ndig - expt, zeroes);
1496 } else { /* 'a', 'A', 'e', or 'E' */
1497 if (ndig > 1 || flags & ALT) {
1498 PRINT (cp, 1);
1499 cp++;
1500 PRINT (&decimal_point, 1);
1501 if (_fpvalue) {
1502 PRINT (cp, ndig - 1);
1503 } else /* 0.[0..] */
1504 /* __dtoa irregularity */
1505 PAD (ndig - 1, zeroes);
1506 } else /* XeYYY */
1507 PRINT (cp, 1);
1508 PRINT (expstr, expsize);
1511 #else /* !FLOATING_POINT */
1512 PRINT (cp, size);
1513 #endif
1514 /* left-adjusting padding (always blank) */
1515 if (flags & LADJUST)
1516 PAD (width - realsz, blanks);
1518 /* finally, adjust ret */
1519 ret += width > realsz ? width : realsz;
1521 FLUSH (); /* copy out the I/O vectors */
1523 if (malloc_buf != NULL) {
1524 _free_r (data, malloc_buf);
1525 malloc_buf = NULL;
1528 done:
1529 FLUSH ();
1530 error:
1531 if (malloc_buf != NULL)
1532 _free_r (data, malloc_buf);
1533 #ifndef STRING_ONLY
1534 _newlib_flockfile_end (fp);
1535 #endif
1536 return (__sferror (fp) ? EOF : ret);
1537 /* NOTREACHED */
1540 #ifdef FLOATING_POINT
1542 /* Using reentrant DATA, convert finite VALUE into a string of digits
1543 with no decimal point, using NDIGITS precision and FLAGS as guides
1544 to whether trailing zeros must be included. Set *SIGN to nonzero
1545 if VALUE was negative. Set *DECPT to the exponent plus one. Set
1546 *LENGTH to the length of the returned string. CH must be one of
1547 [aAeEfFgG]; different from vfprintf.c:cvt(), the return string
1548 lives in BUF regardless of CH. LEN is the length of BUF, except
1549 when CH is [aA], in which case LEN is not in use. If BUF is not
1550 large enough for the converted string, only the first LEN number
1551 of characters will be returned in BUF, but *LENGTH will be set to
1552 the full length of the string before the truncation. */
1553 static wchar_t *
1554 wcvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags,
1555 wchar_t *sign, int *decpt, int ch, int *length, wchar_t *buf, int len)
1557 int mode, dsgn;
1558 # ifdef _NO_LONGDBL
1559 union double_union tmp;
1561 tmp.d = value;
1562 if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */
1563 value = -value;
1564 *sign = L'-';
1565 } else
1566 *sign = L'\0';
1567 # else /* !_NO_LONGDBL */
1568 union
1570 struct ldieee ieee;
1571 _LONG_DOUBLE val;
1572 } ld;
1574 ld.val = value;
1575 if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */
1576 value = -value;
1577 *sign = L'-';
1578 } else
1579 *sign = L'\0';
1580 # endif /* !_NO_LONGDBL */
1582 # ifdef _WANT_IO_C99_FORMATS
1583 if (ch == L'a' || ch == L'A') {
1584 wchar_t *digits, *bp, *rve;
1585 /* This code assumes FLT_RADIX is a power of 2. The initial
1586 division ensures the digit before the decimal will be less
1587 than FLT_RADIX (unless it is rounded later). There is no
1588 loss of precision in these calculations. */
1589 value = FREXP (value, decpt) / 8;
1590 if (!value)
1591 *decpt = 1;
1592 digits = ch == L'a' ? L"0123456789abcdef" : L"0123456789ABCDEF";
1593 bp = buf;
1594 do {
1595 value *= 16;
1596 mode = (int) value;
1597 value -= mode;
1598 *bp++ = digits[mode];
1599 } while (ndigits-- && value);
1600 if (value > 0.5 || (value == 0.5 && mode & 1)) {
1601 /* round to even */
1602 rve = bp;
1603 while (*--rve == digits[0xf]) {
1604 *rve = L'0';
1606 *rve = *rve == L'9' ? digits[0xa] : *rve + 1;
1607 } else {
1608 while (ndigits-- >= 0) {
1609 *bp++ = L'0';
1612 *length = bp - buf;
1613 return buf;
1615 # endif /* _WANT_IO_C99_FORMATS */
1616 if (ch == L'f' || ch == L'F') {
1617 mode = 3; /* ndigits after the decimal point */
1618 } else {
1619 /* To obtain ndigits after the decimal point for the 'e'
1620 * and 'E' formats, round to ndigits + 1 significant
1621 * figures.
1623 if (ch == L'e' || ch == L'E') {
1624 ndigits++;
1626 mode = 2; /* ndigits significant digits */
1630 char *digits, *bp, *rve;
1631 #ifndef _MB_CAPABLE
1632 int i;
1633 #endif
1635 digits = _DTOA_R (data, value, mode, ndigits, decpt, &dsgn, &rve);
1637 if ((ch != L'g' && ch != L'G') || flags & ALT) { /* Print trailing zeros */
1638 bp = digits + ndigits;
1639 if (ch == L'f' || ch == L'F') {
1640 if (*digits == L'0' && value)
1641 *decpt = -ndigits + 1;
1642 bp += *decpt;
1644 if (value == 0) /* kludge for __dtoa irregularity */
1645 rve = bp;
1646 while (rve < bp)
1647 *rve++ = '0';
1650 *length = rve - digits; /* full length of the string */
1651 #ifdef _MB_CAPABLE
1652 _mbsnrtowcs_r (data, buf, (const char **) &digits, *length,
1653 len, NULL);
1654 #else
1655 for (i = 0; i < *length && i < len; ++i)
1656 buf[i] = (wchar_t) digits[i];
1657 #endif
1658 return buf;
1662 static int
1663 wexponent(wchar_t *p0, int exp, int fmtch)
1665 register wchar_t *p, *t;
1666 wchar_t expbuf[MAXEXPLEN];
1667 # ifdef _WANT_IO_C99_FORMATS
1668 int isa = fmtch == L'a' || fmtch == L'A';
1669 # else
1670 # define isa 0
1671 # endif
1673 p = p0;
1674 *p++ = isa ? L'p' - L'a' + fmtch : fmtch;
1675 if (exp < 0) {
1676 exp = -exp;
1677 *p++ = L'-';
1679 else
1680 *p++ = L'+';
1681 t = expbuf + MAXEXPLEN;
1682 if (exp > 9) {
1683 do {
1684 *--t = to_char (exp % 10);
1685 } while ((exp /= 10) > 9);
1686 *--t = to_char (exp);
1687 for (; t < expbuf + MAXEXPLEN; *p++ = *t++);
1689 else {
1690 if (!isa)
1691 *p++ = L'0';
1692 *p++ = to_char (exp);
1694 return (p - p0);
1696 #endif /* FLOATING_POINT */
1699 #ifndef _NO_POS_ARGS
1701 /* Positional argument support.
1702 Written by Jeff Johnston
1704 Copyright (c) 2002 Red Hat Incorporated.
1705 All rights reserved.
1707 Redistribution and use in source and binary forms, with or without
1708 modification, are permitted provided that the following conditions are met:
1710 Redistributions of source code must retain the above copyright
1711 notice, this list of conditions and the following disclaimer.
1713 Redistributions in binary form must reproduce the above copyright
1714 notice, this list of conditions and the following disclaimer in the
1715 documentation and/or other materials provided with the distribution.
1717 The name of Red Hat Incorporated may not be used to endorse
1718 or promote products derived from this software without specific
1719 prior written permission.
1721 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1722 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1723 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1724 DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY
1725 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1726 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1727 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1728 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1729 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1730 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
1732 /* function to get positional parameter N where n = N - 1 */
1733 static union arg_val *
1734 get_arg (struct _reent *data,
1735 int n,
1736 wchar_t *fmt,
1737 va_list *ap,
1738 int *numargs_p,
1739 union arg_val *args,
1740 int *arg_type,
1741 wchar_t **last_fmt)
1743 wchar_t ch;
1744 int number, flags;
1745 int spec_type;
1746 int numargs = *numargs_p;
1747 __CH_CLASS chtype;
1748 __STATE state, next_state;
1749 __ACTION action;
1750 int pos, last_arg;
1751 int max_pos_arg = n;
1752 /* Only need types that can be reached via vararg promotions. */
1753 enum types { INT, LONG_INT, QUAD_INT, CHAR_PTR, DOUBLE, LONG_DOUBLE, WIDE_CHAR };
1755 /* if this isn't the first call, pick up where we left off last time */
1756 if (*last_fmt != NULL)
1757 fmt = *last_fmt;
1759 /* we need to process either to end of fmt string or until we have actually
1760 read the desired parameter from the vararg list. */
1761 while (*fmt && n >= numargs)
1763 while (*fmt != L'\0' && *fmt != L'%')
1764 fmt += 1;
1766 if (*fmt == L'\0')
1767 break;
1768 state = START;
1769 flags = 0;
1770 pos = -1;
1771 number = 0;
1772 spec_type = INT;
1774 /* Use state/action table to process format specifiers. We ignore invalid
1775 formats and we are only interested in information that tells us how to
1776 read the vararg list. */
1777 while (state != DONE)
1779 ch = *fmt++;
1780 chtype = ch < (wchar_t) 256 ? __chclass[ch] : OTHER;
1781 next_state = __state_table[state][chtype];
1782 action = __action_table[state][chtype];
1783 state = next_state;
1785 switch (action)
1787 case GETMOD: /* we have format modifier */
1788 switch (ch)
1790 case L'h':
1791 /* No flag needed, since short and char promote to int. */
1792 break;
1793 case L'L':
1794 flags |= LONGDBL;
1795 break;
1796 case L'q':
1797 flags |= QUADINT;
1798 break;
1799 # ifdef _WANT_IO_C99_FORMATS
1800 case L'j':
1801 if (sizeof (intmax_t) == sizeof (long))
1802 flags |= LONGINT;
1803 else
1804 flags |= QUADINT;
1805 break;
1806 case L'z':
1807 if (sizeof (size_t) <= sizeof (int))
1808 /* no flag needed */;
1809 else if (sizeof (size_t) <= sizeof (long))
1810 flags |= LONGINT;
1811 else
1812 /* POSIX states that at least one programming
1813 environment must support size_t no wider than
1814 long, but that means other environments can
1815 have size_t as wide as long long. */
1816 flags |= QUADINT;
1817 break;
1818 case L't':
1819 if (sizeof (ptrdiff_t) <= sizeof (int))
1820 /* no flag needed */;
1821 else if (sizeof (ptrdiff_t) <= sizeof (long))
1822 flags |= LONGINT;
1823 else
1824 /* POSIX states that at least one programming
1825 environment must support ptrdiff_t no wider than
1826 long, but that means other environments can
1827 have ptrdiff_t as wide as long long. */
1828 flags |= QUADINT;
1829 break;
1830 # endif /* _WANT_IO_C99_FORMATS */
1831 case L'l':
1832 default:
1833 # if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG
1834 if (*fmt == L'l')
1836 flags |= QUADINT;
1837 ++fmt;
1839 else
1840 # endif
1841 flags |= LONGINT;
1842 break;
1844 break;
1845 case GETARG: /* we have format specifier */
1847 numargs &= (MAX_POS_ARGS - 1);
1848 /* process the specifier and translate it to a type to fetch from varargs */
1849 switch (ch)
1851 case L'd':
1852 case L'i':
1853 case L'o':
1854 case L'x':
1855 case L'X':
1856 case L'u':
1857 if (flags & LONGINT)
1858 spec_type = LONG_INT;
1859 # ifndef _NO_LONGLONG
1860 else if (flags & QUADINT)
1861 spec_type = QUAD_INT;
1862 # endif
1863 else
1864 spec_type = INT;
1865 break;
1866 # ifdef _WANT_IO_C99_FORMATS
1867 case L'a':
1868 case L'A':
1869 case L'F':
1870 # endif
1871 case L'f':
1872 case L'g':
1873 case L'G':
1874 case L'E':
1875 case L'e':
1876 # ifndef _NO_LONGDBL
1877 if (flags & LONGDBL)
1878 spec_type = LONG_DOUBLE;
1879 else
1880 # endif
1881 spec_type = DOUBLE;
1882 break;
1883 case L's':
1884 # ifdef _WANT_IO_C99_FORMATS
1885 case L'S': /* POSIX extension */
1886 # endif
1887 case L'p':
1888 case L'n':
1889 spec_type = CHAR_PTR;
1890 break;
1891 case L'c':
1892 # ifdef _WANT_IO_C99_FORMATS
1893 if (flags & LONGINT)
1894 spec_type = WIDE_CHAR;
1895 else
1896 # endif
1897 spec_type = INT;
1898 break;
1899 # ifdef _WANT_IO_C99_FORMATS
1900 case L'C': /* POSIX extension */
1901 spec_type = WIDE_CHAR;
1902 break;
1903 # endif
1906 /* if we have a positional parameter, just store the type, otherwise
1907 fetch the parameter from the vararg list */
1908 if (pos != -1)
1909 arg_type[pos] = spec_type;
1910 else
1912 switch (spec_type)
1914 case LONG_INT:
1915 args[numargs++].val_long = va_arg (*ap, long);
1916 break;
1917 case QUAD_INT:
1918 args[numargs++].val_quad_t = va_arg (*ap, quad_t);
1919 break;
1920 case WIDE_CHAR:
1921 args[numargs++].val_wint_t = va_arg (*ap, wint_t);
1922 break;
1923 case INT:
1924 args[numargs++].val_int = va_arg (*ap, int);
1925 break;
1926 case CHAR_PTR:
1927 args[numargs++].val_wchar_ptr_t = va_arg (*ap, wchar_t *);
1928 break;
1929 case DOUBLE:
1930 args[numargs++].val_double = va_arg (*ap, double);
1931 break;
1932 case LONG_DOUBLE:
1933 args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
1934 break;
1938 break;
1939 case GETPOS: /* we have positional specifier */
1940 if (arg_type[0] == -1)
1941 memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
1942 pos = number - 1;
1943 max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos);
1944 break;
1945 case PWPOS: /* we have positional specifier for width or precision */
1946 if (arg_type[0] == -1)
1947 memset (arg_type, 0, sizeof (int) * MAX_POS_ARGS);
1948 number -= 1;
1949 arg_type[number] = INT;
1950 max_pos_arg = (max_pos_arg > number ? max_pos_arg : number);
1951 break;
1952 case GETPWB: /* we require format pushback */
1953 --fmt;
1954 /* fallthrough */
1955 case GETPW: /* we have a variable precision or width to acquire */
1956 args[numargs++].val_int = va_arg (*ap, int);
1957 break;
1958 case NUMBER: /* we have a number to process */
1959 number = (ch - '0');
1960 while ((ch = *fmt) != '\0' && is_digit (ch))
1962 number = number * 10 + (ch - '0');
1963 ++fmt;
1965 break;
1966 case SKIPNUM: /* we have a number to skip */
1967 while ((ch = *fmt) != '\0' && is_digit (ch))
1968 ++fmt;
1969 break;
1970 case NOOP:
1971 default:
1972 break; /* do nothing */
1977 /* process all arguments up to at least the one we are looking for and if we
1978 have seen the end of the string, then process up to the max argument needed */
1979 if (*fmt == '\0')
1980 last_arg = max_pos_arg;
1981 else
1982 last_arg = n;
1984 while (numargs <= last_arg)
1986 switch (arg_type[numargs])
1988 case LONG_INT:
1989 args[numargs++].val_long = va_arg (*ap, long);
1990 break;
1991 case QUAD_INT:
1992 args[numargs++].val_quad_t = va_arg (*ap, quad_t);
1993 break;
1994 case CHAR_PTR:
1995 args[numargs++].val_wchar_ptr_t = va_arg (*ap, wchar_t *);
1996 break;
1997 case DOUBLE:
1998 args[numargs++].val_double = va_arg (*ap, double);
1999 break;
2000 case LONG_DOUBLE:
2001 args[numargs++].val__LONG_DOUBLE = va_arg (*ap, _LONG_DOUBLE);
2002 break;
2003 case WIDE_CHAR:
2004 args[numargs++].val_wint_t = va_arg (*ap, wint_t);
2005 break;
2006 case INT:
2007 default:
2008 args[numargs++].val_int = va_arg (*ap, int);
2009 break;
2013 /* alter the global numargs value and keep a reference to the last bit of the fmt
2014 string we processed here because the caller will continue processing where we started */
2015 *numargs_p = numargs;
2016 *last_fmt = fmt;
2017 return &args[n];
2019 #endif /* !_NO_POS_ARGS */