| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: vfprintf.c,v 1.77 2016/08/29 12:20:57 millert Exp $ */  | 
    ||
2  | 
    /*-  | 
    ||
3  | 
    * Copyright (c) 1990 The Regents of the University of California.  | 
    ||
4  | 
    * All rights reserved.  | 
    ||
5  | 
    *  | 
    ||
6  | 
    * This code is derived from software contributed to Berkeley by  | 
    ||
7  | 
    * Chris Torek.  | 
    ||
8  | 
    *  | 
    ||
9  | 
    * Redistribution and use in source and binary forms, with or without  | 
    ||
10  | 
    * modification, are permitted provided that the following conditions  | 
    ||
11  | 
    * are met:  | 
    ||
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.  | 
    ||
20  | 
    *  | 
    ||
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  | 
    ||
31  | 
    * SUCH DAMAGE.  | 
    ||
32  | 
    */  | 
    ||
33  | 
    |||
34  | 
    /*  | 
    ||
35  | 
    * Actual printf innards.  | 
    ||
36  | 
    *  | 
    ||
37  | 
    * This code is large and complicated...  | 
    ||
38  | 
    */  | 
    ||
39  | 
    |||
40  | 
    #include <sys/types.h>  | 
    ||
41  | 
    #include <sys/mman.h>  | 
    ||
42  | 
    |||
43  | 
    #include <errno.h>  | 
    ||
44  | 
    #include <langinfo.h>  | 
    ||
45  | 
    #include <limits.h>  | 
    ||
46  | 
    #include <stdarg.h>  | 
    ||
47  | 
    #include <stddef.h>  | 
    ||
48  | 
    #include <stdio.h>  | 
    ||
49  | 
    #include <stdint.h>  | 
    ||
50  | 
    #include <stdlib.h>  | 
    ||
51  | 
    #include <string.h>  | 
    ||
52  | 
    #include <unistd.h>  | 
    ||
53  | 
    #include <syslog.h>  | 
    ||
54  | 
    #include <wchar.h>  | 
    ||
55  | 
    |||
56  | 
    #include "local.h"  | 
    ||
57  | 
    #include "fvwrite.h"  | 
    ||
58  | 
    |||
59  | 
    union arg { | 
    ||
60  | 
    int intarg;  | 
    ||
61  | 
    unsigned int uintarg;  | 
    ||
62  | 
    long longarg;  | 
    ||
63  | 
    unsigned long ulongarg;  | 
    ||
64  | 
    long long longlongarg;  | 
    ||
65  | 
    unsigned long long ulonglongarg;  | 
    ||
66  | 
    ptrdiff_t ptrdiffarg;  | 
    ||
67  | 
    size_t sizearg;  | 
    ||
68  | 
    ssize_t ssizearg;  | 
    ||
69  | 
    intmax_t intmaxarg;  | 
    ||
70  | 
    uintmax_t uintmaxarg;  | 
    ||
71  | 
    void *pvoidarg;  | 
    ||
72  | 
    char *pchararg;  | 
    ||
73  | 
    signed char *pschararg;  | 
    ||
74  | 
    short *pshortarg;  | 
    ||
75  | 
    int *pintarg;  | 
    ||
76  | 
    long *plongarg;  | 
    ||
77  | 
    long long *plonglongarg;  | 
    ||
78  | 
    ptrdiff_t *pptrdiffarg;  | 
    ||
79  | 
    ssize_t *pssizearg;  | 
    ||
80  | 
    intmax_t *pintmaxarg;  | 
    ||
81  | 
    #ifdef FLOATING_POINT  | 
    ||
82  | 
    double doublearg;  | 
    ||
83  | 
    long double longdoublearg;  | 
    ||
84  | 
    #endif  | 
    ||
85  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
86  | 
    wint_t wintarg;  | 
    ||
87  | 
    wchar_t *pwchararg;  | 
    ||
88  | 
    #endif  | 
    ||
89  | 
    };  | 
    ||
90  | 
    |||
91  | 
    static int __find_arguments(const char *fmt0, va_list ap, union arg **argtable,  | 
    ||
92  | 
    size_t *argtablesiz);  | 
    ||
93  | 
    static int __grow_type_table(unsigned char **typetable, int *tablesize);  | 
    ||
94  | 
    |||
95  | 
    /*  | 
    ||
96  | 
    * Flush out all the vectors defined by the given uio,  | 
    ||
97  | 
    * then reset it so that it can be reused.  | 
    ||
98  | 
    */  | 
    ||
99  | 
    static int  | 
    ||
100  | 
    __sprint(FILE *fp, struct __suio *uio)  | 
    ||
101  | 
    { | 
    ||
102  | 
    int err;  | 
    ||
103  | 
    |||
104  | 
    ✗✓ | 3240  | 
    	if (uio->uio_resid == 0) { | 
    
105  | 
    uio->uio_iovcnt = 0;  | 
    ||
106  | 
    return (0);  | 
    ||
107  | 
    }  | 
    ||
108  | 
    1620  | 
    err = __sfvwrite(fp, uio);  | 
    |
109  | 
    1620  | 
    uio->uio_resid = 0;  | 
    |
110  | 
    1620  | 
    uio->uio_iovcnt = 0;  | 
    |
111  | 
    1620  | 
    return (err);  | 
    |
112  | 
    1620  | 
    }  | 
    |
113  | 
    |||
114  | 
    /*  | 
    ||
115  | 
    * Helper function for `fprintf to unbuffered unix file': creates a  | 
    ||
116  | 
    * temporary buffer. We only work on write-only files; this avoids  | 
    ||
117  | 
    * worries about ungetc buffers and so forth.  | 
    ||
118  | 
    */  | 
    ||
119  | 
    static int  | 
    ||
120  | 
    __sbprintf(FILE *fp, const char *fmt, va_list ap)  | 
    ||
121  | 
    { | 
    ||
122  | 
    int ret;  | 
    ||
123  | 
    36  | 
    FILE fake;  | 
    |
124  | 
    18  | 
    struct __sfileext fakeext;  | 
    |
125  | 
    18  | 
    unsigned char buf[BUFSIZ];  | 
    |
126  | 
    |||
127  | 
    18  | 
    _FILEEXT_SETUP(&fake, &fakeext);  | 
    |
128  | 
    /* copy the important variables */  | 
    ||
129  | 
    18  | 
    fake._flags = fp->_flags & ~__SNBF;  | 
    |
130  | 
    18  | 
    fake._file = fp->_file;  | 
    |
131  | 
    18  | 
    fake._cookie = fp->_cookie;  | 
    |
132  | 
    18  | 
    fake._write = fp->_write;  | 
    |
133  | 
    |||
134  | 
    /* set up the buffer */  | 
    ||
135  | 
    18  | 
    fake._bf._base = fake._p = buf;  | 
    |
136  | 
    18  | 
    fake._bf._size = fake._w = sizeof(buf);  | 
    |
137  | 
    18  | 
    fake._lbfsize = 0; /* not actually used, but Just In Case */  | 
    |
138  | 
    |||
139  | 
    /* do the work, then copy any error status */  | 
    ||
140  | 
    18  | 
    ret = __vfprintf(&fake, fmt, ap);  | 
    |
141  | 
    ✓✗✗✓ | 
    36  | 
    if (ret >= 0 && __sflush(&fake))  | 
    
142  | 
    ret = EOF;  | 
    ||
143  | 
    ✗✓ | 18  | 
    if (fake._flags & __SERR)  | 
    
144  | 
    fp->_flags |= __SERR;  | 
    ||
145  | 
    18  | 
    return (ret);  | 
    |
146  | 
    18  | 
    }  | 
    |
147  | 
    |||
148  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
149  | 
    /*  | 
    ||
150  | 
    * Convert a wide character string argument for the %ls format to a multibyte  | 
    ||
151  | 
    * string representation. If not -1, prec specifies the maximum number of  | 
    ||
152  | 
    * bytes to output, and also means that we can't assume that the wide char  | 
    ||
153  | 
    * string is null-terminated.  | 
    ||
154  | 
    */  | 
    ||
155  | 
    static char *  | 
    ||
156  | 
    __wcsconv(wchar_t *wcsarg, int prec)  | 
    ||
157  | 
    { | 
    ||
158  | 
    mbstate_t mbs;  | 
    ||
159  | 
    char buf[MB_LEN_MAX];  | 
    ||
160  | 
    wchar_t *p;  | 
    ||
161  | 
    char *convbuf;  | 
    ||
162  | 
    size_t clen, nbytes;  | 
    ||
163  | 
    |||
164  | 
    /* Allocate space for the maximum number of bytes we could output. */  | 
    ||
165  | 
    	if (prec < 0) { | 
    ||
166  | 
    memset(&mbs, 0, sizeof(mbs));  | 
    ||
167  | 
    p = wcsarg;  | 
    ||
168  | 
    nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);  | 
    ||
169  | 
    if (nbytes == (size_t)-1)  | 
    ||
170  | 
    return (NULL);  | 
    ||
171  | 
    	} else { | 
    ||
172  | 
    /*  | 
    ||
173  | 
    * Optimisation: if the output precision is small enough,  | 
    ||
174  | 
    * just allocate enough memory for the maximum instead of  | 
    ||
175  | 
    * scanning the string.  | 
    ||
176  | 
    */  | 
    ||
177  | 
    if (prec < 128)  | 
    ||
178  | 
    nbytes = prec;  | 
    ||
179  | 
    		else { | 
    ||
180  | 
    nbytes = 0;  | 
    ||
181  | 
    p = wcsarg;  | 
    ||
182  | 
    memset(&mbs, 0, sizeof(mbs));  | 
    ||
183  | 
    			for (;;) { | 
    ||
184  | 
    clen = wcrtomb(buf, *p++, &mbs);  | 
    ||
185  | 
    if (clen == 0 || clen == (size_t)-1 ||  | 
    ||
186  | 
    nbytes + clen > (size_t)prec)  | 
    ||
187  | 
    break;  | 
    ||
188  | 
    nbytes += clen;  | 
    ||
189  | 
    }  | 
    ||
190  | 
    if (clen == (size_t)-1)  | 
    ||
191  | 
    return (NULL);  | 
    ||
192  | 
    }  | 
    ||
193  | 
    }  | 
    ||
194  | 
    if ((convbuf = malloc(nbytes + 1)) == NULL)  | 
    ||
195  | 
    return (NULL);  | 
    ||
196  | 
    |||
197  | 
    /* Fill the output buffer. */  | 
    ||
198  | 
    p = wcsarg;  | 
    ||
199  | 
    memset(&mbs, 0, sizeof(mbs));  | 
    ||
200  | 
    if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,  | 
    ||
201  | 
    	    nbytes, &mbs)) == (size_t)-1) { | 
    ||
202  | 
    free(convbuf);  | 
    ||
203  | 
    return (NULL);  | 
    ||
204  | 
    }  | 
    ||
205  | 
    convbuf[nbytes] = '\0';  | 
    ||
206  | 
    return (convbuf);  | 
    ||
207  | 
    }  | 
    ||
208  | 
    #endif  | 
    ||
209  | 
    |||
210  | 
    #ifdef FLOATING_POINT  | 
    ||
211  | 
    #include <float.h>  | 
    ||
212  | 
    #include <locale.h>  | 
    ||
213  | 
    #include <math.h>  | 
    ||
214  | 
    #include "floatio.h"  | 
    ||
215  | 
    #include "gdtoa.h"  | 
    ||
216  | 
    |||
217  | 
    #define DEFPREC 6  | 
    ||
218  | 
    |||
219  | 
    static int exponent(char *, int, int);  | 
    ||
220  | 
    #endif /* FLOATING_POINT */  | 
    ||
