1 | /*-␊ |
2 | * Copyright (c) 1990, 1993␊ |
3 | *␉The Regents of the University of California. All rights reserved.␊ |
4 | *␊ |
5 | * This code is derived from software contributed to Berkeley by␊ |
6 | * Chris Torek.␊ |
7 | *␊ |
8 | * Redistribution and use in source and binary forms, with or without␊ |
9 | * modification, are permitted provided that the following conditions␊ |
10 | * are met:␊ |
11 | * 1. Redistributions of source code must retain the above copyright␊ |
12 | * notice, this list of conditions and the following disclaimer.␊ |
13 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
14 | * notice, this list of conditions and the following disclaimer in the␊ |
15 | * documentation and/or other materials provided with the distribution.␊ |
16 | * 3. All advertising materials mentioning features or use of this software␊ |
17 | * must display the following acknowledgement:␊ |
18 | *␉This product includes software developed by the University of␊ |
19 | *␉California, Berkeley and its contributors.␊ |
20 | * 4. Neither the name of the University nor the names of its contributors␊ |
21 | * may be used to endorse or promote products derived from this software␊ |
22 | * without specific prior written permission.␊ |
23 | *␊ |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND␊ |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE␊ |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE␊ |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE␊ |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL␊ |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS␊ |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)␊ |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT␊ |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY␊ |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF␊ |
34 | * SUCH DAMAGE.␊ |
35 | */␊ |
36 | ␊ |
37 | #if defined(LIBC_SCCS) && !defined(lint)␊ |
38 | #if 0␊ |
39 | static char sccsid[] = "@(#)vfprintf.c␉8.1 (Berkeley) 6/4/93";␊ |
40 | #endif␊ |
41 | static const char rcsid[] =␊ |
42 | "$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.22.2.6 2012/11/17 07:23:37 svnexp Exp $";␊ |
43 | #endif /* LIBC_SCCS and not lint */␊ |
44 | ␊ |
45 | /*␊ |
46 | * Actual printf innards.␊ |
47 | *␊ |
48 | * This code is large and complicated...␊ |
49 | */␊ |
50 | ␊ |
51 | #include <sys/types.h>␊ |
52 | ␊ |
53 | #include <limits.h>␊ |
54 | #include "stdio.h"␊ |
55 | #include "libsaio.h"␊ |
56 | ␊ |
57 | #if __STDC__␊ |
58 | #include <stdarg.h>␊ |
59 | #else␊ |
60 | #include <varargs.h>␊ |
61 | #endif␊ |
62 | ␊ |
63 | //#include "libc_private.h"␊ |
64 | #include "local.h"␊ |
65 | #include "fvwrite.h"␊ |
66 | #include "printflocal.h"␊ |
67 | ␊ |
68 | static int␉__sprint __P((FILE *, struct __suio *));␊ |
69 | static int␉__sbprintf __P((FILE *, const char *, va_list));␊ |
70 | static char *␉__ultoa __P((u_long, char *, int, int, char *));␊ |
71 | static char *␉__uqtoa __P((u_quad_t, char *, int, int, char *));␊ |
72 | ␊ |
73 | /*␊ |
74 | * Flush out all the vectors defined by the given uio,␊ |
75 | * then reset it so that it can be reused.␊ |
76 | */␊ |
77 | static int␊ |
78 | __sprint(FILE *fp, struct __suio *uio)␊ |
79 | {␊ |
80 | ␉int err;␊ |
81 | ␊ |
82 | ␉if (uio->uio_resid == 0) {␊ |
83 | ␉␉uio->uio_iovcnt = 0;␊ |
84 | ␉␉return (0);␊ |
85 | ␉}␊ |
86 | ␉err = __sfvwrite(fp, uio);␊ |
87 | ␉uio->uio_resid = 0;␊ |
88 | ␉uio->uio_iovcnt = 0;␊ |
89 | ␉return (err);␊ |
90 | }␊ |
91 | ␊ |
92 | /*␊ |
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.␊ |
96 | */␊ |
97 | static int␊ |
98 | __sbprintf(FILE *fp, const char *fmt, va_list ap)␊ |
99 | {␊ |
100 | ␉int ret;␊ |
101 | ␉FILE fake;␊ |
102 | ␉unsigned char buf[BUFSIZ];␊ |
103 | ␊ |
104 | ␉/* copy the important variables */␊ |
105 | ␉fake._flags = fp->_flags & ~__SNBF;␊ |
106 | ␉fake._file = fp->_file;␊ |
107 | ␉fake._cookie = fp->_cookie;␊ |
108 | ␉fake._write = fp->_write;␊ |
109 | ␊ |
110 | ␉/* set up the buffer */␊ |
111 | ␉fake._bf._base = fake._p = buf;␊ |
112 | ␉fake._bf._size = fake._w = sizeof(buf);␊ |
113 | ␉fake._lbfsize = 0;␉/* not actually used, but Just In Case */␊ |
114 | ␊ |
115 | ␉/* do the work, then copy any error status */␊ |
116 | ␉ret = vfprintf(&fake, fmt, ap);␊ |
117 | ␉if (ret >= 0 && fflush(&fake))␊ |
118 | ␉␉ret = EOF;␊ |
119 | ␉if (fake._flags & __SERR)␊ |
120 | ␉␉fp->_flags |= __SERR;␊ |
121 | ␉return (ret);␊ |
122 | }␊ |
123 | ␊ |
124 | /*␊ |
125 | * Macros for converting digits to letters and vice versa␊ |
126 | */␊ |
127 | #define␉to_digit(c)␉((c) - '0')␊ |
128 | #define is_digit(c)␉((unsigned)to_digit(c) <= 9)␊ |
129 | #define␉to_char(n)␉((n) + '0')␊ |
130 | ␊ |
131 | /*␊ |
132 | * Convert an unsigned long to ASCII for printf purposes, returning␊ |
133 | * a pointer to the first character of the string representation.␊ |
134 | * Octal numbers can be forced to have a leading zero; hex numbers␊ |
135 | * use the given digits.␊ |
136 | */␊ |
137 | static char *␊ |
138 | __ultoa(u_long val, char *endp, int base, int octzero, char *xdigs)␊ |
139 | {␊ |
140 | ␉register char *cp = endp;␊ |
141 | ␉register long sval;␊ |
142 | ␊ |
143 | ␉/*␊ |
144 | ␉ * Handle the three cases separately, in the hope of getting␊ |
145 | ␉ * better/faster code.␊ |
146 | ␉ */␊ |
147 | ␉switch (base) {␊ |
148 | case 10:␊ |
149 | if (val < 10) {␉/* many numbers are 1 digit */␊ |
150 | *--cp = to_char(val);␊ |
151 | return (cp);␊ |
152 | }␊ |
153 | /*␊ |
154 | * On many machines, unsigned arithmetic is harder than␊ |
155 | * signed arithmetic, so we do at most one unsigned mod and␊ |
156 | * divide; this is sufficient to reduce the range of␊ |
157 | * the incoming value to where signed arithmetic works.␊ |
158 | */␊ |
159 | if (val > LONG_MAX) {␊ |
160 | *--cp = to_char(val % 10);␊ |
161 | sval = val / 10;␊ |
162 | } else␊ |
163 | sval = val;␊ |
164 | do {␊ |
165 | *--cp = to_char(sval % 10);␊ |
166 | sval /= 10;␊ |
167 | } while (sval != 0);␊ |
168 | break;␊ |
169 | ␊ |
170 | case 8:␊ |
171 | do {␊ |
172 | *--cp = to_char(val & 7);␊ |
173 | val >>= 3;␊ |
174 | } while (val);␊ |
175 | if (octzero && *cp != '0')␊ |
176 | *--cp = '0';␊ |
177 | break;␊ |
178 | ␊ |
179 | case 16:␊ |
180 | do {␊ |
181 | *--cp = xdigs[val & 15];␊ |
182 | val >>= 4;␊ |
183 | } while (val);␊ |
184 | break;␊ |
185 | ␊ |
186 | default:␉␉␉/* oops */␊ |
187 | abort();␊ |
188 | ␉}␊ |
189 | ␉return (cp);␊ |
190 | }␊ |
191 | ␊ |
192 | /* Identical to __ultoa, but for quads. */␊ |
193 | static char *␊ |
194 | __uqtoa(u_quad_t val, char *endp, int base, int octzero, char *xdigs)␊ |
195 | {␊ |
196 | ␉char *cp = endp;␊ |
197 | ␉quad_t sval;␊ |
198 | ␊ |
199 | ␉/* quick test for small values; __ultoa is typically much faster */␊ |
200 | ␉/* (perhaps instead we should run until small, then call __ultoa?) */␊ |
201 | ␉if (val <= ULONG_MAX)␊ |
202 | ␉␉return (__ultoa((u_long)val, endp, base, octzero, xdigs));␊ |
203 | ␉switch (base) {␊ |
204 | case 10:␊ |
205 | if (val < 10) {␊ |
206 | *--cp = to_char(val % 10);␊ |
207 | return (cp);␊ |
208 | }␊ |
209 | if (val > QUAD_MAX) {␊ |
210 | *--cp = to_char(val % 10);␊ |
211 | sval = val / 10;␊ |
212 | } else␊ |
213 | sval = val;␊ |
214 | do {␊ |
215 | *--cp = to_char(sval % 10);␊ |
216 | sval /= 10;␊ |
217 | } while (sval != 0);␊ |
218 | break;␊ |
219 | ␊ |
220 | case 8:␊ |
221 | do {␊ |
222 | *--cp = to_char(val & 7);␊ |
223 | val >>= 3;␊ |
224 | } while (val);␊ |
225 | if (octzero && *cp != '0')␊ |
226 | *--cp = '0';␊ |
227 | break;␊ |
228 | ␊ |
229 | case 16:␊ |
230 | do {␊ |
231 | *--cp = xdigs[val & 15];␊ |
232 | val >>= 4;␊ |
233 | } while (val);␊ |
234 | break;␊ |
235 | ␊ |
236 | default:␊ |
237 | abort();␊ |
238 | ␉}␊ |
239 | ␉return (cp);␊ |
240 | }␊ |
241 | ␊ |
242 | #ifndef NO_FLOATING_POINT␊ |
243 | ␊ |
244 | ␊ |
245 | #else /* no FLOATING_POINT */␊ |
246 | ␊ |
247 | #define␉BUF␉␉68␊ |
248 | ␊ |
249 | #endif /* FLOATING_POINT */␊ |
250 | ␊ |
251 | #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */␊ |
252 | ␊ |
253 | /*␊ |
254 | * Flags used during conversion.␊ |
255 | */␊ |
256 | #define␉ALT␉␉0x001␉␉/* alternate form */␊ |
257 | #define␉HEXPREFIX␉0x002␉␉/* add 0x or 0X prefix */␊ |
258 | #define␉LADJUST␉␉0x004␉␉/* left adjustment */␊ |
259 | #define␉LONGDBL␉␉0x008␉␉/* long double */␊ |
260 | #define␉LONGINT␉␉0x010␉␉/* long integer */␊ |
261 | #define␉QUADINT␉␉0x020␉␉/* quad integer */␊ |
262 | #define␉SHORTINT␉0x040␉␉/* short integer */␊ |
263 | #define␉ZEROPAD␉␉0x080␉␉/* zero (as opposed to blank) pad */␊ |
264 | #define FPT␉␉0x100␉␉/* Floating point number */␊ |
265 | int␊ |
266 | vfprintf(FILE *fp, const char *fmt0, va_list ap)␊ |
267 | {␊ |
268 | ␉char *fmt;␉␉/* format string */␊ |
269 | ␉int ch;␉␉␉/* character from fmt */␊ |
270 | ␉int n, n2;␉␉/* handy integer (short term usage) */␊ |
271 | ␉char *cp;␉␉/* handy char pointer (short term usage) */␊ |
272 | ␉struct __siov *iovp;␉/* for PRINT macro */␊ |
273 | ␉int flags;␉␉/* flags as above */␊ |
274 | ␉int ret;␉␉/* return value accumulator */␊ |
275 | ␉int width;␉␉/* width from format (%8d), or 0 */␊ |
276 | ␉int prec;␉␉/* precision from format (%.3d), or -1 */␊ |
277 | ␉char sign;␉␉/* sign prefix (' ', '+', '-', or \0) */␊ |
278 | #ifndef NO_FLOATING_POINT␊ |
279 | ␉char *decimal_point = localeconv()->decimal_point;␊ |
280 | ␉char softsign;␉␉/* temporary negative sign for floats */␊ |
281 | ␉double _double;␉␉/* double precision arguments %[eEfgG] */␊ |
282 | ␉int expt;␉␉/* integer value of exponent */␊ |
283 | ␉int expsize;␉␉/* character count for expstr */␊ |
284 | ␉int ndig;␉␉/* actual number of digits returned by cvt */␊ |
285 | ␉char expstr[7];␉␉/* buffer for exponent string */␊ |
286 | ␉char *dtoaresult;␉/* buffer allocated by dtoa */␊ |
287 | #endif␊ |
288 | ␉u_long␉ulval = 0;␉␉/* integer arguments %[diouxX] */␊ |
289 | ␉u_quad_t uqval = 0;␉␉/* %q integers */␊ |
290 | ␉int base;␉␉/* base for [diouxX] conversion */␊ |
291 | ␉int dprec;␉␉/* a copy of prec if [diouxX], 0 otherwise */␊ |
292 | ␉int realsz;␉␉/* field size expanded by dprec, sign, etc */␊ |
293 | ␉int size;␉␉/* size of converted field or string */␊ |
294 | ␉int prsize; /* max size of printed field */␊ |
295 | ␉char *xdigs = NULL;␉␉/* digits for [xX] conversion */␊ |
296 | #define NIOV 8␊ |
297 | ␉struct __suio uio;␉/* output information: summary */␊ |
298 | ␉struct __siov iov[NIOV];/* ... and individual io vectors */␊ |
299 | ␉char buf[BUF];␉␉/* space for %c, %[diouxX], %[eEfgG] */␊ |
300 | ␉char ox[2];␉␉/* space for 0x hex-prefix */␊ |
301 | union arg *argtable; /* args, built due to positional arg */␊ |
302 | ␉union arg statargtable [STATIC_ARG_TBL_SIZE];␊ |
303 | int nextarg; /* 1-based argument index */␊ |
304 | va_list orgap; /* original argument pointer */␊ |
305 | ␊ |
306 | ␉/*␊ |
307 | ␉ * Choose PADSIZE to trade efficiency vs. size. If larger printf␊ |
308 | ␉ * fields occur frequently, increase PADSIZE and make the initialisers␊ |
309 | ␉ * below longer.␊ |
310 | ␉ */␊ |
311 | #define␉PADSIZE␉16␉␉/* pad chunk size */␊ |
312 | ␉static char blanks[PADSIZE] =␊ |
313 | {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};␊ |
314 | ␉static char zeroes[PADSIZE] =␊ |
315 | {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};␊ |
316 | ␊ |
317 | ␉/*␊ |
318 | ␉ * BEWARE, these `goto error' on error, and PAD uses `n'.␊ |
319 | ␉ */␊ |
320 | #define␉PRINT(ptr, len) { \␊ |
321 | iovp->iov_base = (ptr); \␊ |
322 | iovp->iov_len = (len); \␊ |
323 | uio.uio_resid += (len); \␊ |
324 | iovp++; \␊ |
325 | if (++uio.uio_iovcnt >= NIOV) { \␊ |
326 | if (__sprint(fp, &uio)) \␊ |
327 | goto error; \␊ |
328 | iovp = iov; \␊ |
329 | } \␊ |
330 | }␊ |
331 | #define␉PAD(howmany, with) { \␊ |
332 | if ((n = (howmany)) > 0) { \␊ |
333 | while (n > PADSIZE) { \␊ |
334 | PRINT(with, PADSIZE); \␊ |
335 | n -= PADSIZE; \␊ |
336 | } \␊ |
337 | PRINT(with, n); \␊ |
338 | } \␊ |
339 | }␊ |
340 | #define␉FLUSH() { \␊ |
341 | if (uio.uio_resid && __sprint(fp, &uio)) \␊ |
342 | goto error; \␊ |
343 | uio.uio_iovcnt = 0; \␊ |
344 | iovp = iov; \␊ |
345 | }␊ |
346 | ␊ |
347 | ␉/*␊ |
348 | ␉ * Get the argument indexed by nextarg. If the argument table is␊ |
349 | ␉ * built, use it to get the argument. If its not, get the next␊ |
350 | ␉ * argument (and arguments must be gotten sequentially).␊ |
351 | ␉ */␊ |
352 | #define GETARG(type) \␊ |
353 | ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \␊ |
354 | (nextarg++, va_arg(ap, type)))␊ |
355 | ␊ |
356 | ␉/*␊ |
357 | ␉ * To extend shorts properly, we need both signed and unsigned␊ |
358 | ␉ * argument extraction methods.␊ |
359 | ␉ */␊ |
360 | #define␉SARG() \␊ |
361 | (flags&LONGINT ? GETARG(long) : \␊ |
362 | flags&SHORTINT ? (long)(short)GETARG(int) : \␊ |
363 | flags&CHARINT ? (long)(signed char)GETARG(int) : \␊ |
364 | (long)GETARG(int))␊ |
365 | #define␉UARG() \␊ |
366 | (flags&LONGINT ? GETARG(u_long) : \␊ |
367 | flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \␊ |
368 | flags&CHARINT ? (u_long)(u_char)GETARG(int) : \␊ |
369 | (u_long)GETARG(u_int))␊ |
370 | #define␉INTMAX_SIZE␉(INTMAXT|SIZET|PTRDIFFT|LLONGINT)␊ |
371 | #define SJARG() \␊ |
372 | (flags&INTMAXT ? GETARG(intmax_t) : \␊ |
373 | flags&SIZET ? (intmax_t)GETARG(ssize_t) : \␊ |
374 | flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \␊ |
375 | (intmax_t)GETARG(long long))␊ |
376 | #define␉UJARG() \␊ |
377 | (flags&INTMAXT ? GETARG(uintmax_t) : \␊ |
378 | flags&SIZET ? (uintmax_t)GETARG(size_t) : \␊ |
379 | flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \␊ |
380 | (uintmax_t)GETARG(unsigned long long))␊ |
381 | ␊ |
382 | ␉/*␊ |
383 | ␉ * Get * arguments, including the form *nn$. Preserve the nextarg␊ |
384 | ␉ * that the argument can be gotten once the type is determined.␊ |
385 | ␉ */␊ |
386 | #define GETASTER(val) \␊ |
387 | n2 = 0; \␊ |
388 | cp = fmt; \␊ |
389 | while (is_digit(*cp)) { \␊ |
390 | n2 = 10 * n2 + to_digit(*cp); \␊ |
391 | cp++; \␊ |
392 | } \␊ |
393 | if (*cp == '$') { \␊ |
394 | int hold = nextarg; \␊ |
395 | if (argtable == NULL) { \␊ |
396 | argtable = statargtable; \␊ |
397 | if (__find_arguments (fmt0, orgap, &argtable)) { \␊ |
398 | ret = EOF; \␊ |
399 | goto error; \␊ |
400 | } \␊ |
401 | } \␊ |
402 | nextarg = n2; \␊ |
403 | val = GETARG (int); \␊ |
404 | nextarg = hold; \␊ |
405 | fmt = ++cp; \␊ |
406 | } else { \␊ |
407 | val = GETARG (int); \␊ |
408 | }␊ |
409 | ␊ |
410 | ␊ |
411 | #ifndef NO_FLOATING_POINT␊ |
412 | ␉dtoaresult = NULL;␊ |
413 | #endif␊ |
414 | ␉/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */␊ |
415 | ␉if (prepwrite(fp) != 0)␊ |
416 | ␉␉return (EOF);␊ |
417 | ␊ |
418 | ␉/* optimise fprintf(stderr) (and other unbuffered Unix files) */␊ |
419 | ␉if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&␊ |
420 | ␉ fp->_file >= 0) {␊ |
421 | ␉␉return (__sbprintf(fp, fmt0, ap));␊ |
422 | ␉}␊ |
423 | ␊ |
424 | ␉fmt = (char *)fmt0;␊ |
425 | argtable = NULL;␊ |
426 | nextarg = 1;␊ |
427 | orgap = ap;␊ |
428 | ␉uio.uio_iov = iovp = iov;␊ |
429 | ␉uio.uio_resid = 0;␊ |
430 | ␉uio.uio_iovcnt = 0;␊ |
431 | ␉ret = 0;␊ |
432 | ␊ |
433 | ␉/*␊ |
434 | ␉ * Scan the format for conversions (`%' character).␊ |
435 | ␉ */␊ |
436 | ␉for (;;) {␊ |
437 | ␉␉for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)␊ |
438 | /* void */;␊ |
439 | ␉␉if ((n = fmt - cp) != 0) {␊ |
440 | ␉␉␉if ((unsigned)ret + n > INT_MAX) {␊ |
441 | ␉␉␉␉ret = EOF;␊ |
442 | ␉␉␉␉goto error;␊ |
443 | ␉␉␉}␊ |
444 | ␉␉␉PRINT(cp, n);␊ |
445 | ␉␉␉ret += n;␊ |
446 | ␉␉}␊ |
447 | ␉␉if (ch == '\0')␊ |
448 | ␉␉␉goto done;␊ |
449 | ␉␉fmt++;␉␉/* skip over '%' */␊ |
450 | ␊ |
451 | ␉␉flags = 0;␊ |
452 | ␉␉dprec = 0;␊ |
453 | ␉␉width = 0;␊ |
454 | ␉␉prec = -1;␊ |
455 | ␉␉sign = '\0';␊ |
456 | ␊ |
457 | rflag:␉␉ch = *fmt++;␊ |
458 | reswitch:␉switch (ch) {␊ |
459 | ␉␉case ' ':␊ |
460 | ␉␉␉/*␊ |
461 | ␉␉␉ * ``If the space and + flags both appear, the space␊ |
462 | ␉␉␉ * flag will be ignored.''␊ |
463 | ␉␉␉ *␉-- ANSI X3J11␊ |
464 | ␉␉␉ */␊ |
465 | ␉␉␉if (!sign)␊ |
466 | ␉␉␉␉sign = ' ';␊ |
467 | ␉␉␉goto rflag;␊ |
468 | ␉␉case '#':␊ |
469 | ␉␉␉flags |= ALT;␊ |
470 | ␉␉␉goto rflag;␊ |
471 | ␉␉case '*':␊ |
472 | ␉␉␉/*␊ |
473 | ␉␉␉ * ``A negative field width argument is taken as a␊ |
474 | ␉␉␉ * - flag followed by a positive field width.''␊ |
475 | ␉␉␉ *␉-- ANSI X3J11␊ |
476 | ␉␉␉ * They don't exclude field widths read from args.␊ |
477 | ␉␉␉ */␊ |
478 | ␉␉␉GETASTER (width);␊ |
479 | ␉␉␉if (width >= 0)␊ |
480 | ␉␉␉␉goto rflag;␊ |
481 | ␉␉␉width = -width;␊ |
482 | ␉␉␉/* FALLTHROUGH */␊ |
483 | ␉␉case '-':␊ |
484 | ␉␉␉flags |= LADJUST;␊ |
485 | ␉␉␉goto rflag;␊ |
486 | ␉␉case '+':␊ |
487 | ␉␉␉sign = '+';␊ |
488 | ␉␉␉goto rflag;␊ |
489 | ␉␉case '.':␊ |
490 | ␉␉␉if ((ch = *fmt++) == '*') {␊ |
491 | ␉␉␉␉GETASTER (n);␊ |
492 | ␉␉␉␉prec = n < 0 ? -1 : n;␊ |
493 | ␉␉␉␉goto rflag;␊ |
494 | ␉␉␉}␊ |
495 | ␉␉␉n = 0;␊ |
496 | ␉␉␉while (is_digit(ch)) {␊ |
497 | ␉␉␉␉n = 10 * n + to_digit(ch);␊ |
498 | ␉␉␉␉ch = *fmt++;␊ |
499 | ␉␉␉}␊ |
500 | ␉␉␉prec = n < 0 ? -1 : n;␊ |
501 | ␉␉␉goto reswitch;␊ |
502 | ␉␉case '0':␊ |
503 | ␉␉␉/*␊ |
504 | ␉␉␉ * ``Note that 0 is taken as a flag, not as the␊ |
505 | ␉␉␉ * beginning of a field width.''␊ |
506 | ␉␉␉ *␉-- ANSI X3J11␊ |
507 | ␉␉␉ */␊ |
508 | ␉␉␉flags |= ZEROPAD;␊ |
509 | ␉␉␉goto rflag;␊ |
510 | ␉␉case '1': case '2': case '3': case '4':␊ |
511 | ␉␉case '5': case '6': case '7': case '8': case '9':␊ |
512 | ␉␉␉n = 0;␊ |
513 | ␉␉␉do {␊ |
514 | ␉␉␉␉n = 10 * n + to_digit(ch);␊ |
515 | ␉␉␉␉ch = *fmt++;␊ |
516 | ␉␉␉} while (is_digit(ch));␊ |
517 | ␉␉␉if (ch == '$') {␊ |
518 | ␉␉␉␉nextarg = n;␊ |
519 | if (argtable == NULL) {␊ |
520 | argtable = statargtable;␊ |
521 | __find_arguments (fmt0, orgap,␊ |
522 | &argtable);␊ |
523 | ␉␉␉␉}␊ |
524 | ␉␉␉␉goto rflag;␊ |
525 | }␊ |
526 | ␉␉␉width = n;␊ |
527 | ␉␉␉goto reswitch;␊ |
528 | #ifndef NO_FLOATING_POINT␊ |
529 | ␉␉case 'L':␊ |
530 | ␉␉␉flags |= LONGDBL;␊ |
531 | ␉␉␉goto rflag;␊ |
532 | #endif␊ |
533 | ␉␉case 'h':␊ |
534 | ␉␉␉flags |= SHORTINT;␊ |
535 | ␉␉␉goto rflag;␊ |
536 | ␉␉case 'l':␊ |
537 | ␉␉␉if (flags & LONGINT)␊ |
538 | ␉␉␉␉flags |= QUADINT;␊ |
539 | ␉␉␉else␊ |
540 | ␉␉␉␉flags |= LONGINT;␊ |
541 | ␉␉␉goto rflag;␊ |
542 | ␉␉case 'q':␊ |
543 | ␉␉␉flags |= QUADINT;␊ |
544 | ␉␉␉goto rflag;␊ |
545 | ␉␉case 'c':␊ |
546 | ␉␉␉*(cp = buf) = GETARG(int);␊ |
547 | ␉␉␉size = 1;␊ |
548 | ␉␉␉sign = '\0';␊ |
549 | ␉␉␉break;␊ |
550 | ␉␉case 'D':␊ |
551 | ␉␉␉flags |= LONGINT;␊ |
552 | ␉␉␉/*FALLTHROUGH*/␊ |
553 | ␉␉case 'd':␊ |
554 | ␉␉case 'i':␊ |
555 | ␉␉␉if (flags & QUADINT) {␊ |
556 | ␉␉␉␉uqval = GETARG(quad_t);␊ |
557 | ␉␉␉␉if ((quad_t)uqval < 0) {␊ |
558 | ␉␉␉␉␉uqval = -uqval;␊ |
559 | ␉␉␉␉␉sign = '-';␊ |
560 | ␉␉␉␉}␊ |
561 | ␉␉␉} else {␊ |
562 | ␉␉␉␉ulval = SARG();␊ |
563 | ␉␉␉␉if ((long)ulval < 0) {␊ |
564 | ␉␉␉␉␉ulval = -ulval;␊ |
565 | ␉␉␉␉␉sign = '-';␊ |
566 | ␉␉␉␉}␊ |
567 | ␉␉␉}␊ |
568 | ␉␉␉base = 10;␊ |
569 | ␉␉␉goto number;␊ |
570 | #ifndef NO_FLOATING_POINT␊ |
571 | ␉␉case 'e':␊ |
572 | ␉␉case 'E':␊ |
573 | ␉␉case 'f':␊ |
574 | ␉␉␉goto fp_begin;␊ |
575 | ␉␉case 'g':␊ |
576 | ␉␉case 'G':␊ |
577 | ␉␉␉if (prec == 0)␊ |
578 | ␉␉␉␉prec = 1;␊ |
579 | fp_begin:␉␉if (prec == -1)␊ |
580 | prec = DEFPREC;␊ |
581 | ␉␉␉if (flags & LONGDBL)␊ |
582 | /* XXX this loses precision. */␊ |
583 | ␉␉␉␉_double = (double)GETARG(long double);␊ |
584 | ␉␉␉else␊ |
585 | ␉␉␉␉_double = GETARG(double);␊ |
586 | ␉␉␉/* do this before tricky precision changes */␊ |
587 | ␉␉␉if (isinf(_double)) {␊ |
588 | ␉␉␉␉if (_double < 0)␊ |
589 | ␉␉␉␉␉sign = '-';␊ |
590 | ␉␉␉␉cp = "Inf";␊ |
591 | ␉␉␉␉size = 3;␊ |
592 | ␉␉␉␉break;␊ |
593 | ␉␉␉}␊ |
594 | ␉␉␉if (isnan(_double)) {␊ |
595 | ␉␉␉␉cp = "NaN";␊ |
596 | ␉␉␉␉size = 3;␊ |
597 | ␉␉␉␉break;␊ |
598 | ␉␉␉}␊ |
599 | ␉␉␉flags |= FPT;␊ |
600 | ␉␉␉if (dtoaresult != NULL) {␊ |
601 | ␉␉␉␉free(dtoaresult);␊ |
602 | ␉␉␉␉dtoaresult = NULL;␊ |
603 | ␉␉␉}␊ |
604 | ␉␉␉cp = cvt(_double, prec, flags, &softsign,␊ |
605 | &expt, ch, &ndig, &dtoaresult);␊ |
606 | ␉␉␉if (ch == 'g' || ch == 'G') {␊ |
607 | ␉␉␉␉if (expt <= -4 || expt > prec)␊ |
608 | ␉␉␉␉␉ch = (ch == 'g') ? 'e' : 'E';␊ |
609 | ␉␉␉␉else␊ |
610 | ␉␉␉␉␉ch = 'g';␊ |
611 | ␉␉␉}␊ |
612 | ␉␉␉if (ch <= 'e') {␉/* 'e' or 'E' fmt */␊ |
613 | ␉␉␉␉--expt;␊ |
614 | ␉␉␉␉expsize = exponent(expstr, expt, ch);␊ |
615 | ␉␉␉␉size = expsize + ndig;␊ |
616 | ␉␉␉␉if (ndig > 1 || flags & ALT)␊ |
617 | ␉␉␉␉␉++size;␊ |
618 | ␉␉␉} else if (ch == 'f') {␉␉/* f fmt */␊ |
619 | ␉␉␉␉if (expt > 0) {␊ |
620 | ␉␉␉␉␉size = expt;␊ |
621 | ␉␉␉␉␉if (prec || flags & ALT)␊ |
622 | ␉␉␉␉␉␉size += prec + 1;␊ |
623 | ␉␉␉␉} else␉/* "0.X" */␊ |
624 | ␉␉␉␉␉size = prec + 2;␊ |
625 | ␉␉␉} else if (expt >= ndig) {␉/* fixed g fmt */␊ |
626 | ␉␉␉␉size = expt;␊ |
627 | ␉␉␉␉if (flags & ALT)␊ |
628 | ␉␉␉␉␉++size;␊ |
629 | ␉␉␉} else␊ |
630 | ␉␉␉␉size = ndig + (expt > 0 ?␊ |
631 | 1 : 2 - expt);␊ |
632 | ␊ |
633 | ␉␉␉if (softsign)␊ |
634 | ␉␉␉␉sign = '-';␊ |
635 | ␉␉␉break;␊ |
636 | #endif /* FLOATING_POINT */␊ |
637 | ␉␉case 'n':␊ |
638 | ␉␉␉if (flags & QUADINT)␊ |
639 | ␉␉␉␉*GETARG(quad_t *) = ret;␊ |
640 | ␉␉␉else if (flags & LONGINT)␊ |
641 | ␉␉␉␉*GETARG(long *) = ret;␊ |
642 | ␉␉␉else if (flags & SHORTINT)␊ |
643 | ␉␉␉␉*GETARG(short *) = ret;␊ |
644 | ␉␉␉else␊ |
645 | ␉␉␉␉*GETARG(int *) = ret;␊ |
646 | ␉␉␉continue;␉/* no output */␊ |
647 | ␉␉case 'O':␊ |
648 | ␉␉␉flags |= LONGINT;␊ |
649 | ␉␉␉/*FALLTHROUGH*/␊ |
650 | ␉␉case 'o':␊ |
651 | ␉␉␉if (flags & QUADINT)␊ |
652 | ␉␉␉␉uqval = GETARG(u_quad_t);␊ |
653 | ␉␉␉else␊ |
654 | ␉␉␉␉ulval = UARG();␊ |
655 | ␉␉␉base = 8;␊ |
656 | ␉␉␉goto nosign;␊ |
657 | ␉␉case 'p':␊ |
658 | ␉␉␉/*␊ |
659 | ␉␉␉ * ``The argument shall be a pointer to void. The␊ |
660 | ␉␉␉ * value of the pointer is converted to a sequence␊ |
661 | ␉␉␉ * of printable characters, in an implementation-␊ |
662 | ␉␉␉ * defined manner.''␊ |
663 | ␉␉␉ *␉-- ANSI X3J11␊ |
664 | ␉␉␉ */␊ |
665 | ␉␉␉ulval = (u_long)GETARG(void *);␊ |
666 | ␉␉␉base = 16;␊ |
667 | ␉␉␉xdigs = "0123456789abcdef";␊ |
668 | ␉␉␉flags = (flags & ~QUADINT) | HEXPREFIX;␊ |
669 | ␉␉␉ch = 'x';␊ |
670 | ␉␉␉goto nosign;␊ |
671 | ␉␉case 's':␊ |
672 | ␉␉␉if ((cp = GETARG(char *)) == NULL)␊ |
673 | ␉␉␉␉cp = "(null)";␊ |
674 | ␉␉␉if (prec >= 0) {␊ |
675 | ␉␉␉␉/*␊ |
676 | ␉␉␉␉ * can't use strlen; can only look for the␊ |
677 | ␉␉␉␉ * NUL in the first `prec' characters, and␊ |
678 | ␉␉␉␉ * strlen() will go further.␊ |
679 | ␉␉␉␉ */␊ |
680 | ␉␉␉␉char *p = memchr(cp, 0, (size_t)prec);␊ |
681 | ␊ |
682 | ␉␉␉␉if (p != NULL) {␊ |
683 | ␉␉␉␉␉size = p - cp;␊ |
684 | ␉␉␉␉␉if (size > prec)␊ |
685 | ␉␉␉␉␉␉size = prec;␊ |
686 | ␉␉␉␉} else␊ |
687 | ␉␉␉␉␉size = prec;␊ |
688 | ␉␉␉} else␊ |
689 | ␉␉␉␉size = strlen(cp);␊ |
690 | ␉␉␉sign = '\0';␊ |
691 | ␉␉␉break;␊ |
692 | ␉␉case 'U':␊ |
693 | ␉␉␉flags |= LONGINT;␊ |
694 | ␉␉␉/*FALLTHROUGH*/␊ |
695 | ␉␉case 'u':␊ |
696 | ␉␉␉if (flags & QUADINT)␊ |
697 | ␉␉␉␉uqval = GETARG(u_quad_t);␊ |
698 | ␉␉␉else␊ |
699 | ␉␉␉␉ulval = UARG();␊ |
700 | ␉␉␉base = 10;␊ |
701 | ␉␉␉goto nosign;␊ |
702 | ␉␉case 'X':␊ |
703 | ␉␉␉xdigs = "0123456789ABCDEF";␊ |
704 | ␉␉␉goto hex;␊ |
705 | ␉␉case 'x':␊ |
706 | ␉␉␉xdigs = "0123456789abcdef";␊ |
707 | hex:␉␉␉if (flags & QUADINT)␊ |
708 | uqval = GETARG(u_quad_t);␊ |
709 | else␊ |
710 | ulval = UARG();␊ |
711 | ␉␉␉base = 16;␊ |
712 | ␉␉␉/* leading 0x/X only if non-zero */␊ |
713 | ␉␉␉if (flags & ALT &&␊ |
714 | ␉␉␉ (flags & QUADINT ? uqval != 0 : ulval != 0))␊ |
715 | ␉␉␉␉flags |= HEXPREFIX;␊ |
716 | ␊ |
717 | ␉␉␉/* unsigned conversions */␊ |
718 | nosign:␉␉␉sign = '\0';␊ |
719 | ␉␉␉/*␊ |
720 | ␉␉␉ * ``... diouXx conversions ... if a precision is␊ |
721 | ␉␉␉ * specified, the 0 flag will be ignored.''␊ |
722 | ␉␉␉ *␉-- ANSI X3J11␊ |
723 | ␉␉␉ */␊ |
724 | number:␉␉␉if ((dprec = prec) >= 0)␊ |
725 | flags &= ~ZEROPAD;␊ |
726 | ␊ |
727 | ␉␉␉/*␊ |
728 | ␉␉␉ * ``The result of converting a zero value with an␊ |
729 | ␉␉␉ * explicit precision of zero is no characters.''␊ |
730 | ␉␉␉ *␉-- ANSI X3J11␊ |
731 | ␉␉␉ */␊ |
732 | ␉␉␉cp = buf + BUF;␊ |
733 | ␉␉␉if (flags & QUADINT) {␊ |
734 | ␉␉␉␉if (uqval != 0 || prec != 0)␊ |
735 | ␉␉␉␉␉cp = __uqtoa(uqval, cp, base,␊ |
736 | flags & ALT, xdigs);␊ |
737 | ␉␉␉} else {␊ |
738 | ␉␉␉␉if (ulval != 0 || prec != 0)␊ |
739 | ␉␉␉␉␉cp = __ultoa(ulval, cp, base,␊ |
740 | flags & ALT, xdigs);␊ |
741 | ␉␉␉}␊ |
742 | ␉␉␉size = buf + BUF - cp;␊ |
743 | ␉␉␉break;␊ |
744 | ␉␉default:␉/* "%?" prints ?, unless ? is NUL */␊ |
745 | ␉␉␉if (ch == '\0')␊ |
746 | ␉␉␉␉goto done;␊ |
747 | ␉␉␉/* pretend it was %c with argument ch */␊ |
748 | ␉␉␉cp = buf;␊ |
749 | ␉␉␉*cp = ch;␊ |
750 | ␉␉␉size = 1;␊ |
751 | ␉␉␉sign = '\0';␊ |
752 | ␉␉␉break;␊ |
753 | }␊ |
754 | ␊ |
755 | ␉␉/*␊ |
756 | ␉␉ * All reasonable formats wind up here. At this point, `cp'␊ |
757 | ␉␉ * points to a string which (if not flags&LADJUST) should be␊ |
758 | ␉␉ * padded out to `width' places. If flags&ZEROPAD, it should␊ |
759 | ␉␉ * first be prefixed by any sign or other prefix; otherwise,␊ |
760 | ␉␉ * it should be blank padded before the prefix is emitted.␊ |
761 | ␉␉ * After any left-hand padding and prefixing, emit zeroes␊ |
762 | ␉␉ * required by a decimal [diouxX] precision, then print the␊ |
763 | ␉␉ * string proper, then emit zeroes required by any leftover␊ |
764 | ␉␉ * floating precision; finally, if LADJUST, pad with blanks.␊ |
765 | ␉␉ *␊ |
766 | ␉␉ * Compute actual size, so we know how much to pad.␊ |
767 | ␉␉ * size excludes decimal prec; realsz includes it.␊ |
768 | ␉␉ */␊ |
769 | ␉␉realsz = dprec > size ? dprec : size;␊ |
770 | ␉␉if (sign)␊ |
771 | ␉␉␉realsz++;␊ |
772 | ␉␉else if (flags & HEXPREFIX)␊ |
773 | ␉␉␉realsz += 2;␊ |
774 | ␊ |
775 | ␉␉prsize = width > realsz ? width : realsz;␊ |
776 | ␉␉if ((unsigned)ret + prsize > INT_MAX) {␊ |
777 | ␉␉␉ret = EOF;␊ |
778 | ␉␉␉goto error;␊ |
779 | ␉␉}␊ |
780 | ␊ |
781 | ␉␉/* right-adjusting blank padding */␊ |
782 | ␉␉if ((flags & (LADJUST|ZEROPAD)) == 0)␊ |
783 | ␉␉␉PAD(width - realsz, blanks);␊ |
784 | ␊ |
785 | ␉␉/* prefix */␊ |
786 | ␉␉if (sign) {␊ |
787 | ␉␉␉PRINT(&sign, 1);␊ |
788 | ␉␉} else if (flags & HEXPREFIX) {␊ |
789 | ␉␉␉ox[0] = '0';␊ |
790 | ␉␉␉ox[1] = ch;␊ |
791 | ␉␉␉PRINT(ox, 2);␊ |
792 | ␉␉}␊ |
793 | ␊ |
794 | ␉␉/* right-adjusting zero padding */␊ |
795 | ␉␉if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)␊ |
796 | ␉␉␉PAD(width - realsz, zeroes);␊ |
797 | ␊ |
798 | ␉␉/* leading zeroes from decimal precision */␊ |
799 | ␉␉PAD(dprec - size, zeroes);␊ |
800 | ␊ |
801 | ␉␉/* the string or number proper */␊ |
802 | #ifndef NO_FLOATING_POINT␊ |
803 | ␉␉if ((flags & FPT) == 0) {␊ |
804 | ␉␉␉PRINT(cp, size);␊ |
805 | ␉␉} else {␉/* glue together f_p fragments */␊ |
806 | ␉␉␉if (ch >= 'f') {␉/* 'f' or 'g' */␊ |
807 | ␉␉␉␉if (_double == 0) {␊ |
808 | ␉␉␉␉␉/* kludge for __dtoa irregularity */␊ |
809 | ␉␉␉␉␉PRINT("0", 1);␊ |
810 | ␉␉␉␉␉if (expt < ndig || (flags & ALT) != 0) {␊ |
811 | ␉␉␉␉␉␉PRINT(decimal_point, 1);␊ |
812 | ␉␉␉␉␉␉PAD(ndig - 1, zeroes);␊ |
813 | ␉␉␉␉␉}␊ |
814 | ␉␉␉␉} else if (expt <= 0) {␊ |
815 | ␉␉␉␉␉PRINT("0", 1);␊ |
816 | ␉␉␉␉␉PRINT(decimal_point, 1);␊ |
817 | ␉␉␉␉␉PAD(-expt, zeroes);␊ |
818 | ␉␉␉␉␉PRINT(cp, ndig);␊ |
819 | ␉␉␉␉} else if (expt >= ndig) {␊ |
820 | ␉␉␉␉␉PRINT(cp, ndig);␊ |
821 | ␉␉␉␉␉PAD(expt - ndig, zeroes);␊ |
822 | ␉␉␉␉␉if (flags & ALT)␊ |
823 | ␉␉␉␉␉␉PRINT(decimal_point, 1);␊ |
824 | ␉␉␉␉} else {␊ |
825 | ␉␉␉␉␉PRINT(cp, expt);␊ |
826 | ␉␉␉␉␉cp += expt;␊ |
827 | ␉␉␉␉␉PRINT(decimal_point, 1);␊ |
828 | ␉␉␉␉␉PRINT(cp, ndig-expt);␊ |
829 | ␉␉␉␉}␊ |
830 | ␉␉␉} else {␉/* 'e' or 'E' */␊ |
831 | ␉␉␉␉if (ndig > 1 || flags & ALT) {␊ |
832 | ␉␉␉␉␉ox[0] = *cp++;␊ |
833 | ␉␉␉␉␉ox[1] = *decimal_point;␊ |
834 | ␉␉␉␉␉PRINT(ox, 2);␊ |
835 | ␉␉␉␉␉if (_double) {␊ |
836 | ␉␉␉␉␉␉PRINT(cp, ndig-1);␊ |
837 | ␉␉␉␉␉} else␉/* 0.[0..] */␊ |
838 | /* __dtoa irregularity */␊ |
839 | ␉␉␉␉␉␉PAD(ndig - 1, zeroes);␊ |
840 | ␉␉␉␉} else␉/* XeYYY */␊ |
841 | ␉␉␉␉␉PRINT(cp, 1);␊ |
842 | ␉␉␉␉PRINT(expstr, expsize);␊ |
843 | ␉␉␉}␊ |
844 | ␉␉}␊ |
845 | #else␊ |
846 | ␉␉PRINT(cp, size);␊ |
847 | #endif␊ |
848 | ␉␉/* left-adjusting padding (always blank) */␊ |
849 | ␉␉if (flags & LADJUST)␊ |
850 | ␉␉␉PAD(width - realsz, blanks);␊ |
851 | ␊ |
852 | ␉␉/* finally, adjust ret */␊ |
853 | ␉␉ret += prsize;␊ |
854 | ␊ |
855 | ␉␉FLUSH();␉/* copy out the I/O vectors */␊ |
856 | ␉}␊ |
857 | done:␊ |
858 | ␉FLUSH();␊ |
859 | error:␊ |
860 | #ifndef NO_FLOATING_POINT␊ |
861 | ␉if (dtoaresult != NULL)␊ |
862 | ␉␉free(dtoaresult);␊ |
863 | #endif␊ |
864 | ␉if (__sferror(fp))␊ |
865 | ␉␉ret = EOF;␊ |
866 | if ((argtable != NULL) && (argtable != statargtable))␊ |
867 | free (argtable);␊ |
868 | ␉return (ret);␊ |
869 | ␉/* NOTREACHED */␊ |
870 | }␊ |
871 | |