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>
41 unsigned long ulongarg
;
42 long long longlongarg
;
43 unsigned long long ulonglongarg
;
51 signed char *pschararg
;
55 long long *plonglongarg
;
56 ptrdiff_t *pptrdiffarg
;
61 long double longdoublearg
;
65 static int __find_arguments(const char *fmt0
, va_list ap
, union arg
**argtable
,
67 static int __grow_type_table(unsigned char **typetable
, int *tablesize
);
70 * Flush out all the vectors defined by the given uio,
71 * then reset it so that it can be reused.
74 __sprint(LTTNG_UST_LFILE
*fp
, struct __lttng_ust_suio
*uio
)
78 if (uio
->uio_resid
== 0) {
82 err
= __sfvwrite(fp
, uio
);
89 * Helper function for `fprintf to unbuffered unix file': creates a
90 * temporary buffer. We only work on write-only files; this avoids
91 * worries about ungetc buffers and so forth.
94 //__sbprintf(LTTNG_UST_LFILE *fp, const char *fmt, va_list ap)
97 // LTTNG_UST_LFILE fake;
98 // struct __sfileext fakeext;
99 // unsigned char buf[BUFSIZ];
101 // _FILEEXT_SETUP(&fake, &fakeext);
102 // /* copy the important variables */
103 // fake._flags = fp->_flags & ~__SNBF;
104 // fake._file = fp->_file;
105 // fake._cookie = fp->_cookie;
106 // fake._write = fp->_write;
108 // /* set up the buffer */
109 // fake._bf._base = fake._p = buf;
110 // fake._bf._size = fake._w = sizeof(buf);
111 // fake._lbfsize = 0; /* not actually used, but Just In Case */
113 // /* do the work, then copy any error status */
114 // ret = ust_safe_vfprintf(&fake, fmt, ap);
115 // if (ret >= 0 && fflush(&fake))
117 // if (fake._flags & __SERR)
118 // fp->_flags |= __SERR;
123 #ifdef FLOATING_POINT
131 extern char *__dtoa(double, int, int, int *, int *, char **);
132 extern void __freedtoa(char *);
133 static int exponent(char *, int, int);
134 #endif /* FLOATING_POINT */
137 * The size of the buffer we use as scratch space for integer
138 * conversions, among other things. Technically, we would need the
139 * most space for base 10 conversions with thousands' grouping
140 * characters between each pair of digits. 100 bytes is a
141 * conservative overestimate even for a 128-bit uintmax_t.
145 #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
149 * Macros for converting digits to letters and vice versa
151 #define to_digit(c) ((c) - '0')
152 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
153 #define to_char(n) ((n) + '0')
156 * Flags used during conversion.
158 #define ALT 0x0001 /* alternate form */
159 #define LADJUST 0x0004 /* left adjustment */
160 #define LONGDBL 0x0008 /* long double; unimplemented */
161 #define LONGINT 0x0010 /* long integer */
162 #define LLONGINT 0x0020 /* long long integer */
163 #define SHORTINT 0x0040 /* short integer */
164 #define ZEROPAD 0x0080 /* zero (as opposed to blank) pad */
165 #define FPT 0x0100 /* Floating point number */
166 #define PTRINT 0x0200 /* (unsigned) ptrdiff_t */
167 #define SIZEINT 0x0400 /* (signed) size_t */
168 #define CHARINT 0x0800 /* 8 bit integer */
169 #define MAXINT 0x1000 /* largest integer size (intmax_t) */
171 int ust_safe_vfprintf(LTTNG_UST_LFILE
*fp
, const char *fmt0
, va_list ap
)
173 char *fmt
; /* format string */
174 int ch
; /* character from fmt */
175 int n
, n2
; /* handy integers (short term usage) */
176 char *cp
; /* handy char pointer (short term usage) */
177 struct __lttng_ust_siov
*iovp
; /* for PRINT macro */
178 int flags
; /* flags as above */
179 int ret
; /* return value accumulator */
180 int width
; /* width from format (%8d), or 0 */
181 int prec
; /* precision from format; <0 for N/A */
182 char sign
; /* sign prefix (' ', '+', '-', or \0) */
185 #ifdef FLOATING_POINT
187 * We can decompose the printed representation of floating
188 * point numbers into several parts, some of which may be empty:
190 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
193 * A: 'sign' holds this value if present; '\0' otherwise
194 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
195 * C: cp points to the string MMMNNN. Leading and trailing
196 * zeros are not in the string and must be added.
197 * D: expchar holds this character; '\0' if no exponent, e.g. %f
198 * F: at least two digits for decimal, at least one digit for hex
200 char *decimal_point
= localeconv()->decimal_point
;
201 int signflag
; /* true if float is negative */
202 union { /* floating point arguments %[aAeEfFgG] */
206 int expt
; /* integer value of exponent */
207 char expchar
; /* exponent character: [eEpP\0] */
208 char *dtoaend
; /* pointer to end of converted digits */
209 int expsize
; /* character count for expstr */
210 int lead
; /* sig figs before decimal or group sep */
211 int ndig
; /* actual number of digits returned by dtoa */
212 char expstr
[MAXEXPDIG
+2]; /* buffer for exponent string: e+ZZZ */
213 char *dtoaresult
= NULL
;
216 uintmax_t _umax
; /* integer arguments %[diouxX] */
217 enum { OCT
, DEC
, HEX
} base
; /* base for %[diouxX] conversion */
218 int dprec
; /* a copy of prec if %[diouxX], 0 otherwise */
219 int realsz
; /* field size expanded by dprec */
220 int size
; /* size of converted field or string */
221 const char *xdigs
= NULL
; /* digits for %[xX] conversion */
223 struct __lttng_ust_suio uio
; /* output information: summary */
224 struct __lttng_ust_siov iov
[NIOV
];/* ... and individual io vectors */
225 char buf
[BUF
]; /* buffer with space for digits of uintmax_t */
226 char ox
[2]; /* space for 0x; ox[1] is either x, X, or \0 */
227 union arg
*argtable
; /* args, built due to positional arg */
228 union arg statargtable
[STATIC_ARG_TBL_SIZE
];
230 int nextarg
; /* 1-based argument index */
231 va_list orgap
; /* original argument pointer */
234 * Choose PADSIZE to trade efficiency vs. size. If larger printf
235 * fields occur frequently, increase PADSIZE and make the initialisers
238 #define PADSIZE 16 /* pad chunk size */
239 static char blanks
[PADSIZE
] =
240 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
241 static char zeroes
[PADSIZE
] =
242 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
244 static const char xdigs_lower
[16] = "0123456789abcdef";
245 static const char xdigs_upper
[16] = "0123456789ABCDEF";
248 * BEWARE, these `goto error' on error, and PAD uses `n'.
250 #define PRINT(ptr, len) do { \
251 iovp->iov_base = (ptr); \
252 iovp->iov_len = (len); \
253 uio.uio_resid += (len); \
255 if (++uio.uio_iovcnt >= NIOV) { \
256 if (__sprint(fp, &uio)) \
261 #define PAD(howmany, with) do { \
262 if ((n = (howmany)) > 0) { \
263 while (n > PADSIZE) { \
264 PRINT(with, PADSIZE); \
270 #define PRINTANDPAD(p, ep, len, with) do { \
276 PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
278 #define FLUSH() do { \
279 if (uio.uio_resid && __sprint(fp, &uio)) \
281 uio.uio_iovcnt = 0; \
286 * To extend shorts properly, we need both signed and unsigned
287 * argument extraction methods.
290 ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
291 flags&LLONGINT ? GETARG(long long) : \
292 flags&LONGINT ? GETARG(long) : \
293 flags&PTRINT ? GETARG(ptrdiff_t) : \
294 flags&SIZEINT ? GETARG(ssize_t) : \
295 flags&SHORTINT ? (short)GETARG(int) : \
296 flags&CHARINT ? (__signed char)GETARG(int) : \
299 ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
300 flags&LLONGINT ? GETARG(unsigned long long) : \
301 flags&LONGINT ? GETARG(unsigned long) : \
302 flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
303 flags&SIZEINT ? GETARG(size_t) : \
304 flags&SHORTINT ? (unsigned short)GETARG(int) : \
305 flags&CHARINT ? (unsigned char)GETARG(int) : \
306 GETARG(unsigned int)))
309 * Append a digit to a value and check for overflow.
311 #define APPEND_DIGIT(val, dig) do { \
312 if ((val) > INT_MAX / 10) \
315 if ((val) > INT_MAX - to_digit((dig))) \
317 (val) += to_digit((dig)); \
321 * Get * arguments, including the form *nn$. Preserve the nextarg
322 * that the argument can be gotten once the type is determined.
324 #define GETASTER(val) \
327 while (is_digit(*cp)) { \
328 APPEND_DIGIT(n2, *cp); \
332 int hold = nextarg; \
333 if (argtable == NULL) { \
334 argtable = statargtable; \
335 __find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
346 * Get the argument indexed by nextarg. If the argument table is
347 * built, use it to get the argument. If its not, get the next
348 * argument (and arguments must be gotten sequentially).
350 #define GETARG(type) \
351 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
352 (nextarg++, va_arg(ap, type)))
354 _SET_ORIENTATION(fp
, -1);
355 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
361 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
362 // if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
364 // return (__sbprintf(fp, fmt0, ap));
370 uio
.uio_iov
= iovp
= iov
;
375 memset(&ps
, 0, sizeof(ps
));
377 * Scan the format for conversions (`%' character).
381 while ((n
= ust_safe_mbrtowc(&wc
, fmt
, MB_CUR_MAX
, &ps
)) > 0) {
389 ptrdiff_t m
= fmt
- cp
;
390 if (m
< 0 || m
> INT_MAX
- ret
)
397 fmt
++; /* skip over '%' */
407 reswitch
: switch (ch
) {
410 * ``If the space and + flags both appear, the space
411 * flag will be ignored.''
421 /* grouping not implemented */
425 * ``A negative field width argument is taken as a
426 * - flag followed by a positive field width.''
428 * They don't exclude field widths read from args.
433 if (width
== INT_MIN
)
444 if ((ch
= *fmt
++) == '*') {
446 prec
= n
< 0 ? -1 : n
;
450 while (is_digit(ch
)) {
456 if (argtable
== NULL
) {
457 argtable
= statargtable
;
458 __find_arguments(fmt0
, orgap
,
459 &argtable
, &argtablesiz
);
467 * ``Note that 0 is taken as a flag, not as the
468 * beginning of a field width.''
473 case '1': case '2': case '3': case '4':
474 case '5': case '6': case '7': case '8': case '9':
479 } while (is_digit(ch
));
482 if (argtable
== NULL
) {
483 argtable
= statargtable
;
484 __find_arguments(fmt0
, orgap
,
485 &argtable
, &argtablesiz
);
491 #ifdef FLOATING_POINT
525 *(cp
= buf
) = GETARG(int);
535 if ((intmax_t)_umax
< 0) {
541 #ifdef FLOATING_POINT
556 __freedtoa(dtoaresult
);
557 if (flags
& LONGDBL
) {
558 fparg
.ldbl
= GETARG(long double);
560 __hldtoa(fparg
.ldbl
, xdigs
, prec
,
561 &expt
, &signflag
, &dtoaend
);
562 if (dtoaresult
== NULL
) {
567 fparg
.dbl
= GETARG(double);
569 __hdtoa(fparg
.dbl
, xdigs
, prec
,
570 &expt
, &signflag
, &dtoaend
);
571 if (dtoaresult
== NULL
) {
584 if (prec
< 0) /* account for digit before decpt */
595 expchar
= ch
- ('g' - 'e');
602 __freedtoa(dtoaresult
);
603 if (flags
& LONGDBL
) {
604 fparg
.ldbl
= GETARG(long double);
606 __ldtoa(&fparg
.ldbl
, expchar
? 2 : 3, prec
,
607 &expt
, &signflag
, &dtoaend
);
608 if (dtoaresult
== NULL
) {
613 fparg
.dbl
= GETARG(double);
615 __dtoa(fparg
.dbl
, expchar
? 2 : 3, prec
,
616 &expt
, &signflag
, &dtoaend
);
617 if (dtoaresult
== NULL
) {
627 if (expt
== INT_MAX
) { /* inf or nan */
629 cp
= (ch
>= 'a') ? "nan" : "NAN";
632 cp
= (ch
>= 'a') ? "inf" : "INF";
639 if (ch
== 'g' || ch
== 'G') {
640 if (expt
> -4 && expt
<= prec
) {
641 /* Make %[gG] smell like %[fF] */
651 * Make %[gG] smell like %[eE], but
652 * trim trailing zeroes if no # flag.
659 expsize
= exponent(expstr
, expt
- 1, expchar
);
660 size
= expsize
+ prec
;
661 if (prec
> 1 || flags
& ALT
)
664 /* space for digits before decimal point */
669 /* space for decimal pt and following digits */
670 if (prec
|| flags
& ALT
)
675 #endif /* FLOATING_POINT */
677 if (flags
& LLONGINT
)
678 *GETARG(long long *) = ret
;
679 else if (flags
& LONGINT
)
680 *GETARG(long *) = ret
;
681 else if (flags
& SHORTINT
)
682 *GETARG(short *) = ret
;
683 else if (flags
& CHARINT
)
684 *GETARG(__signed
char *) = ret
;
685 else if (flags
& PTRINT
)
686 *GETARG(ptrdiff_t *) = ret
;
687 else if (flags
& SIZEINT
)
688 *GETARG(ssize_t
*) = ret
;
689 else if (flags
& MAXINT
)
690 *GETARG(intmax_t *) = ret
;
692 *GETARG(int *) = ret
;
693 continue; /* no output */
703 * ``The argument shall be a pointer to void. The
704 * value of the pointer is converted to a sequence
705 * of printable characters, in an implementation-
710 _umax
= (u_long
)GETARG(void *);
716 if ((cp
= GETARG(char *)) == NULL
)
720 * can't use strlen; can only look for the
721 * NUL in the first `prec' characters, and
722 * strlen() will go further.
724 char *p
= memchr(cp
, 0, prec
);
726 size
= p
? (p
- cp
) : prec
;
730 if ((len
= strlen(cp
)) > INT_MAX
)
750 /* leading 0x/X only if non-zero */
751 if (flags
& ALT
&& _umax
!= 0)
754 /* unsigned conversions */
757 * ``... diouXx conversions ... if a precision is
758 * specified, the 0 flag will be ignored.''
761 number
: if ((dprec
= prec
) >= 0)
765 * ``The result of converting a zero value with an
766 * explicit precision of zero is no characters.''
770 if (_umax
!= 0 || prec
!= 0) {
772 * Unsigned mod is hard, and unsigned mod
773 * by a constant is easier than that by
774 * a variable; hence this switch.
779 *--cp
= to_char(_umax
& 7);
782 /* handle octal leading 0 */
783 if (flags
& ALT
&& *cp
!= '0')
788 /* many numbers are 1 digit */
789 while (_umax
>= 10) {
790 *--cp
= to_char(_umax
% 10);
793 *--cp
= to_char(_umax
);
798 *--cp
= xdigs
[_umax
& 15];
804 cp
= "bug in ust_safe_vfprintf: bad base";
809 size
= buf
+ BUF
- cp
;
810 if (size
> BUF
) /* should never happen */
814 default: /* "%?" prints ?, unless ? is NUL */
817 /* pretend it was %c with argument ch */
826 * All reasonable formats wind up here. At this point, `cp'
827 * points to a string which (if not flags&LADJUST) should be
828 * padded out to `width' places. If flags&ZEROPAD, it should
829 * first be prefixed by any sign or other prefix; otherwise,
830 * it should be blank padded before the prefix is emitted.
831 * After any left-hand padding and prefixing, emit zeroes
832 * required by a decimal %[diouxX] precision, then print the
833 * string proper, then emit zeroes required by any leftover
834 * floating precision; finally, if LADJUST, pad with blanks.
836 * Compute actual size, so we know how much to pad.
837 * size excludes decimal prec; realsz includes it.
839 realsz
= dprec
> size
? dprec
: size
;
845 /* right-adjusting blank padding */
846 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
847 PAD(width
- realsz
, blanks
);
852 if (ox
[1]) { /* ox[1] is either x, X, or \0 */
857 /* right-adjusting zero padding */
858 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
859 PAD(width
- realsz
, zeroes
);
861 /* leading zeroes from decimal precision */
862 PAD(dprec
- size
, zeroes
);
864 /* the string or number proper */
865 #ifdef FLOATING_POINT
866 if ((flags
& FPT
) == 0) {
868 } else { /* glue together f_p fragments */
869 if (!expchar
) { /* %[fF] or sufficiently short %[gG] */
872 if (prec
|| flags
& ALT
)
873 PRINT(decimal_point
, 1);
875 /* already handled initial 0's */
878 PRINTANDPAD(cp
, dtoaend
, lead
, zeroes
);
880 if (prec
|| flags
& ALT
)
881 PRINT(decimal_point
, 1);
883 PRINTANDPAD(cp
, dtoaend
, prec
, zeroes
);
884 } else { /* %[eE] or sufficiently long %[gG] */
885 if (prec
> 1 || flags
& ALT
) {
887 buf
[1] = *decimal_point
;
890 PAD(prec
- ndig
, zeroes
);
894 PRINT(expstr
, expsize
);
900 /* left-adjusting padding (always blank) */
902 PAD(width
- realsz
, blanks
);
904 /* finally, adjust ret */
907 if (width
> INT_MAX
- ret
)
911 FLUSH(); /* copy out the I/O vectors */
926 #ifdef FLOATING_POINT
928 __freedtoa(dtoaresult
);
930 if (argtable
!= NULL
&& argtable
!= statargtable
) {
931 munmap(argtable
, argtablesiz
);
938 * Type ids for argument type table.
954 #define T_LONG_DOUBLE 14
960 #define T_SSIZEINT 20
961 #define TP_SSIZEINT 21
969 * Find all arguments when a positional parameter is encountered. Returns a
970 * table, indexed by argument number, of pointers to each arguments. The
971 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
972 * It will be replaced with a mmap-ed one if it overflows (malloc cannot be
973 * used since we are attempting to make snprintf thread safe, and alloca is
974 * problematic since we have nested functions..)
977 __find_arguments(const char *fmt0
, va_list ap
, union arg
**argtable
,
980 char *fmt
; /* format string */
981 int ch
; /* character from fmt */
982 int n
, n2
; /* handy integer (short term usage) */
983 char *cp
; /* handy char pointer (short term usage) */
984 int flags
; /* flags as above */
985 unsigned char *typetable
; /* table of types */
986 unsigned char stattypetable
[STATIC_ARG_TBL_SIZE
];
987 int tablesize
; /* current size of type table */
988 int tablemax
; /* largest used index in table */
989 int nextarg
; /* 1-based argument index */
990 int ret
= 0; /* return value */
995 * Add an argument type to the table, expanding if necessary.
997 #define ADDTYPE(type) \
998 ((nextarg >= tablesize) ? \
999 __grow_type_table(&typetable, &tablesize) : 0, \
1000 (nextarg > tablemax) ? tablemax = nextarg : 0, \
1001 typetable[nextarg++] = type)
1004 ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
1005 ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1006 ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
1007 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
1008 ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
1009 ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
1010 ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
1013 ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
1014 ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1015 ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
1016 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
1017 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
1018 ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
1019 ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))
1022 * Add * arguments to the type array.
1024 #define ADDASTER() \
1027 while (is_digit(*cp)) { \
1028 APPEND_DIGIT(n2, *cp); \
1032 int hold = nextarg; \
1041 typetable
= stattypetable
;
1042 tablesize
= STATIC_ARG_TBL_SIZE
;
1045 memset(typetable
, T_UNUSED
, STATIC_ARG_TBL_SIZE
);
1046 memset(&ps
, 0, sizeof(ps
));
1049 * Scan the format for conversions (`%' character).
1053 while ((n
= ust_safe_mbrtowc(&wc
, fmt
, MB_CUR_MAX
, &ps
)) > 0) {
1062 fmt
++; /* skip over '%' */
1067 reswitch
: switch (ch
) {
1079 if ((ch
= *fmt
++) == '*') {
1083 while (is_digit(ch
)) {
1089 case '1': case '2': case '3': case '4':
1090 case '5': case '6': case '7': case '8': case '9':
1093 APPEND_DIGIT(n
,ch
);
1095 } while (is_digit(ch
));
1101 #ifdef FLOATING_POINT
1141 #ifdef FLOATING_POINT
1150 if (flags
& LONGDBL
)
1151 ADDTYPE(T_LONG_DOUBLE
);
1155 #endif /* FLOATING_POINT */
1157 if (flags
& LLONGINT
)
1159 else if (flags
& LONGINT
)
1161 else if (flags
& SHORTINT
)
1163 else if (flags
& PTRINT
)
1165 else if (flags
& SIZEINT
)
1166 ADDTYPE(TP_SSIZEINT
);
1167 else if (flags
& MAXINT
)
1171 continue; /* no output */
1192 default: /* "%?" prints ?, unless ? is NUL */
1200 * Build the argument table.
1202 if (tablemax
>= STATIC_ARG_TBL_SIZE
) {
1203 *argtablesiz
= sizeof(union arg
) * (tablemax
+ 1);
1204 *argtable
= mmap(NULL
, *argtablesiz
,
1205 PROT_WRITE
|PROT_READ
, MAP_ANON
|MAP_PRIVATE
, -1, 0);
1206 if (*argtable
== MAP_FAILED
)
1211 /* XXX is this required? */
1212 (*argtable
)[0].intarg
= 0;
1214 for (n
= 1; n
<= tablemax
; n
++) {
1215 switch (typetable
[n
]) {
1222 (*argtable
)[n
].intarg
= va_arg(ap
, int);
1225 (*argtable
)[n
].pshortarg
= va_arg(ap
, short *);
1228 (*argtable
)[n
].uintarg
= va_arg(ap
, unsigned int);
1231 (*argtable
)[n
].pintarg
= va_arg(ap
, int *);
1234 (*argtable
)[n
].longarg
= va_arg(ap
, long);
1237 (*argtable
)[n
].ulongarg
= va_arg(ap
, unsigned long);
1240 (*argtable
)[n
].plongarg
= va_arg(ap
, long *);
1243 (*argtable
)[n
].longlongarg
= va_arg(ap
, long long);
1246 (*argtable
)[n
].ulonglongarg
= va_arg(ap
, unsigned long long);
1249 (*argtable
)[n
].plonglongarg
= va_arg(ap
, long long *);
1251 #ifdef FLOATING_POINT
1253 (*argtable
)[n
].doublearg
= va_arg(ap
, double);
1256 (*argtable
)[n
].longdoublearg
= va_arg(ap
, long double);
1260 (*argtable
)[n
].pchararg
= va_arg(ap
, char *);
1263 (*argtable
)[n
].pvoidarg
= va_arg(ap
, void *);
1266 (*argtable
)[n
].ptrdiffarg
= va_arg(ap
, ptrdiff_t);
1269 (*argtable
)[n
].pptrdiffarg
= va_arg(ap
, ptrdiff_t *);
1272 (*argtable
)[n
].sizearg
= va_arg(ap
, size_t);
1275 (*argtable
)[n
].ssizearg
= va_arg(ap
, ssize_t
);
1278 (*argtable
)[n
].pssizearg
= va_arg(ap
, ssize_t
*);
1281 (*argtable
)[n
].intmaxarg
= va_arg(ap
, intmax_t);
1292 if (typetable
!= NULL
&& typetable
!= stattypetable
) {
1293 munmap(typetable
, *argtablesiz
);
1300 * Increase the size of the type table.
1303 __grow_type_table(unsigned char **typetable
, int *tablesize
)
1305 unsigned char *oldtable
= *typetable
;
1306 int newsize
= *tablesize
* 2;
1308 if (newsize
< getpagesize())
1309 newsize
= getpagesize();
1311 if (*tablesize
== STATIC_ARG_TBL_SIZE
) {
1312 *typetable
= mmap(NULL
, newsize
, PROT_WRITE
|PROT_READ
,
1313 MAP_ANON
|MAP_PRIVATE
, -1, 0);
1314 if (*typetable
== MAP_FAILED
)
1316 bcopy(oldtable
, *typetable
, *tablesize
);
1318 unsigned char *new = mmap(NULL
, newsize
, PROT_WRITE
|PROT_READ
,
1319 MAP_ANON
|MAP_PRIVATE
, -1, 0);
1320 if (new == MAP_FAILED
)
1322 memmove(new, *typetable
, *tablesize
);
1323 munmap(*typetable
, *tablesize
);
1326 memset(*typetable
+ *tablesize
, T_UNUSED
, (newsize
- *tablesize
));
1328 *tablesize
= newsize
;
1333 #ifdef FLOATING_POINT
1335 exponent(char *p0
, int exp
, int fmtch
)
1338 char expbuf
[MAXEXPDIG
];
1347 t
= expbuf
+ MAXEXPDIG
;
1350 *--t
= to_char(exp
% 10);
1351 } while ((exp
/= 10) > 9);
1352 *--t
= to_char(exp
);
1353 for (; t
< expbuf
+ MAXEXPDIG
; *p
++ = *t
++)
1357 * Exponents for decimal floating point conversions
1358 * (%[eEgG]) must be at least two characters long,
1359 * whereas exponents for hexadecimal conversions can
1360 * be only one character long.
1362 if (fmtch
== 'e' || fmtch
== 'E')
1364 *p
++ = to_char(exp
);
1368 #endif /* FLOATING_POINT */
This page took 0.102688 seconds and 4 git commands to generate.