221  | 
    |||
222  | 
    /*  | 
    ||
223  | 
    * The size of the buffer we use as scratch space for integer  | 
    ||
224  | 
    * conversions, among other things. Technically, we would need the  | 
    ||
225  | 
    * most space for base 10 conversions with thousands' grouping  | 
    ||
226  | 
    * characters between each pair of digits. 100 bytes is a  | 
    ||
227  | 
    * conservative overestimate even for a 128-bit uintmax_t.  | 
    ||
228  | 
    */  | 
    ||
229  | 
    #define BUF 100  | 
    ||
230  | 
    |||
231  | 
    #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */  | 
    ||
232  | 
    |||
233  | 
    |||
234  | 
    /*  | 
    ||
235  | 
    * Macros for converting digits to letters and vice versa  | 
    ||
236  | 
    */  | 
    ||
237  | 
    #define to_digit(c) ((c) - '0')  | 
    ||
238  | 
    #define is_digit(c) ((unsigned)to_digit(c) <= 9)  | 
    ||
239  | 
    #define to_char(n) ((n) + '0')  | 
    ||
240  | 
    |||
241  | 
    /*  | 
    ||
242  | 
    * Flags used during conversion.  | 
    ||
243  | 
    */  | 
    ||
244  | 
    #define ALT 0x0001 /* alternate form */  | 
    ||
245  | 
    #define LADJUST 0x0004 /* left adjustment */  | 
    ||
246  | 
    #define LONGDBL 0x0008 /* long double */  | 
    ||
247  | 
    #define LONGINT 0x0010 /* long integer */  | 
    ||
248  | 
    #define LLONGINT 0x0020 /* long long integer */  | 
    ||
249  | 
    #define SHORTINT 0x0040 /* short integer */  | 
    ||
250  | 
    #define ZEROPAD 0x0080 /* zero (as opposed to blank) pad */  | 
    ||
251  | 
    #define FPT 0x0100 /* Floating point number */  | 
    ||
252  | 
    #define PTRINT 0x0200 /* (unsigned) ptrdiff_t */  | 
    ||
253  | 
    #define SIZEINT 0x0400 /* (signed) size_t */  | 
    ||
254  | 
    #define CHARINT 0x0800 /* 8 bit integer */  | 
    ||
255  | 
    #define MAXINT 0x1000 /* largest integer size (intmax_t) */  | 
    ||
256  | 
    |||
257  | 
    int  | 
    ||
258  | 
    vfprintf(FILE *fp, const char *fmt0, __va_list ap)  | 
    ||
259  | 
    { | 
    ||
260  | 
    int ret;  | 
    ||
261  | 
    |||
262  | 
    ✗✓ | 60  | 
    FLOCKFILE(fp);  | 
    
263  | 
    30  | 
    ret = __vfprintf(fp, fmt0, ap);  | 
    |
264  | 
    ✗✓ | 30  | 
    FUNLOCKFILE(fp);  | 
    
265  | 
    30  | 
    return (ret);  | 
    |
266  | 
    }  | 
    ||
267  | 
    DEF_STRONG(vfprintf);  | 
    ||
268  | 
    |||
269  | 
    int  | 
    ||
270  | 
    __vfprintf(FILE *fp, const char *fmt0, __va_list ap)  | 
    ||
271  | 
    { | 
    ||
272  | 
    char *fmt; /* format string */  | 
    ||
273  | 
    int ch; /* character from fmt */  | 
    ||
274  | 
    int n, n2; /* handy integers (short term usage) */  | 
    ||
275  | 
    char *cp; /* handy char pointer (short term usage) */  | 
    ||
276  | 
    struct __siov *iovp; /* for PRINT macro */  | 
    ||
277  | 
    int flags; /* flags as above */  | 
    ||
278  | 
    int ret; /* return value accumulator */  | 
    ||
279  | 
    int width; /* width from format (%8d), or 0 */  | 
    ||
280  | 
    int prec; /* precision from format; <0 for N/A */  | 
    ||
281  | 
    1644  | 
    	char sign;		/* sign prefix (' ', '+', '-', or \0) */ | 
    |
282  | 
    822  | 
    wchar_t wc;  | 
    |
283  | 
    822  | 
    mbstate_t ps;  | 
    |
284  | 
    #ifdef FLOATING_POINT  | 
    ||
285  | 
    /*  | 
    ||
286  | 
    * We can decompose the printed representation of floating  | 
    ||
287  | 
    * point numbers into several parts, some of which may be empty:  | 
    ||
288  | 
    *  | 
    ||
289  | 
    * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ  | 
    ||
290  | 
    * A B ---C--- D E F  | 
    ||
291  | 
    *  | 
    ||
292  | 
    * A: 'sign' holds this value if present; '\0' otherwise  | 
    ||
293  | 
    * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal  | 
    ||
294  | 
    * C: cp points to the string MMMNNN. Leading and trailing  | 
    ||
295  | 
    * zeros are not in the string and must be added.  | 
    ||
296  | 
    * D: expchar holds this character; '\0' if no exponent, e.g. %f  | 
    ||
297  | 
    * F: at least two digits for decimal, at least one digit for hex  | 
    ||
298  | 
    */  | 
    ||
299  | 
    char *decimal_point = NULL;  | 
    ||
300  | 
    822  | 
    int signflag; /* true if float is negative */  | 
    |
301  | 
    822  | 
    	union {			/* floating point arguments %[aAeEfFgG] */ | 
    |
302  | 
    double dbl;  | 
    ||
303  | 
    long double ldbl;  | 
    ||
304  | 
    } fparg;  | 
    ||
305  | 
    822  | 
    int expt; /* integer value of exponent */  | 
    |
306  | 
    char expchar; /* exponent character: [eEpP\0] */  | 
    ||
307  | 
    822  | 
    char *dtoaend; /* pointer to end of converted digits */  | 
    |
308  | 
    int expsize; /* character count for expstr */  | 
    ||
309  | 
    int lead; /* sig figs before decimal or group sep */  | 
    ||
310  | 
    int ndig; /* actual number of digits returned by dtoa */  | 
    ||
311  | 
    822  | 
    char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */  | 
    |
312  | 
    char *dtoaresult = NULL;  | 
    ||
313  | 
    #endif  | 
    ||
314  | 
    |||
315  | 
    uintmax_t _umax; /* integer arguments %[diouxX] */  | 
    ||
316  | 
    	enum { OCT, DEC, HEX } base;	/* base for %[diouxX] conversion */ | 
    ||
317  | 
    int dprec; /* a copy of prec if %[diouxX], 0 otherwise */  | 
    ||
318  | 
    int realsz; /* field size expanded by dprec */  | 
    ||
319  | 
    int size; /* size of converted field or string */  | 
    ||
320  | 
    const char *xdigs; /* digits for %[xX] conversion */  | 
    ||
321  | 
    #define NIOV 8  | 
    ||
322  | 
    822  | 
    struct __suio uio; /* output information: summary */  | 
    |
323  | 
    822  | 
    struct __siov iov[NIOV];/* ... and individual io vectors */  | 
    |
324  | 
    822  | 
    char buf[BUF]; /* buffer with space for digits of uintmax_t */  | 
    |
325  | 
    822  | 
    char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */  | 
    |
326  | 
    822  | 
    union arg *argtable; /* args, built due to positional arg */  | 
    |
327  | 
    822  | 
    union arg statargtable[STATIC_ARG_TBL_SIZE];  | 
    |
328  | 
    822  | 
    size_t argtablesiz;  | 
    |
329  | 
    int nextarg; /* 1-based argument index */  | 
    ||
330  | 
    822  | 
    va_list orgap; /* original argument pointer */  | 
    |
331  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
332  | 
    char *convbuf; /* buffer for wide to multi-byte conversion */  | 
    ||
333  | 
    #endif  | 
    ||
334  | 
    |||
335  | 
    /*  | 
    ||
336  | 
    * Choose PADSIZE to trade efficiency vs. size. If larger printf  | 
    ||
337  | 
    * fields occur frequently, increase PADSIZE and make the initialisers  | 
    ||
338  | 
    * below longer.  | 
    ||
339  | 
    */  | 
    ||
340  | 
    #define PADSIZE 16 /* pad chunk size */  | 
    ||
341  | 
    static char blanks[PADSIZE] =  | 
    ||
342  | 
    	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; | 
    ||
343  | 
    static char zeroes[PADSIZE] =  | 
    ||
344  | 
    	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; | 
    ||
345  | 
    |||
346  | 
    static const char xdigs_lower[16] = "0123456789abcdef";  | 
    ||
347  | 
    static const char xdigs_upper[16] = "0123456789ABCDEF";  | 
    ||
348  | 
    |||
349  | 
    /*  | 
    ||
350  | 
    * BEWARE, these `goto error' on error, and PAD uses `n'.  | 
    ||
351  | 
    */  | 
    ||
352  | 
    #define	PRINT(ptr, len) do { \ | 
    ||
353  | 
    iovp->iov_base = (ptr); \  | 
    ||
354  | 
    iovp->iov_len = (len); \  | 
    ||
355  | 
    uio.uio_resid += (len); \  | 
    ||
356  | 
    iovp++; \  | 
    ||
357  | 
    	if (++uio.uio_iovcnt >= NIOV) { \ | 
    ||
358  | 
    if (__sprint(fp, &uio)) \  | 
    ||
359  | 
    goto error; \  | 
    ||
360  | 
    iovp = iov; \  | 
    ||
361  | 
    } \  | 
    ||
362  | 
    } while (0)  | 
    ||
363  | 
    #define	PAD(howmany, with) do { \ | 
    ||
364  | 
    	if ((n = (howmany)) > 0) { \ | 
    ||
365  | 
    		while (n > PADSIZE) { \ | 
    ||
366  | 
    PRINT(with, PADSIZE); \  | 
    ||
367  | 
    n -= PADSIZE; \  | 
    ||
368  | 
    } \  | 
    ||
369  | 
    PRINT(with, n); \  | 
    ||
370  | 
    } \  | 
    ||
371  | 
    } while (0)  | 
    ||
372  | 
    #define	PRINTANDPAD(p, ep, len, with) do {	\ | 
    ||
373  | 
    n2 = (ep) - (p); \  | 
    ||
374  | 
    if (n2 > (len)) \  | 
    ||
375  | 
    n2 = (len); \  | 
    ||
376  | 
    if (n2 > 0) \  | 
    ||
377  | 
    PRINT((p), n2); \  | 
    ||
378  | 
    PAD((len) - (n2 > 0 ? n2 : 0), (with)); \  | 
    ||
379  | 
    } while(0)  | 
    ||
380  | 
    #define	FLUSH() do { \ | 
    ||
381  | 
    if (uio.uio_resid && __sprint(fp, &uio)) \  | 
    ||
382  | 
    goto error; \  | 
    ||
383  | 
    uio.uio_iovcnt = 0; \  | 
    ||
384  | 
    iovp = iov; \  | 
    ||
385  | 
    } while (0)  | 
    ||
386  | 
    |||
387  | 
    /*  | 
    ||
388  | 
    * To extend shorts properly, we need both signed and unsigned  | 
    ||
389  | 
    * argument extraction methods.  | 
    ||
390  | 
    */  | 
    ||
391  | 
    #define SARG() \  | 
    ||
392  | 
    ((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \  | 
    ||
393  | 
    flags&LLONGINT ? GETARG(long long) : \  | 
    ||
394  | 
    flags&LONGINT ? GETARG(long) : \  | 
    ||
395  | 
    flags&PTRINT ? GETARG(ptrdiff_t) : \  | 
    ||
396  | 
    flags&SIZEINT ? GETARG(ssize_t) : \  | 
    ||
397  | 
    flags&SHORTINT ? (short)GETARG(int) : \  | 
    ||
398  | 
    flags&CHARINT ? (signed char)GETARG(int) : \  | 
    ||
399  | 
    GETARG(int)))  | 
    ||
