Merge from vendor branch CVS:
[dragonfly.git] / lib / libc / stdio / vfprintf.c
1 /*-
2  * Copyright (c) 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Chris Torek.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * @(#)vfprintf.c       8.1 (Berkeley) 6/4/93
37  * $FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.34 2001/12/13 19:45:41 phantom Exp $
38  * $DragonFly: src/lib/libc/stdio/vfprintf.c,v 1.14 2005/11/20 11:07:30 swildner Exp $
39  */
40
41 /*
42  * Actual printf innards.
43  *
44  * This code is large and complicated...
45  */
46
47 #include "namespace.h"
48 #include <sys/types.h>
49
50 #include <ctype.h>
51 #include <limits.h>
52 #include <locale.h>
53 #include <stddef.h>
54 #include <stdint.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58
59 #include <stdarg.h>
60 #include "un-namespace.h"
61
62 #include "libc_private.h"
63 #include "local.h"
64 #include "priv_stdio.h"
65
66 /* Borrowed from sys/systm.h, which is _KERNEL-only: */
67 #define CTASSERT(x)             _CTASSERT(x, __LINE__)
68 #define _CTASSERT(x, y)         __CTASSERT(x, y)
69 #define __CTASSERT(x, y)        typedef char __assert ## y[(x) ? 1 : -1]
70
71 /* This code assumes that a quad_t can fit in a long long: */
72 CTASSERT(sizeof(quad_t) == sizeof(long long));
73
74 union arg {
75         int                      intarg;
76         unsigned int             uintarg;
77         long                     longarg;
78         unsigned long            ulongarg;
79         long long                longlongarg;
80         unsigned long long       ulonglongarg;
81         ptrdiff_t                ptrdiffarg;
82         size_t                   sizearg;
83         intmax_t                 intmaxarg;
84         uintmax_t                uintmaxarg;
85         void                    *pvoidarg;
86         char                    *pchararg;
87         signed char             *pschararg;
88         short                   *pshortarg;
89         int                     *pintarg;
90         long                    *plongarg;
91         long long               *plonglongarg;
92         ptrdiff_t               *pptrdiffarg;
93         size_t                  *psizearg;
94         intmax_t                *pintmaxarg;
95 #ifndef NO_FLOATING_POINT
96         double                   doublearg;
97         long double              longdoublearg;
98 #endif
99 };
100
101 /*
102  * Type ids for argument type table.
103  */
104 enum typeid {
105         T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
106         T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
107         T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
108         T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
109         T_DOUBLE, T_LONG_DOUBLE
110 };
111
112 static int      __sprint(FILE *, struct __suio *);
113 static int      __sbprintf(FILE *, const char *, va_list) __printflike(2, 0);
114 static char *   __ujtoa(uintmax_t, char *, int, int, const char *, int,
115                      char, const char *);
116 static char *   __ultoa(u_long, char *, int, int, const char *, int,
117                      char, const char *);
118 static void     __find_arguments(const char *, va_list, union arg **);
119 static void     __grow_type_table(int, enum typeid **, int *);
120
121 /*
122  * Flush out all the vectors defined by the given uio,
123  * then reset it so that it can be reused.
124  */
125 static int
126 __sprint(FILE *fp, struct __suio *uio)
127 {
128         int err;
129
130         if (uio->uio_resid == 0) {
131                 uio->uio_iovcnt = 0;
132                 return (0);
133         }
134         err = __sfvwrite(fp, uio);
135         uio->uio_resid = 0;
136         uio->uio_iovcnt = 0;
137         return (err);
138 }
139
140 /*
141  * Helper function for `fprintf to unbuffered unix file': creates a
142  * temporary buffer.  We only work on write-only files; this avoids
143  * worries about ungetc buffers and so forth.
144  */
145 static int
146 __sbprintf(FILE *fp, const char *fmt, va_list ap)
147 {
148         int ret;
149         FILE fake;
150         unsigned char buf[BUFSIZ];
151
152         /* copy the important variables */
153         fake.pub._flags = fp->pub._flags & ~__SNBF;
154         fake.pub._fileno = fp->pub._fileno;
155         fake._cookie = fp->_cookie;
156         fake._write = fp->_write;
157
158         fake._up = fp->_up;
159         fake.fl_mutex = fp->fl_mutex;
160         fake.fl_owner = fp->fl_owner;
161         fake.fl_count = fp->fl_count;
162
163         /* set up the buffer */
164         fake._bf._base = fake.pub._p = buf;
165         fake._bf._size = fake.pub._w = sizeof(buf);
166         fake.pub._lbfsize = 0;  /* not actually used, but Just In Case */
167
168         /* do the work, then copy any error status */
169         ret = __vfprintf(&fake, fmt, ap);
170         if (ret >= 0 && __fflush(&fake))
171                 ret = EOF;
172         if (fake.pub._flags & __SERR)
173                 fp->pub._flags |= __SERR;
174         return (ret);
175 }
176
177 /*
178  * Macros for converting digits to letters and vice versa
179  */
180 #define to_digit(c)     ((c) - '0')
181 #define is_digit(c)     ((unsigned)to_digit(c) <= 9)
182 #define to_char(n)      ((n) + '0')
183
184 /*
185  * Convert an unsigned long to ASCII for printf purposes, returning
186  * a pointer to the first character of the string representation.
187  * Octal numbers can be forced to have a leading zero; hex numbers
188  * use the given digits.
189  */
190 static char *
191 __ultoa(u_long val, char *endp, int base, int octzero, const char *xdigs,
192         int needgrp, char thousep, const char *grp)
193 {
194         char *cp = endp;
195         long sval;
196         int ndig;
197
198         /*
199          * Handle the three cases separately, in the hope of getting
200          * better/faster code.
201          */
202         switch (base) {
203         case 10:
204                 if (val < 10) { /* many numbers are 1 digit */
205                         *--cp = to_char(val);
206                         return (cp);
207                 }
208                 ndig = 0;
209                 /*
210                  * On many machines, unsigned arithmetic is harder than
211                  * signed arithmetic, so we do at most one unsigned mod and
212                  * divide; this is sufficient to reduce the range of
213                  * the incoming value to where signed arithmetic works.
214                  */
215                 if (val > LONG_MAX) {
216                         *--cp = to_char(val % 10);
217                         ndig++;
218                         sval = val / 10;
219                 } else
220                         sval = val;
221                 do {
222                         *--cp = to_char(sval % 10);
223                         ndig++;
224                         /*
225                          * If (*grp == CHAR_MAX) then no more grouping
226                          * should be performed.
227                          */
228                         if (needgrp && ndig == *grp && *grp != CHAR_MAX &&
229                             sval > 9) {
230                                 *--cp = thousep;
231                                 ndig = 0;
232                                 /*
233                                  * If (*(grp+1) == '\0') then we have to
234                                  * use *grp character (last grouping rule)
235                                  * for all next cases
236                                  */
237                                 if (*(grp + 1) != '\0')
238                                         grp++;
239                         }
240                         sval /= 10;
241                 } while (sval != 0);
242                 break;
243
244         case 8:
245                 do {
246                         *--cp = to_char(val & 7);
247                         val >>= 3;
248                 } while (val);
249                 if (octzero && *cp != '0')
250                         *--cp = '0';
251                 break;
252
253         case 16:
254                 do {
255                         *--cp = xdigs[(size_t)val & 15];
256                         val >>= 4;
257                 } while (val);
258                 break;
259
260         default:                        /* oops */
261                 abort();
262         }
263         return (cp);
264 }
265
266 /* Identical to __ultoa, but for intmax_t. */
267 static char *
268 __ujtoa(u_quad_t val, char *endp, int base, int octzero, const char *xdigs,
269         int needgrp, char thousep, const char *grp)
270 {
271         char *cp = endp;
272         intmax_t sval;
273         int ndig;
274
275         /* quick test for small values; __ultoa is typically much faster */
276         /* (perhaps instead we should run until small, then call __ultoa?) */
277         if (val <= ULONG_MAX)
278                 return (__ultoa((u_long)val, endp, base, octzero, xdigs,
279                     needgrp, thousep, grp));
280         switch (base) {
281         case 10:
282                 if (val < 10) {
283                         *--cp = to_char(val % 10);
284                         return (cp);
285                 }
286                 ndig = 0;
287                 if (val > INTMAX_MAX) {
288                         *--cp = to_char(val % 10);
289                         ndig++;
290                         sval = val / 10;
291                 } else
292                         sval = val;
293                 do {
294                         *--cp = to_char(sval % 10);
295                         ndig++;
296                         /*
297                          * If (*grp == CHAR_MAX) then no more grouping
298                          * should be performed.
299                          */
300                         if (needgrp && *grp != CHAR_MAX && ndig == *grp &&
301                             sval > 9) {
302                                 *--cp = thousep;
303                                 ndig = 0;
304                                 /*
305                                  * If (*(grp+1) == '\0') then we have to
306                                  * use *grp character (last grouping rule)
307                                  * for all next cases
308                                  */
309                                 if (*(grp + 1) != '\0')
310                                         grp++;
311                         }
312                         sval /= 10;
313                 } while (sval != 0);
314                 break;
315
316         case 8:
317                 do {
318                         *--cp = to_char(val & 7);
319                         val >>= 3;
320                 } while (val);
321                 if (octzero && *cp != '0')
322                         *--cp = '0';
323                 break;
324
325         case 16:
326                 do {
327                         *--cp = xdigs[(size_t)val & 15];
328                         val >>= 4;
329                 } while (val);
330                 break;
331
332         default:
333                 abort();
334         }
335         return (cp);
336 }
337
338 /*
339  * MT-safe version
340  */
341 int
342 vfprintf(FILE *fp, const char *fmt0, va_list ap)
343 {
344         int ret;
345
346         FLOCKFILE(fp);
347         ret = __vfprintf(fp, fmt0, ap);
348         FUNLOCKFILE(fp);
349         return (ret);
350 }
351
352 #ifndef NO_FLOATING_POINT
353 #include <math.h>
354 #include "floatio.h"
355
356 #define BUF             ((MAXEXPDIG * 2) + MAXFRACT + 1) /* + decimal point */
357 #define DEFPREC         6
358
359 static char *cvt (double, int, int, char *, int *, int, int *, char **);
360 static int exponent (char *, int, int);
361
362 #else /* no NO_FLOATING_POINT */
363
364 #define BUF             136
365
366 #endif /* NO_FLOATING_POINT */
367
368 #define STATIC_ARG_TBL_SIZE 8           /* Size of static argument table. */
369
370 /*
371  * Flags used during conversion.
372  */
373 #define ALT             0x001           /* alternate form */
374 #define HEXPREFIX       0x002           /* add 0x or 0X prefix */
375 #define LADJUST         0x004           /* left adjustment */
376 #define LONGDBL         0x008           /* long double */
377 #define LONGINT         0x010           /* long integer */
378 #define LLONGINT        0x020           /* long long integer */
379 #define SHORTINT        0x040           /* short integer */
380 #define ZEROPAD         0x080           /* zero (as opposed to blank) pad */
381 #define FPT             0x100           /* Floating point number */
382 #define GROUPING        0x200           /* use grouping ("'" flag) */
383                                         /* C99 additional size modifiers: */
384 #define SIZET           0x400           /* size_t */
385 #define PTRDIFFT        0x800           /* ptrdiff_t */
386 #define INTMAXT         0x1000          /* intmax_t */
387 #define CHARINT         0x2000          /* print char using int format */
388 /*
389  * Non-MT-safe version
390  */
391 int
392 __vfprintf(FILE *fp, const char *fmt0, va_list ap)
393 {
394         char *fmt;              /* format string */
395         int ch;                 /* character from fmt */
396         int n, n2;              /* handy integer (short term usage) */
397         char *cp;               /* handy char pointer (short term usage) */
398         struct __siov *iovp;    /* for PRINT macro */
399         int flags;              /* flags as above */
400         int ret;                /* return value accumulator */
401         int width;              /* width from format (%8d), or 0 */
402         int prec;               /* precision from format (%.3d), or -1 */
403         char sign;              /* sign prefix (' ', '+', '-', or \0) */
404         char thousands_sep;     /* locale specific thousands separator */
405         const char *grouping;   /* locale specific numeric grouping rules */
406 #ifndef NO_FLOATING_POINT
407         const char *decimal_point;      /* locale specific decimal point */
408         char softsign;          /* temporary negative sign for floats */
409         double _double;         /* double precision arguments %[eEfgG] */
410         int expt;               /* integer value of exponent */
411         int expsize;            /* character count for expstr */
412         int ndig;               /* actual number of digits returned by cvt */
413         char expstr[7];         /* buffer for exponent string */
414         char *dtoaresult;       /* buffer allocated by dtoa */
415 #endif
416         u_long  ulval;          /* integer arguments %[diouxX] */
417         uintmax_t ujval;        /* %j, %ll, %q, %t, %z integers */
418         int base;               /* base for [diouxX] conversion */
419         int dprec;              /* a copy of prec if [diouxX], 0 otherwise */
420         int realsz;             /* field size expanded by dprec, sign, etc */
421         int size;               /* size of converted field or string */
422         int prsize;             /* max size of printed field */
423         const char *xdigs;      /* digits for [xX] conversion */
424 #define NIOV 8
425         struct __suio uio;      /* output information: summary */
426         struct __siov iov[NIOV];/* ... and individual io vectors */
427         char buf[BUF];          /* space for %c, %[diouxX], %[eEfFgG] */
428         char ox[2];             /* space for 0x hex-prefix */
429         union arg *argtable;    /* args, built due to positional arg */
430         union arg statargtable[STATIC_ARG_TBL_SIZE];
431         int nextarg;            /* 1-based argument index */
432         va_list orgap;          /* original argument pointer */
433
434         _double = 0;
435         expsize = 0;
436         ulval = 0;
437         ujval = 0;
438         xdigs = NULL;
439
440         /*
441          * Choose PADSIZE to trade efficiency vs. size.  If larger printf
442          * fields occur frequently, increase PADSIZE and make the initialisers
443          * below longer.
444          */
445 #define PADSIZE 16              /* pad chunk size */
446         static char blanks[PADSIZE] =
447          {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
448         static char zeroes[PADSIZE] =
449          {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
450
451         /*
452          * BEWARE, these `goto error' on error, and PAD uses `n'.
453          */
454 #define PRINT(ptr, len) { \
455         iovp->iov_base = __DECONST(void *, ptr); \
456         iovp->iov_len = (len); \
457         uio.uio_resid += (len); \
458         iovp++; \
459         if (++uio.uio_iovcnt >= NIOV) { \
460                 if (__sprint(fp, &uio)) \
461                         goto error; \
462                 iovp = iov; \
463         } \
464 }
465 #define PAD(howmany, with) { \
466         if ((n = (howmany)) > 0) { \
467                 while (n > PADSIZE) { \
468                         PRINT(with, PADSIZE); \
469                         n -= PADSIZE; \
470                 } \
471                 PRINT(with, n); \
472         } \
473 }
474 #define FLUSH() { \
475         if (uio.uio_resid && __sprint(fp, &uio)) \
476                 goto error; \
477         uio.uio_iovcnt = 0; \
478         iovp = iov; \
479 }
480
481         /*
482          * Get the argument indexed by nextarg.   If the argument table is
483          * built, use it to get the argument.  If its not, get the next
484          * argument (and arguments must be gotten sequentially).
485          */
486 #define GETARG(type) \
487         ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
488             (nextarg++, va_arg(ap, type)))
489
490         /*
491          * To extend shorts properly, we need both signed and unsigned
492          * argument extraction methods.
493          */
494 #define SARG() \
495         (flags&LONGINT ? GETARG(long) : \
496             flags&SHORTINT ? (long)(short)GETARG(int) : \
497             flags&CHARINT ? (long)(signed char)GETARG(int) : \
498             (long)GETARG(int))
499 #define UARG() \
500         (flags&LONGINT ? GETARG(u_long) : \
501             flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
502             flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
503             (u_long)GETARG(u_int))
504 #define INTMAX_SIZE     (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
505 #define SJARG() \
506         (flags&INTMAXT ? GETARG(intmax_t) : \
507             flags&SIZET ? (intmax_t)GETARG(size_t) : \
508             flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
509             (intmax_t)GETARG(long long))
510 #define UJARG() \
511         (flags&INTMAXT ? GETARG(uintmax_t) : \
512             flags&SIZET ? (uintmax_t)GETARG(size_t) : \
513             flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
514             (uintmax_t)GETARG(unsigned long long))
515
516         /*
517          * Get * arguments, including the form *nn$.  Preserve the nextarg
518          * that the argument can be gotten once the type is determined.
519          */
520 #define GETASTER(val) \
521         n2 = 0; \
522         cp = fmt; \
523         while (is_digit(*cp)) { \
524                 n2 = 10 * n2 + to_digit(*cp); \
525                 cp++; \
526         } \
527         if (*cp == '$') { \
528                 int hold = nextarg; \
529                 if (argtable == NULL) { \
530                         argtable = statargtable; \
531                         __find_arguments (fmt0, orgap, &argtable); \
532                 } \
533                 nextarg = n2; \
534                 val = GETARG (int); \
535                 nextarg = hold; \
536                 fmt = ++cp; \
537         } else { \
538                 val = GETARG (int); \
539         }
540
541
542         thousands_sep = '\0';
543         grouping = NULL;
544 #ifndef NO_FLOATING_POINT
545         dtoaresult = NULL;
546         decimal_point = localeconv()->decimal_point;
547 #endif
548         /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
549         if (cantwrite(fp)) {
550                 return (EOF);
551         }
552
553         /* optimise fprintf(stderr) (and other unbuffered Unix files) */
554         if ((fp->pub._flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
555             fp->pub._fileno >= 0) {
556                 return (__sbprintf(fp, fmt0, ap));
557         }
558
559         fmt = (char *)fmt0;
560         argtable = NULL;
561         nextarg = 1;
562         va_copy(orgap, ap);
563         uio.uio_iov = iovp = iov;
564         uio.uio_resid = 0;
565         uio.uio_iovcnt = 0;
566         ret = 0;
567
568         /*
569          * Scan the format for conversions (`%' character).
570          */
571         for (;;) {
572                 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
573                         /* void */;
574                 if ((n = fmt - cp) != 0) {
575                         if ((unsigned)ret + n > INT_MAX) {
576                                 ret = EOF;
577                                 goto error;
578                         }
579                         PRINT(cp, n);
580                         ret += n;
581                 }
582                 if (ch == '\0')
583                         goto done;
584                 fmt++;          /* skip over '%' */
585
586                 flags = 0;
587                 dprec = 0;
588                 width = 0;
589                 prec = -1;
590                 sign = '\0';
591
592 rflag:          ch = *fmt++;
593 reswitch:       switch (ch) {
594                 case ' ':
595                         /*
596                          * ``If the space and + flags both appear, the space
597                          * flag will be ignored.''
598                          *      -- ANSI X3J11
599                          */
600                         if (!sign)
601                                 sign = ' ';
602                         goto rflag;
603                 case '#':
604                         flags |= ALT;
605                         goto rflag;
606                 case '*':
607                         /*
608                          * ``A negative field width argument is taken as a
609                          * - flag followed by a positive field width.''
610                          *      -- ANSI X3J11
611                          * They don't exclude field widths read from args.
612                          */
613                         GETASTER (width);
614                         if (width >= 0)
615                                 goto rflag;
616                         width = -width;
617                         /* FALLTHROUGH */
618                 case '-':
619                         flags |= LADJUST;
620                         goto rflag;
621                 case '+':
622                         sign = '+';
623                         goto rflag;
624                 case '\'':
625                         flags |= GROUPING;
626                         thousands_sep = *(localeconv()->thousands_sep);
627                         grouping = localeconv()->grouping;
628                         goto rflag;
629                 case '.':
630                         if ((ch = *fmt++) == '*') {
631                                 GETASTER (n);
632                                 prec = n < 0 ? -1 : n;
633                                 goto rflag;
634                         }
635                         n = 0;
636                         while (is_digit(ch)) {
637                                 n = 10 * n + to_digit(ch);
638                                 ch = *fmt++;
639                         }
640                         prec = n < 0 ? -1 : n;
641                         goto reswitch;
642                 case '0':
643                         /*
644                          * ``Note that 0 is taken as a flag, not as the
645                          * beginning of a field width.''
646                          *      -- ANSI X3J11
647                          */
648                         flags |= ZEROPAD;
649                         goto rflag;
650                 case '1': case '2': case '3': case '4':
651                 case '5': case '6': case '7': case '8': case '9':
652                         n = 0;
653                         do {
654                                 n = 10 * n + to_digit(ch);
655                                 ch = *fmt++;
656                         } while (is_digit(ch));
657                         if (ch == '$') {
658                                 nextarg = n;
659                                 if (argtable == NULL) {
660                                         argtable = statargtable;
661                                         __find_arguments (fmt0, orgap,
662                                                 &argtable);
663                                 }
664                                 goto rflag;
665                         }
666                         width = n;
667                         goto reswitch;
668 #ifndef NO_FLOATING_POINT
669                 case 'L':
670                         flags |= LONGDBL;
671                         goto rflag;
672 #endif
673                 case 'h':
674                         if (flags & SHORTINT) {
675                                 flags &= ~SHORTINT;
676                                 flags |= CHARINT;
677                         } else
678                                 flags |= SHORTINT;
679                         goto rflag;
680                 case 'j':
681                         flags |= INTMAXT;
682                         goto rflag;
683                 case 'l':
684                         if (flags & LONGINT) {
685                                 flags &= ~LONGINT;
686                                 flags |= LLONGINT;
687                         } else
688                                 flags |= LONGINT;
689                         goto rflag;
690                 case 'q':
691                         flags |= LLONGINT;
692                         goto rflag;
693                 case 't':
694                         flags |= PTRDIFFT;
695                         goto rflag;
696                 case 'z':
697                         flags |= SIZET;
698                         goto rflag;
699                 case 'c':
700                         *(cp = buf) = GETARG(int);
701                         size = 1;
702                         sign = '\0';
703                         break;
704                 case 'D':
705                         flags |= LONGINT;
706                         /*FALLTHROUGH*/
707                 case 'd':
708                 case 'i':
709                         if (flags & INTMAX_SIZE) {
710                                 ujval = SJARG();
711                                 if ((intmax_t)ujval < 0) {
712                                         ujval = -ujval;
713                                         sign = '-';
714                                 }
715                         } else {
716                                 ulval = SARG();
717                                 if ((long)ulval < 0) {
718                                         ulval = -ulval;
719                                         sign = '-';
720                                 }
721                         }
722                         base = 10;
723                         goto number;
724 #ifndef NO_FLOATING_POINT
725 #ifdef HEXFLOAT
726                 case 'a':
727                 case 'A':
728 #endif
729                 case 'e':
730                 case 'E':
731                         /*
732                          * Grouping apply to %i, %d, %u, %f, %F, %g, %G
733                          * conversion specifiers only. For other conversions
734                          * behavior is undefined.
735                          *      -- POSIX
736                          */
737                         flags &= ~GROUPING;
738                         /*FALLTHROUGH*/
739                 case 'f':
740                 case 'F':
741                         goto fp_begin;
742                 case 'g':
743                 case 'G':
744                         if (prec == 0)
745                                 prec = 1;
746 fp_begin:               if (prec == -1)
747                                 prec = DEFPREC;
748                         if (flags & LONGDBL)
749                                 /* XXX this loses precision. */
750                                 _double = (double)GETARG(long double);
751                         else
752                                 _double = GETARG(double);
753                         /* do this before tricky precision changes */
754                         if (isinf(_double)) {
755                                 if (_double < 0)
756                                         sign = '-';
757                                 if (isupper(ch))
758                                         cp = "INF";
759                                 else
760                                         cp = "inf";
761                                 size = 3;
762                                 break;
763                         }
764                         if (isnan(_double)) {
765                                 if (isupper(ch))
766                                         cp = "NAN";
767                                 else
768                                         cp = "nan";
769                                 size = 3;
770                                 break;
771                         }
772                         flags |= FPT;
773                         if (dtoaresult != NULL) {
774                                 free(dtoaresult);
775                                 dtoaresult = NULL;
776                         }
777                         cp = cvt(_double, prec, flags, &softsign,
778                                 &expt, ch, &ndig, &dtoaresult);
779                         if (ch == 'g' || ch == 'G') {
780                                 if (expt <= -4 || expt > prec)
781                                         ch = (ch == 'g') ? 'e' : 'E';
782                                 else
783                                         ch = 'g';
784                         }
785                         if (ch == 'e' || ch == 'E') {
786                                 --expt;
787                                 expsize = exponent(expstr, expt, ch);
788                                 size = expsize + ndig;
789                                 if (ndig > 1 || flags & ALT)
790                                         ++size;
791                         } else if (ch == 'f' || ch == 'F') {
792                                 if (expt > 0) {
793                                         size = expt;
794                                         if (prec || flags & ALT)
795                                                 size += prec + 1;
796                                 } else  /* "0.X" */
797                                         size = prec + 2;
798                         } else if (expt >= ndig) {      /* fixed g fmt */
799                                 size = expt;
800                                 if (flags & ALT)
801                                         ++size;
802                         } else
803                                 size = ndig + (expt > 0 ?
804                                         1 : 2 - expt);
805
806                         if (softsign)
807                                 sign = '-';
808                         break;
809 #endif /* NO_FLOATING_POINT */
810                 case 'n':
811                         /*
812                          * Assignment-like behavior is specified if the
813                          * value overflows or is otherwise unrepresentable.
814                          * C99 says to use `signed char' for %hhn conversions.
815                          */
816                         if (flags & LLONGINT)
817                                 *GETARG(long long *) = ret;
818                         else if (flags & SIZET)
819                                 *GETARG(ssize_t *) = (ssize_t)ret;
820                         else if (flags & PTRDIFFT)
821                                 *GETARG(ptrdiff_t *) = ret;
822                         else if (flags & INTMAXT)
823                                 *GETARG(intmax_t *) = ret;
824                         else if (flags & LONGINT)
825                                 *GETARG(long *) = ret;
826                         else if (flags & SHORTINT)
827                                 *GETARG(short *) = ret;
828                         else if (flags & CHARINT)
829                                 *GETARG(signed char *) = ret;
830                         else
831                                 *GETARG(int *) = ret;
832                         continue;       /* no output */
833                 case 'O':
834                         flags |= LONGINT;
835                         /*FALLTHROUGH*/
836                 case 'o':
837                         if (flags & INTMAX_SIZE)
838                                 ujval = UJARG();
839                         else
840                                 ulval = UARG();
841                         base = 8;
842                         goto nosign;
843                 case 'p':
844                         /*
845                          * ``The argument shall be a pointer to void.  The
846                          * value of the pointer is converted to a sequence
847                          * of printable characters, in an implementation-
848                          * defined manner.''
849                          *      -- ANSI X3J11
850                          */
851                         ujval = (uintmax_t)(uintptr_t)GETARG(void *);
852                         base = 16;
853                         xdigs = "0123456789abcdef";
854                         flags = flags | INTMAXT | HEXPREFIX;
855                         ch = 'x';
856                         goto nosign;
857                 case 's':
858                         if ((cp = GETARG(char *)) == NULL)
859                                 cp = "(null)";
860                         if (prec >= 0) {
861                                 /*
862                                  * can't use strlen; can only look for the
863                                  * NUL in the first `prec' characters, and
864                                  * strlen() will go further.
865                                  */
866                                 char *p = memchr(cp, 0, (size_t)prec);
867
868                                 if (p != NULL) {
869                                         size = p - cp;
870                                         if (size > prec)
871                                                 size = prec;
872                                 } else
873                                         size = prec;
874                         } else
875                                 size = strlen(cp);
876                         sign = '\0';
877                         break;
878                 case 'U':
879                         flags |= LONGINT;
880                         /*FALLTHROUGH*/
881                 case 'u':
882                         if (flags & INTMAX_SIZE)
883                                 ujval = UJARG();
884                         else
885                                 ulval = UARG();
886                         base = 10;
887                         goto nosign;
888                 case 'X':
889                         xdigs = "0123456789ABCDEF";
890                         goto hex;
891                 case 'x':
892                         xdigs = "0123456789abcdef";
893 hex:
894                         if (flags & INTMAX_SIZE)
895                                 ujval = UJARG();
896                         else
897                                 ulval = UARG();
898                         base = 16;
899                         /* leading 0x/X only if non-zero */
900                         if (flags & ALT &&
901                             (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
902                                 flags |= HEXPREFIX;
903
904                         flags &= ~GROUPING;
905                         /* unsigned conversions */
906 nosign:                 sign = '\0';
907                         /*
908                          * ``... diouXx conversions ... if a precision is
909                          * specified, the 0 flag will be ignored.''
910                          *      -- ANSI X3J11
911                          */
912 number:                 if ((dprec = prec) >= 0)
913                                 flags &= ~ZEROPAD;
914
915                         /*
916                          * ``The result of converting a zero value with an
917                          * explicit precision of zero is no characters.''
918                          *      -- ANSI X3J11
919                          */
920                         cp = buf + BUF;
921                         if (flags & INTMAX_SIZE) {
922                                 if (ujval != 0 || prec != 0)
923                                         cp = __ujtoa(ujval, cp, base,
924                                             flags & ALT, xdigs,
925                                             flags & GROUPING, thousands_sep,
926                                             grouping);
927                         } else {
928                                 if (ulval != 0 || prec != 0)
929                                         cp = __ultoa(ulval, cp, base,
930                                             flags & ALT, xdigs,
931                                             flags & GROUPING, thousands_sep,
932                                             grouping);
933                         }
934                         size = buf + BUF - cp;
935                         break;
936                 default:        /* "%?" prints ?, unless ? is NUL */
937                         if (ch == '\0')
938                                 goto done;
939                         /* pretend it was %c with argument ch */
940                         cp = buf;
941                         *cp = ch;
942                         size = 1;
943                         sign = '\0';
944                         break;
945                 }
946
947                 /*
948                  * All reasonable formats wind up here.  At this point, `cp'
949                  * points to a string which (if not flags&LADJUST) should be
950                  * padded out to `width' places.  If flags&ZEROPAD, it should
951                  * first be prefixed by any sign or other prefix; otherwise,
952                  * it should be blank padded before the prefix is emitted.
953                  * After any left-hand padding and prefixing, emit zeroes
954                  * required by a decimal [diouxX] precision, then print the
955                  * string proper, then emit zeroes required by any leftover
956                  * floating precision; finally, if LADJUST, pad with blanks.
957                  *
958                  * Compute actual size, so we know how much to pad.
959                  * size excludes decimal prec; realsz includes it.
960                  */
961                 realsz = dprec > size ? dprec : size;
962                 if (sign)
963                         realsz++;
964                 else if (flags & HEXPREFIX)
965                         realsz += 2;
966
967                 prsize = width > realsz ? width : realsz;
968                 if ((unsigned)ret + prsize > INT_MAX) {
969                         ret = EOF;
970                         goto error;
971                 }
972
973                 /* right-adjusting blank padding */
974                 if ((flags & (LADJUST|ZEROPAD)) == 0)
975                         PAD(width - realsz, blanks);
976
977                 /* prefix */
978                 if (sign) {
979                         PRINT(&sign, 1);
980                 } else if (flags & HEXPREFIX) {
981                         ox[0] = '0';
982                         ox[1] = ch;
983                         PRINT(ox, 2);
984                 }
985
986                 /* right-adjusting zero padding */
987                 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
988                         PAD(width - realsz, zeroes);
989
990                 /* leading zeroes from decimal precision */
991                 PAD(dprec - size, zeroes);
992
993                 /* the string or number proper */
994 #ifndef NO_FLOATING_POINT
995                 if ((flags & FPT) == 0) {
996                         PRINT(cp, size);
997                 } else {        /* glue together f_p fragments */
998                         if (ch >= 'f') {        /* 'f' or 'g' */
999                                 if (_double == 0) {
1000                                         /* kludge for __dtoa irregularity */
1001                                         PRINT("0", 1);
1002                                         if (expt < ndig || (flags & ALT) != 0) {
1003                                                 PRINT(decimal_point, 1);
1004                                                 PAD(ndig - 1, zeroes);
1005                                         }
1006                                 } else if (expt <= 0) {
1007                                         PRINT("0", 1);
1008                                         PRINT(decimal_point, 1);
1009                                         PAD(-expt, zeroes);
1010                                         PRINT(cp, ndig);
1011                                 } else if (expt >= ndig) {
1012                                         PRINT(cp, ndig);
1013                                         PAD(expt - ndig, zeroes);
1014                                         if (flags & ALT)
1015                                                 PRINT(decimal_point, 1);
1016                                 } else {
1017                                         PRINT(cp, expt);
1018                                         cp += expt;
1019                                         PRINT(decimal_point, 1);
1020                                         PRINT(cp, ndig-expt);
1021                                 }
1022                         } else {        /* 'e' or 'E' */
1023                                 if (ndig > 1 || flags & ALT) {
1024                                         ox[0] = *cp++;
1025                                         ox[1] = *decimal_point;
1026                                         PRINT(ox, 2);
1027                                         if (_double) {
1028                                                 PRINT(cp, ndig-1);
1029                                         } else  /* 0.[0..] */
1030                                                 /* __dtoa irregularity */
1031                                                 PAD(ndig - 1, zeroes);
1032                                 } else  /* XeYYY */
1033                                         PRINT(cp, 1);
1034                                 PRINT(expstr, expsize);
1035                         }
1036                 }
1037 #else
1038                 PRINT(cp, size);
1039 #endif
1040                 /* left-adjusting padding (always blank) */
1041                 if (flags & LADJUST)
1042                         PAD(width - realsz, blanks);
1043
1044                 /* finally, adjust ret */
1045                 ret += prsize;
1046
1047                 FLUSH();        /* copy out the I/O vectors */
1048         }
1049 done:
1050         FLUSH();
1051 error:
1052 #ifndef NO_FLOATING_POINT
1053         if (dtoaresult != NULL)
1054                 free(dtoaresult);
1055 #endif
1056         if (__sferror(fp))
1057                 ret = EOF;
1058         if ((argtable != NULL) && (argtable != statargtable))
1059                 free (argtable);
1060         return (ret);
1061         /* NOTREACHED */
1062 }
1063
1064 /*
1065  * Find all arguments when a positional parameter is encountered.  Returns a
1066  * table, indexed by argument number, of pointers to each arguments.  The
1067  * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
1068  * It will be replaces with a malloc-ed one if it overflows.
1069  */ 
1070 static void
1071 __find_arguments (const char *fmt0, va_list ap, union arg **argtable)
1072 {
1073         char *fmt;              /* format string */
1074         int ch;                 /* character from fmt */
1075         int n, n2;              /* handy integer (short term usage) */
1076         char *cp;               /* handy char pointer (short term usage) */
1077         int flags;              /* flags as above */
1078         int width;              /* width from format (%8d), or 0 */
1079         enum typeid *typetable; /* table of types */
1080         enum typeid stattypetable[STATIC_ARG_TBL_SIZE];
1081         int tablesize;          /* current size of type table */
1082         int tablemax;           /* largest used index in table */
1083         int nextarg;            /* 1-based argument index */
1084
1085         /*
1086          * Add an argument type to the table, expanding if necessary.
1087          */
1088 #define ADDTYPE(type) \
1089         ((nextarg >= tablesize) ? \
1090                 __grow_type_table(nextarg, &typetable, &tablesize) : 0, \
1091         (nextarg > tablemax) ? tablemax = nextarg : 0, \
1092         typetable[nextarg++] = type)
1093
1094 #define ADDSARG() \
1095         ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \
1096                 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
1097                 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
1098                 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
1099                 ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT))))))
1100
1101 #define ADDUARG() \
1102         ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \
1103                 ((flags&SIZET) ? ADDTYPE(T_SIZET) : \
1104                 ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \
1105                 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
1106                 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT))))))
1107
1108         /*
1109          * Add * arguments to the type array.
1110          */
1111 #define ADDASTER() \
1112         n2 = 0; \
1113         cp = fmt; \
1114         while (is_digit(*cp)) { \
1115                 n2 = 10 * n2 + to_digit(*cp); \
1116                 cp++; \
1117         } \
1118         if (*cp == '$') { \
1119                 int hold = nextarg; \
1120                 nextarg = n2; \
1121                 ADDTYPE (T_INT); \
1122                 nextarg = hold; \
1123                 fmt = ++cp; \
1124         } else { \
1125                 ADDTYPE (T_INT); \
1126         }
1127         fmt = (char *)fmt0;
1128         typetable = stattypetable;
1129         tablesize = STATIC_ARG_TBL_SIZE;
1130         tablemax = 0; 
1131         nextarg = 1;
1132         memset (typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
1133
1134         /*
1135          * Scan the format for conversions (`%' character).
1136          */
1137         for (;;) {
1138                 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
1139                         /* void */;
1140                 if (ch == '\0')
1141                         goto done;
1142                 fmt++;          /* skip over '%' */
1143
1144                 flags = 0;
1145                 width = 0;
1146
1147 rflag:          ch = *fmt++;
1148 reswitch:       switch (ch) {
1149                 case ' ':
1150                 case '#':
1151                         goto rflag;
1152                 case '*':
1153                         ADDASTER ();
1154                         goto rflag;
1155                 case '-':
1156                 case '+':
1157                 case '\'':
1158                         goto rflag;
1159                 case '.':
1160                         if ((ch = *fmt++) == '*') {
1161                                 ADDASTER ();
1162                                 goto rflag;
1163                         }
1164                         while (is_digit(ch)) {
1165                                 ch = *fmt++;
1166                         }
1167                         goto reswitch;
1168                 case '0':
1169                         goto rflag;
1170                 case '1': case '2': case '3': case '4':
1171                 case '5': case '6': case '7': case '8': case '9':
1172                         n = 0;
1173                         do {
1174                                 n = 10 * n + to_digit(ch);
1175                                 ch = *fmt++;
1176                         } while (is_digit(ch));
1177                         if (ch == '$') {
1178                                 nextarg = n;
1179                                 goto rflag;
1180                         }
1181                         width = n;
1182                         goto reswitch;
1183 #ifndef NO_FLOATING_POINT
1184                 case 'L':
1185                         flags |= LONGDBL;
1186                         goto rflag;
1187 #endif
1188                 case 'h':
1189                         if (flags & SHORTINT) {
1190                                 flags &= ~SHORTINT;
1191                                 flags |= CHARINT;
1192                         } else
1193                                 flags |= SHORTINT;
1194                         goto rflag;
1195                 case 'j':
1196                         flags |= INTMAXT;
1197                         goto rflag;
1198                 case 'l':
1199                         if (flags & LONGINT) {
1200                                 flags &= ~LONGINT;
1201                                 flags |= LLONGINT;
1202                         } else
1203                                 flags |= LONGINT;
1204                         goto rflag;
1205                 case 'q':
1206                         flags |= LLONGINT;
1207                         goto rflag;
1208                 case 't':
1209                         flags |= PTRDIFFT;
1210                         goto rflag;
1211                 case 'z':
1212                         flags |= SIZET;
1213                         goto rflag;
1214                 case 'c':
1215                         ADDTYPE(T_INT);
1216                         break;
1217                 case 'D':
1218                         flags |= LONGINT;
1219                         /*FALLTHROUGH*/
1220                 case 'd':
1221                 case 'i':
1222                         ADDSARG();
1223                         break;
1224 #ifndef NO_FLOATING_POINT
1225 #ifdef HEXFLOAT
1226                 case 'a':
1227                 case 'A':
1228 #endif
1229                 case 'e':
1230                 case 'E':
1231                 case 'f':
1232                 case 'g':
1233                 case 'G':
1234                         if (flags & LONGDBL)
1235                                 ADDTYPE(T_LONG_DOUBLE);
1236                         else
1237                                 ADDTYPE(T_DOUBLE);
1238                         break;
1239 #endif /* NO_FLOATING_POINT */
1240                 case 'n':
1241                         if (flags & INTMAXT)
1242                                 ADDTYPE(TP_INTMAXT);
1243                         else if (flags & PTRDIFFT)
1244                                 ADDTYPE(TP_PTRDIFFT);
1245                         else if (flags & SIZET)
1246                                 ADDTYPE(TP_SIZET);
1247                         else if (flags & LLONGINT)
1248                                 ADDTYPE(TP_LLONG);
1249                         else if (flags & LONGINT)
1250                                 ADDTYPE(TP_LONG);
1251                         else if (flags & SHORTINT)
1252                                 ADDTYPE(TP_SHORT);
1253                         else if (flags & CHARINT)
1254                                 ADDTYPE(TP_SCHAR);
1255                         else
1256                                 ADDTYPE(TP_INT);
1257                         continue;       /* no output */
1258                 case 'O':
1259                         flags |= LONGINT;
1260                         /*FALLTHROUGH*/
1261                 case 'o':
1262                         ADDUARG();
1263                         break;
1264                 case 'p':
1265                         ADDTYPE(TP_VOID);
1266                         break;
1267                 case 's':
1268                         ADDTYPE(TP_CHAR);
1269                         break;
1270                 case 'U':
1271                         flags |= LONGINT;
1272                         /*FALLTHROUGH*/
1273                 case 'u':
1274                 case 'X':
1275                 case 'x':
1276                         ADDUARG();
1277                         break;
1278                 default:        /* "%?" prints ?, unless ? is NUL */
1279                         if (ch == '\0')
1280                                 goto done;
1281                         break;
1282                 }
1283         }
1284 done:
1285         /*
1286          * Build the argument table.
1287          */
1288         if (tablemax >= STATIC_ARG_TBL_SIZE) {
1289                 *argtable = (union arg *)
1290                     malloc(sizeof(union arg) * (tablemax + 1));
1291         }
1292         (*argtable)[0].intarg = 0;
1293         for (n = 1; n <= tablemax; n++) {
1294                 switch (typetable [n]) {
1295                     case T_UNUSED: /* "whoops" */
1296                     case T_INT:
1297                         (*argtable)[n].intarg = va_arg(ap, int);
1298                         break;
1299                     case TP_SCHAR:
1300                         (*argtable) [n].pschararg = va_arg (ap, signed char *);
1301                     case TP_SHORT:
1302                         (*argtable)[n].pshortarg = va_arg(ap, short *);
1303                         break;
1304                     case T_U_INT:
1305                         (*argtable)[n].uintarg = va_arg(ap, unsigned int);
1306                         break;
1307                     case TP_INT:
1308                         (*argtable)[n].pintarg = va_arg(ap, int *);
1309                         break;
1310                     case T_LONG:
1311                         (*argtable)[n].longarg = va_arg(ap, long);
1312                         break;
1313                     case T_U_LONG:
1314                         (*argtable)[n].ulongarg = va_arg(ap, unsigned long);
1315                         break;
1316                     case TP_LONG:
1317                         (*argtable)[n].plongarg = va_arg(ap, long *);
1318                         break;
1319                     case T_LLONG:
1320                         (*argtable)[n].longlongarg = va_arg(ap, long long);
1321                         break;
1322                     case T_U_LLONG:
1323                         (*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long);
1324                         break;
1325                     case TP_LLONG:
1326                         (*argtable)[n].plonglongarg = va_arg(ap, long long *);
1327                         break;
1328                     case T_PTRDIFFT:
1329                         (*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t);
1330                         break;
1331                     case TP_PTRDIFFT:
1332                         (*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *);
1333                         break;
1334                     case T_SIZET:
1335                         (*argtable)[n].sizearg = va_arg(ap, size_t);
1336                         break;
1337                     case TP_SIZET:
1338                         (*argtable)[n].psizearg = va_arg(ap, ssize_t *);
1339                         break;
1340                     case T_INTMAXT:
1341                         (*argtable)[n].intmaxarg = va_arg(ap, intmax_t);
1342                         break;
1343                     case T_UINTMAXT:
1344                         (*argtable)[n].uintmaxarg = va_arg(ap, uintmax_t);
1345                         break;
1346                     case TP_INTMAXT:
1347                         (*argtable)[n].pintmaxarg = va_arg (ap, intmax_t *);
1348                         break;
1349                     case T_DOUBLE:
1350                         (*argtable)[n].doublearg = va_arg(ap, double);
1351                         break;
1352                     case T_LONG_DOUBLE:
1353                         (*argtable)[n].longdoublearg = va_arg(ap, long double);
1354                         break;
1355                     case TP_CHAR:
1356                         (*argtable)[n].pchararg = va_arg(ap, char *);
1357                         break;
1358                     case TP_VOID:
1359                         (*argtable)[n].pvoidarg = va_arg(ap, void *);
1360                         break;
1361                 }
1362         }
1363
1364         if ((typetable != NULL) && (typetable != stattypetable))
1365                 free (typetable);
1366 }
1367
1368 /*
1369  * Increase the size of the type table.
1370  */
1371 static void
1372 __grow_type_table(int nextarg, enum typeid **typetable, int *tablesize)
1373 {
1374         enum typeid * const oldtable = *typetable;
1375         const int oldsize = *tablesize;
1376         enum typeid *newtable;
1377         int newsize = oldsize * 2;
1378
1379         if (newsize < nextarg + 1)
1380                 newsize = nextarg + 1;
1381         if (oldsize == STATIC_ARG_TBL_SIZE) {
1382                 if ((newtable = malloc(newsize)) == NULL)
1383                         abort();                        /* XXX handle better */
1384                 bcopy(oldtable, newtable, oldsize);
1385         } else {
1386                 if ((newtable = reallocf(oldtable, newsize)) == NULL)
1387                         abort();                        /* XXX handle better */
1388         }
1389         memset(&newtable[oldsize], T_UNUSED, newsize - oldsize);
1390
1391         *typetable = newtable;
1392         *tablesize = newsize;
1393 }
1394
1395
1396 #ifndef NO_FLOATING_POINT
1397
1398 extern char *__dtoa (double, int, int, int *, int *, char **, char **);
1399
1400 static char *
1401 cvt(double value, int ndigits, int flags, char *sign, int *decpt,
1402     int ch, int *length, char **dtoaresultp)
1403 {
1404         int mode, dsgn;
1405         char *digits, *bp, *rve;
1406
1407         if (ch == 'f')
1408                 mode = 3;               /* ndigits after the decimal point */
1409         else {
1410                 /*
1411                  * To obtain ndigits after the decimal point for the 'e'
1412                  * and 'E' formats, round to ndigits + 1 significant
1413                  * figures.
1414                  */
1415                 if (ch == 'e' || ch == 'E')
1416                         ndigits++;
1417                 mode = 2;               /* ndigits significant digits */
1418         }
1419         digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve, dtoaresultp);
1420         *sign = dsgn != 0;
1421         if ((ch != 'g' && ch != 'G') || flags & ALT) {
1422                 /* print trailing zeros */
1423                 bp = digits + ndigits;
1424                 if (ch == 'f') {
1425                         if (*digits == '0' && value)
1426                                 *decpt = -ndigits + 1;
1427                         bp += *decpt;
1428                 }
1429                 if (value == 0) /* kludge for __dtoa irregularity */
1430                         rve = bp;
1431                 while (rve < bp)
1432                         *rve++ = '0';
1433         }
1434         *length = rve - digits;
1435         return (digits);
1436 }
1437
1438 static int
1439 exponent(char *p0, int expo, int fmtch)
1440 {
1441         char *p, *t;
1442         char expbuf[MAXEXPDIG];
1443
1444         p = p0;
1445         *p++ = fmtch;
1446         if (expo < 0) {
1447                 expo = -expo;
1448                 *p++ = '-';
1449         }
1450         else
1451                 *p++ = '+';
1452         t = expbuf + MAXEXPDIG;
1453         if (expo > 9) {
1454                 do {
1455                         *--t = to_char(expo % 10);
1456                 } while ((expo /= 10) > 9);
1457                 *--t = to_char(expo);
1458                 for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
1459         }
1460         else {
1461                 *p++ = '0';
1462                 *p++ = to_char(expo);
1463         }
1464         return (p - p0);
1465 }
1466 #endif /* NO_FLOATING_POINT */