1/** @file
2    Implementation of internals for printf and wprintf.
3
4    Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
5    This program and the accompanying materials are licensed and made available
6    under the terms and conditions of the BSD License that accompanies this
7    distribution.  The full text of the license may be found at
8    http://opensource.org/licenses/bsd-license.
9
10    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11    WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13    Copyright (c) 1990, 1993
14    The Regents of the University of California.  All rights reserved.
15
16    This code is derived from software contributed to Berkeley by
17    Chris Torek.
18
19    Redistribution and use in source and binary forms, with or without
20    modification, are permitted provided that the following conditions
21    are met:
22      - Redistributions of source code must retain the above copyright
23        notice, this list of conditions and the following disclaimer.
24      - Redistributions in binary form must reproduce the above copyright
25        notice, this list of conditions and the following disclaimer in the
26        documentation and/or other materials provided with the distribution.
27      - Neither the name of the University nor the names of its contributors
28        may be used to endorse or promote products derived from this software
29        without specific prior written permission.
30
31    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
32    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
35    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41    POSSIBILITY OF SUCH DAMAGE.
42
43    NetBSD: vfwprintf.c,v 1.9.2.1.4.1 2008/04/08 21:10:55 jdc Exp
44    vfprintf.c  8.1 (Berkeley) 6/4/93
45**/
46#include  <LibConfig.h>
47
48#include "namespace.h"
49#include <sys/types.h>
50
51#include <assert.h>
52#include <ctype.h>
53#include <limits.h>
54#include <locale.h>
55#include <stdarg.h>
56#include <stddef.h>
57#include <stdint.h>
58#include <stdio.h>
59#include <stdlib.h>
60#include <string.h>
61#include <errno.h>
62#include <wchar.h>
63#include <wctype.h>
64
65#include "reentrant.h"
66#include "local.h"
67#include "extern.h"
68#include "fvwrite.h"
69
70#ifdef  _MSC_VER
71  // Keep compiler quiet about conversions from larger to smaller types.
72  #pragma warning ( disable : 4244 )
73#endif
74
75#ifndef NARROW
76#define MCHAR_T   char
77#define CHAR_T    wchar_t
78#define STRLEN(a) wcslen(a)
79#define MEMCHR(a, b, c) wmemchr(a, b, c)
80#define SCONV(a, b) __mbsconv(a, b)
81#define STRCONST(a) L ## a
82#define WDECL(a, b) a ## w ## b
83#define END_OF_FILE WEOF
84#define MULTI   0
85#else
86#define MCHAR_T   wchar_t
87#define CHAR_T    char
88#define STRLEN(a) strlen(a)
89#define MEMCHR(a, b, c) memchr(a, b, c)
90#define SCONV(a, b) __wcsconv(a, b)
91#define STRCONST(a) a
92#define WDECL(a, b) a ## b
93#define END_OF_FILE EOF
94#define MULTI   1
95#endif
96
97union arg {
98  int                 intarg;
99  u_int               uintarg;
100  long                longarg;
101  unsigned long       ulongarg;
102  long long           longlongarg;
103  unsigned long long  ulonglongarg;
104  ptrdiff_t           ptrdiffarg;
105  size_t              sizearg;
106  intmax_t            intmaxarg;
107  uintmax_t           uintmaxarg;
108  void               *pvoidarg;
109  char               *pchararg;
110  signed char        *pschararg;
111  short              *pshortarg;
112  int                *pintarg;
113  long               *plongarg;
114  long long          *plonglongarg;
115  ptrdiff_t          *pptrdiffarg;
116  size_t             *psizearg;
117  intmax_t           *pintmaxarg;
118#ifndef NO_FLOATING_POINT
119  double              doublearg;
120  long double         longdoublearg;
121#endif
122  wint_t              wintarg;
123  wchar_t            *pwchararg;
124};
125
126/*
127 * Type ids for argument type table.
128 */
129enum typeid {
130  T_UNUSED,   TP_SHORT,     T_INT,          T_U_INT,  TP_INT,
131  T_LONG,     T_U_LONG,     TP_LONG,        T_LLONG,  T_U_LLONG,
132  TP_LLONG,   T_PTRDIFFT,   TP_PTRDIFFT,    T_SIZET,  TP_SIZET,
133  T_INTMAXT,  T_UINTMAXT,   TP_INTMAXT,     TP_VOID,  TP_CHAR,
134  TP_SCHAR,   T_DOUBLE,     T_LONG_DOUBLE,  T_WINT,   TP_WCHAR
135};
136
137static int      __sbprintf(FILE *, const CHAR_T *, va_list);
138static CHAR_T  *__ujtoa(uintmax_t, CHAR_T *, int, int, const char *, int,
139                        char, const char *);
140static CHAR_T  *__ultoa(u_long, CHAR_T *, int, int, const char *, int,
141                        char, const char *);
142#ifndef NARROW
143static CHAR_T  *__mbsconv(char *, int);
144static wint_t   __xfputwc(CHAR_T, FILE *);
145#else
146static char    *__wcsconv(wchar_t *, int);
147static int      __sprint(FILE *, struct __suio *);
148#endif
149static int      __find_arguments(const CHAR_T *, va_list, union arg **);
150static int      __grow_type_table(int, enum typeid **, int *);
151
152/*
153 * Helper function for `fprintf to unbuffered unix file': creates a
154 * temporary buffer.  We only work on write-only files; this avoids
155 * worries about ungetc buffers and so forth.
156 */
157static int
158__sbprintf(FILE *fp, const CHAR_T *fmt, va_list ap)
159{
160  int ret;
161  FILE fake;
162  struct __sfileext fakeext;
163  unsigned char buf[BUFSIZ];
164
165  _DIAGASSERT(fp != NULL);
166  _DIAGASSERT(fmt != NULL);
167  if(fp == NULL) {
168    errno = EINVAL;
169    return (EOF);
170  }
171
172  _FILEEXT_SETUP(&fake, &fakeext);
173
174  /* copy the important variables */
175  fake._flags   = fp->_flags & ~__SNBF;
176  fake._file    = fp->_file;
177  fake._cookie  = fp->_cookie;
178  fake._write   = fp->_write;
179
180  /* set up the buffer */
181  fake._bf._base  = fake._p = buf;
182  fake._bf._size  = fake._w = sizeof(buf);
183  fake._lbfsize   = 0;  /* not actually used, but Just In Case */
184
185  /* do the work, then copy any error status */
186  ret = WDECL(__vf,printf_unlocked)(&fake, fmt, ap);
187  if (ret >= 0 && fflush(&fake))
188    ret = END_OF_FILE;
189  if (fake._flags & __SERR)
190    fp->_flags |= __SERR;
191  return (ret);
192}
193
194#ifndef NARROW
195/*
196 * Like __fputwc, but handles fake string (__SSTR) files properly.
197 * File must already be locked.
198 */
199static wint_t
200__xfputwc(wchar_t wc, FILE *fp)
201{
202  static const mbstate_t initial = { 0 };
203  mbstate_t mbs;
204  char buf[MB_LEN_MAX];
205  struct __suio uio;
206  struct __siov iov;
207  size_t len;
208
209  if ((fp->_flags & __SSTR) == 0)
210    return (__fputwc_unlock(wc, fp));
211
212  mbs = initial;
213  if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) {
214    fp->_flags |= __SERR;
215    return (END_OF_FILE);
216  }
217  uio.uio_iov     = &iov;
218  uio.uio_resid   = (int)len;
219  uio.uio_iovcnt  = 1;
220  iov.iov_base    = buf;
221  iov.iov_len     = len;
222  return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : END_OF_FILE);
223}
224#else
225/*
226 * Flush out all the vectors defined by the given uio,
227 * then reset it so that it can be reused.
228 */
229static int
230__sprint(FILE *fp, struct __suio *uio)
231{
232  int err;
233
234  _DIAGASSERT(fp != NULL);
235  _DIAGASSERT(uio != NULL);
236  if(fp == NULL) {
237    errno = EINVAL;
238    return (EOF);
239  }
240
241  if (uio->uio_resid == 0) {
242    uio->uio_iovcnt = 0;
243    return (0);
244  }
245  err = __sfvwrite(fp, uio);
246  uio->uio_resid = 0;
247  uio->uio_iovcnt = 0;
248  return (err);
249}
250#endif
251
252/*
253 * Macros for converting digits to letters and vice versa
254 */
255#define to_digit(c) ((c) - '0')
256#define is_digit(c) ((unsigned)to_digit(c) <= 9)
257#define to_char(n)  (CHAR_T)((n) + '0')
258
259/*
260 * Convert an unsigned long to ASCII for printf purposes, returning
261 * a pointer to the first character of the string representation.
262 * Octal numbers can be forced to have a leading zero; hex numbers
263 * use the given digits.
264 */
265static CHAR_T *
266__ultoa(u_long val, CHAR_T *endp, int base, int octzero, const char *xdigs,
267        int needgrp, char thousep, const char *grp)
268{
269  CHAR_T *cp = endp;
270  LONGN sval;
271  int ndig;
272
273  /*
274   * Handle the three cases separately, in the hope of getting
275   * better/faster code.
276   */
277  switch (base) {
278  case 10:
279    if (val < 10) { /* many numbers are 1 digit */
280      *--cp = to_char(val);
281      return (cp);
282    }
283    ndig = 0;
284    /*
285     * On many machines, unsigned arithmetic is harder than
286     * signed arithmetic, so we do at most one unsigned mod and
287     * divide; this is sufficient to reduce the range of
288     * the incoming value to where signed arithmetic works.
289     */
290    if (val > LONG_MAX) {
291      *--cp = to_char(val % 10);
292      ndig++;
293      sval = (LONGN)(val / 10);
294    } else
295      sval = (LONGN)val;
296    do {
297      *--cp = to_char(sval % 10);
298      ndig++;
299      /*
300       * If (*grp == CHAR_MAX) then no more grouping
301       * should be performed.
302       */
303      if (needgrp && ndig == *grp && *grp != CHAR_MAX
304          && sval > 9) {
305        *--cp = thousep;
306        ndig = 0;
307        /*
308         * If (*(grp+1) == '\0') then we have to
309         * use *grp character (last grouping rule)
310         * for all next cases
311         */
312        if (*(grp+1) != '\0')
313          grp++;
314      }
315      sval /= 10;
316    } while (sval != 0);
317    break;
318
319  case 8:
320    do {
321      *--cp = to_char(val & 7);
322      val >>= 3;
323    } while (val);
324    if (octzero && *cp != '0')
325      *--cp = '0';
326    break;
327
328  case 16:
329    do {
330      *--cp = xdigs[(size_t)val & 15];
331      val >>= 4;
332    } while (val);
333    break;
334
335  default:      /* oops */
336    abort();
337  }
338  return (cp);
339}
340
341/* Identical to __ultoa, but for intmax_t. */
342static CHAR_T *
343__ujtoa(uintmax_t val, CHAR_T *endp, int base, int octzero,
344        const char *xdigs, int needgrp, char thousep, const char *grp)
345{
346  CHAR_T *cp = endp;
347  intmax_t sval;
348  int ndig;
349
350  /* quick test for small values; __ultoa is typically much faster */
351  /* (perhaps instead we should run until small, then call __ultoa?) */
352  if (val <= ULONG_MAX)
353    return (__ultoa((u_long)val, endp, base, octzero, xdigs,
354        needgrp, thousep, grp));
355  switch (base) {
356  case 10:
357    if (val < 10) {
358      *--cp = to_char(val % 10);
359      return (cp);
360    }
361    ndig = 0;
362    if (val > INTMAX_MAX) {
363      *--cp = to_char(val % 10);
364      ndig++;
365      sval = val / 10;
366    } else
367      sval = val;
368    do {
369      *--cp = to_char(sval % 10);
370      ndig++;
371      /*
372       * If (*grp == CHAR_MAX) then no more grouping
373       * should be performed.
374       */
375      if (needgrp && *grp != CHAR_MAX && ndig == *grp
376          && sval > 9) {
377        *--cp = thousep;
378        ndig = 0;
379        /*
380         * If (*(grp+1) == '\0') then we have to
381         * use *grp character (last grouping rule)
382         * for all next cases
383         */
384        if (*(grp+1) != '\0')
385          grp++;
386      }
387      sval /= 10;
388    } while (sval != 0);
389    break;
390
391  case 8:
392    do {
393      *--cp = to_char(val & 7);
394      val >>= 3;
395    } while (val);
396    if (octzero && *cp != '0')
397      *--cp = '0';
398    break;
399
400  case 16:
401    do {
402      *--cp = xdigs[(size_t)val & 15];
403      val >>= 4;
404    } while (val);
405    break;
406
407  default:
408    abort();
409  }
410  return (cp);
411}
412
413#ifndef NARROW
414/*
415 * Convert a multibyte character string argument for the %s format to a wide
416 * string representation. ``prec'' specifies the maximum number of bytes
417 * to output. If ``prec'' is greater than or equal to zero, we can't assume
418 * that the multibyte char. string ends in a null character.
419 */
420static wchar_t *
421__mbsconv(char *mbsarg, int prec)
422{
423  static const mbstate_t initial = { 0 };
424  mbstate_t mbs;
425  wchar_t *convbuf, *wcp;
426  const char *p;
427  size_t insize, nchars, nconv;
428
429  if (mbsarg == NULL)
430    return (NULL);
431
432  /*
433   * Supplied argument is a multibyte string; convert it to wide
434   * characters first.
435   */
436  if (prec >= 0) {
437    /*
438     * String is not guaranteed to be NUL-terminated. Find the
439     * number of characters to print.
440     */
441    p = mbsarg;
442    insize = nchars = nconv = 0;
443    mbs = initial;
444    while (nchars != (size_t)prec) {
445      nconv = mbrlen(p, MB_CUR_MAX, &mbs);
446      if (nconv == 0 || nconv == (size_t)-1 ||
447          nconv == (size_t)-2)
448        break;
449      p += nconv;
450      nchars++;
451      insize += nconv;
452    }
453    if (nconv == (size_t)-1 || nconv == (size_t)-2)
454      return (NULL);
455  } else
456    insize = strlen(mbsarg);
457
458  /*
459   * Allocate buffer for the result and perform the conversion,
460   * converting at most `size' bytes of the input multibyte string to
461   * wide characters for printing.
462   */
463  convbuf = malloc((insize + 1) * sizeof(*convbuf));
464  if (convbuf == NULL)
465    return (NULL);
466  wcp = convbuf;
467  p = mbsarg;
468  mbs = initial;
469  nconv = 0;
470  while (insize != 0) {
471    nconv = mbrtowc(wcp, p, insize, &mbs);
472    if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
473      break;
474    wcp++;
475    p += nconv;
476    insize -= nconv;
477  }
478  if (nconv == (size_t)-1 || nconv == (size_t)-2) {
479    free(convbuf);
480    return (NULL);
481  }
482  *wcp = L'\0';
483
484  return (convbuf);
485}
486#else
487/*
488 * Convert a wide character string argument for the %ls format to a multibyte
489 * string representation. If not -1, prec specifies the maximum number of
490 * bytes to output, and also means that we can't assume that the wide char.
491 * string ends is null-terminated.
492 */
493static char *
494__wcsconv(wchar_t *wcsarg, int prec)
495{
496  static const mbstate_t initial = { 0 };
497  mbstate_t mbs;
498  char buf[MB_LEN_MAX];
499  wchar_t *p;
500  char *convbuf;
501  size_t clen, nbytes;
502
503  /* Allocate space for the maximum number of bytes we could output. */
504  if (prec < 0) {
505    p = wcsarg;
506    mbs = initial;
507    nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
508    if (nbytes == (size_t)-1)
509      return (NULL);
510  } else {
511    /*
512     * Optimisation: if the output precision is small enough,
513     * just allocate enough memory for the maximum instead of
514     * scanning the string.
515     */
516    if (prec < 128)
517      nbytes = prec;
518    else {
519      nbytes = 0;
520      p = wcsarg;
521      mbs = initial;
522      for (;;) {
523        clen = wcrtomb(buf, *p++, &mbs);
524        if (clen == 0 || clen == (size_t)-1 ||
525            nbytes + clen > (size_t)prec)
526          break;
527        nbytes += clen;
528      }
529    }
530  }
531  if ((convbuf = malloc(nbytes + 1)) == NULL)
532    return (NULL);
533
534  /* Fill the output buffer. */
535  p = wcsarg;
536  mbs = initial;
537  if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
538      nbytes, &mbs)) == (size_t)-1) {
539    free(convbuf);
540    return (NULL);
541  }
542  convbuf[nbytes] = '\0';
543  return (convbuf);
544}
545#endif
546
547/*
548 * MT-safe version
549 */
550int
551WDECL(vf,printf)(FILE * __restrict fp, const CHAR_T * __restrict fmt0, va_list ap)
552{
553  int ret;
554
555  if(fp == NULL) {
556    errno = EINVAL;
557    return (EOF);
558  }
559  FLOCKFILE(fp);
560  ret = WDECL(__vf,printf_unlocked)(fp, fmt0, ap);
561  FUNLOCKFILE(fp);
562  return (ret);
563}
564
565#ifndef NO_FLOATING_POINT
566
567#include <float.h>
568#include <math.h>
569#include "floatio.h"
570
571#define DEFPREC   6
572
573static int exponent(CHAR_T *, int, int);
574#ifndef WIDE_DOUBLE
575static char *cvt(double, int, int, char *, int *, int, int *);
576#endif
577
578#endif /* !NO_FLOATING_POINT */
579
580/*
581 * The size of the buffer we use as scratch space for integer
582 * conversions, among other things.  Technically, we would need the
583 * most space for base 10 conversions with thousands' grouping
584 * characters between each pair of digits.  100 bytes is a
585 * conservative overestimate even for a 128-bit uintmax_t.
586 */
587#define BUF 100
588
589#define STATIC_ARG_TBL_SIZE 8           /* Size of static argument table. */
590
591/*
592 * Flags used during conversion.
593 */
594#define ALT       0x001   /* alternate form */
595#define LADJUST   0x004   /* left adjustment */
596#define LONGDBL   0x008   /* long double */
597#define LONGINT   0x010   /* long integer */
598#define LLONGINT  0x020   /* long long integer */
599#define SHORTINT  0x040   /* short integer */
600#define ZEROPAD   0x080   /* zero (as opposed to blank) pad */
601#define FPT       0x100   /* Floating point number */
602#define GROUPING  0x200   /* use grouping ("'" flag) */
603          /* C99 additional size modifiers: */
604#define SIZET     0x400   /* size_t */
605#define PTRDIFFT  0x800   /* ptrdiff_t */
606#define INTMAXT   0x1000    /* intmax_t */
607#define CHARINT   0x2000    /* print char using int format */
608
609/*
610 * Non-MT-safe version
611 */
612int
613WDECL(__vf,printf_unlocked)(FILE *fp, const CHAR_T *fmt0, va_list ap)
614{
615  CHAR_T *fmt;    /* format string */
616  int ch;     /* character from fmt */
617  int n, n2;    /* handy integer (short term usage) */
618  CHAR_T *cp;   /* handy char pointer (short term usage) */
619  int flags;    /* flags as above */
620  int ret;    /* return value accumulator (number of items converted)*/
621  int width;    /* width from format (%8d), or 0 */
622  int prec;   /* precision from format; <0 for N/A */
623  CHAR_T sign;    /* sign prefix (' ', '+', '-', or \0) */
624  char thousands_sep; /* locale specific thousands separator */
625  const char *grouping; /* locale specific numeric grouping rules */
626#ifndef NO_FLOATING_POINT
627  /*
628   * We can decompose the printed representation of floating
629   * point numbers into several parts, some of which may be empty:
630   *
631   * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
632   *    A       B     ---C---      D       E   F
633   *
634   * A: 'sign' holds this value if present; '\0' otherwise
635   * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
636   * C: cp points to the string MMMNNN.  Leading and trailing
637   *  zeros are not in the string and must be added.
638   * D: expchar holds this character; '\0' if no exponent, e.g. %f
639   * F: at least two digits for decimal, at least one digit for hex
640   */
641  char *decimal_point;  /* locale specific decimal point */
642#ifdef WIDE_DOUBLE
643  int signflag;   /* true if float is negative */
644  union {     /* floating point arguments %[aAeEfFgG] */
645    double dbl;
646    long double ldbl;
647  } fparg;
648  char *dtoaend;    /* pointer to end of converted digits */
649#else
650  double _double;   /* double precision arguments %[eEfgG] */
651  char softsign;    /* temporary negative sign for floats */
652#endif
653  char *dtoaresult; /* buffer allocated by dtoa */
654  int expt = 0;   /* integer value of exponent */
655  char expchar;   /* exponent character: [eEpP\0] */
656  int expsize;    /* character count for expstr */
657  int lead;   /* sig figs before decimal or group sep */
658  int ndig;   /* actual number of digits returned by dtoa */
659  CHAR_T expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
660  int nseps;    /* number of group separators with ' */
661  int nrepeats;   /* number of repeats of the last group */
662#endif
663  u_long  ulval;    /* integer arguments %[diouxX] */
664  uintmax_t ujval;  /* %j, %ll, %q, %t, %z integers */
665  int base;   /* base for [diouxX] conversion */
666  int dprec;    /* a copy of prec if [diouxX], 0 otherwise */
667  int realsz;   /* field size expanded by dprec, sign, etc */
668  int size;   /* size of converted field or string */
669  int prsize;             /* max size of printed field */
670  const char *xdigs;  /* digits for %[xX] conversion */
671#ifdef NARROW
672#define NIOV 8
673  struct __siov *iovp;  /* for PRINT macro */
674  struct __suio uio;  /* output information: summary */
675  struct __siov iov[NIOV];/* ... and individual io vectors */
676#else
677  int n3;
678#endif
679  CHAR_T buf[BUF];  /* buffer with space for digits of uintmax_t */
680  CHAR_T ox[2];   /* space for 0x hex-prefix */
681  union arg *argtable;  /* args, built due to positional arg */
682  union arg statargtable [STATIC_ARG_TBL_SIZE];
683  int nextarg;    /* 1-based argument index */
684  va_list orgap;    /* original argument pointer */
685  CHAR_T *convbuf;  /* multibyte to wide conversion result */
686
687  /*
688   * Choose PADSIZE to trade efficiency vs. size.  If larger printf
689   * fields occur frequently, increase PADSIZE and make the initialisers
690   * below longer.
691   */
692#define PADSIZE 16    /* pad chunk size */
693  static CHAR_T blanks[PADSIZE] =
694   {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
695  static CHAR_T zeroes[PADSIZE] =
696   {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
697
698  static const char xdigs_lower[17] = "0123456789abcdef";
699  static const char xdigs_upper[17] = "0123456789ABCDEF";
700
701  /*
702   * BEWARE, these `goto error' on error, PRINT uses `n2' and
703   * PAD uses `n'.
704   */
705#ifndef NARROW
706#define PRINT(ptr, len) do {      \
707  for (n3 = 0; n3 < (len); n3++)    \
708    __xfputwc((ptr)[n3], fp); \
709} while (/*CONSTCOND*/0)
710#define FLUSH()
711#else
712#define PRINT(ptr, len) do { \
713  iovp->iov_base = __UNCONST(ptr); \
714  iovp->iov_len = (len); \
715  uio.uio_resid += (len); \
716  iovp++; \
717  if (++uio.uio_iovcnt >= NIOV) { \
718    if (__sprint(fp, &uio)) \
719      goto error; \
720    iovp = iov; \
721  } \
722} while (/*CONSTCOND*/0)
723#define FLUSH() do { \
724  if (uio.uio_resid && __sprint(fp, &uio)) \
725    goto error; \
726  uio.uio_iovcnt = 0; \
727  iovp = iov; \
728} while (/*CONSTCOND*/0)
729#endif /* NARROW */
730
731#define PAD(howmany, with)  do {    \
732  if ((n = (howmany)) > 0) {    \
733    while (n > PADSIZE) {   \
734      PRINT(with, PADSIZE); \
735      n -= PADSIZE;   \
736    }       \
737    PRINT(with, n);     \
738  }         \
739} while (/*CONSTCOND*/0)
740#define PRINTANDPAD(p, ep, len, with) do {  \
741  n2 = (ep) - (p);            \
742  if (n2 > (len))       \
743    n2 = (len);     \
744  if (n2 > 0)       \
745    PRINT((p), n2);     \
746  PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
747} while(/*CONSTCOND*/0)
748
749  /*
750   * Get the argument indexed by nextarg.   If the argument table is
751   * built, use it to get the argument.  If its not, get the next
752   * argument (and arguments must be gotten sequentially).
753   */
754#define GETARG(type) \
755  ((/*CONSTCOND*/argtable != NULL) ? *((type*)(void*)(&argtable[nextarg++])) : \
756      (nextarg++, va_arg(ap, type)))
757
758  /*
759   * To extend shorts properly, we need both signed and unsigned
760   * argument extraction methods.
761   */
762#define SARG() \
763  ((long)(flags&LONGINT ? GETARG(long) : \
764      flags&SHORTINT ? (short)GETARG(int) : \
765      flags&CHARINT ? (signed char)GETARG(int) : \
766      GETARG(int)))
767
768#define UARG() \
769  ((u_long)(flags&LONGINT ? GETARG(u_long) : \
770      flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
771      flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
772      (u_long)GETARG(u_int)))
773
774#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
775
776#define SJARG() \
777  (flags&INTMAXT ? GETARG(intmax_t) : \
778      flags&SIZET ? (intmax_t)GETARG(size_t) : \
779      flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
780      (intmax_t)GETARG(long long))
781
782#define UJARG() \
783  (flags&INTMAXT ? GETARG(uintmax_t) : \
784      flags&SIZET ? (uintmax_t)GETARG(size_t) : \
785      flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
786      (uintmax_t)GETARG(unsigned long long))
787
788  /*
789   * Get * arguments, including the form *nn$.  Preserve the nextarg
790   * that the argument can be gotten once the type is determined.
791   */
792#define GETASTER(val) \
793  n2 = 0; \
794  cp = fmt; \
795  while (is_digit(*cp)) { \
796    n2 = 10 * n2 + to_digit(*cp); \
797    cp++; \
798  } \
799  if (*cp == '$') { \
800    int hold = nextarg; \
801    if (argtable == NULL) { \
802      argtable = statargtable; \
803      if (__find_arguments(fmt0, orgap, &argtable) == -1) \
804        goto oomem; \
805    } \
806    nextarg = n2; \
807    val = GETARG (int); \
808    nextarg = hold; \
809    fmt = ++cp; \
810  } else { \
811    val = GETARG (int); \
812  }
813
814  _DIAGASSERT(fp != NULL);
815  _DIAGASSERT(fmt0 != NULL);
816  if(fp == NULL) {
817    errno = EINVAL;
818    return (EOF);
819  }
820
821  _SET_ORIENTATION(fp, -1);
822
823  ndig = -1;  /* XXX gcc */
824
825  thousands_sep = '\0';
826  grouping = NULL;
827#ifndef NO_FLOATING_POINT
828  decimal_point = localeconv()->decimal_point;
829  expsize = 0;    /* XXXGCC -Wuninitialized [sh3,m68000] */
830#endif
831  convbuf = NULL;
832  /* sorry, f{w,}printf(read_only_file, L"") returns {W,}EOF, not 0 */
833  if (cantwrite(fp)) {
834    errno = EBADF;
835    return (END_OF_FILE);
836  }
837
838  /* optimise fprintf(stderr) (and other unbuffered Unix files) */
839  if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
840      fp->_file >= 0)
841    return (__sbprintf(fp, fmt0, ap));
842
843  fmt = (CHAR_T *)__UNCONST(fmt0);
844  argtable = NULL;
845  nextarg = 1;
846  va_copy(orgap, ap);
847#ifdef NARROW
848  uio.uio_iov = iovp = iov;
849  uio.uio_resid = 0;
850  uio.uio_iovcnt = 0;
851#endif
852  ret = 0;
853
854  /*
855   * Scan the format for conversions (`%' character).
856   */
857  for (;;)
858  {
859    const CHAR_T *result;
860
861    for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
862      continue;
863    if ((n = (int)(fmt - cp)) != 0) {
864      if ((unsigned)ret + n > INT_MAX) {
865        ret = END_OF_FILE;
866        goto error;
867      }
868      PRINT(cp, n);
869      ret += n;
870    }
871    if (ch == '\0')
872      goto done;
873    fmt++;    /* skip over '%' */
874
875    flags = 0;
876    dprec = 0;
877    width = 0;
878    prec = -1;
879    sign = '\0';
880    ox[1] = '\0';
881    expchar = '\0';
882    lead = 0;
883    nseps = nrepeats = 0;
884    ulval = 0;
885    ujval = 0;
886    xdigs = NULL;
887
888rflag:    ch = *fmt++;
889reswitch: switch (ch) {
890    case ' ':
891      /*-
892       * ``If the space and + flags both appear, the space
893       * flag will be ignored.''
894       *  -- ANSI X3J11
895       */
896      if (!sign)
897        sign = ' ';
898      goto rflag;
899    case '#':
900      flags |= ALT;
901      goto rflag;
902    case '*':
903      /*-
904       * ``A negative field width argument is taken as a
905       * - flag followed by a positive field width.''
906       *  -- ANSI X3J11
907       * They don't exclude field widths read from args.
908       */
909      GETASTER (width);
910      if (width >= 0)
911        goto rflag;
912      width = -width;
913      /* FALLTHROUGH */
914    case '-':
915      flags |= LADJUST;
916      goto rflag;
917    case '+':
918      sign = '+';
919      goto rflag;
920    case '\'':
921      flags |= GROUPING;
922      thousands_sep = *(localeconv()->thousands_sep);
923      grouping = localeconv()->grouping;
924      goto rflag;
925    case '.':
926      if ((ch = *fmt++) == '*') {
927        GETASTER (prec);
928        goto rflag;
929      }
930      prec = 0;
931      while (is_digit(ch)) {
932        prec = 10 * prec + to_digit(ch);
933        ch = *fmt++;
934      }
935      goto reswitch;
936    case '0':
937      /*-
938       * ``Note that 0 is taken as a flag, not as the
939       * beginning of a field width.''
940       *  -- ANSI X3J11
941       */
942      flags |= ZEROPAD;
943      goto rflag;
944    case '1': case '2': case '3': case '4':
945    case '5': case '6': case '7': case '8': case '9':
946      n = 0;
947      do {
948        n = 10 * n + to_digit(ch);
949        ch = *fmt++;
950      } while (is_digit(ch));
951      if (ch == '$') {
952        nextarg = n;
953        if (argtable == NULL) {
954          argtable = statargtable;
955          if (__find_arguments(fmt0, orgap,
956              &argtable) == -1)
957            goto oomem;
958        }
959        goto rflag;
960      }
961      width = n;
962      goto reswitch;
963#ifndef NO_FLOATING_POINT
964    case 'L':
965      flags |= LONGDBL;
966      goto rflag;
967#endif
968    case 'h':
969      if (flags & SHORTINT) {
970        flags &= ~SHORTINT;
971        flags |= CHARINT;
972      } else
973        flags |= SHORTINT;
974      goto rflag;
975    case 'j':
976      flags |= INTMAXT;
977      goto rflag;
978    case 'l':
979      if (flags & LONGINT) {
980        flags &= ~LONGINT;
981        flags |= LLONGINT;
982      } else
983        flags |= LONGINT;
984      goto rflag;
985    case 'q':
986      flags |= LLONGINT;  /* not necessarily */
987      goto rflag;
988    case 't':
989      flags |= PTRDIFFT;
990      goto rflag;
991    case 'z':
992      flags |= SIZET;
993      goto rflag;
994    case 'C':
995      flags |= LONGINT;
996      /*FALLTHROUGH*/
997    case 'c':
998#ifdef NARROW
999      if (flags & LONGINT) {
1000        static const mbstate_t initial = { 0 };
1001        mbstate_t mbs;
1002        size_t mbseqlen;
1003
1004        mbs = initial;
1005        mbseqlen = wcrtomb(buf,
1006            /* The compiler "knows" that wint_t may be smaller than an int so
1007               it warns about it when used as the type argument to va_arg().
1008               Since any type of parameter smaller than an int is promoted to an int on a
1009               function call, we must call GETARG with type int instead of wint_t.
1010            */
1011            (wchar_t)GETARG(int), &mbs);
1012        if (mbseqlen == (size_t)-1) {
1013          fp->_flags |= __SERR;
1014          goto error;
1015        }
1016        size = (int)mbseqlen;
1017      } else {
1018        *buf = (char)(GETARG(int));
1019        size = 1;
1020      }
1021#else
1022      if (flags & LONGINT)
1023        *buf = (wchar_t)GETARG(int);
1024      else
1025        *buf = (wchar_t)btowc(GETARG(int));
1026      size = 1;
1027#endif
1028      result = buf;
1029      sign = '\0';
1030      break;
1031    case 'D':
1032      flags |= LONGINT;
1033      /*FALLTHROUGH*/
1034    case 'd':
1035    case 'i':
1036      if (flags & INTMAX_SIZE) {
1037        ujval = SJARG();
1038        if ((intmax_t)ujval < 0) {
1039          ujval = (uintmax_t)(-((intmax_t)ujval));
1040          sign = '-';
1041        }
1042      } else {
1043        ulval = SARG();
1044        if ((long)ulval < 0) {
1045          ulval = (u_long)(-((long)ulval));
1046          sign = '-';
1047        }
1048      }
1049      base = 10;
1050      goto number;
1051#ifndef NO_FLOATING_POINT
1052#ifdef WIDE_DOUBLE
1053    case 'a':
1054    case 'A':
1055      if (ch == 'a') {
1056        ox[1] = 'x';
1057        xdigs = xdigs_lower;
1058        expchar = 'p';
1059      } else {
1060        ox[1] = 'X';
1061        xdigs = xdigs_upper;
1062        expchar = 'P';
1063      }
1064      if (flags & LONGDBL) {
1065        fparg.ldbl = GETARG(long double);
1066        dtoaresult =
1067            __hldtoa(fparg.ldbl, xdigs, prec,
1068                &expt, &signflag, &dtoaend);
1069      } else {
1070        fparg.dbl = GETARG(double);
1071        dtoaresult =
1072            __hdtoa(fparg.dbl, xdigs, prec,
1073                &expt, &signflag, &dtoaend);
1074      }
1075      if (dtoaresult == NULL)
1076        goto oomem;
1077
1078      if (prec < 0)
1079        prec = dtoaend - dtoaresult;
1080      if (expt == INT_MAX)
1081        ox[1] = '\0';
1082      ndig = dtoaend - dtoaresult;
1083      if (convbuf != NULL)
1084        free(convbuf);
1085#ifndef NARROW
1086      result = convbuf = __mbsconv(dtoaresult, -1);
1087#else
1088      /*XXX inefficient*/
1089      result = convbuf = strdup(dtoaresult);
1090#endif
1091      if (result == NULL)
1092        goto oomem;
1093      __freedtoa(dtoaresult);
1094      goto fp_common;
1095    case 'e':
1096    case 'E':
1097      expchar = ch;
1098      if (prec < 0)
1099        prec = DEFPREC;
1100      goto fp_begin;
1101    case 'f':
1102    case 'F':
1103      expchar = '\0';
1104      goto fp_begin;
1105    case 'g':
1106    case 'G':
1107      expchar = ch - ('g' - 'e');
1108      if (prec == 0)
1109        prec = 1;
1110fp_begin:
1111      if (prec < 0)
1112        prec = DEFPREC;
1113      if (flags & LONGDBL) {
1114        fparg.ldbl = GETARG(long double);
1115        dtoaresult =
1116            __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
1117            &expt, &signflag, &dtoaend);
1118      } else {
1119        fparg.dbl = GETARG(double);
1120        dtoaresult =
1121            __dtoa(fparg.dbl, expchar ? 2 : 3, prec,
1122            &expt, &signflag, &dtoaend);
1123        if (expt == 9999)
1124          expt = INT_MAX;
1125      }
1126      if (dtoaresult == NULL)
1127        goto oomem;
1128      ndig = dtoaend - dtoaresult;
1129      if (convbuf != NULL)
1130        free(convbuf);
1131#ifndef NARROW
1132      result = convbuf = __mbsconv(dtoaresult, -1);
1133#else
1134      /*XXX inefficient*/
1135      result = convbuf = strdup(dtoaresult);
1136#endif
1137      if (result == NULL)
1138        goto oomem;
1139      __freedtoa(dtoaresult);
1140fp_common:
1141      if (signflag)
1142        sign = '-';
1143      if (expt == INT_MAX) {  /* inf or nan */
1144        if (*result == 'N') {
1145          result = (ch >= 'a') ? STRCONST("nan") :
1146              STRCONST("NAN");
1147          sign = '\0';
1148        } else
1149          result = (ch >= 'a') ? STRCONST("inf") :
1150              STRCONST("INF");
1151        size = 3;
1152        break;
1153      }
1154#else
1155    //case 'e':
1156    //case 'E':
1157    //case 'f':
1158    //case 'F':
1159    //case 'g':
1160    //case 'G':
1161    //  if (prec == -1) {
1162    //    prec = DEFPREC;
1163    //  } else if ((ch == 'g' || ch == 'G') && prec == 0) {
1164    //    prec = 1;
1165    //  }
1166    case 'e':
1167    case 'E':
1168      expchar = ch;
1169      if (prec < 0)
1170        prec = DEFPREC;
1171      goto fp_begin;
1172    case 'f':
1173    case 'F':
1174      expchar = '\0';
1175      goto fp_begin;
1176    case 'g':
1177    case 'G':
1178      expchar = ch - ('g' - 'e');
1179      if (prec == 0)
1180        prec = 1;
1181fp_begin:
1182      if (prec < 0)
1183        prec = DEFPREC;
1184
1185      if (flags & LONGDBL) {
1186        _double = (double) GETARG(long double);
1187      } else {
1188        _double = GETARG(double);
1189      }
1190
1191      /* do this before tricky precision changes */
1192      if (isinf(_double)) {
1193        if (_double < 0)
1194          sign = '-';
1195        if (ch == 'E' || ch == 'F' || ch == 'G')
1196          result = STRCONST("INF");
1197        else
1198          result = STRCONST("inf");
1199        size = 3;
1200        break;
1201      }
1202      if (isnan(_double)) {
1203        if (ch == 'E' || ch == 'F' || ch == 'G')
1204          result = STRCONST("NAN");
1205        else
1206          result = STRCONST("nan");
1207        size = 3;
1208        break;
1209      }
1210
1211      flags |= FPT;
1212      dtoaresult = cvt(_double, prec, flags, &softsign, &expt, ch, &ndig);
1213      if (dtoaresult == NULL)
1214        goto oomem;
1215      if (convbuf != NULL)
1216        free(convbuf);
1217#ifndef NARROW
1218      result = convbuf = __mbsconv(dtoaresult, -1);
1219#else
1220      /*XXX inefficient*/
1221      result = convbuf = strdup(dtoaresult);
1222#endif
1223      if (result == NULL)
1224        goto oomem;
1225      __freedtoa(dtoaresult);
1226      if (softsign)
1227        sign = '-';
1228#endif
1229      flags |= FPT;
1230      if (ch == 'g' || ch == 'G') {
1231        if (expt > -4 && expt <= prec) {
1232          /* Make %[gG] smell like %[fF] */
1233          expchar = '\0';
1234          if (flags & ALT)
1235            prec -= expt;
1236          else
1237            prec = ndig - expt;
1238          if (prec < 0)
1239            prec = 0;
1240        } else {
1241          /*
1242           * Make %[gG] smell like %[eE], but
1243           * trim trailing zeroes if no # flag.
1244           *
1245           * Note: The precision field used with [gG] is the number significant
1246           * digits to print.  When converting to [eE] the digit before the
1247           * decimal must not be included in the precision value.
1248           */
1249          if (!(flags & ALT))
1250            prec = ndig - 1;
1251        }
1252      }
1253      if (expchar) {
1254        dprec = prec; /* In some cases dprec will not be set.  Make sure it is set now */
1255        expsize = exponent(expstr, expt - 1, expchar);
1256        size = expsize + prec + 1; /* Leading digit + exponent string + precision */
1257        if (prec >= 1 || flags & ALT)
1258          ++size; /* Decimal point is added to character count */
1259      } else {
1260        /* space for digits before decimal point */
1261        if (expt > 0)
1262          size = expt;
1263        else  /* "0" */
1264          size = 1;
1265        /* space for decimal pt and following digits */
1266        if (prec || flags & ALT)
1267          size += prec + 1;
1268        if (grouping && expt > 0) {
1269          /* space for thousands' grouping */
1270          nseps = nrepeats = 0;
1271          lead = expt;
1272          while (*grouping != CHAR_MAX) {
1273            if (lead <= *grouping)
1274              break;
1275            lead -= *grouping;
1276            if (*(grouping+1)) {
1277              nseps++;
1278              grouping++;
1279            } else
1280              nrepeats++;
1281          }
1282          size += nseps + nrepeats;
1283        } else
1284          lead = expt;
1285      }
1286      break;
1287#endif /* !NO_FLOATING_POINT */
1288    case 'n':
1289      /*
1290       * Assignment-like behavior is specified if the
1291       * value overflows or is otherwise unrepresentable.
1292       * C99 says to use `signed char' for %hhn conversions.
1293       */
1294      if (flags & LLONGINT)
1295        *GETARG(long long *) = ret;
1296      else if (flags & SIZET)
1297        *GETARG(ssize_t *) = (ssize_t)ret;
1298      else if (flags & PTRDIFFT)
1299        *GETARG(ptrdiff_t *) = ret;
1300      else if (flags & INTMAXT)
1301        *GETARG(intmax_t *) = ret;
1302      else if (flags & LONGINT)
1303        *GETARG(long *) = ret;
1304      else if (flags & SHORTINT)
1305        *GETARG(short *) = ret;
1306      else if (flags & CHARINT)
1307        *GETARG(signed char *) = ret;
1308      else
1309        *GETARG(int *) = ret;
1310      continue; /* no output */
1311    case 'O':
1312      flags |= LONGINT;
1313      /*FALLTHROUGH*/
1314    case 'o':
1315      if (flags & INTMAX_SIZE)
1316        ujval = UJARG();
1317      else
1318        ulval = UARG();
1319      base = 8;
1320      goto nosign;
1321    case 'p':
1322      /*-
1323       * ``The argument shall be a pointer to void.  The
1324       * value of the pointer is converted to a sequence
1325       * of printable characters, in an implementation-
1326       * defined manner.''
1327       *  -- ANSI X3J11
1328       */
1329      ujval = (uintmax_t) (UINTN) GETARG(void *);
1330      base = 16;
1331      xdigs = xdigs_lower;
1332      flags = flags | INTMAXT;
1333      ox[1] = 'x';
1334      goto nosign;
1335    case 'S':
1336      flags |= LONGINT;
1337      /*FALLTHROUGH*/
1338    case 's':
1339      if (((flags & LONGINT) ? 1:0) != MULTI) {
1340        if ((result = GETARG(CHAR_T *)) == NULL)
1341          result = STRCONST("(null)");
1342      } else {
1343        MCHAR_T *mc;
1344
1345        if (convbuf != NULL)
1346          free(convbuf);
1347        if ((mc = GETARG(MCHAR_T *)) == NULL)
1348          result = STRCONST("(null)");
1349        else {
1350          convbuf = SCONV(mc, prec);
1351          if (convbuf == NULL) {
1352            fp->_flags |= __SERR;
1353            goto error;
1354          }
1355          result = convbuf;
1356        }
1357      }
1358
1359      if (prec >= 0) {
1360        /*
1361         * can't use STRLEN; can only look for the
1362         * NUL in the first `prec' characters, and
1363         * STRLEN() will go further.
1364         */
1365        CHAR_T *p = MEMCHR(result, 0, (size_t)prec);
1366
1367        if (p != NULL) {
1368          size = p - result;
1369          if (size > prec)
1370            size = prec;
1371        } else
1372          size = prec;
1373      } else
1374        size = (int)STRLEN(result);
1375      sign = '\0';
1376      break;
1377    case 'U':
1378      flags |= LONGINT;
1379      /*FALLTHROUGH*/
1380    case 'u':
1381      if (flags & INTMAX_SIZE)
1382        ujval = UJARG();
1383      else
1384        ulval = UARG();
1385      base = 10;
1386      goto nosign;
1387    case 'X':
1388      xdigs = xdigs_upper;
1389      goto hex;
1390    case 'x':
1391      xdigs = xdigs_lower;
1392hex:
1393      if (flags & INTMAX_SIZE)
1394        ujval = UJARG();
1395      else
1396        ulval = UARG();
1397      base = 16;
1398      /* leading 0x/X only if non-zero */
1399      if (flags & ALT &&
1400          (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
1401        ox[1] = ch;
1402
1403      flags &= ~GROUPING;
1404      /* unsigned conversions */
1405nosign:     sign = '\0';
1406      /*-
1407       * ``... diouXx conversions ... if a precision is
1408       * specified, the 0 flag will be ignored.''
1409       *  -- ANSI X3J11
1410       */
1411number:     if ((dprec = prec) >= 0)
1412        flags &= ~ZEROPAD;
1413
1414      /*-
1415       * ``The result of converting a zero value with an
1416       * explicit precision of zero is no characters.''
1417       *  -- ANSI X3J11
1418       *
1419       * ``The C Standard is clear enough as is.  The call
1420       * printf("%#.0o", 0) should print 0.''
1421       *  -- Defect Report #151
1422       */
1423      result = cp = buf + BUF;
1424      if (flags & INTMAX_SIZE) {
1425        if (ujval != 0 || prec != 0 ||
1426            (flags & ALT && base == 8))
1427        {
1428          result = __ujtoa(ujval, cp, base,
1429              flags & ALT, xdigs,
1430              flags & GROUPING, thousands_sep,
1431              grouping);
1432        }
1433      } else {
1434        if (ulval != 0 || prec != 0 ||
1435            (flags & ALT && base == 8))
1436          result = __ultoa(ulval, cp, base,
1437              flags & ALT, xdigs,
1438              flags & GROUPING, thousands_sep,
1439              grouping);
1440      }
1441      size = buf + BUF - result;
1442      if (size > BUF) /* should never happen */
1443        abort();
1444      break;
1445    default:  /* "%?" prints ?, unless ? is NUL */
1446      if (ch == '\0')
1447        goto done;
1448      /* pretend it was %c with argument ch */
1449      *buf = ch;
1450      result = buf;
1451      size = 1;
1452      sign = '\0';
1453      break;
1454    }
1455
1456    /*
1457     * All reasonable formats wind up here.  At this point, `result'
1458     * points to a string which (if not flags&LADJUST) should be
1459     * padded out to `width' places.  If flags&ZEROPAD, it should
1460     * first be prefixed by any sign or other prefix; otherwise,
1461     * it should be blank padded before the prefix is emitted.
1462     * After any left-hand padding and prefixing, emit zeroes
1463     * required by a decimal [diouxX] precision, then print the
1464     * string proper, then emit zeroes required by any leftover
1465     * floating precision; finally, if LADJUST, pad with blanks.
1466     *
1467     * Compute actual size, so we know how much to pad.
1468     * size excludes decimal prec; realsz includes it.
1469     */
1470    realsz = dprec > size ? dprec : size;
1471    if (sign)
1472      realsz++;
1473    if (ox[1])
1474      realsz += 2;
1475
1476    prsize = width > realsz ? width : realsz;
1477    if ((unsigned)ret + prsize > INT_MAX) {
1478      ret = END_OF_FILE;
1479      goto error;
1480    }
1481
1482    /* right-adjusting blank padding */
1483    if ((flags & (LADJUST|ZEROPAD)) == 0)
1484      PAD(width - realsz, blanks);
1485
1486    /* prefix */
1487    if (sign)
1488      PRINT(&sign, 1);
1489
1490    if (ox[1]) {  /* ox[1] is either x, X, or \0 */
1491      ox[0] = '0';
1492      PRINT(ox, 2);
1493    }
1494
1495    /* right-adjusting zero padding */
1496    if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1497      PAD(width - realsz, zeroes);
1498
1499    /* leading zeroes from decimal precision */
1500    PAD(dprec - size, zeroes);
1501
1502    /* the string or number proper */
1503#ifndef NO_FLOATING_POINT
1504    if ((flags & FPT) == 0) {
1505      PRINT(result, size);
1506    } else {  /* glue together f_p fragments */
1507      if (!expchar) { /* %[fF] or sufficiently short %[gG] */
1508        if (expt <= 0) {
1509          PRINT(zeroes, 1);
1510          if (prec || flags & ALT)
1511            PRINT(decimal_point, 1);
1512          PAD(-expt, zeroes);
1513          /* already handled initial 0's */
1514          prec += expt;
1515        } else {
1516          PRINTANDPAD(result, convbuf + ndig,
1517              lead, zeroes);
1518          result += lead;
1519          if (grouping) {
1520            while (nseps>0 || nrepeats>0) {
1521              if (nrepeats > 0)
1522                nrepeats--;
1523              else {
1524                grouping--;
1525                nseps--;
1526              }
1527              PRINT(&thousands_sep,
1528                  1);
1529              PRINTANDPAD(result,
1530                  convbuf + ndig,
1531                  *grouping, zeroes);
1532              result += *grouping;
1533            }
1534            if (result > convbuf + ndig)
1535              result = convbuf + ndig;
1536          }
1537          if (prec || flags & ALT) {
1538            buf[0] = *decimal_point;
1539            PRINT(buf, 1);
1540          }
1541        }
1542        PRINTANDPAD(result, convbuf + ndig, prec,
1543            zeroes);
1544      } else {  /* %[eE] or sufficiently long %[gG] */
1545        if (prec >= 1 || flags & ALT) {
1546          buf[0] = *result++;
1547          buf[1] = *decimal_point;
1548          PRINT(buf, 2);
1549          PRINT(result, ndig-1);
1550          PAD(prec - ndig, zeroes);
1551        } else  /* XeYYY */
1552          PRINT(result, 1);
1553        PRINT(expstr, expsize);
1554      }
1555    }
1556#else
1557    PRINT(result, size);
1558#endif
1559    /* left-adjusting padding (always blank) */
1560    if (flags & LADJUST)
1561      PAD(width - realsz, blanks);
1562
1563    /* finally, adjust ret */
1564    ret += prsize;
1565    FLUSH();
1566  }
1567done:
1568  FLUSH();
1569error:
1570  va_end(orgap);
1571  if (convbuf != NULL)
1572    free(convbuf);
1573  if (__sferror(fp))
1574    ret = END_OF_FILE;
1575  if ((argtable != NULL) && (argtable != statargtable))
1576    free (argtable);
1577  return (ret);
1578  /* NOTREACHED */
1579oomem:
1580  errno = ENOMEM;
1581  ret = END_OF_FILE;
1582  goto error;
1583}
1584
1585/*
1586 * Find all arguments when a positional parameter is encountered.  Returns a
1587 * table, indexed by argument number, of pointers to each arguments.  The
1588 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
1589 * It will be replaces with a malloc-ed one if it overflows.
1590 */
1591static int
1592__find_arguments(const CHAR_T *fmt0, va_list ap, union arg **argtable)
1593{
1594  CHAR_T *fmt;    /* format string */
1595  int ch;     /* character from fmt */
1596  int n, n2;    /* handy integer (short term usage) */
1597  CHAR_T *cp;   /* handy char pointer (short term usage) */
1598  int flags;    /* flags as above */
1599  enum typeid *typetable; /* table of types */
1600  enum typeid stattypetable [STATIC_ARG_TBL_SIZE];
1601  int tablesize;    /* current size of type table */
1602  int tablemax;   /* largest used index in table */
1603  int nextarg;    /* 1-based argument index */
1604
1605  /*
1606   * Add an argument type to the table, expanding if necessary.
1607   */
1608#define ADDTYPE(type) \
1609  do { \
1610    if (nextarg >= tablesize) \
1611      if (__grow_type_table(nextarg, &typetable, \
1612          &tablesize) == -1) \
1613        return -1; \
1614    if (nextarg > tablemax) \
1615      tablemax = nextarg; \
1616    typetable[nextarg++] = type; \
1617  } while (/*CONSTCOND*/0)
1618
1619#define ADDSARG() \
1620  do { \
1621    if (flags & INTMAXT)  \
1622      ADDTYPE(T_INTMAXT); \
1623    else if (flags & SIZET)  \
1624      ADDTYPE(T_SIZET); \
1625    else if (flags & PTRDIFFT) \
1626      ADDTYPE(T_PTRDIFFT); \
1627    else if (flags & LLONGINT) \
1628      ADDTYPE(T_LLONG); \
1629    else if (flags & LONGINT) \
1630      ADDTYPE(T_LONG); \
1631    else \
1632      ADDTYPE(T_INT); \
1633  } while (/*CONSTCOND*/0)
1634
1635#define ADDUARG() \
1636  do { \
1637    if (flags & INTMAXT)  \
1638      ADDTYPE(T_UINTMAXT); \
1639    else if (flags & SIZET)  \
1640      ADDTYPE(T_SIZET); \
1641    else if (flags & PTRDIFFT) \
1642      ADDTYPE(T_PTRDIFFT); \
1643    else if (flags & LLONGINT) \
1644      ADDTYPE(T_U_LLONG); \
1645    else if (flags & LONGINT) \
1646      ADDTYPE(T_U_LONG); \
1647    else \
1648      ADDTYPE(T_U_INT); \
1649  } while (/*CONSTCOND*/0)
1650  /*
1651   * Add * arguments to the type array.
1652   */
1653#define ADDASTER() \
1654  n2 = 0; \
1655  cp = fmt; \
1656  while (is_digit(*cp)) { \
1657    n2 = 10 * n2 + to_digit(*cp); \
1658    cp++; \
1659  } \
1660  if (*cp == '$') { \
1661    int hold = nextarg; \
1662    nextarg = n2; \
1663    ADDTYPE(T_INT); \
1664    nextarg = hold; \
1665    fmt = ++cp; \
1666  } else { \
1667    ADDTYPE(T_INT); \
1668  }
1669  fmt = (CHAR_T *)__UNCONST(fmt0);
1670  typetable = stattypetable;
1671  tablesize = STATIC_ARG_TBL_SIZE;
1672  tablemax = 0;
1673  nextarg = 1;
1674  for (n = 0; n < STATIC_ARG_TBL_SIZE; n++)
1675    typetable[n] = T_UNUSED;
1676
1677  /*
1678   * Scan the format for conversions (`%' character).
1679   */
1680  for (;;) {
1681    for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
1682      /* void */;
1683    if (ch == '\0')
1684      goto done;
1685    fmt++;    /* skip over '%' */
1686
1687    flags = 0;
1688
1689rflag:    ch = *fmt++;
1690reswitch: switch (ch) {
1691    case ' ':
1692    case '#':
1693      goto rflag;
1694    case '*':
1695      ADDASTER ();
1696      goto rflag;
1697    case '-':
1698    case '+':
1699    case '\'':
1700      goto rflag;
1701    case '.':
1702      if ((ch = *fmt++) == '*') {
1703        ADDASTER ();
1704        goto rflag;
1705      }
1706      while (is_digit(ch)) {
1707        ch = *fmt++;
1708      }
1709      goto reswitch;
1710    case '0':
1711      goto rflag;
1712    case '1': case '2': case '3': case '4':
1713    case '5': case '6': case '7': case '8': case '9':
1714      n = 0;
1715      do {
1716        n = 10 * n + to_digit(ch);
1717        ch = *fmt++;
1718      } while (is_digit(ch));
1719      if (ch == '$') {
1720        nextarg = n;
1721        goto rflag;
1722      }
1723      goto reswitch;
1724#ifndef NO_FLOATING_POINT
1725    case 'L':
1726      flags |= LONGDBL;
1727      goto rflag;
1728#endif
1729    case 'h':
1730      if (flags & SHORTINT) {
1731        flags &= ~SHORTINT;
1732        flags |= CHARINT;
1733      } else
1734        flags |= SHORTINT;
1735      goto rflag;
1736    case 'j':
1737      flags |= INTMAXT;
1738      goto rflag;
1739    case 'l':
1740      if (flags & LONGINT) {
1741        flags &= ~LONGINT;
1742        flags |= LLONGINT;
1743      } else
1744        flags |= LONGINT;
1745      goto rflag;
1746    case 'q':
1747      flags |= LLONGINT;  /* not necessarily */
1748      goto rflag;
1749    case 't':
1750      flags |= PTRDIFFT;
1751      goto rflag;
1752    case 'z':
1753      flags |= SIZET;
1754      goto rflag;
1755    case 'C':
1756      flags |= LONGINT;
1757      /*FALLTHROUGH*/
1758    case 'c':
1759      if (flags & LONGINT)
1760        ADDTYPE(T_WINT);
1761      else
1762        ADDTYPE(T_INT);
1763      break;
1764    case 'D':
1765      flags |= LONGINT;
1766      /*FALLTHROUGH*/
1767    case 'd':
1768    case 'i':
1769      ADDSARG();
1770      break;
1771#ifndef NO_FLOATING_POINT
1772    case 'a':
1773    case 'A':
1774    case 'e':
1775    case 'E':
1776    case 'f':
1777    case 'g':
1778    case 'G':
1779      if (flags & LONGDBL)
1780        ADDTYPE(T_LONG_DOUBLE);
1781      else
1782        ADDTYPE(T_DOUBLE);
1783      break;
1784#endif /* !NO_FLOATING_POINT */
1785    case 'n':
1786      if (flags & INTMAXT)
1787        ADDTYPE(TP_INTMAXT);
1788      else if (flags & PTRDIFFT)
1789        ADDTYPE(TP_PTRDIFFT);
1790      else if (flags & SIZET)
1791        ADDTYPE(TP_SIZET);
1792      else if (flags & LLONGINT)
1793        ADDTYPE(TP_LLONG);
1794      else if (flags & LONGINT)
1795        ADDTYPE(TP_LONG);
1796      else if (flags & SHORTINT)
1797        ADDTYPE(TP_SHORT);
1798      else if (flags & CHARINT)
1799        ADDTYPE(TP_SCHAR);
1800      else
1801        ADDTYPE(TP_INT);
1802      continue; /* no output */
1803    case 'O':
1804      flags |= LONGINT;
1805      /*FALLTHROUGH*/
1806    case 'o':
1807      ADDUARG();
1808      break;
1809    case 'p':
1810      ADDTYPE(TP_VOID);
1811      break;
1812    case 'S':
1813      flags |= LONGINT;
1814      /*FALLTHROUGH*/
1815    case 's':
1816      if (flags & LONGINT)
1817        ADDTYPE(TP_WCHAR);
1818      else
1819        ADDTYPE(TP_CHAR);
1820      break;
1821    case 'U':
1822      flags |= LONGINT;
1823      /*FALLTHROUGH*/
1824    case 'u':
1825    case 'X':
1826    case 'x':
1827      ADDUARG();
1828      break;
1829    default:  /* "%?" prints ?, unless ? is NUL */
1830      if (ch == '\0')
1831        goto done;
1832      break;
1833    }
1834  }
1835done:
1836  /*
1837   * Build the argument table.
1838   */
1839  if (tablemax >= STATIC_ARG_TBL_SIZE) {
1840    *argtable = (union arg *)
1841        malloc (sizeof (union arg) * (tablemax + 1));
1842    if (*argtable == NULL)
1843      return -1;
1844  }
1845
1846  (*argtable) [0].intarg = 0;
1847  for (n = 1; n <= tablemax; n++) {
1848    switch (typetable [n]) {
1849        case T_UNUSED: /* whoops! */
1850      (*argtable) [n].intarg = va_arg (ap, int);
1851      break;
1852        case TP_SCHAR:
1853      (*argtable) [n].pschararg = va_arg (ap, signed char *);
1854      break;
1855        case TP_SHORT:
1856      (*argtable) [n].pshortarg = va_arg (ap, short *);
1857      break;
1858        case T_INT:
1859      (*argtable) [n].intarg = va_arg (ap, int);
1860      break;
1861        case T_U_INT:
1862      (*argtable) [n].uintarg = va_arg (ap, unsigned int);
1863      break;
1864        case TP_INT:
1865      (*argtable) [n].pintarg = va_arg (ap, int *);
1866      break;
1867        case T_LONG:
1868      (*argtable) [n].longarg = va_arg (ap, long);
1869      break;
1870        case T_U_LONG:
1871      (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
1872      break;
1873        case TP_LONG:
1874      (*argtable) [n].plongarg = va_arg (ap, long *);
1875      break;
1876        case T_LLONG:
1877      (*argtable) [n].longlongarg = va_arg (ap, long long);
1878      break;
1879        case T_U_LLONG:
1880      (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
1881      break;
1882        case TP_LLONG:
1883      (*argtable) [n].plonglongarg = va_arg (ap, long long *);
1884      break;
1885        case T_PTRDIFFT:
1886      (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
1887      break;
1888        case TP_PTRDIFFT:
1889      (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
1890      break;
1891        case T_SIZET:
1892      (*argtable) [n].sizearg = va_arg (ap, size_t);
1893      break;
1894        case TP_SIZET:
1895      (*argtable) [n].psizearg = va_arg (ap, size_t *);
1896      break;
1897        case T_INTMAXT:
1898      (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
1899      break;
1900        case T_UINTMAXT:
1901      (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
1902      break;
1903        case TP_INTMAXT:
1904      (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
1905      break;
1906        case T_DOUBLE:
1907#ifndef NO_FLOATING_POINT
1908      (*argtable) [n].doublearg = va_arg (ap, double);
1909#endif
1910      break;
1911        case T_LONG_DOUBLE:
1912#ifndef NO_FLOATING_POINT
1913      (*argtable) [n].longdoublearg = va_arg (ap, long double);
1914#endif
1915      break;
1916        case TP_CHAR:
1917      (*argtable) [n].pchararg = va_arg (ap, char *);
1918      break;
1919        case TP_VOID:
1920      (*argtable) [n].pvoidarg = va_arg (ap, void *);
1921      break;
1922        case T_WINT:
1923      (*argtable) [n].wintarg = va_arg (ap, int);
1924      break;
1925        case TP_WCHAR:
1926      (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
1927      break;
1928    }
1929  }
1930
1931  if ((typetable != NULL) && (typetable != stattypetable))
1932    free (typetable);
1933  return 0;
1934}
1935
1936/*
1937 * Increase the size of the type table.
1938 */
1939static int
1940__grow_type_table (int nextarg, enum typeid **typetable, int *tablesize)
1941{
1942  enum typeid *const oldtable = *typetable;
1943  const int oldsize = *tablesize;
1944  enum typeid *newtable;
1945  int n, newsize = oldsize * 2;
1946
1947  if (newsize < nextarg + 1)
1948    newsize = nextarg + 1;
1949  if (oldsize == STATIC_ARG_TBL_SIZE) {
1950    if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
1951      return -1;
1952    memcpy(newtable, oldtable, oldsize * sizeof(enum typeid));
1953  } else {
1954    newtable = realloc(oldtable, newsize * sizeof(enum typeid));
1955    if (newtable == NULL) {
1956      free(oldtable);
1957      return -1;
1958    }
1959  }
1960  for (n = oldsize; n < newsize; n++)
1961    newtable[n] = T_UNUSED;
1962
1963  *typetable = newtable;
1964  *tablesize = newsize;
1965  return 0;
1966}
1967
1968
1969#ifndef NO_FLOATING_POINT
1970#ifndef WIDE_DOUBLE
1971static char *
1972cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch,
1973    int *length)
1974{
1975  int mode, dsgn;
1976  char *digits, *bp, *rve;
1977
1978  _DIAGASSERT(decpt != NULL);
1979  _DIAGASSERT(length != NULL);
1980  _DIAGASSERT(sign != NULL);
1981
1982  if (ch == 'f') {
1983    mode = 3;   /* ndigits after the decimal point */
1984  } else {
1985    /* To obtain ndigits after the decimal point for the 'e'
1986     * and 'E' formats, round to ndigits + 1 significant
1987     * figures.
1988     */
1989    if (ch == 'e' || ch == 'E') {
1990      ndigits++;
1991    }
1992    mode = 2;   /* ndigits significant digits */
1993  }
1994
1995  digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
1996  if (digits == NULL)
1997    return NULL;
1998  if (dsgn) {
1999    value = -value;
2000    *sign = '-';
2001  } else
2002    *sign = '\000';
2003  if ((ch != 'g' && ch != 'G') || flags & ALT) {  /* Print trailing zeros */
2004    bp = digits + ndigits;
2005    if (ch == 'f') {
2006      if (*digits == '0' && value)
2007        *decpt = -ndigits + 1;
2008      bp += *decpt;
2009    }
2010    while (rve < bp)
2011      *rve++ = '0';
2012  }
2013  *length = rve - digits;
2014  return digits;
2015}
2016#endif
2017
2018static int
2019exponent(CHAR_T *p0, int expo, int fmtch)
2020{
2021  CHAR_T *p, *t;
2022  CHAR_T expbuf[MAXEXPDIG];
2023
2024  p = p0;
2025  *p++ = fmtch;
2026  if (expo < 0) {
2027    expo = -expo;
2028    *p++ = '-';
2029  }
2030  else
2031    *p++ = '+';
2032  t = expbuf + MAXEXPDIG;
2033  if (expo > 9) {
2034    do {
2035      *--t = to_char(expo % 10);
2036    } while ((expo /= 10) > 9);
2037    *--t = to_char(expo);
2038    for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
2039  }
2040  else {
2041    /*
2042     * Exponents for decimal floating point conversions
2043     * (%[eEgG]) must be at least two characters long,
2044     * whereas exponents for hexadecimal conversions can
2045     * be only one character long.
2046     */
2047    if (fmtch == 'e' || fmtch == 'E')
2048      *p++ = '0';
2049    *p++ = to_char(expo);
2050  }
2051  return (p - p0);
2052}
2053#endif /* !NO_FLOATING_POINT */
2054