400  | 
    #define UARG() \  | 
    ||
401  | 
    ((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \  | 
    ||
402  | 
    flags&LLONGINT ? GETARG(unsigned long long) : \  | 
    ||
403  | 
    flags&LONGINT ? GETARG(unsigned long) : \  | 
    ||
404  | 
    flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \  | 
    ||
405  | 
    flags&SIZEINT ? GETARG(size_t) : \  | 
    ||
406  | 
    flags&SHORTINT ? (unsigned short)GETARG(int) : \  | 
    ||
407  | 
    flags&CHARINT ? (unsigned char)GETARG(int) : \  | 
    ||
408  | 
    GETARG(unsigned int)))  | 
    ||
409  | 
    |||
410  | 
    /*  | 
    ||
411  | 
    * Append a digit to a value and check for overflow.  | 
    ||
412  | 
    */  | 
    ||
413  | 
    #define APPEND_DIGIT(val, dig) do { \ | 
    ||
414  | 
    if ((val) > INT_MAX / 10) \  | 
    ||
415  | 
    goto overflow; \  | 
    ||
416  | 
    (val) *= 10; \  | 
    ||
417  | 
    if ((val) > INT_MAX - to_digit((dig))) \  | 
    ||
418  | 
    goto overflow; \  | 
    ||
419  | 
    (val) += to_digit((dig)); \  | 
    ||
420  | 
    } while (0)  | 
    ||
421  | 
    |||
422  | 
    /*  | 
    ||
423  | 
    * Get * arguments, including the form *nn$. Preserve the nextarg  | 
    ||
424  | 
    * that the argument can be gotten once the type is determined.  | 
    ||
425  | 
    */  | 
    ||
426  | 
    #define GETASTER(val) \  | 
    ||
427  | 
    n2 = 0; \  | 
    ||
428  | 
    cp = fmt; \  | 
    ||
429  | 
    	while (is_digit(*cp)) { \ | 
    ||
430  | 
    APPEND_DIGIT(n2, *cp); \  | 
    ||
431  | 
    cp++; \  | 
    ||
432  | 
    } \  | 
    ||
433  | 
    	if (*cp == '$') { \ | 
    ||
434  | 
    int hold = nextarg; \  | 
    ||
435  | 
    		if (argtable == NULL) { \ | 
    ||
436  | 
    argtable = statargtable; \  | 
    ||
437  | 
    if (__find_arguments(fmt0, orgap, &argtable, \  | 
    ||
438  | 
    			    &argtablesiz) == -1) { \ | 
    ||
439  | 
    ret = -1; \  | 
    ||
440  | 
    goto error; \  | 
    ||
441  | 
    } \  | 
    ||
442  | 
    } \  | 
    ||
443  | 
    nextarg = n2; \  | 
    ||
444  | 
    val = GETARG(int); \  | 
    ||
445  | 
    nextarg = hold; \  | 
    ||
446  | 
    fmt = ++cp; \  | 
    ||
447  | 
    	} else { \ | 
    ||
448  | 
    val = GETARG(int); \  | 
    ||
449  | 
    }  | 
    ||
450  | 
    |||
451  | 
    /*  | 
    ||
452  | 
    * Get the argument indexed by nextarg. If the argument table is  | 
    ||
453  | 
    * built, use it to get the argument. If its not, get the next  | 
    ||
454  | 
    * argument (and arguments must be gotten sequentially).  | 
    ||
455  | 
    */  | 
    ||
456  | 
    #define GETARG(type) \  | 
    ||
457  | 
    ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \  | 
    ||
458  | 
    (nextarg++, va_arg(ap, type)))  | 
    ||
459  | 
    |||
460  | 
    ✓✗✓✗ ✓✓  | 
    4086  | 
    _SET_ORIENTATION(fp, -1);  | 
    
461  | 
    /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */  | 
    ||
462  | 
    ✓✗✓✓ ✗✓  | 
    1650  | 
    	if (cantwrite(fp)) { | 
    
463  | 
    errno = EBADF;  | 
    ||
464  | 
    return (EOF);  | 
    ||
465  | 
    }  | 
    ||
466  | 
    |||
467  | 
    /* optimise fprintf(stderr) (and other unbuffered Unix files) */  | 
    ||
468  | 
    ✓✓✓✗ | 
    840  | 
    if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&  | 
    
469  | 
    18  | 
    fp->_file >= 0)  | 
    |
470  | 
    18  | 
    return (__sbprintf(fp, fmt0, ap));  | 
    |
471  | 
    |||
472  | 
    fmt = (char *)fmt0;  | 
    ||
473  | 
    804  | 
    argtable = NULL;  | 
    |
474  | 
    nextarg = 1;  | 
    ||
475  | 
    804  | 
    va_copy(orgap, ap);  | 
    |
476  | 
    804  | 
    uio.uio_iov = iovp = iov;  | 
    |
477  | 
    804  | 
    uio.uio_resid = 0;  | 
    |
478  | 
    804  | 
    uio.uio_iovcnt = 0;  | 
    |
479  | 
    ret = 0;  | 
    ||
480  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
481  | 
    convbuf = NULL;  | 
    ||
482  | 
    #endif  | 
    ||
483  | 
    |||
484  | 
    804  | 
    memset(&ps, 0, sizeof(ps));  | 
    |
485  | 
    /*  | 
    ||
486  | 
    * Scan the format for conversions (`%' character).  | 
    ||
487  | 
    */  | 
    ||
