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