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