488  | 
    1620  | 
    	for (;;) { | 
    |
489  | 
    size_t len;  | 
    ||
490  | 
    |||
491  | 
    cp = fmt;  | 
    ||
492  | 
    ✓✓ | 18558  | 
    		while ((len = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) != 0) { | 
    
493  | 
    ✗✓ | 8475  | 
    			if (len == (size_t)-1 || len == (size_t)-2) { | 
    
494  | 
    ret = -1;  | 
    ||
495  | 
    goto error;  | 
    ||
496  | 
    }  | 
    ||
497  | 
    8475  | 
    fmt += len;  | 
    |
498  | 
    ✓✓ | 8475  | 
    			if (wc == '%') { | 
    
499  | 
    816  | 
    fmt--;  | 
    |
500  | 
    816  | 
    break;  | 
    |
501  | 
    }  | 
    ||
502  | 
    }  | 
    ||
503  | 
    ✓✓ | 1620  | 
    		if (fmt != cp) { | 
    
504  | 
    1608  | 
    ptrdiff_t m = fmt - cp;  | 
    |
505  | 
    ✓✗✗✓ | 
    3216  | 
    if (m < 0 || m > INT_MAX - ret)  | 
    
506  | 
    goto overflow;  | 
    ||
507  | 
    ✗✓✗✗ | 
    1608  | 
    PRINT(cp, m);  | 
    
508  | 
    1608  | 
    ret += m;  | 
    |
509  | 
    ✓✗ | 1608  | 
    }  | 
    
510  | 
    ✓✓ | 1620  | 
    if (len == 0)  | 
    
511  | 
    804  | 
    goto done;  | 
    |
512  | 
    816  | 
    fmt++; /* skip over '%' */  | 
    |
513  | 
    |||
514  | 
    flags = 0;  | 
    ||
515  | 
    dprec = 0;  | 
    ||
516  | 
    width = 0;  | 
    ||
517  | 
    prec = -1;  | 
    ||
518  | 
    816  | 
    sign = '\0';  | 
    |
519  | 
    816  | 
    ox[1] = '\0';  | 
    |
520  | 
    |||
521  | 
    816  | 
    rflag: ch = *fmt++;  | 
    |
522  | 
    ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✓  | 
    816  | 
    reswitch:	switch (ch) { | 
    
523  | 
    case ' ':  | 
    ||
524  | 
    /*  | 
    ||
525  | 
    * ``If the space and + flags both appear, the space  | 
    ||
526  | 
    * flag will be ignored.''  | 
    ||
527  | 
    * -- ANSI X3J11  | 
    ||
528  | 
    */  | 
    ||
529  | 
    if (!sign)  | 
    ||
530  | 
    sign = ' ';  | 
    ||
531  | 
    goto rflag;  | 
    ||
532  | 
    case '#':  | 
    ||
533  | 
    flags |= ALT;  | 
    ||
534  | 
    goto rflag;  | 
    ||
535  | 
    case '\'':  | 
    ||
536  | 
    /* grouping not implemented */  | 
    ||
537  | 
    goto rflag;  | 
    ||
538  | 
    case '*':  | 
    ||
539  | 
    /*  | 
    ||
540  | 
    * ``A negative field width argument is taken as a  | 
    ||
541  | 
    * - flag followed by a positive field width.''  | 
    ||
542  | 
    * -- ANSI X3J11  | 
    ||
543  | 
    * They don't exclude field widths read from args.  | 
    ||
544  | 
    */  | 
    ||
545  | 
    GETASTER(width);  | 
    ||
546  | 
    if (width >= 0)  | 
    ||
547  | 
    goto rflag;  | 
    ||
548  | 
    if (width == INT_MIN)  | 
    ||
549  | 
    goto overflow;  | 
    ||
550  | 
    width = -width;  | 
    ||
551  | 
    /* FALLTHROUGH */  | 
    ||
552  | 
    case '-':  | 
    ||
553  | 
    flags |= LADJUST;  | 
    ||
554  | 
    goto rflag;  | 
    ||
555  | 
    case '+':  | 
    ||
556  | 
    sign = '+';  | 
    ||
557  | 
    goto rflag;  | 
    ||
558  | 
    case '.':  | 
    ||
559  | 
    			if ((ch = *fmt++) == '*') { | 
    ||
560  | 
    GETASTER(n);  | 
    ||
561  | 
    prec = n < 0 ? -1 : n;  | 
    ||
562  | 
    goto rflag;  | 
    ||
563  | 
    }  | 
    ||
564  | 
    n = 0;  | 
    ||
565  | 
    			while (is_digit(ch)) { | 
    ||
566  | 
    APPEND_DIGIT(n, ch);  | 
    ||
567  | 
    ch = *fmt++;  | 
    ||
568  | 
    }  | 
    ||
569  | 
    			if (ch == '$') { | 
    ||
570  | 
    nextarg = n;  | 
    ||
571  | 
    				if (argtable == NULL) { | 
    ||
572  | 
    argtable = statargtable;  | 
    ||
573  | 
    if (__find_arguments(fmt0, orgap,  | 
    ||
574  | 
    					    &argtable, &argtablesiz) == -1) { | 
    ||
575  | 
    ret = -1;  | 
    ||
576  | 
    goto error;  | 
    ||
577  | 
    }  | 
    ||
578  | 
    }  | 
    ||
579  | 
    goto rflag;  | 
    ||
580  | 
    }  | 
    ||
581  | 
    prec = n;  | 
    ||
582  | 
    goto reswitch;  | 
    ||
583  | 
    case '0':  | 
    ||
584  | 
    /*  | 
    ||
585  | 
    * ``Note that 0 is taken as a flag, not as the  | 
    ||
586  | 
    * beginning of a field width.''  | 
    ||
587  | 
    * -- ANSI X3J11  | 
    ||
588  | 
    */  | 
    ||
589  | 
    flags |= ZEROPAD;  | 
    ||
590  | 
    goto rflag;  | 
    ||
591  | 
    case '1': case '2': case '3': case '4':  | 
    ||
592  | 
    case '5': case '6': case '7': case '8': case '9':  | 
    ||
593  | 
    n = 0;  | 
    ||
594  | 
    			do { | 
    ||
595  | 
    APPEND_DIGIT(n, ch);  | 
    ||
596  | 
    ch = *fmt++;  | 
    ||
597  | 
    } while (is_digit(ch));  | 
    ||
598  | 
    			if (ch == '$') { | 
    ||
599  | 
    nextarg = n;  | 
    ||
600  | 
    				if (argtable == NULL) { | 
    ||
601  | 
    argtable = statargtable;  | 
    ||
602  | 
    if (__find_arguments(fmt0, orgap,  | 
    ||
603  | 
    					    &argtable, &argtablesiz) == -1) { | 
    ||
604  | 
    ret = -1;  | 
    ||
605  | 
    goto error;  | 
    ||
606  | 
    }  | 
    ||
607  | 
    }  | 
    ||
608  | 
    goto rflag;  | 
    ||
609  | 
    }  | 
    ||
610  | 
    width = n;  | 
    ||
611  | 
    goto reswitch;  | 
    ||
612  | 
    #ifdef FLOATING_POINT  | 
    ||
613  | 
    case 'L':  | 
    ||
614  | 
    flags |= LONGDBL;  | 
    ||
615  | 
    goto rflag;  | 
    ||
616  | 
    #endif  | 
    ||
617  | 
    case 'h':  | 
    ||
618  | 
    			if (*fmt == 'h') { | 
    ||
619  | 
    fmt++;  | 
    ||
620  | 
    flags |= CHARINT;  | 
    ||
621  | 
    			} else { | 
    ||
622  | 
    flags |= SHORTINT;  | 
    ||
623  | 
    }  | 
    ||
624  | 
    goto rflag;  | 
    ||
625  | 
    case 'j':  | 
    ||
626  | 
    flags |= MAXINT;  | 
    ||
627  | 
    goto rflag;  | 
    ||
628  | 
    case 'l':  | 
    ||
629  | 
    			if (*fmt == 'l') { | 
    ||
630  | 
    fmt++;  | 
    ||
631  | 
    flags |= LLONGINT;  | 
    ||
632  | 
    			} else { | 
    ||
633  | 
    flags |= LONGINT;  | 
    ||
634  | 
    }  | 
    ||
635  | 
    goto rflag;  | 
    ||
636  | 
    case 'q':  | 
    ||
637  | 
    flags |= LLONGINT;  | 
    ||
638  | 
    goto rflag;  | 
    ||
639  | 
    case 't':  | 
    ||
640  | 
    flags |= PTRINT;  | 
    ||
641  | 
    goto rflag;  | 
    ||
642  | 
    case 'z':  | 
    ||
643  | 
    flags |= SIZEINT;  | 
    ||
644  | 
    goto rflag;  | 
    ||
645  | 
    case 'c':  | 
    ||
646  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
647  | 
    ✗✓ | 768  | 
    			if (flags & LONGINT) { | 
    
648  | 
    mbstate_t mbs;  | 
    ||
649  | 
    size_t mbseqlen;  | 
    ||
650  | 
    |||
651  | 
    memset(&mbs, 0, sizeof(mbs));  | 
    ||
652  | 
    mbseqlen = wcrtomb(buf,  | 
    ||
653  | 
    (wchar_t)GETARG(wint_t), &mbs);  | 
    ||
654  | 
    				if (mbseqlen == (size_t)-1) { | 
    ||
655  | 
    ret = -1;  | 
    ||
656  | 
    goto error;  | 
    ||
657  | 
    }  | 
    ||
658  | 
    cp = buf;  | 
    ||
659  | 
    size = (int)mbseqlen;  | 
    ||
660  | 
    			} else { | 
    ||
661  | 
    #endif  | 
    ||
662  | 
    ✗✓✓✗ | 
    3072  | 
    *(cp = buf) = GETARG(int);  | 
    
663  | 
    size = 1;  | 
    ||
664  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
665  | 
    }  | 
    ||
666  | 
    #endif  | 
    ||
667  | 
    768  | 
    sign = '\0';  | 
    |
668  | 
    768  | 
    break;  | 
    |
669  | 
    case 'D':  | 
    ||
670  | 
    flags |= LONGINT;  | 
    ||
671  | 
    /*FALLTHROUGH*/  | 
    ||
672  | 
    case 'd':  | 
    ||
673  | 
    case 'i':  | 
    ||
674  | 
    ✗✓✗✗ ✗✗✗✓ ✗✗✗✗ ✗✓✗✗ ✗✗✗✓ ✗✗✗✗ ✗✓✗✗ ✗✗✗✓ ✗✗✗✗ ✗✓✗✗ ✗✗✗✓ ✓✗  | 
    468  | 
    _umax = SARG();  | 
    
675  | 
    ✗✓ | 36  | 
    			if ((intmax_t)_umax < 0) { | 
    
676  | 
    _umax = -_umax;  | 
    ||
677  | 
    sign = '-';  | 
    ||
678  | 
    }  | 
    ||
679  | 
    base = DEC;  | 
    ||
680  | 
    36  | 
    goto number;  | 
    |
681  | 
    #ifdef FLOATING_POINT  | 
    ||
682  | 
    case 'a':  | 
    ||
683  | 
    case 'A':  | 
    ||
684  | 
    			if (ch == 'a') { | 
    ||
685  | 
    ox[1] = 'x';  | 
    ||
686  | 
    xdigs = xdigs_lower;  | 
    ||
687  | 
    expchar = 'p';  | 
    ||
688  | 
    			} else { | 
    ||
689  | 
    ox[1] = 'X';  | 
    ||
690  | 
    xdigs = xdigs_upper;  | 
    ||
691  | 
    expchar = 'P';  | 
    ||
692  | 
    }  | 
    ||
693  | 
    if (prec >= 0)  | 
    ||
694  | 
    prec++;  | 
    ||
695  | 
    if (dtoaresult)  | 
    ||
696  | 
    __freedtoa(dtoaresult);  | 
    ||
697  | 
    			if (flags & LONGDBL) { | 
    ||
698  | 
    fparg.ldbl = GETARG(long double);  | 
    ||
699  | 
    dtoaresult = cp =  | 
    ||
700  | 
    __hldtoa(fparg.ldbl, xdigs, prec,  | 
    ||
701  | 
    &expt, &signflag, &dtoaend);  | 
    ||
702  | 
    				if (dtoaresult == NULL) { | 
    ||
703  | 
    errno = ENOMEM;  | 
    ||
704  | 
    goto error;  | 
    ||
705  | 
    }  | 
    ||
706  | 
    			} else { | 
    ||
707  | 
    fparg.dbl = GETARG(double);  | 
    ||
708  | 
    dtoaresult = cp =  | 
    ||
709  | 
    __hdtoa(fparg.dbl, xdigs, prec,  | 
    ||
710  | 
    &expt, &signflag, &dtoaend);  | 
    ||
711  | 
    				if (dtoaresult == NULL) { | 
    ||
712  | 
    errno = ENOMEM;  | 
    ||
713  | 
    goto error;  | 
    ||
714  | 
    }  | 
    ||
715  | 
    }  | 
    ||
716  | 
    if (prec < 0)  | 
    ||
717  | 
    prec = dtoaend - cp;  | 
    ||
718  | 
    if (expt == INT_MAX)  | 
    ||
719  | 
    ox[1] = '\0';  | 
    ||
720  | 
    goto fp_common;  | 
    ||
721  | 
    case 'e':  | 
    ||
722  | 
    case 'E':  | 
    ||
723  | 
    expchar = ch;  | 
    ||
724  | 
    if (prec < 0) /* account for digit before decpt */  | 
    ||
725  | 
    prec = DEFPREC + 1;  | 
    ||
726  | 
    else  | 
    ||
727  | 
    prec++;  | 
    ||
728  | 
    goto fp_begin;  | 
    ||
729  | 
    case 'f':  | 
    ||
730  | 
    case 'F':  | 
    ||
731  | 
    expchar = '\0';  | 
    ||
732  | 
    goto fp_begin;  | 
    ||
733  | 
    case 'g':  | 
    ||
734  | 
    case 'G':  | 
    ||
735  | 
    			expchar = ch - ('g' - 'e'); | 
    ||
736  | 
    if (prec == 0)  | 
    ||
737  | 
    prec = 1;  | 
    ||
738  | 
    fp_begin:  | 
    ||
739  | 
    if (prec < 0)  | 
    ||
740  | 
    prec = DEFPREC;  | 
    ||
741  | 
    if (dtoaresult)  | 
    ||
742  | 
    __freedtoa(dtoaresult);  | 
    ||
743  | 
    			if (flags & LONGDBL) { | 
    ||
744  | 
    fparg.ldbl = GETARG(long double);  | 
    ||
745  | 
    dtoaresult = cp =  | 
    ||
746  | 
    __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,  | 
    ||
747  | 
    &expt, &signflag, &dtoaend);  | 
    ||
748  | 
    				if (dtoaresult == NULL) { | 
    ||
749  | 
    errno = ENOMEM;  | 
    ||
750  | 
    goto error;  | 
    ||
751  | 
    }  | 
    ||
752  | 
    			} else { | 
    ||
753  | 
    fparg.dbl = GETARG(double);  | 
    ||
754  | 
    dtoaresult = cp =  | 
    ||
755  | 
    __dtoa(fparg.dbl, expchar ? 2 : 3, prec,  | 
    ||
756  | 
    &expt, &signflag, &dtoaend);  | 
    ||
757  | 
    				if (dtoaresult == NULL) { | 
    ||
758  | 
    errno = ENOMEM;  | 
    ||
759  | 
    goto error;  | 
    ||
760  | 
    }  | 
    ||
761  | 
    if (expt == 9999)  | 
    ||
762  | 
    expt = INT_MAX;  | 
    ||
763  | 
    }  | 
    ||
764  | 
    fp_common:  | 
    ||
765  | 
    if (signflag)  | 
    ||
766  | 
    sign = '-';  | 
    ||
767  | 
    			if (expt == INT_MAX) {	/* inf or nan */ | 
    ||
768  | 
    if (*cp == 'N')  | 
    ||
769  | 
    cp = (ch >= 'a') ? "nan" : "NAN";  | 
    ||
770  | 
    else  | 
    ||
771  | 
    cp = (ch >= 'a') ? "inf" : "INF";  | 
    ||
772  | 
    size = 3;  | 
    ||
773  | 
    flags &= ~ZEROPAD;  | 
    ||
774  | 
    break;  | 
    ||
775  | 
    }  | 
    ||
776  | 
    flags |= FPT;  | 
    ||
777  | 
    ndig = dtoaend - cp;  | 
    ||
778  | 
     			if (ch == 'g' || ch == 'G') { | 
    ||
779  | 
    				if (expt > -4 && expt <= prec) { | 
    ||
780  | 
    /* Make %[gG] smell like %[fF] */  | 
    ||
781  | 
    expchar = '\0';  | 
    ||
782  | 
    if (flags & ALT)  | 
    ||
783  | 
    prec -= expt;  | 
    ||
784  | 
    else  | 
    ||
785  | 
    prec = ndig - expt;  | 
    ||
786  | 
    if (prec < 0)  | 
    ||
787  | 
    prec = 0;  | 
    ||
788  | 
    				} else { | 
    ||
789  | 
    /*  | 
    ||
790  | 
    * Make %[gG] smell like %[eE], but  | 
    ||
791  | 
    * trim trailing zeroes if no # flag.  | 
    ||
792  | 
    */  | 
    ||
793  | 
    if (!(flags & ALT))  | 
    ||
794  | 
    prec = ndig;  | 
    ||
795  | 
    }  | 
    ||
796  | 
    }  | 
    ||
797  | 
    			if (expchar) { | 
    ||
798  | 
    expsize = exponent(expstr, expt - 1, expchar);  | 
    ||
799  | 
    size = expsize + prec;  | 
    ||
800  | 
    if (prec > 1 || flags & ALT)  | 
    ||
801  | 
    ++size;  | 
    ||
802  | 
    			} else { | 
    ||
803  | 
    /* space for digits before decimal point */  | 
    ||
804  | 
    if (expt > 0)  | 
    ||
805  | 
    size = expt;  | 
    ||
806  | 
    else /* "0" */  | 
    ||
807  | 
    size = 1;  | 
    ||
808  | 
    /* space for decimal pt and following digits */  | 
    ||
809  | 
    if (prec || flags & ALT)  | 
    ||
810  | 
    size += prec + 1;  | 
    ||
811  | 
    lead = expt;  | 
    ||
812  | 
    }  | 
    ||
813  | 
    break;  | 
    ||
814  | 
    #endif /* FLOATING_POINT */  | 
    ||
815  | 
    #ifndef NO_PRINTF_PERCENT_N  | 
    ||
816  | 
    case 'n':  | 
    ||
817  | 
    if (flags & LLONGINT)  | 
    ||
818  | 
    *GETARG(long long *) = ret;  | 
    ||
819  | 
    else if (flags & LONGINT)  | 
    ||
820  | 
    *GETARG(long *) = ret;  | 
    ||
821  | 
    else if (flags & SHORTINT)  | 
    ||
822  | 
    *GETARG(short *) = ret;  | 
    ||
823  | 
    else if (flags & CHARINT)  | 
    ||
824  | 
    *GETARG(signed char *) = ret;  | 
    ||
825  | 
    else if (flags & PTRINT)  | 
    ||
826  | 
    *GETARG(ptrdiff_t *) = ret;  | 
    ||
827  | 
    else if (flags & SIZEINT)  | 
    ||
828  | 
    *GETARG(ssize_t *) = ret;  | 
    ||
829  | 
    else if (flags & MAXINT)  | 
    ||
830  | 
    *GETARG(intmax_t *) = ret;  | 
    ||
831  | 
    else  | 
    ||
832  | 
    *GETARG(int *) = ret;  | 
    ||
833  | 
    continue; /* no output */  | 
    ||
834  | 
    #endif /* NO_PRINTF_PERCENT_N */  | 
    ||
835  | 
    case 'O':  | 
    ||
836  | 
    flags |= LONGINT;  | 
    ||
837  | 
    /*FALLTHROUGH*/  | 
    ||
838  | 
    case 'o':  | 
    ||
839  | 
    _umax = UARG();  | 
    ||
840  | 
    base = OCT;  | 
    ||
841  | 
    goto nosign;  | 
    ||
842  | 
    case 'p':  | 
    ||
843  | 
    /*  | 
    ||
844  | 
    * ``The argument shall be a pointer to void. The  | 
    ||
845  | 
    * value of the pointer is converted to a sequence  | 
    ||
846  | 
    * of printable characters, in an implementation-  | 
    ||
847  | 
    * defined manner.''  | 
    ||
848  | 
    * -- ANSI X3J11  | 
    ||
849  | 
    */  | 
    ||
850  | 
    _umax = (u_long)GETARG(void *);  | 
    ||
851  | 
    base = HEX;  | 
    ||
852  | 
    xdigs = xdigs_lower;  | 
    ||
853  | 
    ox[1] = 'x';  | 
    ||
854  | 
    goto nosign;  | 
    ||
855  | 
    case 's':  | 
    ||
856  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
857  | 
    ✗✓ | 6  | 
    			if (flags & LONGINT) { | 
    
858  | 
    wchar_t *wcp;  | 
    ||
859  | 
    |||
860  | 
    free(convbuf);  | 
    ||
861  | 
    convbuf = NULL;  | 
    ||
862  | 
    				if ((wcp = GETARG(wchar_t *)) == NULL) { | 
    ||
863  | 
    struct syslog_data sdata = SYSLOG_DATA_INIT;  | 
    ||
864  | 
    int save_errno = errno;  | 
    ||
865  | 
    |||
866  | 
    syslog_r(LOG_CRIT | LOG_CONS, &sdata,  | 
    ||
867  | 
    "vfprintf %%ls NULL in \"%s\"", fmt0);  | 
    ||
868  | 
    errno = save_errno;  | 
    ||
869  | 
    |||
870  | 
    cp = "(null)";  | 
    ||
871  | 
    				} else { | 
    ||
872  | 
    convbuf = __wcsconv(wcp, prec);  | 
    ||
873  | 
    					if (convbuf == NULL) { | 
    ||
874  | 
    ret = -1;  | 
    ||
875  | 
    goto error;  | 
    ||
876  | 
    }  | 
    ||
877  | 
    cp = convbuf;  | 
    ||
878  | 
    }  | 
    ||
879  | 
    } else  | 
    ||
880  | 
    #endif /* PRINTF_WIDE_CHAR */  | 
    ||
881  | 
    ✗✓✓✗ ✗✓  | 
    24  | 
    			if ((cp = GETARG(char *)) == NULL) { | 
    
882  | 
    struct syslog_data sdata = SYSLOG_DATA_INIT;  | 
    ||
883  | 
    int save_errno = errno;  | 
    ||
884  | 
    |||
885  | 
    syslog_r(LOG_CRIT | LOG_CONS, &sdata,  | 
    ||
886  | 
    "vfprintf %%s NULL in \"%s\"", fmt0);  | 
    ||
887  | 
    errno = save_errno;  | 
    ||
888  | 
    |||
889  | 
    cp = "(null)";  | 
    ||
890  | 
    }  | 
    ||
891  | 
    ✗✓ | 18  | 
    len = prec >= 0 ? strnlen(cp, prec) : strlen(cp);  | 
    
892  | 
    ✗✓ | 6  | 
    if (len > INT_MAX)  | 
    
893  | 
    goto overflow;  | 
    ||
894  | 
    6  | 
    size = (int)len;  | 
    |
895  | 
    6  | 
    sign = '\0';  | 
    |
896  | 
    6  | 
    break;  | 
    |
897  | 
    case 'U':  | 
    ||
898  | 
    flags |= LONGINT;  | 
    ||
899  | 
    /*FALLTHROUGH*/  | 
    ||
900  | 
    case 'u':  | 
    ||
901  | 
    _umax = UARG();  | 
    ||
902  | 
    base = DEC;  | 
    ||
903  | 
    goto nosign;  | 
    ||
904  | 
    case 'X':  | 
    ||
905  | 
    xdigs = xdigs_upper;  | 
    ||
906  | 
    goto hex;  | 
    ||
907  | 
    case 'x':  | 
    ||
908  | 
    xdigs = xdigs_lower;  | 
    ||
909  | 
    hex: _umax = UARG();  | 
    ||
910  | 
    base = HEX;  | 
    ||
911  | 
    /* leading 0x/X only if non-zero */  | 
    ||
912  | 
    if (flags & ALT && _umax != 0)  | 
    ||
913  | 
    ox[1] = ch;  | 
    ||
914  | 
    |||
915  | 
    /* unsigned conversions */  | 
    ||
916  | 
    nosign: sign = '\0';  | 
    ||
917  | 
    /*  | 
    ||
918  | 
    * ``... diouXx conversions ... if a precision is  | 
    ||
919  | 
    * specified, the 0 flag will be ignored.''  | 
    ||
920  | 
    * -- ANSI X3J11  | 
    ||
921  | 
    */  | 
    ||
922  | 
    ✗✓ | 36  | 
    number: if ((dprec = prec) >= 0)  | 
    
923  | 
    flags &= ~ZEROPAD;  | 
    ||
924  | 
    |||
925  | 
    /*  | 
    ||
926  | 
    * ``The result of converting a zero value with an  | 
    ||
927  | 
    * explicit precision of zero is no characters.''  | 
    ||
928  | 
    * -- ANSI X3J11  | 
    ||
929  | 
    */  | 
    ||
930  | 
    36  | 
    cp = buf + BUF;  | 
    |
931  | 
    ✓✗ | 36  | 
    			if (_umax != 0 || prec != 0) { | 
    
932  | 
    /*  | 
    ||
933  | 
    * Unsigned mod is hard, and unsigned mod  | 
    ||
934  | 
    * by a constant is easier than that by  | 
    ||
935  | 
    * a variable; hence this switch.  | 
    ||
936  | 
    */  | 
    ||
937  | 
    ✗✓✗✗ | 
    36  | 
    				switch (base) { | 
    
938  | 
    case OCT:  | 
    ||
939  | 
    					do { | 
    ||
940  | 
    *--cp = to_char(_umax & 7);  | 
    ||
941  | 
    _umax >>= 3;  | 
    ||
942  | 
    } while (_umax);  | 
    ||
943  | 
    /* handle octal leading 0 */  | 
    ||
944  | 
    if (flags & ALT && *cp != '0')  | 
    ||
945  | 
    *--cp = '0';  | 
    ||
946  | 
    break;  | 
    ||
947  | 
    |||
948  | 
    case DEC:  | 
    ||
949  | 
    /* many numbers are 1 digit */  | 
    ||
950  | 
    ✓✓ | 192  | 
    					while (_umax >= 10) { | 
    
951  | 
    60  | 
    *--cp = to_char(_umax % 10);  | 
    |
952  | 
    60  | 
    _umax /= 10;  | 
    |
953  | 
    }  | 
    ||
954  | 
    36  | 
    *--cp = to_char(_umax);  | 
    |
955  | 
    36  | 
    break;  | 
    |
956  | 
    |||
957  | 
    case HEX:  | 
    ||
958  | 
    					do { | 
    ||
959  | 
    *--cp = xdigs[_umax & 15];  | 
    ||
960  | 
    _umax >>= 4;  | 
    ||
961  | 
    } while (_umax);  | 
    ||
962  | 
    break;  | 
    ||
963  | 
    |||
964  | 
    default:  | 
    ||
965  | 
    cp = "bug in vfprintf: bad base";  | 
    ||
966  | 
    size = strlen(cp);  | 
    ||
967  | 
    goto skipsize;  | 
    ||
968  | 
    }  | 
    ||
969  | 
    }  | 
    ||
970  | 
    36  | 
    size = buf + BUF - cp;  | 
    |
971  | 
    ✗✓ | 36  | 
    if (size > BUF) /* should never happen */  | 
    
972  | 
    abort();  | 
    ||
973  | 
    skipsize:  | 
    ||
974  | 
    break;  | 
    ||
975  | 
    default: /* "%?" prints ?, unless ? is NUL */  | 
    ||
976  | 
    ✗✓ | 6  | 
    if (ch == '\0')  | 
    
977  | 
    goto done;  | 
    ||
978  | 
    /* pretend it was %c with argument ch */  | 
    ||
979  | 
    6  | 
    cp = buf;  | 
    |
980  | 
    6  | 
    *cp = ch;  | 
    |
981  | 
    size = 1;  | 
    ||
982  | 
    6  | 
    sign = '\0';  | 
    |
983  | 
    6  | 
    break;  | 
    |
984  | 
    }  | 
    ||
