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