]>
git.saurik.com Git - apple/libc.git/blob - stdio.subproj/vfprintf.c
f819e259b1313657f8394ea02b50ab71e024ec6f
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1990, 1993
24 * The Regents of the University of California. All rights reserved.
26 * This code is derived from software contributed to Berkeley by
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * Actual printf innards.
61 * This code is large and complicated...
64 #include <sys/types.h>
80 /* Define FLOATING_POINT to get floating point. */
81 #define FLOATING_POINT
83 static int __sprint
__P((FILE *, struct __suio
*));
84 static int __sbprintf
__P((FILE *, const char *, va_list));
85 static char * __ultoa
__P((u_long
, char *, int, int, char *));
86 static char * __uqtoa
__P((u_quad_t
, char *, int, int, char *));
87 static void __find_arguments
__P((const char *, va_list, void ***));
88 static void __grow_type_table
__P((int, unsigned char **, int *));
91 * Flush out all the vectors defined by the given uio,
92 * then reset it so that it can be reused.
97 register struct __suio
*uio
;
101 if (uio
->uio_resid
== 0) {
105 err
= __sfvwrite(fp
, uio
);
112 * Helper function for `fprintf to unbuffered unix file': creates a
113 * temporary buffer. We only work on write-only files; this avoids
114 * worries about ungetc buffers and so forth.
117 __sbprintf(fp
, fmt
, ap
)
124 unsigned char buf
[BUFSIZ
];
126 /* copy the important variables */
127 fake
._flags
= fp
->_flags
& ~__SNBF
;
128 fake
._file
= fp
->_file
;
129 fake
._cookie
= fp
->_cookie
;
130 fake
._write
= fp
->_write
;
132 /* set up the buffer */
133 fake
._bf
._base
= fake
._p
= buf
;
134 fake
._bf
._size
= fake
._w
= sizeof(buf
);
135 fake
._lbfsize
= 0; /* not actually used, but Just In Case */
137 /* do the work, then copy any error status */
138 ret
= vfprintf(&fake
, fmt
, ap
);
139 if (ret
>= 0 && fflush(&fake
))
141 if (fake
._flags
& __SERR
)
142 fp
->_flags
|= __SERR
;
147 * Macros for converting digits to letters and vice versa
149 #define to_digit(c) ((c) - '0')
150 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
151 #define to_char(n) ((n) + '0')
154 * Convert an unsigned long to ASCII for printf purposes, returning
155 * a pointer to the first character of the string representation.
156 * Octal numbers can be forced to have a leading zero; hex numbers
157 * use the given digits.
160 __ultoa(val
, endp
, base
, octzero
, xdigs
)
166 register char *cp
= endp
;
170 * Handle the three cases separately, in the hope of getting
171 * better/faster code.
175 if (val
< 10) { /* many numbers are 1 digit */
176 *--cp
= to_char(val
);
180 * On many machines, unsigned arithmetic is harder than
181 * signed arithmetic, so we do at most one unsigned mod and
182 * divide; this is sufficient to reduce the range of
183 * the incoming value to where signed arithmetic works.
185 if (val
> LONG_MAX
) {
186 *--cp
= to_char(val
% 10);
191 *--cp
= to_char(sval
% 10);
198 *--cp
= to_char(val
& 7);
201 if (octzero
&& *cp
!= '0')
207 *--cp
= xdigs
[val
& 15];
218 /* Identical to __ultoa, but for quads. */
220 __uqtoa(val
, endp
, base
, octzero
, xdigs
)
221 register u_quad_t val
;
226 register char *cp
= endp
;
227 register quad_t sval
;
229 /* quick test for small values; __ultoa is typically much faster */
230 /* (perhaps instead we should run until small, then call __ultoa?) */
231 if (val
<= ULONG_MAX
)
232 return (__ultoa((u_long
)val
, endp
, base
, octzero
, xdigs
));
236 *--cp
= to_char(val
% 10);
239 if (val
> QUAD_MAX
) {
240 *--cp
= to_char(val
% 10);
245 *--cp
= to_char(sval
% 10);
252 *--cp
= to_char(val
& 7);
255 if (octzero
&& *cp
!= '0')
261 *--cp
= xdigs
[val
& 15];
272 #ifdef FLOATING_POINT
276 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
279 static char *cvt
__P((double, int, int, char *, int *, int, int *));
280 static int exponent
__P((char *, int, int));
282 #else /* no FLOATING_POINT */
286 #endif /* FLOATING_POINT */
288 #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
291 * Flags used during conversion.
293 #define ALT 0x001 /* alternate form */
294 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
295 #define LADJUST 0x004 /* left adjustment */
296 #define LONGDBL 0x008 /* long double */
297 #define LONGINT 0x010 /* long integer */
298 #define QUADINT 0x020 /* quad integer */
299 #define SHORTINT 0x040 /* short integer */
300 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
301 #define FPT 0x100 /* Floating point number */
303 vfprintf(fp
, fmt0
, ap
)
308 register char *fmt
; /* format string */
309 register int ch
; /* character from fmt */
310 register int n
, n2
; /* handy integer (short term usage) */
311 register char *cp
; /* handy char pointer (short term usage) */
312 register struct __siov
*iovp
;/* for PRINT macro */
313 register int flags
; /* flags as above */
314 int ret
; /* return value accumulator */
315 int width
; /* width from format (%8d), or 0 */
316 int prec
; /* precision from format (%.3d), or -1 */
317 char sign
; /* sign prefix (' ', '+', '-', or \0) */
318 #ifdef FLOATING_POINT
319 char softsign
; /* temporary negative sign for floats */
320 double _double
= 0; /* double precision arguments %[eEfgG] */
321 int expt
; /* integer value of exponent */
322 int expsize
= 0; /* character count for expstr */
323 int ndig
; /* actual number of digits returned by cvt */
324 char expstr
[7]; /* buffer for exponent string */
326 u_long ulval
= 0; /* integer arguments %[diouxX] */
327 u_quad_t uqval
= 0; /* %q integers */
328 int base
; /* base for [diouxX] conversion */
329 int dprec
; /* a copy of prec if [diouxX], 0 otherwise */
330 int realsz
; /* field size expanded by dprec, sign, etc */
331 int size
; /* size of converted field or string */
332 int prsize
; /* max size of printed field */
333 char *xdigs
= NULL
; /* digits for [xX] conversion */
335 struct __suio uio
; /* output information: summary */
336 struct __siov iov
[NIOV
];/* ... and individual io vectors */
337 char buf
[BUF
]; /* space for %c, %[diouxX], %[eEfgG] */
338 char ox
[2]; /* space for 0x hex-prefix */
339 void **argtable
; /* args, built due to positional arg */
340 void *statargtable
[STATIC_ARG_TBL_SIZE
];
341 int nextarg
; /* 1-based argument index */
342 va_list orgap
; /* original argument pointer */
345 * Choose PADSIZE to trade efficiency vs. size. If larger printf
346 * fields occur frequently, increase PADSIZE and make the initialisers
349 #define PADSIZE 16 /* pad chunk size */
350 static char blanks
[PADSIZE
] =
351 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
352 static char zeroes
[PADSIZE
] =
353 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
356 * BEWARE, these `goto error' on error, and PAD uses `n'.
358 #define PRINT(ptr, len) { \
359 iovp->iov_base = (ptr); \
360 iovp->iov_len = (len); \
361 uio.uio_resid += (len); \
363 if (++uio.uio_iovcnt >= NIOV) { \
364 if (__sprint(fp, &uio)) \
369 #define PAD(howmany, with) { \
370 if ((n = (howmany)) > 0) { \
371 while (n > PADSIZE) { \
372 PRINT(with, PADSIZE); \
379 if (uio.uio_resid && __sprint(fp, &uio)) \
381 uio.uio_iovcnt = 0; \
386 * Get the argument indexed by nextarg. If the argument table is
387 * built, use it to get the argument. If its not, get the next
388 * argument (and arguments must be gotten sequentially).
390 #define GETARG(type) \
391 ((argtable != NULL) ? *((type*)(argtable[nextarg++])) : \
392 (nextarg++, va_arg(ap, type)))
395 * To extend shorts properly, we need both signed and unsigned
396 * argument extraction methods.
399 (flags&LONGINT ? GETARG(long) : \
400 flags&SHORTINT ? (long)(short)GETARG(int) : \
403 (flags&LONGINT ? GETARG(u_long) : \
404 flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
405 (u_long)GETARG(u_int))
408 * Get * arguments, including the form *nn$. Preserve the nextarg
409 * that the argument can be gotten once the type is determined.
411 #define GETASTER(val) \
414 while (is_digit(*cp)) { \
415 n2 = 10 * n2 + to_digit(*cp); \
419 int hold = nextarg; \
420 if (argtable == NULL) { \
421 argtable = statargtable; \
422 __find_arguments (fmt0, orgap, &argtable); \
425 val = GETARG (int); \
429 val = GETARG (int); \
434 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
436 /* FUNLOCKFILE(fp); */
440 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
441 if ((fp
->_flags
& (__SNBF
|__SWR
|__SRW
)) == (__SNBF
|__SWR
) &&
443 /* FUNLOCKFILE(fp); */
444 return (__sbprintf(fp
, fmt0
, ap
));
451 uio
.uio_iov
= iovp
= iov
;
457 * Scan the format for conversions (`%' character).
460 for (cp
= fmt
; (ch
= *fmt
) != '\0' && ch
!= '%'; fmt
++)
462 if ((n
= fmt
- cp
) != 0) {
463 if ((unsigned)ret
+ n
> INT_MAX
) {
472 fmt
++; /* skip over '%' */
481 reswitch
: switch (ch
) {
484 * ``If the space and + flags both appear, the space
485 * flag will be ignored.''
496 * ``A negative field width argument is taken as a
497 * - flag followed by a positive field width.''
499 * They don't exclude field widths read from args.
513 if ((ch
= *fmt
++) == '*') {
515 prec
= n
< 0 ? -1 : n
;
519 while (is_digit(ch
)) {
520 n
= 10 * n
+ to_digit(ch
);
523 prec
= n
< 0 ? -1 : n
;
527 * ``Note that 0 is taken as a flag, not as the
528 * beginning of a field width.''
533 case '1': case '2': case '3': case '4':
534 case '5': case '6': case '7': case '8': case '9':
537 n
= 10 * n
+ to_digit(ch
);
539 } while (is_digit(ch
));
542 if (argtable
== NULL
) {
543 argtable
= statargtable
;
544 __find_arguments (fmt0
, orgap
,
551 #ifdef FLOATING_POINT
569 *(cp
= buf
) = GETARG(int);
578 if (flags
& QUADINT
) {
579 uqval
= GETARG(quad_t
);
580 if ((quad_t
)uqval
< 0) {
586 if ((long)ulval
< 0) {
593 #ifdef FLOATING_POINT
602 fp_begin
: if (prec
== -1)
605 /* XXX this loses precision. */
606 _double
= (double)GETARG(long double);
608 _double
= GETARG(double);
609 /* do this before tricky precision changes */
610 if (isinf(_double
)) {
617 if (isnan(_double
)) {
623 cp
= cvt(_double
, prec
, flags
, &softsign
,
625 if (ch
== 'g' || ch
== 'G') {
626 if (expt
<= -4 || expt
> prec
)
627 ch
= (ch
== 'g') ? 'e' : 'E';
631 if (ch
<= 'e') { /* 'e' or 'E' fmt */
633 expsize
= exponent(expstr
, expt
, ch
);
634 size
= expsize
+ ndig
;
635 if (ndig
> 1 || flags
& ALT
)
637 } else if (ch
== 'f') { /* f fmt */
640 if (prec
|| flags
& ALT
)
644 } else if (expt
>= ndig
) { /* fixed g fmt */
649 size
= ndig
+ (expt
> 0 ?
655 #endif /* FLOATING_POINT */
658 *GETARG(quad_t
*) = ret
;
659 else if (flags
& LONGINT
)
660 *GETARG(long *) = ret
;
661 else if (flags
& SHORTINT
)
662 *GETARG(short *) = ret
;
664 *GETARG(int *) = ret
;
665 continue; /* no output */
671 uqval
= GETARG(u_quad_t
);
678 * ``The argument shall be a pointer to void. The
679 * value of the pointer is converted to a sequence
680 * of printable characters, in an implementation-
684 ulval
= (u_long
)GETARG(void *);
686 xdigs
= "0123456789abcdef";
687 flags
= (flags
& ~QUADINT
) | HEXPREFIX
;
691 if ((cp
= GETARG(char *)) == NULL
)
695 * can't use strlen; can only look for the
696 * NUL in the first `prec' characters, and
697 * strlen() will go further.
699 char *p
= memchr(cp
, 0, (size_t)prec
);
716 uqval
= GETARG(u_quad_t
);
722 xdigs
= "0123456789ABCDEF";
725 xdigs
= "0123456789abcdef";
726 hex
: if (flags
& QUADINT
)
727 uqval
= GETARG(u_quad_t
);
731 /* leading 0x/X only if non-zero */
733 (flags
& QUADINT
? uqval
!= 0 : ulval
!= 0))
736 /* unsigned conversions */
739 * ``... diouXx conversions ... if a precision is
740 * specified, the 0 flag will be ignored.''
743 number
: if ((dprec
= prec
) >= 0)
747 * ``The result of converting a zero value with an
748 * explicit precision of zero is no characters.''
752 if (flags
& QUADINT
) {
753 if (uqval
!= 0 || prec
!= 0)
754 cp
= __uqtoa(uqval
, cp
, base
,
757 if (ulval
!= 0 || prec
!= 0)
758 cp
= __ultoa(ulval
, cp
, base
,
761 size
= buf
+ BUF
- cp
;
763 default: /* "%?" prints ?, unless ? is NUL */
766 /* pretend it was %c with argument ch */
775 * All reasonable formats wind up here. At this point, `cp'
776 * points to a string which (if not flags&LADJUST) should be
777 * padded out to `width' places. If flags&ZEROPAD, it should
778 * first be prefixed by any sign or other prefix; otherwise,
779 * it should be blank padded before the prefix is emitted.
780 * After any left-hand padding and prefixing, emit zeroes
781 * required by a decimal [diouxX] precision, then print the
782 * string proper, then emit zeroes required by any leftover
783 * floating precision; finally, if LADJUST, pad with blanks.
785 * Compute actual size, so we know how much to pad.
786 * size excludes decimal prec; realsz includes it.
788 realsz
= dprec
> size
? dprec
: size
;
791 else if (flags
& HEXPREFIX
)
794 prsize
= width
> realsz
? width
: realsz
;
795 if ((unsigned)ret
+ prsize
> INT_MAX
) {
800 /* right-adjusting blank padding */
801 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
802 PAD(width
- realsz
, blanks
);
807 } else if (flags
& HEXPREFIX
) {
813 /* right-adjusting zero padding */
814 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
815 PAD(width
- realsz
, zeroes
);
817 /* leading zeroes from decimal precision */
818 PAD(dprec
- size
, zeroes
);
820 /* the string or number proper */
821 #ifdef FLOATING_POINT
822 if ((flags
& FPT
) == 0) {
824 } else { /* glue together f_p fragments */
825 if (ch
>= 'f') { /* 'f' or 'g' */
827 /* kludge for __dtoa irregularity */
829 (flags
& ALT
) == 0) {
833 PAD(ndig
- 1, zeroes
);
835 } else if (expt
<= 0) {
839 } else if (expt
>= ndig
) {
841 PAD(expt
- ndig
, zeroes
);
848 PRINT(cp
, ndig
-expt
);
850 } else { /* 'e' or 'E' */
851 if (ndig
> 1 || flags
& ALT
) {
858 /* __dtoa irregularity */
859 PAD(ndig
- 1, zeroes
);
862 PRINT(expstr
, expsize
);
868 /* left-adjusting padding (always blank) */
870 PAD(width
- realsz
, blanks
);
872 /* finally, adjust ret */
875 FLUSH(); /* copy out the I/O vectors */
882 /* FUNLOCKFILE(fp); */
883 if ((argtable
!= NULL
) && (argtable
!= statargtable
))
890 * Type ids for argument type table.
906 #define T_LONG_DOUBLE 14
911 * Find all arguments when a positional parameter is encountered. Returns a
912 * table, indexed by argument number, of pointers to each arguments. The
913 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
914 * It will be replaces with a malloc-ed on if it overflows.
917 __find_arguments (fmt0
, ap
, argtable
)
922 register char *fmt
; /* format string */
923 register int ch
; /* character from fmt */
924 register int n
, n2
; /* handy integer (short term usage) */
925 register char *cp
; /* handy char pointer (short term usage) */
926 register int flags
; /* flags as above */
927 int width
; /* width from format (%8d), or 0 */
928 unsigned char *typetable
; /* table of types */
929 unsigned char stattypetable
[STATIC_ARG_TBL_SIZE
];
930 int tablesize
; /* current size of type table */
931 int tablemax
; /* largest used index in table */
932 int nextarg
; /* 1-based argument index */
935 * Add an argument type to the table, expanding if necessary.
937 #define ADDTYPE(type) \
938 ((nextarg >= tablesize) ? \
939 __grow_type_table(nextarg, &typetable, &tablesize) : 0, \
940 typetable[nextarg++] = type, \
941 (nextarg > tablemax) ? tablemax = nextarg : 0)
944 ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
945 ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT)))
948 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
949 ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT)))
952 * Add * arguments to the type array.
957 while (is_digit(*cp)) { \
958 n2 = 10 * n2 + to_digit(*cp); \
962 int hold = nextarg; \
971 typetable
= stattypetable
;
972 tablesize
= STATIC_ARG_TBL_SIZE
;
975 memset (typetable
, T_UNUSED
, STATIC_ARG_TBL_SIZE
);
978 * Scan the format for conversions (`%' character).
981 for (cp
= fmt
; (ch
= *fmt
) != '\0' && ch
!= '%'; fmt
++)
985 fmt
++; /* skip over '%' */
991 reswitch
: switch (ch
) {
1002 if ((ch
= *fmt
++) == '*') {
1006 while (is_digit(ch
)) {
1012 case '1': case '2': case '3': case '4':
1013 case '5': case '6': case '7': case '8': case '9':
1016 n
= 10 * n
+ to_digit(ch
);
1018 } while (is_digit(ch
));
1025 #ifdef FLOATING_POINT
1034 if (flags
& LONGINT
)
1050 if (flags
& QUADINT
) {
1056 #ifdef FLOATING_POINT
1062 if (flags
& LONGDBL
)
1063 ADDTYPE(T_LONG_DOUBLE
);
1067 #endif /* FLOATING_POINT */
1069 if (flags
& QUADINT
)
1071 else if (flags
& LONGINT
)
1073 else if (flags
& SHORTINT
)
1077 continue; /* no output */
1082 if (flags
& QUADINT
)
1097 if (flags
& QUADINT
)
1104 if (flags
& QUADINT
)
1109 default: /* "%?" prints ?, unless ? is NUL */
1117 * Build the argument table.
1119 if (tablemax
>= STATIC_ARG_TBL_SIZE
) {
1120 *argtable
= (void **)
1121 malloc (sizeof (void *) * (tablemax
+ 1));
1124 (*argtable
) [0] = NULL
;
1125 for (n
= 1; n
<= tablemax
; n
++) {
1126 switch (typetable
[n
]) {
1128 (*argtable
) [n
] = (void *) &va_arg (ap
, int);
1131 (*argtable
) [n
] = (void *) &va_arg (ap
, int);
1134 (*argtable
) [n
] = (void *) &va_arg (ap
, int);
1137 (*argtable
) [n
] = (void *) &va_arg (ap
, short *);
1140 (*argtable
) [n
] = (void *) &va_arg (ap
, int);
1143 (*argtable
) [n
] = (void *) &va_arg (ap
, unsigned int);
1146 (*argtable
) [n
] = (void *) &va_arg (ap
, int *);
1149 (*argtable
) [n
] = (void *) &va_arg (ap
, long);
1152 (*argtable
) [n
] = (void *) &va_arg (ap
, unsigned long);
1155 (*argtable
) [n
] = (void *) &va_arg (ap
, long *);
1158 (*argtable
) [n
] = (void *) &va_arg (ap
, quad_t
);
1161 (*argtable
) [n
] = (void *) &va_arg (ap
, u_quad_t
);
1164 (*argtable
) [n
] = (void *) &va_arg (ap
, quad_t
*);
1167 (*argtable
) [n
] = (void *) &va_arg (ap
, double);
1170 (*argtable
) [n
] = (void *) &va_arg (ap
, long double);
1173 (*argtable
) [n
] = (void *) &va_arg (ap
, char *);
1176 (*argtable
) [n
] = (void *) &va_arg (ap
, void *);
1181 if ((typetable
!= NULL
) && (typetable
!= stattypetable
))
1186 * Increase the size of the type table.
1189 __grow_type_table (nextarg
, typetable
, tablesize
)
1191 unsigned char **typetable
;
1194 unsigned char *oldtable
= *typetable
;
1195 int newsize
= *tablesize
* 2;
1197 if (*tablesize
== STATIC_ARG_TBL_SIZE
) {
1198 *typetable
= (unsigned char *)
1199 malloc (sizeof (unsigned char) * newsize
);
1200 bcopy (oldtable
, *typetable
, *tablesize
);
1202 *typetable
= (unsigned char *)
1203 realloc (typetable
, sizeof (unsigned char) * newsize
);
1206 memset (&typetable
[*tablesize
], T_UNUSED
, (newsize
- *tablesize
));
1208 *tablesize
= newsize
;
1212 #ifdef FLOATING_POINT
1214 extern char *__dtoa
__P((double, int, int, int *, int *, char **));
1217 cvt(value
, ndigits
, flags
, sign
, decpt
, ch
, length
)
1219 int ndigits
, flags
, *decpt
, ch
, *length
;
1223 char *digits
, *bp
, *rve
;
1226 mode
= 3; /* ndigits after the decimal point */
1229 * To obtain ndigits after the decimal point for the 'e'
1230 * and 'E' formats, round to ndigits + 1 significant
1233 if (ch
== 'e' || ch
== 'E')
1235 mode
= 2; /* ndigits significant digits */
1242 digits
= __dtoa(value
, mode
, ndigits
, decpt
, &dsgn
, &rve
);
1243 if ((ch
!= 'g' && ch
!= 'G') || flags
& ALT
) {
1244 /* print trailing zeros */
1245 bp
= digits
+ ndigits
;
1247 if (*digits
== '0' && value
)
1248 *decpt
= -ndigits
+ 1;
1251 if (value
== 0) /* kludge for __dtoa irregularity */
1256 *length
= rve
- digits
;
1261 exponent(p0
, exp
, fmtch
)
1265 register char *p
, *t
;
1266 char expbuf
[MAXEXP
];
1276 t
= expbuf
+ MAXEXP
;
1279 *--t
= to_char(exp
% 10);
1280 } while ((exp
/= 10) > 9);
1281 *--t
= to_char(exp
);
1282 for (; t
< expbuf
+ MAXEXP
; *p
++ = *t
++);
1286 *p
++ = to_char(exp
);
1290 #endif /* FLOATING_POINT */