985  | 
    |||
986  | 
    /*  | 
    ||
987  | 
    * All reasonable formats wind up here. At this point, `cp'  | 
    ||
988  | 
    * points to a string which (if not flags&LADJUST) should be  | 
    ||
989  | 
    * padded out to `width' places. If flags&ZEROPAD, it should  | 
    ||
990  | 
    * first be prefixed by any sign or other prefix; otherwise,  | 
    ||
991  | 
    * it should be blank padded before the prefix is emitted.  | 
    ||
992  | 
    * After any left-hand padding and prefixing, emit zeroes  | 
    ||
993  | 
    * required by a decimal %[diouxX] precision, then print the  | 
    ||
994  | 
    * string proper, then emit zeroes required by any leftover  | 
    ||
995  | 
    * floating precision; finally, if LADJUST, pad with blanks.  | 
    ||
996  | 
    *  | 
    ||
997  | 
    * Compute actual size, so we know how much to pad.  | 
    ||
998  | 
    * size excludes decimal prec; realsz includes it.  | 
    ||
999  | 
    */  | 
    ||
1000  | 
    816  | 
    realsz = dprec > size ? dprec : size;  | 
    |
1001  | 
    ✗✓ | 816  | 
    if (sign)  | 
    
1002  | 
    realsz++;  | 
    ||
