1 /* $OpenBSD: vfprintf.c,v 1.57 2009/10/28 21:15:02 naddy Exp $ */
3 * Copyright (c) 1990 The Regents of the University of California.
6 * This code is derived from software contributed to Berkeley by
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * Actual printf innards.
37 * This code is large and complicated...
40 //#define FLOATING_POINT
42 #include <sys/types.h>
63 unsigned long ulongarg
;
64 long long longlongarg
;
65 unsigned long long ulonglongarg
;
73 signed char *pschararg
;
77 long long *plonglongarg
;
78 ptrdiff_t *pptrdiffarg
;
83 long double longdoublearg
;
87 static int __find_arguments(const char *fmt0
, va_list ap
, union arg
**argtable
,
89 static int __grow_type_table(unsigned char **typetable
, int *tablesize
);
92 * Flush out all the vectors defined by the given uio,
93 * then reset it so that it can be reused.
96 __sprint(LTTNG_UST_LFILE
*fp
, struct __lttng_ust_suio
*uio
)
100 if (uio
->uio_resid
== 0) {
104 err
= __sfvwrite(fp
, uio
);
111 * Helper function for `fprintf to unbuffered unix file': creates a
112 * temporary buffer. We only work on write-only files; this avoids
113 * worries about ungetc buffers and so forth.
116 //__sbprintf(LTTNG_UST_LFILE *fp, const char *fmt, va_list ap)
119 // LTTNG_UST_LFILE fake;
120 // struct __sfileext fakeext;
121 // unsigned char buf[BUFSIZ];
123 // _FILEEXT_SETUP(&fake, &fakeext);
124 // /* copy the important variables */
125 // fake._flags = fp->_flags & ~__SNBF;
126 // fake._file = fp->_file;
127 // fake._cookie = fp->_cookie;
128 // fake._write = fp->_write;
130 // /* set up the buffer */
131 // fake._bf._base = fake._p = buf;
132 // fake._bf._size = fake._w = sizeof(buf);
133 // fake._lbfsize = 0; /* not actually used, but Just In Case */
135 // /* do the work, then copy any error status */
136 // ret = ust_safe_vfprintf(&fake, fmt, ap);
137 // if (ret >= 0 && fflush(&fake))
139 // if (fake._flags & __SERR)
140 // fp->_flags |= __SERR;
145 #ifdef FLOATING_POINT
153 extern char *__dtoa(double, int, int, int *, int *, char **);
154 extern void __freedtoa(char *);
155 static int exponent(char *, int, int);
156 #endif /* FLOATING_POINT */
159 * The size of the buffer we use as scratch space for integer
160 * conversions, among other things. Technically, we would need the
161 * most space for base 10 conversions with thousands' grouping
162 * characters between each pair of digits. 100 bytes is a
163 * conservative overestimate even for a 128-bit uintmax_t.
167 #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
171 * Macros for converting digits to letters and vice versa
173 #define to_digit(c) ((c) - '0')
174 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
175 #define to_char(n) ((n) + '0')
178 * Flags used during conversion.
180 #define ALT 0x0001 /* alternate form */
181 #define LADJUST 0x0004 /* left adjustment */
182 #define LONGDBL 0x0008 /* long double; unimplemented */
183 #define LONGINT 0x0010 /* long integer */
184 #define LLONGINT 0x0020 /* long long integer */
185 #define SHORTINT 0x0040 /* short integer */
186 #define ZEROPAD 0x0080 /* zero (as opposed to blank) pad */
187 #define FPT 0x0100 /* Floating point number */
188 #define PTRINT 0x0200 /* (unsigned) ptrdiff_t */
189 #define SIZEINT 0x0400 /* (signed) size_t */
190 #define CHARINT 0x0800 /* 8 bit integer */
191 #define MAXINT 0x1000 /* largest integer size (intmax_t) */
193 int ust_safe_vfprintf(LTTNG_UST_LFILE
*fp
, const char *fmt0
, va_list ap
)
195 char *fmt
; /* format string */
196 int ch
; /* character from fmt */
197 int n
, n2
; /* handy integers (short term usage) */
198 char *cp
; /* handy char pointer (short term usage) */
199 struct __lttng_ust_siov
*iovp
; /* for PRINT macro */
200 int flags
; /* flags as above */
201 int ret
; /* return value accumulator */
202 int width
; /* width from format (%8d), or 0 */
203 int prec
; /* precision from format; <0 for N/A */
204 char sign
; /* sign prefix (' ', '+', '-', or \0) */
207 #ifdef FLOATING_POINT
209 * We can decompose the printed representation of floating
210 * point numbers into several parts, some of which may be empty:
212 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
215 * A: 'sign' holds this value if present; '\0' otherwise
216 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
217 * C: cp points to the string MMMNNN. Leading and trailing
218 * zeros are not in the string and must be added.
219 * D: expchar holds this character; '\0' if no exponent, e.g. %f
220 * F: at least two digits for decimal, at least one digit for hex
222 char *decimal_point
= localeconv()->decimal_point
;
223 int signflag
; /* true if float is negative */
224 union { /* floating point arguments %[aAeEfFgG] */
228 int expt
; /* integer value of exponent */
229 char expchar
; /* exponent character: [eEpP\0] */
230 char *dtoaend
; /* pointer to end of converted digits */
231 int expsize
; /* character count for expstr */
232 int lead
; /* sig figs before decimal or group sep */
233 int ndig
; /* actual number of digits returned by dtoa */
234 char expstr
[MAXEXPDIG
+2]; /* buffer for exponent string: e+ZZZ */
235 char *dtoaresult
= NULL
;
238 uintmax_t _umax
; /* integer arguments %[diouxX] */
239 enum { OCT
, DEC
, HEX
} base
; /* base for %[diouxX] conversion */
240 int dprec
; /* a copy of prec if %[diouxX], 0 otherwise */
241 int realsz
; /* field size expanded by dprec */
242 int size
; /* size of converted field or string */
243 const char *xdigs
= NULL
; /* digits for %[xX] conversion */
245 struct __lttng_ust_suio uio
; /* output information: summary */
246 struct __lttng_ust_siov iov
[NIOV
];/* ... and individual io vectors */
247 char buf
[BUF
]; /* buffer with space for digits of uintmax_t */
248 char ox
[2]; /* space for 0x; ox[1] is either x, X, or \0 */
249 union arg
*argtable
; /* args, built due to positional arg */
250 union arg statargtable
[STATIC_ARG_TBL_SIZE
];
252 int nextarg
; /* 1-based argument index */
253 va_list orgap
; /* original argument pointer */
256 * Choose PADSIZE to trade efficiency vs. size. If larger printf
257 * fields occur frequently, increase PADSIZE and make the initialisers
260 #define PADSIZE 16 /* pad chunk size */
261 static char blanks
[PADSIZE
] =
262 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
263 static char zeroes
[PADSIZE
] =
264 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
266 static const char xdigs_lower
[16] = "0123456789abcdef";
267 static const char xdigs_upper
[16] = "0123456789ABCDEF";
270 * BEWARE, these `goto error' on error, and PAD uses `n'.
272 #define PRINT(ptr, len) do { \
273 iovp->iov_base = (ptr); \
274 iovp->iov_len = (len); \
275 uio.uio_resid += (len); \
277 if (++uio.uio_iovcnt >= NIOV) { \
278 if (__sprint(fp, &uio)) \
283 #define PAD(howmany, with) do { \
284 if ((n = (howmany)) > 0) { \
285 while (n > PADSIZE) { \
286 PRINT(with, PADSIZE); \
292 #define PRINTANDPAD(p, ep, len, with) do { \
298 PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
300 #define FLUSH() do { \
301 if (uio.uio_resid && __sprint(fp, &uio)) \
303 uio.uio_iovcnt = 0; \
308 * To extend shorts properly, we need both signed and unsigned
309 * argument extraction methods.
312 ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
313 flags&LLONGINT ? GETARG(long long) : \
314 flags&LONGINT ? GETARG(long) : \
315 flags&PTRINT ? GETARG(ptrdiff_t) : \
316 flags&SIZEINT ? GETARG(ssize_t) : \
317 flags&SHORTINT ? (short)GETARG(int) : \
318 flags&CHARINT ? (__signed char)GETARG(int) : \
321 ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
322 flags&LLONGINT ? GETARG(unsigned long long) : \
323 flags&LONGINT ? GETARG(unsigned long) : \
324 flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
325 flags&SIZEINT ? GETARG(size_t) : \
326 flags&SHORTINT ? (unsigned short)GETARG(int) : \
327 flags&CHARINT ? (unsigned char)GETARG(int) : \
328 GETARG(unsigned int)))
331 * Append a digit to a value and check for overflow.
333 #define APPEND_DIGIT(val, dig) do { \
334 if ((val) > INT_MAX / 10) \
337 if ((val) > INT_MAX - to_digit((dig))) \
339 (val) += to_digit((dig)); \
343 * Get * arguments, including the form *nn$. Preserve the nextarg
344 * that the argument can be gotten once the type is determined.
346 #define GETASTER(val) \
349 while (is_digit(*cp)) { \
350 APPEND_DIGIT(n2, *cp); \
354 int hold = nextarg; \
355 if (argtable == NULL) { \
356 argtable = statargtable; \
357 __find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
368 * Get the argument indexed by nextarg. If the argument table is
369 * built, use it to get the argument. If its not, get the next
370 * argument (and arguments must be gotten sequentially).
372 #define GETARG(type) \
373 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
374 (nextarg++, va_arg(ap, type)))
376 _SET_ORIENTATION(fp
, -1);
377 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
383 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
384 // if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
386 // return (__sbprintf(fp, fmt0, ap));
392 uio
.uio_iov
= iovp
= iov
;
397 memset(&ps
, 0, sizeof(ps
));
399 * Scan the format for conversions (`%' character).
403 while ((n
= ust_safe_mbrtowc(&wc
, fmt
, MB_CUR_MAX
, &ps
)) > 0) {
411 ptrdiff_t m
= fmt
- cp
;
412 if (m
< 0 || m
> INT_MAX
- ret
)
419 fmt
++; /* skip over '%' */
429 reswitch
: switch (ch
) {
432 * ``If the space and + flags both appear, the space
433 * flag will be ignored.''
443 /* grouping not implemented */
447 * ``A negative field width argument is taken as a
448 * - flag followed by a positive field width.''
450 * They don't exclude field widths read from args.
455 if (width
== INT_MIN
)
466 if ((ch
= *fmt
++) == '*') {
468 prec
= n
< 0 ? -1 : n
;
472 while (is_digit(ch
)) {
478 if (argtable
== NULL
) {
479 argtable
= statargtable
;
480 __find_arguments(fmt0
, orgap
,
481 &argtable
, &argtablesiz
);
489 * ``Note that 0 is taken as a flag, not as the
490 * beginning of a field width.''
495 case '1': case '2': case '3': case '4':
496 case '5': case '6': case '7': case '8': case '9':
501 } while (is_digit(ch
));
504 if (argtable
== NULL
) {
505 argtable
= statargtable
;
506 __find_arguments(fmt0
, orgap
,
507 &argtable
, &argtablesiz
);
513 #ifdef FLOATING_POINT
547 *(cp
= buf
) = GETARG(int);
557 if ((intmax_t)_umax
< 0) {
563 #ifdef FLOATING_POINT
578 __freedtoa(dtoaresult
);
579 if (flags
& LONGDBL
) {
580 fparg
.ldbl
= GETARG(long double);
582 __hldtoa(fparg
.ldbl
, xdigs
, prec
,
583 &expt
, &signflag
, &dtoaend
);
584 if (dtoaresult
== NULL
) {
589 fparg
.dbl
= GETARG(double);
591 __hdtoa(fparg
.dbl
, xdigs
, prec
,
592 &expt
, &signflag
, &dtoaend
);
593 if (dtoaresult
== NULL
) {
606 if (prec
< 0) /* account for digit before decpt */
617 expchar
= ch
- ('g' - 'e');
624 __freedtoa(dtoaresult
);
625 if (flags
& LONGDBL
) {
626 fparg
.ldbl
= GETARG(long double);
628 __ldtoa(&fparg
.ldbl
, expchar
? 2 : 3, prec
,
629 &expt
, &signflag
, &dtoaend
);
630 if (dtoaresult
== NULL
) {
635 fparg
.dbl
= GETARG(double);
637 __dtoa(fparg
.dbl
, expchar
? 2 : 3, prec
,
638 &expt
, &signflag
, &dtoaend
);
639 if (dtoaresult
== NULL
) {
649 if (expt
== INT_MAX
) { /* inf or nan */
651 cp
= (ch
>= 'a') ? "nan" : "NAN";
654 cp
= (ch
>= 'a') ? "inf" : "INF";
661 if (ch
== 'g' || ch
== 'G') {
662 if (expt
> -4 && expt
<= prec
) {
663 /* Make %[gG] smell like %[fF] */
673 * Make %[gG] smell like %[eE], but
674 * trim trailing zeroes if no # flag.
681 expsize
= exponent(expstr
, expt
- 1, expchar
);
682 size
= expsize
+ prec
;
683 if (prec
> 1 || flags
& ALT
)
686 /* space for digits before decimal point */
691 /* space for decimal pt and following digits */
692 if (prec
|| flags
& ALT
)
697 #endif /* FLOATING_POINT */
699 if (flags
& LLONGINT
)
700 *GETARG(long long *) = ret
;
701 else if (flags
& LONGINT
)
702 *GETARG(long *) = ret
;
703 else if (flags
& SHORTINT
)
704 *GETARG(short *) = ret
;
705 else if (flags
& CHARINT
)
706 *GETARG(__signed
char *) = ret
;
707 else if (flags
& PTRINT
)
708 *GETARG(ptrdiff_t *) = ret
;
709 else if (flags
& SIZEINT
)
710 *GETARG(ssize_t
*) = ret
;
711 else if (flags
& MAXINT
)
712 *GETARG(intmax_t *) = ret
;
714 *GETARG(int *) = ret
;
715 continue; /* no output */
725 * ``The argument shall be a pointer to void. The
726 * value of the pointer is converted to a sequence
727 * of printable characters, in an implementation-
732 _umax
= (u_long
)GETARG(void *);
738 if ((cp
= GETARG(char *)) == NULL
)
742 * can't use strlen; can only look for the
743 * NUL in the first `prec' characters, and
744 * strlen() will go further.
746 char *p
= memchr(cp
, 0, prec
);
748 size
= p
? (p
- cp
) : prec
;
752 if ((len
= strlen(cp
)) > INT_MAX
)
772 /* leading 0x/X only if non-zero */
773 if (flags
& ALT
&& _umax
!= 0)
776 /* unsigned conversions */
779 * ``... diouXx conversions ... if a precision is
780 * specified, the 0 flag will be ignored.''
783 number
: if ((dprec
= prec
) >= 0)
787 * ``The result of converting a zero value with an
788 * explicit precision of zero is no characters.''
792 if (_umax
!= 0 || prec
!= 0) {
794 * Unsigned mod is hard, and unsigned mod
795 * by a constant is easier than that by
796 * a variable; hence this switch.
801 *--cp
= to_char(_umax
& 7);
804 /* handle octal leading 0 */
805 if (flags
& ALT
&& *cp
!= '0')
810 /* many numbers are 1 digit */
811 while (_umax
>= 10) {
812 *--cp
= to_char(_umax
% 10);
815 *--cp
= to_char(_umax
);
820 *--cp
= xdigs
[_umax
& 15];
826 cp
= "bug in ust_safe_vfprintf: bad base";
831 size
= buf
+ BUF
- cp
;
832 if (size
> BUF
) /* should never happen */
836 default: /* "%?" prints ?, unless ? is NUL */
839 /* pretend it was %c with argument ch */
848 * All reasonable formats wind up here. At this point, `cp'
849 * points to a string which (if not flags&LADJUST) should be
850 * padded out to `width' places. If flags&ZEROPAD, it should
851 * first be prefixed by any sign or other prefix; otherwise,
852 * it should be blank padded before the prefix is emitted.
853 * After any left-hand padding and prefixing, emit zeroes
854 * required by a decimal %[diouxX] precision, then print the
855 * string proper, then emit zeroes required by any leftover
856 * floating precision; finally, if LADJUST, pad with blanks.
858 * Compute actual size, so we know how much to pad.
859 * size excludes decimal prec; realsz includes it.
861 realsz
= dprec
> size
? dprec
: size
;
867 /* right-adjusting blank padding */
868 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
869 PAD(width
- realsz
, blanks
);
874 if (ox
[1]) { /* ox[1] is either x, X, or \0 */
879 /* right-adjusting zero padding */
880 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
881 PAD(width
- realsz
, zeroes
);
883 /* leading zeroes from decimal precision */
884 PAD(dprec
- size
, zeroes
);
886 /* the string or number proper */
887 #ifdef FLOATING_POINT
888 if ((flags
& FPT
) == 0) {
890 } else { /* glue together f_p fragments */
891 if (!expchar
) { /* %[fF] or sufficiently short %[gG] */
894 if (prec
|| flags
& ALT
)
895 PRINT(decimal_point
, 1);
897 /* already handled initial 0's */
900 PRINTANDPAD(cp
, dtoaend
, lead
, zeroes
);
902 if (prec
|| flags
& ALT
)
903 PRINT(decimal_point
, 1);
905 PRINTANDPAD(cp
, dtoaend
, prec
, zeroes
);
906 } else { /* %[eE] or sufficiently long %[gG] */
907 if (prec
> 1 || flags
& ALT
) {
909 buf
[1] = *decimal_point
;
912 PAD(prec
- ndig
, zeroes
);
916 PRINT(expstr
, expsize
);
922 /* left-adjusting padding (always blank) */
924 PAD(width
- realsz
, blanks
);
926 /* finally, adjust ret */
929 if (width
> INT_MAX
- ret
)
933 FLUSH(); /* copy out the I/O vectors */
948 #ifdef FLOATING_POINT
950 __freedtoa(dtoaresult
);
952 if (argtable
!= NULL
&& argtable
!= statargtable
) {
953 munmap(argtable
, argtablesiz
);
960 * Type ids for argument type table.
976 #define T_LONG_DOUBLE 14
982 #define T_SSIZEINT 20
983 #define TP_SSIZEINT 21
991 * Find all arguments when a positional parameter is encountered. Returns a
992 * table, indexed by argument number, of pointers to each arguments. The
993 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
994 * It will be replaced with a mmap-ed one if it overflows (malloc cannot be
995 * used since we are attempting to make snprintf thread safe, and alloca is
996 * problematic since we have nested functions..)
999 __find_arguments(const char *fmt0
, va_list ap
, union arg
**argtable
,
1000 size_t *argtablesiz
)
1002 char *fmt
; /* format string */
1003 int ch
; /* character from fmt */
1004 int n
, n2
; /* handy integer (short term usage) */
1005 char *cp
; /* handy char pointer (short term usage) */
1006 int flags
; /* flags as above */
1007 unsigned char *typetable
; /* table of types */
1008 unsigned char stattypetable
[STATIC_ARG_TBL_SIZE
];
1009 int tablesize
; /* current size of type table */
1010 int tablemax
; /* largest used index in table */
1011 int nextarg
; /* 1-based argument index */
1012 int ret
= 0; /* return value */
1017 * Add an argument type to the table, expanding if necessary.
1019 #define ADDTYPE(type) \
1020 ((nextarg >= tablesize) ? \
1021 __grow_type_table(&typetable, &tablesize) : 0, \
1022 (nextarg > tablemax) ? tablemax = nextarg : 0, \
1023 typetable[nextarg++] = type)
1026 ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
1027 ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1028 ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
1029 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
1030 ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
1031 ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
1032 ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
1035 ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
1036 ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1037 ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
1038 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
1039 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
1040 ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
1041 ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))
1044 * Add * arguments to the type array.
1046 #define ADDASTER() \
1049 while (is_digit(*cp)) { \
1050 APPEND_DIGIT(n2, *cp); \
1054 int hold = nextarg; \
1063 typetable
= stattypetable
;
1064 tablesize
= STATIC_ARG_TBL_SIZE
;
1067 memset(typetable
, T_UNUSED
, STATIC_ARG_TBL_SIZE
);
1068 memset(&ps
, 0, sizeof(ps
));
1071 * Scan the format for conversions (`%' character).
1075 while ((n
= ust_safe_mbrtowc(&wc
, fmt
, MB_CUR_MAX
, &ps
)) > 0) {
1084 fmt
++; /* skip over '%' */
1089 reswitch
: switch (ch
) {
1101 if ((ch
= *fmt
++) == '*') {
1105 while (is_digit(ch
)) {
1111 case '1': case '2': case '3': case '4':
1112 case '5': case '6': case '7': case '8': case '9':
1115 APPEND_DIGIT(n
,ch
);
1117 } while (is_digit(ch
));
1123 #ifdef FLOATING_POINT
1163 #ifdef FLOATING_POINT
1172 if (flags
& LONGDBL
)
1173 ADDTYPE(T_LONG_DOUBLE
);
1177 #endif /* FLOATING_POINT */
1179 if (flags
& LLONGINT
)
1181 else if (flags
& LONGINT
)
1183 else if (flags
& SHORTINT
)
1185 else if (flags
& PTRINT
)
1187 else if (flags
& SIZEINT
)
1188 ADDTYPE(TP_SSIZEINT
);
1189 else if (flags
& MAXINT
)
1193 continue; /* no output */
1214 default: /* "%?" prints ?, unless ? is NUL */
1222 * Build the argument table.
1224 if (tablemax
>= STATIC_ARG_TBL_SIZE
) {
1225 *argtablesiz
= sizeof(union arg
) * (tablemax
+ 1);
1226 *argtable
= mmap(NULL
, *argtablesiz
,
1227 PROT_WRITE
|PROT_READ
, MAP_ANON
|MAP_PRIVATE
, -1, 0);
1228 if (*argtable
== MAP_FAILED
)
1233 /* XXX is this required? */
1234 (*argtable
)[0].intarg
= 0;
1236 for (n
= 1; n
<= tablemax
; n
++) {
1237 switch (typetable
[n
]) {
1244 (*argtable
)[n
].intarg
= va_arg(ap
, int);
1247 (*argtable
)[n
].pshortarg
= va_arg(ap
, short *);
1250 (*argtable
)[n
].uintarg
= va_arg(ap
, unsigned int);
1253 (*argtable
)[n
].pintarg
= va_arg(ap
, int *);
1256 (*argtable
)[n
].longarg
= va_arg(ap
, long);
1259 (*argtable
)[n
].ulongarg
= va_arg(ap
, unsigned long);
1262 (*argtable
)[n
].plongarg
= va_arg(ap
, long *);
1265 (*argtable
)[n
].longlongarg
= va_arg(ap
, long long);
1268 (*argtable
)[n
].ulonglongarg
= va_arg(ap
, unsigned long long);
1271 (*argtable
)[n
].plonglongarg
= va_arg(ap
, long long *);
1273 #ifdef FLOATING_POINT
1275 (*argtable
)[n
].doublearg
= va_arg(ap
, double);
1278 (*argtable
)[n
].longdoublearg
= va_arg(ap
, long double);
1282 (*argtable
)[n
].pchararg
= va_arg(ap
, char *);
1285 (*argtable
)[n
].pvoidarg
= va_arg(ap
, void *);
1288 (*argtable
)[n
].ptrdiffarg
= va_arg(ap
, ptrdiff_t);
1291 (*argtable
)[n
].pptrdiffarg
= va_arg(ap
, ptrdiff_t *);
1294 (*argtable
)[n
].sizearg
= va_arg(ap
, size_t);
1297 (*argtable
)[n
].ssizearg
= va_arg(ap
, ssize_t
);
1300 (*argtable
)[n
].pssizearg
= va_arg(ap
, ssize_t
*);
1303 (*argtable
)[n
].intmaxarg
= va_arg(ap
, intmax_t);
1314 if (typetable
!= NULL
&& typetable
!= stattypetable
) {
1315 munmap(typetable
, *argtablesiz
);
1322 * Increase the size of the type table.
1325 __grow_type_table(unsigned char **typetable
, int *tablesize
)
1327 unsigned char *oldtable
= *typetable
;
1328 int newsize
= *tablesize
* 2;
1330 if (newsize
< getpagesize())
1331 newsize
= getpagesize();
1333 if (*tablesize
== STATIC_ARG_TBL_SIZE
) {
1334 *typetable
= mmap(NULL
, newsize
, PROT_WRITE
|PROT_READ
,
1335 MAP_ANON
|MAP_PRIVATE
, -1, 0);
1336 if (*typetable
== MAP_FAILED
)
1338 bcopy(oldtable
, *typetable
, *tablesize
);
1340 unsigned char *new = mmap(NULL
, newsize
, PROT_WRITE
|PROT_READ
,
1341 MAP_ANON
|MAP_PRIVATE
, -1, 0);
1342 if (new == MAP_FAILED
)
1344 memmove(new, *typetable
, *tablesize
);
1345 munmap(*typetable
, *tablesize
);
1348 memset(*typetable
+ *tablesize
, T_UNUSED
, (newsize
- *tablesize
));
1350 *tablesize
= newsize
;
1355 #ifdef FLOATING_POINT
1357 exponent(char *p0
, int exp
, int fmtch
)
1360 char expbuf
[MAXEXPDIG
];
1369 t
= expbuf
+ MAXEXPDIG
;
1372 *--t
= to_char(exp
% 10);
1373 } while ((exp
/= 10) > 9);
1374 *--t
= to_char(exp
);
1375 for (; t
< expbuf
+ MAXEXPDIG
; *p
++ = *t
++)
1379 * Exponents for decimal floating point conversions
1380 * (%[eEgG]) must be at least two characters long,
1381 * whereas exponents for hexadecimal conversions can
1382 * be only one character long.
1384 if (fmtch
== 'e' || fmtch
== 'E')
1386 *p
++ = to_char(exp
);
1390 #endif /* FLOATING_POINT */
This page took 0.09879 seconds and 4 git commands to generate.