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>
38 static char null_str
[] = "(null)";
39 static char bad_base_str
[] = "bug in ust_safe_vfprintf: bad base";
45 unsigned long ulongarg
;
46 long long longlongarg
;
47 unsigned long long ulonglongarg
;
55 signed char *pschararg
;
59 long long *plonglongarg
;
60 ptrdiff_t *pptrdiffarg
;
65 long double longdoublearg
;
69 static int __find_arguments(const char *fmt0
, va_list ap
, union arg
**argtable
,
71 static int __grow_type_table(unsigned char **typetable
, int *tablesize
);
74 * Flush out all the vectors defined by the given uio,
75 * then reset it so that it can be reused.
78 __sprint(LTTNG_UST_LFILE
*fp
, struct __lttng_ust_suio
*uio
)
82 if (uio
->uio_resid
== 0) {
86 err
= __sfvwrite(fp
, uio
);
93 * Helper function for `fprintf to unbuffered unix file': creates a
94 * temporary buffer. We only work on write-only files; this avoids
95 * worries about ungetc buffers and so forth.
98 //__sbprintf(LTTNG_UST_LFILE *fp, const char *fmt, va_list ap)
101 // LTTNG_UST_LFILE fake;
102 // struct __sfileext fakeext;
103 // unsigned char buf[BUFSIZ];
105 // _FILEEXT_SETUP(&fake, &fakeext);
106 // /* copy the important variables */
107 // fake._flags = fp->_flags & ~__SNBF;
108 // fake._file = fp->_file;
109 // fake._cookie = fp->_cookie;
110 // fake._write = fp->_write;
112 // /* set up the buffer */
113 // fake._bf._base = fake._p = buf;
114 // fake._bf._size = fake._w = sizeof(buf);
115 // fake._lbfsize = 0; /* not actually used, but Just In Case */
117 // /* do the work, then copy any error status */
118 // ret = ust_safe_vfprintf(&fake, fmt, ap);
119 // if (ret >= 0 && fflush(&fake))
121 // if (fake._flags & __SERR)
122 // fp->_flags |= __SERR;
127 #ifdef FLOATING_POINT
135 extern char *__dtoa(double, int, int, int *, int *, char **);
136 extern void __freedtoa(char *);
137 static int exponent(char *, int, int);
138 #endif /* FLOATING_POINT */
141 * The size of the buffer we use as scratch space for integer
142 * conversions, among other things. Technically, we would need the
143 * most space for base 10 conversions with thousands' grouping
144 * characters between each pair of digits. 100 bytes is a
145 * conservative overestimate even for a 128-bit uintmax_t.
149 #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */
153 * Macros for converting digits to letters and vice versa
155 #define to_digit(c) ((c) - '0')
156 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
157 #define to_char(n) ((n) + '0')
160 * Flags used during conversion.
162 #define ALT 0x0001 /* alternate form */
163 #define LADJUST 0x0004 /* left adjustment */
164 #define LONGDBL 0x0008 /* long double; unimplemented */
165 #define LONGINT 0x0010 /* long integer */
166 #define LLONGINT 0x0020 /* long long integer */
167 #define SHORTINT 0x0040 /* short integer */
168 #define ZEROPAD 0x0080 /* zero (as opposed to blank) pad */
169 #define FPT 0x0100 /* Floating point number */
170 #define PTRINT 0x0200 /* (unsigned) ptrdiff_t */
171 #define SIZEINT 0x0400 /* (signed) size_t */
172 #define CHARINT 0x0800 /* 8 bit integer */
173 #define MAXINT 0x1000 /* largest integer size (intmax_t) */
175 int ust_safe_vfprintf(LTTNG_UST_LFILE
*fp
, const char *fmt0
, va_list ap
)
177 char *fmt
; /* format string */
178 int ch
; /* character from fmt */
179 int n
, n2
; /* handy integers (short term usage) */
180 char *cp
; /* handy char pointer (short term usage) */
181 struct __lttng_ust_siov
*iovp
; /* for PRINT macro */
182 int flags
; /* flags as above */
183 int ret
; /* return value accumulator */
184 int width
; /* width from format (%8d), or 0 */
185 int prec
; /* precision from format; <0 for N/A */
186 char sign
; /* sign prefix (' ', '+', '-', or \0) */
189 #ifdef FLOATING_POINT
191 * We can decompose the printed representation of floating
192 * point numbers into several parts, some of which may be empty:
194 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
197 * A: 'sign' holds this value if present; '\0' otherwise
198 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
199 * C: cp points to the string MMMNNN. Leading and trailing
200 * zeros are not in the string and must be added.
201 * D: expchar holds this character; '\0' if no exponent, e.g. %f
202 * F: at least two digits for decimal, at least one digit for hex
204 char *decimal_point
= localeconv()->decimal_point
;
205 int signflag
; /* true if float is negative */
206 union { /* floating point arguments %[aAeEfFgG] */
210 int expt
; /* integer value of exponent */
211 char expchar
; /* exponent character: [eEpP\0] */
212 char *dtoaend
; /* pointer to end of converted digits */
213 int expsize
; /* character count for expstr */
214 int lead
; /* sig figs before decimal or group sep */
215 int ndig
; /* actual number of digits returned by dtoa */
216 char expstr
[MAXEXPDIG
+2]; /* buffer for exponent string: e+ZZZ */
217 char *dtoaresult
= NULL
;
220 uintmax_t _umax
; /* integer arguments %[diouxX] */
221 enum { OCT
, DEC
, HEX
} base
; /* base for %[diouxX] conversion */
222 int dprec
; /* a copy of prec if %[diouxX], 0 otherwise */
223 int realsz
; /* field size expanded by dprec */
224 int size
; /* size of converted field or string */
225 const char *xdigs
= NULL
; /* digits for %[xX] conversion */
227 struct __lttng_ust_suio uio
; /* output information: summary */
228 struct __lttng_ust_siov iov
[NIOV
];/* ... and individual io vectors */
229 char buf
[BUF
]; /* buffer with space for digits of uintmax_t */
230 char ox
[2]; /* space for 0x; ox[1] is either x, X, or \0 */
231 union arg
*argtable
; /* args, built due to positional arg */
232 union arg statargtable
[STATIC_ARG_TBL_SIZE
];
234 int nextarg
; /* 1-based argument index */
235 va_list orgap
; /* original argument pointer */
238 * Choose PADSIZE to trade efficiency vs. size. If larger printf
239 * fields occur frequently, increase PADSIZE and make the initialisers
242 #define PADSIZE 16 /* pad chunk size */
243 static char blanks
[PADSIZE
] =
244 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
245 static char zeroes
[PADSIZE
] =
246 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
248 static const char xdigs_lower
[16] = "0123456789abcdef";
249 static const char xdigs_upper
[16] = "0123456789ABCDEF";
252 * BEWARE, these `goto error' on error, and PAD uses `n'.
254 #define PRINT(ptr, len) do { \
255 iovp->iov_base = (ptr); \
256 iovp->iov_len = (len); \
257 uio.uio_resid += (len); \
259 if (++uio.uio_iovcnt >= NIOV) { \
260 if (__sprint(fp, &uio)) \
265 #define PAD(howmany, with) do { \
266 if ((n = (howmany)) > 0) { \
267 while (n > PADSIZE) { \
268 PRINT(with, PADSIZE); \
274 #define PRINTANDPAD(p, ep, len, with) do { \
280 PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
282 #define FLUSH() do { \
283 if (uio.uio_resid && __sprint(fp, &uio)) \
285 uio.uio_iovcnt = 0; \
290 * To extend shorts properly, we need both signed and unsigned
291 * argument extraction methods.
294 ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
295 flags&LLONGINT ? GETARG(long long) : \
296 flags&LONGINT ? GETARG(long) : \
297 flags&PTRINT ? GETARG(ptrdiff_t) : \
298 flags&SIZEINT ? GETARG(ssize_t) : \
299 flags&SHORTINT ? (short)GETARG(int) : \
300 flags&CHARINT ? (__signed char)GETARG(int) : \
303 ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
304 flags&LLONGINT ? GETARG(unsigned long long) : \
305 flags&LONGINT ? GETARG(unsigned long) : \
306 flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
307 flags&SIZEINT ? GETARG(size_t) : \
308 flags&SHORTINT ? (unsigned short)GETARG(int) : \
309 flags&CHARINT ? (unsigned char)GETARG(int) : \
310 GETARG(unsigned int)))
313 * Append a digit to a value and check for overflow.
315 #define APPEND_DIGIT(val, dig) do { \
316 if ((val) > INT_MAX / 10) \
319 if ((val) > INT_MAX - to_digit((dig))) \
321 (val) += to_digit((dig)); \
325 * Get * arguments, including the form *nn$. Preserve the nextarg
326 * that the argument can be gotten once the type is determined.
328 #define GETASTER(val) \
331 while (is_digit(*cp)) { \
332 APPEND_DIGIT(n2, *cp); \
336 int hold = nextarg; \
337 if (argtable == NULL) { \
338 argtable = statargtable; \
339 __find_arguments(fmt0, orgap, &argtable, &argtablesiz); \
350 * Get the argument indexed by nextarg. If the argument table is
351 * built, use it to get the argument. If its not, get the next
352 * argument (and arguments must be gotten sequentially).
354 #define GETARG(type) \
355 ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
356 (nextarg++, va_arg(ap, type)))
358 _SET_ORIENTATION(fp
, -1);
359 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
365 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
366 // if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
368 // return (__sbprintf(fp, fmt0, ap));
374 uio
.uio_iov
= iovp
= iov
;
379 memset(&ps
, 0, sizeof(ps
));
381 * Scan the format for conversions (`%' character).
385 while ((n
= ust_safe_mbrtowc(&wc
, fmt
, MB_CUR_MAX
, &ps
)) > 0) {
393 ptrdiff_t m
= fmt
- cp
;
394 if (m
< 0 || m
> INT_MAX
- ret
)
401 fmt
++; /* skip over '%' */
411 reswitch
: switch (ch
) {
414 * ``If the space and + flags both appear, the space
415 * flag will be ignored.''
425 /* grouping not implemented */
429 * ``A negative field width argument is taken as a
430 * - flag followed by a positive field width.''
432 * They don't exclude field widths read from args.
437 if (width
== INT_MIN
)
448 if ((ch
= *fmt
++) == '*') {
450 prec
= n
< 0 ? -1 : n
;
454 while (is_digit(ch
)) {
460 if (argtable
== NULL
) {
461 argtable
= statargtable
;
462 __find_arguments(fmt0
, orgap
,
463 &argtable
, &argtablesiz
);
471 * ``Note that 0 is taken as a flag, not as the
472 * beginning of a field width.''
477 case '1': case '2': case '3': case '4':
478 case '5': case '6': case '7': case '8': case '9':
483 } while (is_digit(ch
));
486 if (argtable
== NULL
) {
487 argtable
= statargtable
;
488 __find_arguments(fmt0
, orgap
,
489 &argtable
, &argtablesiz
);
495 #ifdef FLOATING_POINT
529 *(cp
= buf
) = GETARG(int);
539 if ((intmax_t)_umax
< 0) {
545 #ifdef FLOATING_POINT
560 __freedtoa(dtoaresult
);
561 if (flags
& LONGDBL
) {
562 fparg
.ldbl
= GETARG(long double);
564 __hldtoa(fparg
.ldbl
, xdigs
, prec
,
565 &expt
, &signflag
, &dtoaend
);
566 if (dtoaresult
== NULL
) {
571 fparg
.dbl
= GETARG(double);
573 __hdtoa(fparg
.dbl
, xdigs
, prec
,
574 &expt
, &signflag
, &dtoaend
);
575 if (dtoaresult
== NULL
) {
588 if (prec
< 0) /* account for digit before decpt */
599 expchar
= ch
- ('g' - 'e');
606 __freedtoa(dtoaresult
);
607 if (flags
& LONGDBL
) {
608 fparg
.ldbl
= GETARG(long double);
610 __ldtoa(&fparg
.ldbl
, expchar
? 2 : 3, prec
,
611 &expt
, &signflag
, &dtoaend
);
612 if (dtoaresult
== NULL
) {
617 fparg
.dbl
= GETARG(double);
619 __dtoa(fparg
.dbl
, expchar
? 2 : 3, prec
,
620 &expt
, &signflag
, &dtoaend
);
621 if (dtoaresult
== NULL
) {
631 if (expt
== INT_MAX
) { /* inf or nan */
633 cp
= (ch
>= 'a') ? "nan" : "NAN";
636 cp
= (ch
>= 'a') ? "inf" : "INF";
643 if (ch
== 'g' || ch
== 'G') {
644 if (expt
> -4 && expt
<= prec
) {
645 /* Make %[gG] smell like %[fF] */
655 * Make %[gG] smell like %[eE], but
656 * trim trailing zeroes if no # flag.
663 expsize
= exponent(expstr
, expt
- 1, expchar
);
664 size
= expsize
+ prec
;
665 if (prec
> 1 || flags
& ALT
)
668 /* space for digits before decimal point */
673 /* space for decimal pt and following digits */
674 if (prec
|| flags
& ALT
)
679 #endif /* FLOATING_POINT */
681 if (flags
& LLONGINT
)
682 *GETARG(long long *) = ret
;
683 else if (flags
& LONGINT
)
684 *GETARG(long *) = ret
;
685 else if (flags
& SHORTINT
)
686 *GETARG(short *) = ret
;
687 else if (flags
& CHARINT
)
688 *GETARG(__signed
char *) = ret
;
689 else if (flags
& PTRINT
)
690 *GETARG(ptrdiff_t *) = ret
;
691 else if (flags
& SIZEINT
)
692 *GETARG(ssize_t
*) = ret
;
693 else if (flags
& MAXINT
)
694 *GETARG(intmax_t *) = ret
;
696 *GETARG(int *) = ret
;
697 continue; /* no output */
707 * ``The argument shall be a pointer to void. The
708 * value of the pointer is converted to a sequence
709 * of printable characters, in an implementation-
714 _umax
= (u_long
)GETARG(void *);
720 if ((cp
= GETARG(char *)) == NULL
)
724 * can't use strlen; can only look for the
725 * NUL in the first `prec' characters, and
726 * strlen() will go further.
728 char *p
= memchr(cp
, 0, prec
);
730 size
= p
? (p
- cp
) : prec
;
734 if ((len
= strlen(cp
)) > INT_MAX
)
754 /* leading 0x/X only if non-zero */
755 if (flags
& ALT
&& _umax
!= 0)
758 /* unsigned conversions */
761 * ``... diouXx conversions ... if a precision is
762 * specified, the 0 flag will be ignored.''
765 number
: if ((dprec
= prec
) >= 0)
769 * ``The result of converting a zero value with an
770 * explicit precision of zero is no characters.''
774 if (_umax
!= 0 || prec
!= 0) {
776 * Unsigned mod is hard, and unsigned mod
777 * by a constant is easier than that by
778 * a variable; hence this switch.
783 *--cp
= to_char(_umax
& 7);
786 /* handle octal leading 0 */
787 if (flags
& ALT
&& *cp
!= '0')
792 /* many numbers are 1 digit */
793 while (_umax
>= 10) {
794 *--cp
= to_char(_umax
% 10);
797 *--cp
= to_char(_umax
);
802 *--cp
= xdigs
[_umax
& 15];
813 size
= buf
+ BUF
- cp
;
814 if (size
> BUF
) /* should never happen */
818 default: /* "%?" prints ?, unless ? is NUL */
821 /* pretend it was %c with argument ch */
830 * All reasonable formats wind up here. At this point, `cp'
831 * points to a string which (if not flags&LADJUST) should be
832 * padded out to `width' places. If flags&ZEROPAD, it should
833 * first be prefixed by any sign or other prefix; otherwise,
834 * it should be blank padded before the prefix is emitted.
835 * After any left-hand padding and prefixing, emit zeroes
836 * required by a decimal %[diouxX] precision, then print the
837 * string proper, then emit zeroes required by any leftover
838 * floating precision; finally, if LADJUST, pad with blanks.
840 * Compute actual size, so we know how much to pad.
841 * size excludes decimal prec; realsz includes it.
843 realsz
= dprec
> size
? dprec
: size
;
849 /* right-adjusting blank padding */
850 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
851 PAD(width
- realsz
, blanks
);
856 if (ox
[1]) { /* ox[1] is either x, X, or \0 */
861 /* right-adjusting zero padding */
862 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
863 PAD(width
- realsz
, zeroes
);
865 /* leading zeroes from decimal precision */
866 PAD(dprec
- size
, zeroes
);
868 /* the string or number proper */
869 #ifdef FLOATING_POINT
870 if ((flags
& FPT
) == 0) {
872 } else { /* glue together f_p fragments */
873 if (!expchar
) { /* %[fF] or sufficiently short %[gG] */
876 if (prec
|| flags
& ALT
)
877 PRINT(decimal_point
, 1);
879 /* already handled initial 0's */
882 PRINTANDPAD(cp
, dtoaend
, lead
, zeroes
);
884 if (prec
|| flags
& ALT
)
885 PRINT(decimal_point
, 1);
887 PRINTANDPAD(cp
, dtoaend
, prec
, zeroes
);
888 } else { /* %[eE] or sufficiently long %[gG] */
889 if (prec
> 1 || flags
& ALT
) {
891 buf
[1] = *decimal_point
;
894 PAD(prec
- ndig
, zeroes
);
898 PRINT(expstr
, expsize
);
904 /* left-adjusting padding (always blank) */
906 PAD(width
- realsz
, blanks
);
908 /* finally, adjust ret */
911 if (width
> INT_MAX
- ret
)
915 FLUSH(); /* copy out the I/O vectors */
930 #ifdef FLOATING_POINT
932 __freedtoa(dtoaresult
);
934 if (argtable
!= NULL
&& argtable
!= statargtable
) {
935 munmap(argtable
, argtablesiz
);
942 * Type ids for argument type table.
958 #define T_LONG_DOUBLE 14
964 #define T_SSIZEINT 20
965 #define TP_SSIZEINT 21
973 * Find all arguments when a positional parameter is encountered. Returns a
974 * table, indexed by argument number, of pointers to each arguments. The
975 * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
976 * It will be replaced with a mmap-ed one if it overflows (malloc cannot be
977 * used since we are attempting to make snprintf thread safe, and alloca is
978 * problematic since we have nested functions..)
981 __find_arguments(const char *fmt0
, va_list ap
, union arg
**argtable
,
984 char *fmt
; /* format string */
985 int ch
; /* character from fmt */
986 int n
, n2
; /* handy integer (short term usage) */
987 char *cp
; /* handy char pointer (short term usage) */
988 int flags
; /* flags as above */
989 unsigned char *typetable
; /* table of types */
990 unsigned char stattypetable
[STATIC_ARG_TBL_SIZE
];
991 int tablesize
; /* current size of type table */
992 int tablemax
; /* largest used index in table */
993 int nextarg
; /* 1-based argument index */
994 int ret
= 0; /* return value */
999 * Add an argument type to the table, expanding if necessary.
1001 #define ADDTYPE(type) \
1002 ((nextarg >= tablesize) ? \
1003 __grow_type_table(&typetable, &tablesize) : 0, \
1004 (nextarg > tablemax) ? tablemax = nextarg : 0, \
1005 typetable[nextarg++] = type)
1008 ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
1009 ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1010 ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
1011 ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
1012 ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
1013 ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
1014 ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
1017 ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
1018 ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1019 ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
1020 ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
1021 ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
1022 ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
1023 ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))
1026 * Add * arguments to the type array.
1028 #define ADDASTER() \
1031 while (is_digit(*cp)) { \
1032 APPEND_DIGIT(n2, *cp); \
1036 int hold = nextarg; \
1045 typetable
= stattypetable
;
1046 tablesize
= STATIC_ARG_TBL_SIZE
;
1049 memset(typetable
, T_UNUSED
, STATIC_ARG_TBL_SIZE
);
1050 memset(&ps
, 0, sizeof(ps
));
1053 * Scan the format for conversions (`%' character).
1057 while ((n
= ust_safe_mbrtowc(&wc
, fmt
, MB_CUR_MAX
, &ps
)) > 0) {
1066 fmt
++; /* skip over '%' */
1071 reswitch
: switch (ch
) {
1083 if ((ch
= *fmt
++) == '*') {
1087 while (is_digit(ch
)) {
1093 case '1': case '2': case '3': case '4':
1094 case '5': case '6': case '7': case '8': case '9':
1097 APPEND_DIGIT(n
,ch
);
1099 } while (is_digit(ch
));
1105 #ifdef FLOATING_POINT
1145 #ifdef FLOATING_POINT
1154 if (flags
& LONGDBL
)
1155 ADDTYPE(T_LONG_DOUBLE
);
1159 #endif /* FLOATING_POINT */
1161 if (flags
& LLONGINT
)
1163 else if (flags
& LONGINT
)
1165 else if (flags
& SHORTINT
)
1167 else if (flags
& PTRINT
)
1169 else if (flags
& SIZEINT
)
1170 ADDTYPE(TP_SSIZEINT
);
1171 else if (flags
& MAXINT
)
1175 continue; /* no output */
1196 default: /* "%?" prints ?, unless ? is NUL */
1204 * Build the argument table.
1206 if (tablemax
>= STATIC_ARG_TBL_SIZE
) {
1207 *argtablesiz
= sizeof(union arg
) * (tablemax
+ 1);
1208 *argtable
= mmap(NULL
, *argtablesiz
,
1209 PROT_WRITE
|PROT_READ
, MAP_ANON
|MAP_PRIVATE
, -1, 0);
1210 if (*argtable
== MAP_FAILED
)
1215 /* XXX is this required? */
1216 (*argtable
)[0].intarg
= 0;
1218 for (n
= 1; n
<= tablemax
; n
++) {
1219 switch (typetable
[n
]) {
1226 (*argtable
)[n
].intarg
= va_arg(ap
, int);
1229 (*argtable
)[n
].pshortarg
= va_arg(ap
, short *);
1232 (*argtable
)[n
].uintarg
= va_arg(ap
, unsigned int);
1235 (*argtable
)[n
].pintarg
= va_arg(ap
, int *);
1238 (*argtable
)[n
].longarg
= va_arg(ap
, long);
1241 (*argtable
)[n
].ulongarg
= va_arg(ap
, unsigned long);
1244 (*argtable
)[n
].plongarg
= va_arg(ap
, long *);
1247 (*argtable
)[n
].longlongarg
= va_arg(ap
, long long);
1250 (*argtable
)[n
].ulonglongarg
= va_arg(ap
, unsigned long long);
1253 (*argtable
)[n
].plonglongarg
= va_arg(ap
, long long *);
1255 #ifdef FLOATING_POINT
1257 (*argtable
)[n
].doublearg
= va_arg(ap
, double);
1260 (*argtable
)[n
].longdoublearg
= va_arg(ap
, long double);
1264 (*argtable
)[n
].pchararg
= va_arg(ap
, char *);
1267 (*argtable
)[n
].pvoidarg
= va_arg(ap
, void *);
1270 (*argtable
)[n
].ptrdiffarg
= va_arg(ap
, ptrdiff_t);
1273 (*argtable
)[n
].pptrdiffarg
= va_arg(ap
, ptrdiff_t *);
1276 (*argtable
)[n
].sizearg
= va_arg(ap
, size_t);
1279 (*argtable
)[n
].ssizearg
= va_arg(ap
, ssize_t
);
1282 (*argtable
)[n
].pssizearg
= va_arg(ap
, ssize_t
*);
1285 (*argtable
)[n
].intmaxarg
= va_arg(ap
, intmax_t);
1296 if (typetable
!= NULL
&& typetable
!= stattypetable
) {
1297 munmap(typetable
, *argtablesiz
);
1304 * Increase the size of the type table.
1307 __grow_type_table(unsigned char **typetable
, int *tablesize
)
1309 unsigned char *oldtable
= *typetable
;
1310 int newsize
= *tablesize
* 2;
1312 if (newsize
< getpagesize())
1313 newsize
= getpagesize();
1315 if (*tablesize
== STATIC_ARG_TBL_SIZE
) {
1316 *typetable
= mmap(NULL
, newsize
, PROT_WRITE
|PROT_READ
,
1317 MAP_ANON
|MAP_PRIVATE
, -1, 0);
1318 if (*typetable
== MAP_FAILED
)
1320 bcopy(oldtable
, *typetable
, *tablesize
);
1322 unsigned char *new = mmap(NULL
, newsize
, PROT_WRITE
|PROT_READ
,
1323 MAP_ANON
|MAP_PRIVATE
, -1, 0);
1324 if (new == MAP_FAILED
)
1326 memmove(new, *typetable
, *tablesize
);
1327 munmap(*typetable
, *tablesize
);
1330 memset(*typetable
+ *tablesize
, T_UNUSED
, (newsize
- *tablesize
));
1332 *tablesize
= newsize
;
1337 #ifdef FLOATING_POINT
1339 exponent(char *p0
, int exp
, int fmtch
)
1342 char expbuf
[MAXEXPDIG
];
1351 t
= expbuf
+ MAXEXPDIG
;
1354 *--t
= to_char(exp
% 10);
1355 } while ((exp
/= 10) > 9);
1356 *--t
= to_char(exp
);
1357 for (; t
< expbuf
+ MAXEXPDIG
; *p
++ = *t
++)
1361 * Exponents for decimal floating point conversions
1362 * (%[eEgG]) must be at least two characters long,
1363 * whereas exponents for hexadecimal conversions can
1364 * be only one character long.
1366 if (fmtch
== 'e' || fmtch
== 'E')
1368 *p
++ = to_char(exp
);
1372 #endif /* FLOATING_POINT */
This page took 0.072243 seconds and 4 git commands to generate.