1003  | 
    ✗✓ | 816  | 
    if (ox[1])  | 
    
1004  | 
    realsz+= 2;  | 
    ||
1005  | 
    |||
1006  | 
    /* right-adjusting blank padding */  | 
    ||
1007  | 
    ✓✗ | 816  | 
    if ((flags & (LADJUST|ZEROPAD)) == 0)  | 
    
1008  | 
    ✗✓✗✗ ✗✗✗✗ ✗✗✗✗  | 
    816  | 
    PAD(width - realsz, blanks);  | 
    
1009  | 
    |||
1010  | 
    /* prefix */  | 
    ||
1011  | 
    ✗✓ | 816  | 
    if (sign)  | 
    
1012  | 
    PRINT(&sign, 1);  | 
    ||
1013  | 
    ✗✓ | 816  | 
    		if (ox[1]) {	/* ox[1] is either x, X, or \0 */ | 
    
1014  | 
    ox[0] = '0';  | 
    ||
1015  | 
    PRINT(ox, 2);  | 
    ||
1016  | 
    }  | 
    ||
1017  | 
    |||
1018  | 
    /* right-adjusting zero padding */  | 
    ||
1019  | 
    ✗✓ | 816  | 
    if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)  | 
    
1020  | 
    PAD(width - realsz, zeroes);  | 
    ||
1021  | 
    |||
1022  | 
    /* leading zeroes from decimal precision */  | 
    ||
1023  | 
    ✗✓✗✗ ✗✗✗✗ ✗✗✗✗  | 
    816  | 
    PAD(dprec - size, zeroes);  | 
    
1024  | 
    |||
1025  | 
    /* the string or number proper */  | 
    ||
1026  | 
    #ifdef FLOATING_POINT  | 
    ||
1027  | 
    ✓✗ | 816  | 
    		if ((flags & FPT) == 0) { | 
    
1028  | 
    ✗✓✗✗ | 
    816  | 
    PRINT(cp, size);  | 
    
1029  | 
    		} else {	/* glue together f_p fragments */ | 
    ||
1030  | 
    if (decimal_point == NULL)  | 
    ||
1031  | 
    decimal_point = nl_langinfo(RADIXCHAR);  | 
    ||
1032  | 
    			if (!expchar) {	/* %[fF] or sufficiently short %[gG] */ | 
    ||
1033  | 
    				if (expt <= 0) { | 
    ||
1034  | 
    PRINT(zeroes, 1);  | 
    ||
1035  | 
    if (prec || flags & ALT)  | 
    ||
1036  | 
    PRINT(decimal_point, 1);  | 
    ||
1037  | 
    PAD(-expt, zeroes);  | 
    ||
1038  | 
    /* already handled initial 0's */  | 
    ||
1039  | 
    prec += expt;  | 
    ||
1040  | 
     				} else { | 
    ||
1041  | 
    PRINTANDPAD(cp, dtoaend, lead, zeroes);  | 
    ||
1042  | 
    cp += lead;  | 
    ||
1043  | 
    if (prec || flags & ALT)  | 
    ||
1044  | 
    PRINT(decimal_point, 1);  | 
    ||
1045  | 
    }  | 
    ||
1046  | 
    PRINTANDPAD(cp, dtoaend, prec, zeroes);  | 
    ||
1047  | 
    			} else {	/* %[eE] or sufficiently long %[gG] */ | 
    ||
1048  | 
    				if (prec > 1 || flags & ALT) { | 
    ||
1049  | 
    buf[0] = *cp++;  | 
    ||
1050  | 
    buf[1] = *decimal_point;  | 
    ||
1051  | 
    PRINT(buf, 2);  | 
    ||
1052  | 
    PRINT(cp, ndig-1);  | 
    ||
1053  | 
    PAD(prec - ndig, zeroes);  | 
    ||
1054  | 
    				} else { /* XeYYY */ | 
    ||
1055  | 
    PRINT(cp, 1);  | 
    ||
1056  | 
    }  | 
    ||
1057  | 
    PRINT(expstr, expsize);  | 
    ||
1058  | 
    }  | 
    ||
1059  | 
    }  | 
    ||
1060  | 
    #else  | 
    ||
1061  | 
    PRINT(cp, size);  | 
    ||
1062  | 
    #endif  | 
    ||
1063  | 
    /* left-adjusting padding (always blank) */  | 
    ||
1064  | 
    ✗✓ | 816  | 
    if (flags & LADJUST)  | 
    
1065  | 
    PAD(width - realsz, blanks);  | 
    ||
1066  | 
    |||
1067  | 
    /* finally, adjust ret */  | 
    ||
1068  | 
    ✓✗ | 816  | 
    if (width < realsz)  | 
    
1069  | 
    816  | 
    width = realsz;  | 
    |
1070  | 
    ✗✓ | 816  | 
    if (width > INT_MAX - ret)  | 
    
1071  | 
    goto overflow;  | 
    ||
1072  | 
    816  | 
    ret += width;  | 
    |
1073  | 
    |||
1074  | 
    ✓✗✗✓ | 
    2448  | 
    FLUSH(); /* copy out the I/O vectors */  | 
    
1075  | 
    ✓✓✓✓ ✗✓  | 
    816  | 
    }  | 
    
1076  | 
    done:  | 
    ||
1077  | 
    ✓✗✓✗ | 
    2412  | 
    FLUSH();  | 
    
1078  | 
    error:  | 
    ||
1079  | 
    804  | 
    va_end(orgap);  | 
    |
1080  | 
    ✗✓ | 804  | 
    if (__sferror(fp))  | 
    
1081  | 
    ret = -1;  | 
    ||
1082  | 
    goto finish;  | 
    ||
1083  | 
    |||
1084  | 
    overflow:  | 
    ||
1085  | 
    errno = EOVERFLOW;  | 
    ||
1086  | 
    ret = -1;  | 
    ||
1087  | 
    |||
1088  | 
    finish:  | 
    ||
1089  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
1090  | 
    804  | 
    free(convbuf);  | 
    |
1091  | 
    #endif  | 
    ||
1092  | 
    #ifdef FLOATING_POINT  | 
    ||
1093  | 
    ✗✓ | 804  | 
    if (dtoaresult)  | 
    
1094  | 
    __freedtoa(dtoaresult);  | 
    ||
1095  | 
    #endif  | 
    ||
1096  | 
    ✗✓✗✗ | 
    804  | 
    	if (argtable != NULL && argtable != statargtable) { | 
    
1097  | 
    munmap(argtable, argtablesiz);  | 
    ||
1098  | 
    argtable = NULL;  | 
    ||
1099  | 
    }  | 
    ||
1100  | 
    804  | 
    return (ret);  | 
    |
1101  | 
    822  | 
    }  | 
    |
1102  | 
    |||
1103  | 
    /*  | 
    ||
1104  | 
    * Type ids for argument type table.  | 
    ||
1105  | 
    */  | 
    ||
1106  | 
    #define T_UNUSED 0  | 
    ||
1107  | 
    #define T_SHORT 1  | 
    ||
1108  | 
    #define T_U_SHORT 2  | 
    ||
1109  | 
    #define TP_SHORT 3  | 
    ||
1110  | 
    #define T_INT 4  | 
    ||
1111  | 
    #define T_U_INT 5  | 
    ||
1112  | 
    #define TP_INT 6  | 
    ||
1113  | 
    #define T_LONG 7  | 
    ||
1114  | 
    #define T_U_LONG 8  | 
    ||
1115  | 
    #define TP_LONG 9  | 
    ||
1116  | 
    #define T_LLONG 10  | 
    ||
1117  | 
    #define T_U_LLONG 11  | 
    ||
1118  | 
    #define TP_LLONG 12  | 
    ||
1119  | 
    #define T_DOUBLE 13  | 
    ||
1120  | 
    #define T_LONG_DOUBLE 14  | 
    ||
1121  | 
    #define TP_CHAR 15  | 
    ||
1122  | 
    #define TP_VOID 16  | 
    ||
1123  | 
    #define T_PTRINT 17  | 
    ||
1124  | 
    #define TP_PTRINT 18  | 
    ||
1125  | 
    #define T_SIZEINT 19  | 
    ||
1126  | 
    #define T_SSIZEINT 20  | 
    ||
1127  | 
    #define TP_SSIZEINT 21  | 
    ||
1128  | 
    #define T_MAXINT 22  | 
    ||
1129  | 
    #define T_MAXUINT 23  | 
    ||
1130  | 
    #define TP_MAXINT 24  | 
    ||
1131  | 
    #define T_CHAR 25  | 
    ||
1132  | 
    #define T_U_CHAR 26  | 
    ||
1133  | 
    #define T_WINT 27  | 
    ||
1134  | 
    #define TP_WCHAR 28  | 
    ||
1135  | 
    |||
1136  | 
    /*  | 
    ||
1137  | 
    * Find all arguments when a positional parameter is encountered. Returns a  | 
    ||
1138  | 
    * table, indexed by argument number, of pointers to each arguments. The  | 
    ||
1139  | 
    * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.  | 
    ||
1140  | 
    * It will be replaced with a mmap-ed one if it overflows (malloc cannot be  | 
    ||
1141  | 
    * used since we are attempting to make snprintf thread safe, and alloca is  | 
    ||
1142  | 
    * problematic since we have nested functions..)  | 
    ||
1143  | 
    */  | 
    ||
1144  | 
    static int  | 
    ||
1145  | 
    __find_arguments(const char *fmt0, va_list ap, union arg **argtable,  | 
    ||
1146  | 
    size_t *argtablesiz)  | 
    ||
1147  | 
    { | 
    ||
1148  | 
    char *fmt; /* format string */  | 
    ||
1149  | 
    int ch; /* character from fmt */  | 
    ||
1150  | 
    int n, n2; /* handy integer (short term usage) */  | 
    ||
1151  | 
    char *cp; /* handy char pointer (short term usage) */  | 
    ||
1152  | 
    int flags; /* flags as above */  | 
    ||
1153  | 
    unsigned char *typetable; /* table of types */  | 
    ||
1154  | 
    unsigned char stattypetable[STATIC_ARG_TBL_SIZE];  | 
    ||
1155  | 
    int tablesize; /* current size of type table */  | 
    ||
1156  | 
    int tablemax; /* largest used index in table */  | 
    ||
1157  | 
    int nextarg; /* 1-based argument index */  | 
    ||
1158  | 
    int ret = 0; /* return value */  | 
    ||
1159  | 
    wchar_t wc;  | 
    ||
1160  | 
    mbstate_t ps;  | 
    ||
1161  | 
    |||
1162  | 
    /*  | 
    ||
1163  | 
    * Add an argument type to the table, expanding if necessary.  | 
    ||
1164  | 
    */  | 
    ||
1165  | 
    #define ADDTYPE(type) \  | 
    ||
1166  | 
    ((nextarg >= tablesize) ? \  | 
    ||
1167  | 
    __grow_type_table(&typetable, &tablesize) : 0, \  | 
    ||
1168  | 
    (nextarg > tablemax) ? tablemax = nextarg : 0, \  | 
    ||
1169  | 
    typetable[nextarg++] = type)  | 
    ||
1170  | 
    |||
1171  | 
    #define ADDSARG() \  | 
    ||
1172  | 
    ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \  | 
    ||
1173  | 
    ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \  | 
    ||
1174  | 
    ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \  | 
    ||
1175  | 
    ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \  | 
    ||
1176  | 
    ((flags&LONGINT) ? ADDTYPE(T_LONG) : \  | 
    ||
1177  | 
    ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \  | 
    ||
1178  | 
    ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))  | 
    ||
