1 /* $OpenBSD: vfprintf.c,v 1.57 2009/10/28 21:15:02 naddy Exp $ */
3 * SPDX-License-Identifier: BSD-3-Clause
5 * Copyright (C) 1990 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
13 * Actual printf innards.
15 * This code is large and complicated...
18 //#define FLOATING_POINT
20 #include <sys/types.h>
42 unsigned long ulongarg
;
43 long long longlongarg
;
44 unsigned long long ulonglongarg
;
52 signed char *pschararg
;
56 long long *plonglongarg
;
57 ptrdiff_t *pptrdiffarg
;
62 long double longdoublearg
;
66 static int __find_arguments(const char *fmt0
, va_list ap
, union arg
**argtable
,
68 static int __grow_type_table(unsigned char **typetable
, int *tablesize
);
71 * Flush out all the vectors defined by the given uio,
72 * then reset it so that it can be reused.
75 __sprint(LTTNG_UST_LFILE
*fp
, struct __lttng_ust_suio
*uio
)
79 if (uio
->uio_resid
== 0) {
83 err
= __sfvwrite(fp
, uio
);
90 * Helper function for `fprintf to unbuffered unix file': creates a
91 * temporary buffer. We only work on write-only files; this avoids
92 * worries about ungetc buffers and so forth.
95 //__sbprintf(LTTNG_UST_LFILE *fp, const char *fmt, va_list ap)
98 // LTTNG_UST_LFILE fake;
99 // struct __sfileext fakeext;
100 // unsigned char buf[BUFSIZ];
102 // _FILEEXT_SETUP(&fake, &fakeext);
103 // /* copy the important variables */
104 // fake._flags = fp->_flags & ~__SNBF;
105 // fake._file = fp->_file;
106 // fake._cookie = fp->_cookie;
107 // fake._write = fp->_write;
109 // /* set up the buffer */
110 // fake._bf._base = fake._p = buf;
111 // fake._bf._size = fake._w = sizeof(buf);
112 // fake._lbfsize = 0; /* not actually used, but Just In Case */
114 // /* do the work, then copy any error status */
115 // ret = ust_safe_vfprintf(&fake, fmt, ap);
116 // if (ret >= 0 && fflush(&fake))
118 // if (fake._flags & __SERR)
119 // fp->_flags |= __SERR;
124 #ifdef FLOATING_POINT
132 extern char *__dtoa(double, int, int, int *, int *, char **);
133 extern void __freedtoa(char *);
134 static int exponent(char *, int, int);
135 #endif /* FLOATING_POINT */
138 * The size of the buffer we use as scratch space for integer
139 * conversions, among other things. Technically, we would need the
140 * most space for base 10 conversions with thousands' grouping
141 * characters between each pair of digits. 100 bytes is a
142 * conservative overestimate even for a 128-bit uintmax_t.
146 #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
150 * Macros for converting digits to letters and vice versa
152 #define to_digit(c) ((c) - '0')
153 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
154 #define to_char(n) ((n) + '0')
157 * Flags used during conversion.
159 #define ALT 0x0001 /* alternate form */
160 #define LADJUST 0x0004 /* left adjustment */
161 #define LONGDBL 0x0008 /* long double; unimplemented */
162 #define LONGINT 0x0010 /* long integer */
163 #define LLONGINT 0x0020 /* long long integer */
164 #define SHORTINT 0x0040 /* short integer */
165 #define ZEROPAD 0x0080 /* zero (as opposed to blank) pad */
166 #define FPT 0x0100 /* Floating point number */
167 #define PTRINT 0x0200 /* (unsigned) ptrdiff_t */
168 #define SIZEINT 0x0400 /* (signed) size_t */
169 #define CHARINT 0x0800 /* 8 bit integer */
170 #define MAXINT 0x1000 /* largest integer size (intmax_t) */
172 int ust_safe_vfprintf(LTTNG_UST_LFILE
*fp
, const char *fmt0
, va_list ap
)
174 char *fmt
; /* format string */
175 int ch
; /* character from fmt */
176 int n
, n2
; /* handy integers (short term usage) */
177 char *cp
; /* handy char pointer (short term usage) */
178 struct __lttng_ust_siov
*iovp
; /* for PRINT macro */
179 int flags
; /* flags as above */
180 int ret
; /* return value accumulator */
181 int width
; /* width from format (%8d), or 0 */
182 int prec
; /* precision from format; <0 for N/A */
183 char sign
; /* sign prefix (' ', '+', '-', or \0) */
186 #ifdef FLOATING_POINT
188 * We can decompose the printed representation of floating
189 * point numbers into several parts, some of which may be empty:
191 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
194 * A: 'sign' holds this value if present; '\0' otherwise
195 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
196 * C: cp points to the string MMMNNN. Leading and trailing
197 * zeros are not in the string and must be added.
198 * D: expchar holds this character; '\0' if no exponent, e.g. %f
199 * F: at least two digits for decimal, at least one digit for hex
201 char *decimal_point
= localeconv()->decimal_point
;
202 int signflag
; /* true if float is negative */
203 union { /* floating point arguments %[aAeEfFgG] */
207 int expt
; /* integer value of exponent */
208 char expchar
; /* exponent character: [eEpP\0] */
209 char *dtoaend
; /* pointer to end of converted digits */
210 int expsize
; /* character count for expstr */
211 int lead
; /* sig figs before decimal or group sep */
212 int ndig
; /* actual number of digits returned by dtoa */
213 char expstr
[MAXEXPDIG
+2]; /* buffer for exponent string: e+ZZZ */
214 char *dtoaresult
= NULL
;
217 uintmax_t _umax
; /* integer arguments %[diouxX] */
218 enum { OCT
, DEC
, HEX
} base
; /* base for %[diouxX] conversion */
219 int dprec
; /* a copy of prec if %[diouxX], 0 otherwise */
220 int realsz
; /* field size expanded by dprec */
221 int size
; /* size of converted field or string */
222 const char *xdigs
= NULL
; /* digits for %[xX] conversion */
224 struct __lttng_ust_suio uio
; /* output information: summary */
225 struct __lttng_ust_siov iov
[NIOV
];/* ... and individual io vectors */
226 char buf
[BUF
]; /* buffer with space for digits of uintmax_t */
227 char ox
[2]; /* space for 0x; ox[1] is either x, X, or \0 */
228 union arg
*argtable
; /* args, built due to positional arg */
229 union arg statargtable
[STATIC_ARG_TBL_SIZE
];
231 int nextarg
; /* 1-based argument index */
232 va_list orgap
; /* original argument pointer */
235 * Choose PADSIZE to trade efficiency vs. size. If larger printf
236 * fields occur frequently, increase PADSIZE and make the initialisers
239 #define PADSIZE 16 /* pad chunk size */
240 static char blanks
[PADSIZE
] =
241 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
242 static char zeroes
[PADSIZE
] =
243 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
245 static const char xdigs_lower
[16] = "0123456789abcdef";
246 static const char xdigs_upper
[16] = "0123456789ABCDEF";
249 * BEWARE, these `goto error' on error, and PAD uses `n'.
251 #define PRINT(ptr, len) do { \
252 iovp->iov_base = (ptr); \
253 iovp->iov_len = (len); \
254 uio.uio_resid += (len); \
256 if (++uio.uio_iovcnt >= NIOV) { \
257 if (__sprint(fp, &uio)) \
262 #define PAD(howmany, with) do { \
263 if ((n = (howmany)) > 0) { \
264 while (n > PADSIZE) { \
265 PRINT(with, PADSIZE); \
271 #define PRINTANDPAD(p, ep, len, with) do { \
277 PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
279 #define FLUSH() do { \
280 if (uio.uio_resid && __sprint(fp, &uio)) \
282 uio.uio_iovcnt = 0; \
287 * To extend shorts properly, we need both signed and unsigned
288 * argument extraction methods.
291 ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
292 flags&LLONGINT ? GETARG(long long) : \
293 flags&LONGINT ? GETARG(long) : \
294 flags&PTRINT ? GETARG(ptrdiff_t) : \
295 flags&SIZEINT ? GETARG(ssize_t) : \
296 flags&SHORTINT ? (short)GETARG(int) : \
297 flags&CHARINT ? (__signed char)GETARG(int) : \
300 ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
301 flags&LLONGINT ? GETARG(unsigned long long) : \
302 flags&LONGINT ? GETARG(unsigned long) : \
303 flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
304 flags&SIZEINT ? GETARG(size_t) : \
305 flags&SHORTINT ? (unsigned short)GETARG(int) : \
306 flags&CHARINT ? (unsigned char)GETARG(int) : \
307 GETARG(unsigned int)))
310 * Append a digit to a value and check for overflow.
312 #define APPEND_DIGIT(val, dig) do { \
313 if ((val) > INT_MAX / 10) \
316 if ((val) > INT_MAX - to_digit((dig))) \
318 (val) += to_digit((dig)); \
322 * Get * arguments, including the form *nn$. Preserve the nextarg
323 * that the argument can be gotten once the type is determined.
325 #define GETASTER(val) \
328 while (is_digit(*cp)) { \
329 APPEND_DIGIT(n2, *cp); \
333 int hold = nextarg; \
334 if (argtable == NULL) { \
335 argtable = statargtable; \
336 __find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
347 * Get the argument indexed by nextarg. If the argument table is
348 * built, use it to get the argument. If its not, get the next
349 * argument (and arguments must be gotten sequentially).
351 #define GETARG(type) \
352 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
353 (nextarg++, va_arg(ap, type)))
355 _SET_ORIENTATION(fp
, -1);
356 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
362 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
363 // if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
365 // return (__sbprintf(fp, fmt0, ap));
371 uio
.uio_iov
= iovp
= iov
;
376 memset(&ps
, 0, sizeof(ps
));
378 * Scan the format for conversions (`%' character).
382 while ((n
= ust_safe_mbrtowc(&wc
, fmt
, MB_CUR_MAX
, &ps
)) > 0) {
390 ptrdiff_t m
= fmt
- cp
;
391 if (m
< 0 || m
> INT_MAX
- ret
)
398 fmt
++; /* skip over '%' */
408 reswitch
: switch (ch
) {
411 * ``If the space and + flags both appear, the space
412 * flag will be ignored.''
422 /* grouping not implemented */
426 * ``A negative field width argument is taken as a
427 * - flag followed by a positive field width.''
429 * They don't exclude field widths read from args.
434 if (width
== INT_MIN
)
445 if ((ch
= *fmt
++) == '*') {
447 prec
= n
< 0 ? -1 : n
;
451 while (is_digit(ch
)) {
457 if (argtable
== NULL
) {
458 argtable
= statargtable
;
459 __find_arguments(fmt0
, orgap
,
460 &argtable
, &argtablesiz
);
468 * ``Note that 0 is taken as a flag, not as the
469 * beginning of a field width.''
474 case '1': case '2': case '3': case '4':
475 case '5': case '6': case '7': case '8': case '9':
480 } while (is_digit(ch
));
483 if (argtable
== NULL
) {
484 argtable
= statargtable
;
485 __find_arguments(fmt0
, orgap
,
486 &argtable
, &argtablesiz
);
492 #ifdef FLOATING_POINT
526 *(cp
= buf
) = GETARG(int);
536 if ((intmax_t)_umax
< 0) {
542 #ifdef FLOATING_POINT
557 __freedtoa(dtoaresult
);
558 if (flags
& LONGDBL
) {
559 fparg
.ldbl
= GETARG(long double);
561 __hldtoa(fparg
.ldbl
, xdigs
, prec
,
562 &expt
, &signflag
, &dtoaend
);
563 if (dtoaresult
== NULL
) {
568 fparg
.dbl
= GETARG(double);
570 __hdtoa(fparg
.dbl
, xdigs
, prec
,
571 &expt
, &signflag
, &dtoaend
);
572 if (dtoaresult
== NULL
) {
585 if (prec
< 0) /* account for digit before decpt */
596 expchar
= ch
- ('g' - 'e');
603 __freedtoa(dtoaresult
);
604 if (flags
& LONGDBL
) {
605 fparg
.ldbl
= GETARG(long double);
607 __ldtoa(&fparg
.ldbl
, expchar
? 2 : 3, prec
,
608 &expt
, &signflag
, &dtoaend
);
609 if (dtoaresult
== NULL
) {
614 fparg
.dbl
= GETARG(double);
616 __dtoa(fparg
.dbl
, expchar
? 2 : 3, prec
,
617 &expt
, &signflag
, &dtoaend
);
618 if (dtoaresult
== NULL
) {
628 if (expt
== INT_MAX
) { /* inf or nan */
630 cp
= (ch
>= 'a') ? "nan" : "NAN";
633 cp
= (ch
>= 'a') ? "inf" : "INF";
640 if (ch
== 'g' || ch
== 'G') {
641 if (expt
> -4 && expt
<= prec
) {
642 /* Make %[gG] smell like %[fF] */
652 * Make %[gG] smell like %[eE], but
653 * trim trailing zeroes if no # flag.
660 expsize
= exponent(expstr
, expt
- 1, expchar
);
661 size
= expsize
+ prec
;
662 if (prec
> 1 || flags
& ALT
)
665 /* space for digits before decimal point */
670 /* space for decimal pt and following digits */
671 if (prec
|| flags
& ALT
)
676 #endif /* FLOATING_POINT */
678 if (flags
& LLONGINT
)
679 *GETARG(long long *) = ret
;
680 else if (flags
& LONGINT
)
681 *GETARG(long *) = ret
;
682 else if (flags
& SHORTINT
)
683 *GETARG(short *) = ret
;
684 else if (flags
& CHARINT
)
685 *GETARG(__signed
char *) = ret
;
686 else if (flags
& PTRINT
)
687 *GETARG(ptrdiff_t *) = ret
;
688 else if (flags
& SIZEINT
)
689 *GETARG(ssize_t
*) = ret
;
690 else if (flags
& MAXINT
)
691 *GETARG(intmax_t *) = ret
;
693 *GETARG(int *) = ret
;
694 continue; /* no output */
704 * ``The argument shall be a pointer to void. The
705 * value of the pointer is converted to a sequence
706 * of printable characters, in an implementation-
711 _umax
= (u_long
)GETARG(void *);
717 if ((cp
= GETARG(char *)) == NULL
)
721 * can't use strlen; can only look for the
722 * NUL in the first `prec' characters, and
723 * strlen() will go further.
725 char *p
= memchr(cp
, 0, prec
);
727 size
= p
? (p
- cp
) : prec
;
731 if ((len
= strlen(cp
)) > INT_MAX
)
751 /* leading 0x/X only if non-zero */
752 if (flags
& ALT
&& _umax
!= 0)
755 /* unsigned conversions */
758 * ``... diouXx conversions ... if a precision is
759 * specified, the 0 flag will be ignored.''
762 number
: if ((dprec
= prec
) >= 0)
766 * ``The result of converting a zero value with an
767 * explicit precision of zero is no characters.''
771 if (_umax
!= 0 || prec
!= 0) {
773 * Unsigned mod is hard, and unsigned mod
774 * by a constant is easier than that by
775 * a variable; hence this switch.
780 *--cp
= to_char(_umax
& 7);
783 /* handle octal leading 0 */
784 if (flags
& ALT
&& *cp
!= '0')
789 /* many numbers are 1 digit */
790 while (_umax
>= 10) {
791 *--cp
= to_char(_umax
% 10);
794 *--cp
= to_char(_umax
);
799 *--cp
= xdigs
[_umax
& 15];
805 cp
= "bug in ust_safe_vfprintf: bad base";
810 size
= buf
+ BUF
- cp
;
811 if (size
> BUF
) /* should never happen */
815 default: /* "%?" prints ?, unless ? is NUL */
818 /* pretend it was %c with argument ch */
827 * All reasonable formats wind up here. At this point, `cp'
828 * points to a string which (if not flags&LADJUST) should be
829 * padded out to `width' places. If flags&ZEROPAD, it should
830 * first be prefixed by any sign or other prefix; otherwise,
831 * it should be blank padded before the prefix is emitted.
832 * After any left-hand padding and prefixing, emit zeroes
833 * required by a decimal %[diouxX] precision, then print the
834 * string proper, then emit zeroes required by any leftover
835 * floating precision; finally, if LADJUST, pad with blanks.
837 * Compute actual size, so we know how much to pad.
838 * size excludes decimal prec; realsz includes it.
840 realsz
= dprec
> size
? dprec
: size
;
846 /* right-adjusting blank padding */
847 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
848 PAD(width
- realsz
, blanks
);
853 if (ox
[1]) { /* ox[1] is either x, X, or \0 */
858 /* right-adjusting zero padding */
859 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
860 PAD(width
- realsz
, zeroes
);
862 /* leading zeroes from decimal precision */
863 PAD(dprec
- size
, zeroes
);
865 /* the string or number proper */
866 #ifdef FLOATING_POINT
867 if ((flags
& FPT
) == 0) {
869 } else { /* glue together f_p fragments */
870 if (!expchar
) { /* %[fF] or sufficiently short %[gG] */
873 if (prec
|| flags
& ALT
)
874 PRINT(decimal_point
, 1);
876 /* already handled initial 0's */
879 PRINTANDPAD(cp
, dtoaend
, lead
, zeroes
);
881 if (prec
|| flags
& ALT
)
882 PRINT(decimal_point
, 1);
884 PRINTANDPAD(cp
, dtoaend
, prec
, zeroes
);
885 } else { /* %[eE] or sufficiently long %[gG] */
886 if (prec
> 1 || flags
& ALT
) {
888 buf
[1] = *decimal_point
;
891 PAD(prec
- ndig
, zeroes
);
895 PRINT(expstr
, expsize
);
901 /* left-adjusting padding (always blank) */
903 PAD(width
- realsz
, blanks
);
905 /* finally, adjust ret */
908 if (width
> INT_MAX
- ret
)
912 FLUSH(); /* copy out the I/O vectors */
927 #ifdef FLOATING_POINT
929 __freedtoa(dtoaresult
);
931 if (argtable
!= NULL
&& argtable
!= statargtable
) {
932 munmap(argtable
, argtablesiz
);
939 * Type ids for argument type table.
955 #define T_LONG_DOUBLE 14
961 #define T_SSIZEINT 20
962 #define TP_SSIZEINT 21
970 * Find all arguments when a positional parameter is encountered. Returns a
971 * table, indexed by argument number, of pointers to each arguments. The
972 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
973 * It will be replaced with a mmap-ed one if it overflows (malloc cannot be
974 * used since we are attempting to make snprintf thread safe, and alloca is
975 * problematic since we have nested functions..)
978 __find_arguments(const char *fmt0
, va_list ap
, union arg
**argtable
,
981 char *fmt
; /* format string */
982 int ch
; /* character from fmt */
983 int n
, n2
; /* handy integer (short term usage) */
984 char *cp
; /* handy char pointer (short term usage) */
985 int flags
; /* flags as above */
986 unsigned char *typetable
; /* table of types */
987 unsigned char stattypetable
[STATIC_ARG_TBL_SIZE
];
988 int tablesize
; /* current size of type table */
989 int tablemax
; /* largest used index in table */
990 int nextarg
; /* 1-based argument index */
991 int ret
= 0; /* return value */
996 * Add an argument type to the table, expanding if necessary.
998 #define ADDTYPE(type) \
999 ((nextarg >= tablesize) ? \
1000 __grow_type_table(&typetable, &tablesize) : 0, \
1001 (nextarg > tablemax) ? tablemax = nextarg : 0, \
1002 typetable[nextarg++] = type)
1005 ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
1006 ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1007 ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
1008 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
1009 ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
1010 ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
1011 ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
1014 ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
1015 ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1016 ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
1017 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
1018 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
1019 ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
1020 ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))
1023 * Add * arguments to the type array.
1025 #define ADDASTER() \
1028 while (is_digit(*cp)) { \
1029 APPEND_DIGIT(n2, *cp); \
1033 int hold = nextarg; \
1042 typetable
= stattypetable
;
1043 tablesize
= STATIC_ARG_TBL_SIZE
;
1046 memset(typetable
, T_UNUSED
, STATIC_ARG_TBL_SIZE
);
1047 memset(&ps
, 0, sizeof(ps
));
1050 * Scan the format for conversions (`%' character).
1054 while ((n
= ust_safe_mbrtowc(&wc
, fmt
, MB_CUR_MAX
, &ps
)) > 0) {
1063 fmt
++; /* skip over '%' */
1068 reswitch
: switch (ch
) {
1080 if ((ch
= *fmt
++) == '*') {
1084 while (is_digit(ch
)) {
1090 case '1': case '2': case '3': case '4':
1091 case '5': case '6': case '7': case '8': case '9':
1094 APPEND_DIGIT(n
,ch
);
1096 } while (is_digit(ch
));
1102 #ifdef FLOATING_POINT
1142 #ifdef FLOATING_POINT
1151 if (flags
& LONGDBL
)
1152 ADDTYPE(T_LONG_DOUBLE
);
1156 #endif /* FLOATING_POINT */
1158 if (flags
& LLONGINT
)
1160 else if (flags
& LONGINT
)
1162 else if (flags
& SHORTINT
)
1164 else if (flags
& PTRINT
)
1166 else if (flags
& SIZEINT
)
1167 ADDTYPE(TP_SSIZEINT
);
1168 else if (flags
& MAXINT
)
1172 continue; /* no output */
1193 default: /* "%?" prints ?, unless ? is NUL */
1201 * Build the argument table.
1203 if (tablemax
>= STATIC_ARG_TBL_SIZE
) {
1204 *argtablesiz
= sizeof(union arg
) * (tablemax
+ 1);
1205 *argtable
= mmap(NULL
, *argtablesiz
,
1206 PROT_WRITE
|PROT_READ
, MAP_ANON
|MAP_PRIVATE
, -1, 0);
1207 if (*argtable
== MAP_FAILED
)
1212 /* XXX is this required? */
1213 (*argtable
)[0].intarg
= 0;
1215 for (n
= 1; n
<= tablemax
; n
++) {
1216 switch (typetable
[n
]) {
1223 (*argtable
)[n
].intarg
= va_arg(ap
, int);
1226 (*argtable
)[n
].pshortarg
= va_arg(ap
, short *);
1229 (*argtable
)[n
].uintarg
= va_arg(ap
, unsigned int);
1232 (*argtable
)[n
].pintarg
= va_arg(ap
, int *);
1235 (*argtable
)[n
].longarg
= va_arg(ap
, long);
1238 (*argtable
)[n
].ulongarg
= va_arg(ap
, unsigned long);
1241 (*argtable
)[n
].plongarg
= va_arg(ap
, long *);
1244 (*argtable
)[n
].longlongarg
= va_arg(ap
, long long);
1247 (*argtable
)[n
].ulonglongarg
= va_arg(ap
, unsigned long long);
1250 (*argtable
)[n
].plonglongarg
= va_arg(ap
, long long *);
1252 #ifdef FLOATING_POINT
1254 (*argtable
)[n
].doublearg
= va_arg(ap
, double);
1257 (*argtable
)[n
].longdoublearg
= va_arg(ap
, long double);
1261 (*argtable
)[n
].pchararg
= va_arg(ap
, char *);
1264 (*argtable
)[n
].pvoidarg
= va_arg(ap
, void *);
1267 (*argtable
)[n
].ptrdiffarg
= va_arg(ap
, ptrdiff_t);
1270 (*argtable
)[n
].pptrdiffarg
= va_arg(ap
, ptrdiff_t *);
1273 (*argtable
)[n
].sizearg
= va_arg(ap
, size_t);
1276 (*argtable
)[n
].ssizearg
= va_arg(ap
, ssize_t
);
1279 (*argtable
)[n
].pssizearg
= va_arg(ap
, ssize_t
*);
1282 (*argtable
)[n
].intmaxarg
= va_arg(ap
, intmax_t);
1293 if (typetable
!= NULL
&& typetable
!= stattypetable
) {
1294 munmap(typetable
, *argtablesiz
);
1301 * Increase the size of the type table.
1304 __grow_type_table(unsigned char **typetable
, int *tablesize
)
1306 unsigned char *oldtable
= *typetable
;
1307 int newsize
= *tablesize
* 2;
1309 if (newsize
< getpagesize())
1310 newsize
= getpagesize();
1312 if (*tablesize
== STATIC_ARG_TBL_SIZE
) {
1313 *typetable
= mmap(NULL
, newsize
, PROT_WRITE
|PROT_READ
,
1314 MAP_ANON
|MAP_PRIVATE
, -1, 0);
1315 if (*typetable
== MAP_FAILED
)
1317 bcopy(oldtable
, *typetable
, *tablesize
);
1319 unsigned char *new = mmap(NULL
, newsize
, PROT_WRITE
|PROT_READ
,
1320 MAP_ANON
|MAP_PRIVATE
, -1, 0);
1321 if (new == MAP_FAILED
)
1323 memmove(new, *typetable
, *tablesize
);
1324 munmap(*typetable
, *tablesize
);
1327 memset(*typetable
+ *tablesize
, T_UNUSED
, (newsize
- *tablesize
));
1329 *tablesize
= newsize
;
1334 #ifdef FLOATING_POINT
1336 exponent(char *p0
, int exp
, int fmtch
)
1339 char expbuf
[MAXEXPDIG
];
1348 t
= expbuf
+ MAXEXPDIG
;
1351 *--t
= to_char(exp
% 10);
1352 } while ((exp
/= 10) > 9);
1353 *--t
= to_char(exp
);
1354 for (; t
< expbuf
+ MAXEXPDIG
; *p
++ = *t
++)
1358 * Exponents for decimal floating point conversions
1359 * (%[eEgG]) must be at least two characters long,
1360 * whereas exponents for hexadecimal conversions can
1361 * be only one character long.
1363 if (fmtch
== 'e' || fmtch
== 'E')
1365 *p
++ = to_char(exp
);
1369 #endif /* FLOATING_POINT */
This page took 0.145169 seconds and 5 git commands to generate.