1179  | 
    |||
1180  | 
    #define ADDUARG() \  | 
    ||
1181  | 
    ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \  | 
    ||
1182  | 
    ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \  | 
    ||
1183  | 
    ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \  | 
    ||
1184  | 
    ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \  | 
    ||
1185  | 
    ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \  | 
    ||
1186  | 
    ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \  | 
    ||
1187  | 
    ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))  | 
    ||
1188  | 
    |||
1189  | 
    /*  | 
    ||
1190  | 
    * Add * arguments to the type array.  | 
    ||
1191  | 
    */  | 
    ||
1192  | 
    #define ADDASTER() \  | 
    ||
1193  | 
    n2 = 0; \  | 
    ||
1194  | 
    cp = fmt; \  | 
    ||
1195  | 
    	while (is_digit(*cp)) { \ | 
    ||
1196  | 
    APPEND_DIGIT(n2, *cp); \  | 
    ||
1197  | 
    cp++; \  | 
    ||
1198  | 
    } \  | 
    ||
1199  | 
    	if (*cp == '$') { \ | 
    ||
1200  | 
    int hold = nextarg; \  | 
    ||
1201  | 
    nextarg = n2; \  | 
    ||
1202  | 
    ADDTYPE(T_INT); \  | 
    ||
1203  | 
    nextarg = hold; \  | 
    ||
1204  | 
    fmt = ++cp; \  | 
    ||
1205  | 
    	} else { \ | 
    ||
1206  | 
    ADDTYPE(T_INT); \  | 
    ||
1207  | 
    }  | 
    ||
1208  | 
    fmt = (char *)fmt0;  | 
    ||
1209  | 
    typetable = stattypetable;  | 
    ||
1210  | 
    tablesize = STATIC_ARG_TBL_SIZE;  | 
    ||
1211  | 
    tablemax = 0;  | 
    ||
1212  | 
    nextarg = 1;  | 
    ||
1213  | 
    memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);  | 
    ||
1214  | 
    memset(&ps, 0, sizeof(ps));  | 
    ||
1215  | 
    |||
1216  | 
    /*  | 
    ||
1217  | 
    * Scan the format for conversions (`%' character).  | 
    ||
1218  | 
    */  | 
    ||
1219  | 
    	for (;;) { | 
    ||
1220  | 
    size_t len;  | 
    ||
1221  | 
    |||
1222  | 
    cp = fmt;  | 
    ||
1223  | 
    		while ((len = mbrtowc(&wc, fmt, MB_CUR_MAX, &ps)) != 0) { | 
    ||
1224  | 
    if (len == (size_t)-1 || len == (size_t)-2)  | 
    ||
1225  | 
    return (-1);  | 
    ||
1226  | 
    fmt += len;  | 
    ||
1227  | 
    			if (wc == '%') { | 
    ||
1228  | 
    fmt--;  | 
    ||
1229  | 
    break;  | 
    ||
1230  | 
    }  | 
    ||
1231  | 
    }  | 
    ||
1232  | 
    if (len == 0)  | 
    ||
1233  | 
    goto done;  | 
    ||
1234  | 
    fmt++; /* skip over '%' */  | 
    ||
1235  | 
    |||
1236  | 
    flags = 0;  | 
    ||
1237  | 
    |||
1238  | 
    rflag: ch = *fmt++;  | 
    ||
1239  | 
    reswitch:	switch (ch) { | 
    ||
1240  | 
    case ' ':  | 
    ||
1241  | 
    case '#':  | 
    ||
1242  | 
    case '\'':  | 
    ||
1243  | 
    goto rflag;  | 
    ||
1244  | 
    case '*':  | 
    ||
1245  | 
    ADDASTER();  | 
    ||
1246  | 
    goto rflag;  | 
    ||
1247  | 
    case '-':  | 
    ||
1248  | 
    case '+':  | 
    ||
1249  | 
    goto rflag;  | 
    ||
1250  | 
    case '.':  | 
    ||
1251  | 
    			if ((ch = *fmt++) == '*') { | 
    ||
1252  | 
    ADDASTER();  | 
    ||
1253  | 
    goto rflag;  | 
    ||
1254  | 
    }  | 
    ||
1255  | 
    			while (is_digit(ch)) { | 
    ||
1256  | 
    ch = *fmt++;  | 
    ||
1257  | 
    }  | 
    ||
1258  | 
    goto reswitch;  | 
    ||
1259  | 
    case '0':  | 
    ||
1260  | 
    goto rflag;  | 
    ||
1261  | 
    case '1': case '2': case '3': case '4':  | 
    ||
1262  | 
    case '5': case '6': case '7': case '8': case '9':  | 
    ||
1263  | 
    n = 0;  | 
    ||
1264  | 
    			do { | 
    ||
1265  | 
    APPEND_DIGIT(n ,ch);  | 
    ||
1266  | 
    ch = *fmt++;  | 
    ||
1267  | 
    } while (is_digit(ch));  | 
    ||
1268  | 
    			if (ch == '$') { | 
    ||
1269  | 
    nextarg = n;  | 
    ||
1270  | 
    goto rflag;  | 
    ||
1271  | 
    }  | 
    ||
1272  | 
    goto reswitch;  | 
    ||
1273  | 
    #ifdef FLOATING_POINT  | 
    ||
1274  | 
    case 'L':  | 
    ||
1275  | 
    flags |= LONGDBL;  | 
    ||
1276  | 
    goto rflag;  | 
    ||
1277  | 
    #endif  | 
    ||
1278  | 
    case 'h':  | 
    ||
1279  | 
    			if (*fmt == 'h') { | 
    ||
1280  | 
    fmt++;  | 
    ||
1281  | 
    flags |= CHARINT;  | 
    ||
1282  | 
    			} else { | 
    ||
1283  | 
    flags |= SHORTINT;  | 
    ||
1284  | 
    }  | 
    ||
1285  | 
    goto rflag;  | 
    ||
1286  | 
    case 'j':  | 
    ||
1287  | 
    flags |= MAXINT;  | 
    ||
1288  | 
    goto rflag;  | 
    ||
1289  | 
    case 'l':  | 
    ||
1290  | 
    			if (*fmt == 'l') { | 
    ||
1291  | 
    fmt++;  | 
    ||
1292  | 
    flags |= LLONGINT;  | 
    ||
1293  | 
    			} else { | 
    ||
1294  | 
    flags |= LONGINT;  | 
    ||
1295  | 
    }  | 
    ||
1296  | 
    goto rflag;  | 
    ||
1297  | 
    case 'q':  | 
    ||
1298  | 
    flags |= LLONGINT;  | 
    ||
1299  | 
    goto rflag;  | 
    ||
1300  | 
    case 't':  | 
    ||
1301  | 
    flags |= PTRINT;  | 
    ||
1302  | 
    goto rflag;  | 
    ||
1303  | 
    case 'z':  | 
    ||
1304  | 
    flags |= SIZEINT;  | 
    ||
1305  | 
    goto rflag;  | 
    ||
1306  | 
    case 'c':  | 
    ||
1307  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
1308  | 
    if (flags & LONGINT)  | 
    ||
1309  | 
    ADDTYPE(T_WINT);  | 
    ||
1310  | 
    else  | 
    ||
1311  | 
    #endif  | 
    ||
1312  | 
    ADDTYPE(T_INT);  | 
    ||
1313  | 
    break;  | 
    ||
1314  | 
    case 'D':  | 
    ||
1315  | 
    flags |= LONGINT;  | 
    ||
1316  | 
    /*FALLTHROUGH*/  | 
    ||
1317  | 
    case 'd':  | 
    ||
1318  | 
    case 'i':  | 
    ||
1319  | 
    ADDSARG();  | 
    ||
1320  | 
    break;  | 
    ||
1321  | 
    #ifdef FLOATING_POINT  | 
    ||
1322  | 
    case 'a':  | 
    ||
1323  | 
    case 'A':  | 
    ||
1324  | 
    case 'e':  | 
    ||
1325  | 
    case 'E':  | 
    ||
1326  | 
    case 'f':  | 
    ||
1327  | 
    case 'F':  | 
    ||
1328  | 
    case 'g':  | 
    ||
1329  | 
    case 'G':  | 
    ||
1330  | 
    if (flags & LONGDBL)  | 
    ||
1331  | 
    ADDTYPE(T_LONG_DOUBLE);  | 
    ||
1332  | 
    else  | 
    ||
1333  | 
    ADDTYPE(T_DOUBLE);  | 
    ||
1334  | 
    break;  | 
    ||
1335  | 
    #endif /* FLOATING_POINT */  | 
    ||
1336  | 
    #ifndef NO_PRINTF_PERCENT_N  | 
    ||
1337  | 
    case 'n':  | 
    ||
1338  | 
    if (flags & LLONGINT)  | 
    ||
1339  | 
    ADDTYPE(TP_LLONG);  | 
    ||
1340  | 
    else if (flags & LONGINT)  | 
    ||
1341  | 
    ADDTYPE(TP_LONG);  | 
    ||
1342  | 
    else if (flags & SHORTINT)  | 
    ||
1343  | 
    ADDTYPE(TP_SHORT);  | 
    ||
1344  | 
    else if (flags & PTRINT)  | 
    ||
1345  | 
    ADDTYPE(TP_PTRINT);  | 
    ||
1346  | 
    else if (flags & SIZEINT)  | 
    ||
1347  | 
    ADDTYPE(TP_SSIZEINT);  | 
    ||
1348  | 
    else if (flags & MAXINT)  | 
    ||
1349  | 
    ADDTYPE(TP_MAXINT);  | 
    ||
1350  | 
    else  | 
    ||
1351  | 
    ADDTYPE(TP_INT);  | 
    ||
1352  | 
    continue; /* no output */  | 
    ||
1353  | 
    #endif /* NO_PRINTF_PERCENT_N */  | 
    ||
1354  | 
    case 'O':  | 
    ||
1355  | 
    flags |= LONGINT;  | 
    ||
1356  | 
    /*FALLTHROUGH*/  | 
    ||
1357  | 
    case 'o':  | 
    ||
1358  | 
    ADDUARG();  | 
    ||
1359  | 
    break;  | 
    ||
1360  | 
    case 'p':  | 
    ||
1361  | 
    ADDTYPE(TP_VOID);  | 
    ||
1362  | 
    break;  | 
    ||
1363  | 
    case 's':  | 
    ||
1364  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
1365  | 
    if (flags & LONGINT)  | 
    ||
1366  | 
    ADDTYPE(TP_WCHAR);  | 
    ||
1367  | 
    else  | 
    ||
1368  | 
    #endif  | 
    ||
1369  | 
    ADDTYPE(TP_CHAR);  | 
    ||
1370  | 
    break;  | 
    ||
1371  | 
    case 'U':  | 
    ||
1372  | 
    flags |= LONGINT;  | 
    ||
1373  | 
    /*FALLTHROUGH*/  | 
    ||
1374  | 
    case 'u':  | 
    ||
1375  | 
    case 'X':  | 
    ||
1376  | 
    case 'x':  | 
    ||
1377  | 
    ADDUARG();  | 
    ||
1378  | 
    break;  | 
    ||
1379  | 
    default: /* "%?" prints ?, unless ? is NUL */  | 
    ||
1380  | 
    if (ch == '\0')  | 
    ||
1381  | 
    goto done;  | 
    ||
1382  | 
    break;  | 
    ||
1383  | 
    }  | 
    ||
1384  | 
    }  | 
    ||
1385  | 
    done:  | 
    ||
1386  | 
    /*  | 
    ||
1387  | 
    * Build the argument table.  | 
    ||
1388  | 
    */  | 
    ||
1389  | 
    	if (tablemax >= STATIC_ARG_TBL_SIZE) { | 
    ||
1390  | 
    *argtablesiz = sizeof(union arg) * (tablemax + 1);  | 
    ||
1391  | 
    *argtable = mmap(NULL, *argtablesiz,  | 
    ||
1392  | 
    PROT_WRITE|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);  | 
    ||
1393  | 
    if (*argtable == MAP_FAILED)  | 
    ||
1394  | 
    return (-1);  | 
    ||
1395  | 
    }  | 
    ||
1396  | 
    |||
1397  | 
    	for (n = 1; n <= tablemax; n++) { | 
    ||
1398  | 
    		switch (typetable[n]) { | 
    ||
1399  | 
    case T_UNUSED:  | 
    ||
1400  | 
    case T_CHAR:  | 
    ||
1401  | 
    case T_U_CHAR:  | 
    ||
1402  | 
    case T_SHORT:  | 
    ||
1403  | 
    case T_U_SHORT:  | 
    ||
1404  | 
    case T_INT:  | 
    ||
1405  | 
    (*argtable)[n].intarg = va_arg(ap, int);  | 
    ||
1406  | 
    break;  | 
    ||
1407  | 
    case TP_SHORT:  | 
    ||
1408  | 
    (*argtable)[n].pshortarg = va_arg(ap, short *);  | 
    ||
1409  | 
    break;  | 
    ||
1410  | 
    case T_U_INT:  | 
    ||
1411  | 
    (*argtable)[n].uintarg = va_arg(ap, unsigned int);  | 
    ||
1412  | 
    break;  | 
    ||
1413  | 
    case TP_INT:  | 
    ||
1414  | 
    (*argtable)[n].pintarg = va_arg(ap, int *);  | 
    ||
1415  | 
    break;  | 
    ||
1416  | 
    case T_LONG:  | 
    ||
1417  | 
    (*argtable)[n].longarg = va_arg(ap, long);  | 
    ||
1418  | 
    break;  | 
    ||
1419  | 
    case T_U_LONG:  | 
    ||
1420  | 
    (*argtable)[n].ulongarg = va_arg(ap, unsigned long);  | 
    ||
1421  | 
    break;  | 
    ||
1422  | 
    case TP_LONG:  | 
    ||
1423  | 
    (*argtable)[n].plongarg = va_arg(ap, long *);  | 
    ||
1424  | 
    break;  | 
    ||
1425  | 
    case T_LLONG:  | 
    ||
1426  | 
    (*argtable)[n].longlongarg = va_arg(ap, long long);  | 
    ||
1427  | 
    break;  | 
    ||
1428  | 
    case T_U_LLONG:  | 
    ||
1429  | 
    (*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long);  | 
    ||
1430  | 
    break;  | 
    ||
1431  | 
    case TP_LLONG:  | 
    ||
1432  | 
    (*argtable)[n].plonglongarg = va_arg(ap, long long *);  | 
    ||
1433  | 
    break;  | 
    ||
1434  | 
    #ifdef FLOATING_POINT  | 
    ||
1435  | 
    case T_DOUBLE:  | 
    ||
1436  | 
    (*argtable)[n].doublearg = va_arg(ap, double);  | 
    ||
1437  | 
    break;  | 
    ||
1438  | 
    case T_LONG_DOUBLE:  | 
    ||
1439  | 
    (*argtable)[n].longdoublearg = va_arg(ap, long double);  | 
    ||
1440  | 
    break;  | 
    ||
1441  | 
    #endif  | 
    ||
1442  | 
    case TP_CHAR:  | 
    ||
1443  | 
    (*argtable)[n].pchararg = va_arg(ap, char *);  | 
    ||
1444  | 
    break;  | 
    ||
1445  | 
    case TP_VOID:  | 
    ||
1446  | 
    (*argtable)[n].pvoidarg = va_arg(ap, void *);  | 
    ||
1447  | 
    break;  | 
    ||
1448  | 
    case T_PTRINT:  | 
    ||
1449  | 
    (*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t);  | 
    ||
1450  | 
    break;  | 
    ||
1451  | 
    case TP_PTRINT:  | 
    ||
1452  | 
    (*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *);  | 
    ||
1453  | 
    break;  | 
    ||
1454  | 
    case T_SIZEINT:  | 
    ||
1455  | 
    (*argtable)[n].sizearg = va_arg(ap, size_t);  | 
    ||
1456  | 
    break;  | 
    ||
1457  | 
    case T_SSIZEINT:  | 
    ||
1458  | 
    (*argtable)[n].ssizearg = va_arg(ap, ssize_t);  | 
    ||
1459  | 
    break;  | 
    ||
1460  | 
    case TP_SSIZEINT:  | 
    ||
1461  | 
    (*argtable)[n].pssizearg = va_arg(ap, ssize_t *);  | 
    ||
1462  | 
    break;  | 
    ||
1463  | 
    case T_MAXINT:  | 
    ||
1464  | 
    (*argtable)[n].intmaxarg = va_arg(ap, intmax_t);  | 
    ||
1465  | 
    break;  | 
    ||
1466  | 
    case T_MAXUINT:  | 
    ||
1467  | 
    (*argtable)[n].uintmaxarg = va_arg(ap, uintmax_t);  | 
    ||
1468  | 
    break;  | 
    ||
1469  | 
    case TP_MAXINT:  | 
    ||
1470  | 
    (*argtable)[n].pintmaxarg = va_arg(ap, intmax_t *);  | 
    ||
1471  | 
    break;  | 
    ||
1472  | 
    #ifdef PRINTF_WIDE_CHAR  | 
    ||
1473  | 
    case T_WINT:  | 
    ||
1474  | 
    (*argtable)[n].wintarg = va_arg(ap, wint_t);  | 
    ||
1475  | 
    break;  | 
    ||
1476  | 
    case TP_WCHAR:  | 
    ||
1477  | 
    (*argtable)[n].pwchararg = va_arg(ap, wchar_t *);  | 
    ||
1478  | 
    break;  | 
    ||
1479  | 
    #endif  | 
    ||
1480  | 
    }  | 
    ||
1481  | 
    }  | 
    ||
1482  | 
    goto finish;  | 
    ||
1483  | 
    |||
1484  | 
    overflow:  | 
    ||
1485  | 
    errno = EOVERFLOW;  | 
    ||
1486  | 
    ret = -1;  | 
    ||
1487  | 
    |||
1488  | 
    finish:  | 
    ||
1489  | 
    	if (typetable != NULL && typetable != stattypetable) { | 
    ||
1490  | 
    munmap(typetable, *argtablesiz);  | 
    ||
1491  | 
    typetable = NULL;  | 
    ||
1492  | 
    }  | 
    ||
1493  | 
    return (ret);  | 
    ||
1494  | 
    }  | 
    ||
1495  | 
    |||
1496  | 
    /*  | 
    ||
1497  | 
    * Increase the size of the type table.  | 
    ||
1498  | 
    */  | 
    ||
1499  | 
    static int  | 
    ||
1500  | 
    __grow_type_table(unsigned char **typetable, int *tablesize)  | 
    ||
1501  | 
    { | 
    ||
1502  | 
    unsigned char *oldtable = *typetable;  | 
    ||
1503  | 
    int newsize = *tablesize * 2;  | 
    ||
1504  | 
    |||
1505  | 
    if (newsize < getpagesize())  | 
    ||
1506  | 
    newsize = getpagesize();  | 
    ||
1507  | 
    |||
1508  | 
    	if (*tablesize == STATIC_ARG_TBL_SIZE) { | 
    ||
1509  | 
    *typetable = mmap(NULL, newsize, PROT_WRITE|PROT_READ,  | 
    ||
1510  | 
    MAP_ANON|MAP_PRIVATE, -1, 0);  | 
    ||
1511  | 
    if (*typetable == MAP_FAILED)  | 
    ||
1512  | 
    return (-1);  | 
    ||
1513  | 
    bcopy(oldtable, *typetable, *tablesize);  | 
    ||
1514  | 
    	} else { | 
    ||
1515  | 
    unsigned char *new = mmap(NULL, newsize, PROT_WRITE|PROT_READ,  | 
    ||
1516  | 
    MAP_ANON|MAP_PRIVATE, -1, 0);  | 
    ||
1517  | 
    if (new == MAP_FAILED)  | 
    ||
1518  | 
    return (-1);  | 
    ||
1519  | 
    memmove(new, *typetable, *tablesize);  | 
    ||
1520  | 
    munmap(*typetable, *tablesize);  | 
    ||
1521  | 
    *typetable = new;  | 
    ||
1522  | 
    }  | 
    ||
1523  | 
    memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));  | 
    ||
1524  | 
    |||
1525  | 
    *tablesize = newsize;  | 
    ||
1526  | 
    return (0);  | 
    ||
1527  | 
    }  | 
    ||
1528  | 
    |||
1529  | 
    |||
1530  | 
    #ifdef FLOATING_POINT  | 
    ||
1531  | 
    static int  | 
    ||
1532  | 
    exponent(char *p0, int exp, int fmtch)  | 
    ||
1533  | 
    { | 
    ||
1534  | 
    char *p, *t;  | 
    ||
1535  | 
    char expbuf[MAXEXPDIG];  | 
    ||
1536  | 
    |||
1537  | 
    p = p0;  | 
    ||
1538  | 
    *p++ = fmtch;  | 
    ||
1539  | 
    	if (exp < 0) { | 
    ||
1540  | 
    exp = -exp;  | 
    ||
1541  | 
    *p++ = '-';  | 
    ||
1542  | 
    } else  | 
    ||
1543  | 
    *p++ = '+';  | 
    ||
1544  | 
    t = expbuf + MAXEXPDIG;  | 
    ||
1545  | 
    	if (exp > 9) { | 
    ||
1546  | 
    		do { | 
    ||
1547  | 
    *--t = to_char(exp % 10);  | 
    ||
1548  | 
    } while ((exp /= 10) > 9);  | 
    ||
1549  | 
    *--t = to_char(exp);  | 
    ||
1550  | 
    for (; t < expbuf + MAXEXPDIG; *p++ = *t++)  | 
    ||
1551  | 
    /* nothing */;  | 
    ||
1552  | 
    	} else { | 
    ||
1553  | 
    /*  | 
    ||
1554  | 
    * Exponents for decimal floating point conversions  | 
    ||
1555  | 
    * (%[eEgG]) must be at least two characters long,  | 
    ||
1556  | 
    * whereas exponents for hexadecimal conversions can  | 
    ||
1557  | 
    * be only one character long.  | 
    ||
1558  | 
    */  | 
    ||
1559  | 
    if (fmtch == 'e' || fmtch == 'E')  | 
    ||
1560  | 
    *p++ = '0';  | 
    ||
1561  | 
    *p++ = to_char(exp);  | 
    ||
1562  | 
    }  | 
    ||
1563  | 
    return (p - p0);  | 
    ||
1564  | 
    }  | 
    ||
1565  | 
    #endif /* FLOATING_POINT */  | 
    
| Generated by: GCOVR (Version 3.3) |