Update contrib.
3 * <<vprintf>>, <<vfprintf>>, <<vsprintf>>---format argument list
13 * int vprintf(const char *<[fmt]>, va_list <[list]>);
14 * int vfprintf(FILE *<[fp]>, const char *<[fmt]>, va_list <[list]>);
15 * int vsprintf(char *<[str]>, const char *<[fmt]>, va_list <[list]>);
16 * int _vprintf_r(void *<[reent]>, const char *<[fmt]>,
18 * int _vfprintf_r(void *<[reent]>, FILE *<[fp]>, const char *<[fmt]>,
20 * int _vsprintf_r(void *<[reent]>, char *<[str]>, const char *<[fmt]>,
24 * #include <varargs.h>
25 * int vprintf( <[fmt]>, <[list]>)
28 * int vfprintf(<[fp]>, <[fmt]>, <[list]>)
32 * int vsprintf(<[str]>, <[fmt]>, <[list]>)
36 * int _vprintf_r(<[reent]>, <[fmt]>, <[list]>)
40 * int _vfprintf_r(<[reent]>, <[fp]>, <[fmt]>, <[list]>)
45 * int _vsprintf_r(<[reent]>, <[str]>, <[fmt]>, <[list]>)
50 * <<vprintf>>, <<vfprintf>>, and <<vsprintf>> are (respectively)
51 * variants of <<printf>>, <<fprintf>>, and <<sprintf>>. They differ
52 * only in allowing their caller to pass the variable argument list as a
53 * <<va_list>> object (initialized by <<va_start>>) rather than directly
54 * accepting a variable number of arguments.
56 * The return values are consistent with the corresponding functions:
57 * <<vsprintf>> returns the number of bytes in the output string,
58 * save that the concluding <<NULL>> is not counted.
59 * <<vprintf>> and <<vfprintf>> return the number of characters transmitted.
60 * If an error occurs, <<vprintf>> and <<vfprintf>> return <<EOF>>. No
61 * error returns occur for <<vsprintf>>.
63 * ANSI C requires all three functions.
64 * Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
65 * <<lseek>>, <<read>>, <<sbrk>>, <<write>>.
73 * Copyright (c) 1990 The Regents of the University of California.
74 * All rights reserved.
76 * This code is derived from software contributed to Berkeley by
79 * Redistribution and use in source and binary forms, with or without
80 * modification, are permitted provided that the following conditions
82 * 1. Redistributions of source code must retain the above copyright
83 * notice, this list of conditions and the following disclaimer.
84 * 2. Redistributions in binary form must reproduce the above copyright
85 * notice, this list of conditions and the following disclaimer in the
86 * documentation and/or other materials provided with the distribution.
87 * 3. All advertising materials mentioning features or use of this software
88 * must display the following acknowledgement:
89 * This product includes software developed by the University of
90 * California, Berkeley and its contributors.
91 * 4. Neither the name of the University nor the names of its contributors
92 * may be used to endorse or promote products derived from this software
93 * without specific prior written permission.
95 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
96 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
97 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
98 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
99 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
100 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
101 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
102 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
103 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
104 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
109 * Actual printf innards.
111 * This code is large and complicated...
120 #include <stdlib_r.h>
135 * Flush out all the vectors defined by the given uio,
136 * then reset it so that it can be reused.
139 __sprint(FILE *fp,register struct __suio *uio)
143 if (uio->uio_resid == 0) {
147 err = __sfvwrite(fp, uio);
154 * Helper function for `fprintf to unbuffered unix file': creates a
155 * temporary buffer. We only work on write-only files; this avoids
156 * worries about ungetc buffers and so forth.
159 __sbprintf(register FILE *fp,const char *fmt,va_list ap)
163 unsigned char buf[BUFSIZ];
165 /* copy the important variables */
166 fake._data = fp->_data;
167 fake._flags = (short)(fp->_flags & ~__SNBF);
168 fake._file = fp->_file;
169 fake._cookie = fp->_cookie;
170 fake._write = fp->_write;
172 /* set up the buffer */
173 fake._bf._base = fake._p = buf;
174 fake._bf._size = fake._w = sizeof(buf);
175 fake._lbfsize = 0; /* not actually used, but Just In Case */
177 /* do the work, then copy any error status */
178 ret = vfprintf(&fake, fmt, ap);
179 if (ret >= 0 && fflush(&fake))
181 if (fake._flags & __SERR)
182 fp->_flags |= __SERR;
187 /* #include <locale.h> for decimal_point */
191 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
194 extern int e32cvt (char *buf, int buflen, double, int width, int prec, int flags, int fmt);
198 * Macros for converting digits to letters and vice versa
200 #define to_digit(c) ((c) - '0')
201 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
202 #define to_char(n) ((n) + '0')
205 * Flags used during conversion.
207 #define ALT 0x001 /* alternate form */
208 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */
209 #define LADJUST 0x004 /* left adjustment */
210 #define LONGDBL 0x008 /* long double; unimplemented */
211 #define LONGINT 0x010 /* long integer */
212 #define QUADINT 0x020 /* quad integer */
213 #define SHORTINT 0x040 /* short integer */
214 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
215 #define FPT 0x100 /* Floating point number */
218 vfprintf (FILE * fp, const char *fmt0, va_list ap)
220 return _vfprintf_r (fp->_data, fp, fmt0, ap);
224 A reentrant version of vfprintf().
227 _vfprintf_r (struct _reent *data, FILE * fp, const char *fmt0, va_list ap)
229 register char *fmt; /* format string */
230 register int ch; /* character from fmt */
231 register int n, m; /* handy integers (short term usage) */
232 register char *cp; /* handy char pointer (short term usage) */
233 register struct __siov *iovp;/* for PRINT macro */
234 register int flags; /* flags as above */
235 int ret; /* return value accumulator */
236 int width; /* width from format (%8d), or 0 */
237 int prec; /* precision from format (%.3d), or -1 */
238 char sign; /* sign prefix (' ', '+', '-', or \0) */
241 char *decimal_point = "."; /* localeconv()->decimal_point; */
243 // char softsign; /* temporary negative sign for floats */
244 double _double; /* double precision arguments %[eEfgG] */
245 // int expt; /* integer value of exponent */
246 // int expsize; /* character count for expstr */
247 // int ndig; /* actual number of digits returned by cvt */
248 // char expstr[7]; /* buffer for exponent string */
251 #define quad_t long long
252 #define u_quad_t unsigned long long
256 u_quad_t _uquad; /* integer arguments %[diouxX] */
260 enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
261 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
262 int realsz; /* field size expanded by dprec */
263 int size; /* size of converted field or string */
264 char *xdigs = NULL; /* digits for [xX] conversion */
266 struct __suio uio; /* output information: summary */
267 struct __siov iov[NIOV];/* ... and individual io vectors */
268 char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
269 char ox[2]; /* space for 0x hex-prefix */
272 * Choose PADSIZE to trade efficiency vs. size. If larger printf
273 * fields occur frequently, increase PADSIZE and make the initialisers
276 #define PADSIZE 16 /* pad chunk size */
277 static const char blanks[PADSIZE] =
278 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
279 static const char zeroes[PADSIZE] =
280 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
283 * BEWARE, these `goto error' on error, and PAD uses `n'.
285 #define PRINT(ptr, len) { \
286 iovp->iov_base = (ptr); \
287 iovp->iov_len = (len); \
288 uio.uio_resid += (len); \
290 if (++uio.uio_iovcnt >= NIOV) { \
291 if (__sprint(fp, &uio)) \
296 #define PAD(howmany, with) { \
297 if ((n = (howmany)) > 0) { \
298 while (n > PADSIZE) { \
299 PRINT(with, PADSIZE); \
306 if (uio.uio_resid && __sprint(fp, &uio)) \
308 uio.uio_iovcnt = 0; \
313 * To extend shorts properly, we need both signed and unsigned
314 * argument extraction methods.
318 (flags&QUADINT ? va_arg(ap, quad_t) : \
319 flags&LONGINT ? va_arg(ap, long) : \
320 flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
321 (long)va_arg(ap, int))
323 (flags&QUADINT ? va_arg(ap, u_quad_t) : \
324 flags&LONGINT ? va_arg(ap, u_long) : \
325 flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
326 (u_long)va_arg(ap, u_int))
329 (flags&LONGINT ? va_arg(ap, long) : \
330 flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
331 (long)va_arg(ap, int))
333 (flags&LONGINT ? va_arg(ap, u_long) : \
334 flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
335 (u_long)va_arg(ap, u_int))
340 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
344 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
345 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
347 return (__sbprintf(fp, fmt0, ap));
350 uio.uio_iov = iovp = iov;
356 * Scan the format for conversions (`%' character).
360 while ((n = mbtowc(&wc, fmt, MB_CUR_MAX)) > 0) {
367 if ((m = fmt - cp) != 0) {
373 fmt++; /* skip over '%' */
382 reswitch: switch (ch) {
385 * ``If the space and + flags both appear, the space
386 * flag will be ignored.''
397 * ``A negative field width argument is taken as a
398 * - flag followed by a positive field width.''
400 * They don't exclude field widths read from args.
402 if ((width = va_arg(ap, int)) >= 0)
413 if ((ch = *fmt++) == '*') {
415 prec = n < 0 ? -1 : n;
419 while (is_digit(ch)) {
420 n = 10 * n + to_digit(ch);
423 prec = n < 0 ? -1 : n;
427 * ``Note that 0 is taken as a flag, not as the
428 * beginning of a field width.''
433 case '1': case '2': case '3': case '4':
434 case '5': case '6': case '7': case '8': case '9':
437 n = 10 * n + to_digit(ch);
439 } while (is_digit(ch));
460 *(cp = buf) = (char)va_arg(ap, int);
471 if ((quad_t)_uquad < 0)
473 if ((long) _uquad < 0)
480 _uquad = (u_long)(-(long)_uquad);
494 } else if ((ch == 'g' || ch == 'G') && prec == 0) {
498 if (flags & LONGDBL) {
499 _double = (double) va_arg(ap, long double);
501 _double = va_arg(ap, double);
504 /* do this before tricky precision changes */
505 if (isinf(_double)) {
512 if (isnan(_double)) {
519 cp = cvt(data, _double, prec, flags, &softsign,
521 if (ch == 'g' || ch == 'G') {
522 if (expt <= -4 || expt > prec)
523 ch = (ch == 'g') ? 'e' : 'E';
527 if (ch <= 'e') { /* 'e' or 'E' fmt */
529 expsize = exponent(expstr, expt, ch);
530 size = expsize + ndig;
531 if (ndig > 1 || flags & ALT)
533 } else if (ch == 'f') { /* f fmt */
536 if (prec || flags & ALT)
540 } else if (expt >= ndig) { /* fixed g fmt */
545 size = ndig + (expt > 0 ?
555 size = e32cvt(buf, BUF, _double, width, prec, flags, ch);
563 *va_arg(ap, quad_t *) = ret;
567 *va_arg(ap, long *) = ret;
568 else if (flags & SHORTINT)
569 *va_arg(ap, short *) = (short)ret;
571 *va_arg(ap, int *) = ret;
572 continue; /* no output */
582 * ``The argument shall be a pointer to void. The
583 * value of the pointer is converted to a sequence
584 * of printable characters, in an implementation-
589 _uquad = (u_long)va_arg(ap, void *);
591 xdigs = "0123456789abcdef";
596 if ((cp = va_arg(ap, char *)) == NULL)
600 * can't use strlen; can only look for the
601 * NUL in the first `prec' characters, and
602 * strlen() will go further.
604 char *p = (char *)memchr(cp, 0, prec);
624 xdigs = "0123456789ABCDEF";
627 xdigs = "0123456789abcdef";
628 hex: _uquad = UARG();
630 /* leading 0x/X only if non-zero */
631 if (flags & ALT && _uquad != 0)
634 /* unsigned conversions */
637 * ``... diouXx conversions ... if a precision is
638 * specified, the 0 flag will be ignored.''
641 number: if ((dprec = prec) >= 0)
645 * ``The result of converting a zero value with an
646 * explicit precision of zero is no characters.''
650 if (_uquad != 0 || prec != 0) {
652 * Unsigned mod is hard, and unsigned mod
653 * by a constant is easier than that by
654 * a variable; hence this switch.
659 *--cp = (char)to_char(_uquad & 7);
662 /* handle octal leading 0 */
663 if (flags & ALT && *cp != '0')
668 /* many numbers are 1 digit */
669 while (_uquad >= 10) {
670 *--cp = (char)to_char(_uquad % 10);
673 *--cp = (char)to_char(_uquad);
678 *--cp = xdigs[_uquad & 15];
684 cp = "bug in vfprintf: bad base";
689 /* Workaround GCC compiler bug: size = buf + BUF - cp */
691 char *temp = buf+BUF;
696 default: /* "%?" prints ?, unless ? is NUL */
699 /* pretend it was %c with argument ch */
708 * All reasonable formats wind up here. At this point, `cp'
709 * points to a string which (if not flags&LADJUST) should be
710 * padded out to `width' places. If flags&ZEROPAD, it should
711 * first be prefixed by any sign or other prefix; otherwise,
712 * it should be blank padded before the prefix is emitted.
713 * After any left-hand padding and prefixing, emit zeroes
714 * required by a decimal [diouxX] precision, then print the
715 * string proper, then emit zeroes required by any leftover
716 * floating precision; finally, if LADJUST, pad with blanks.
718 * Compute actual size, so we know how much to pad.
719 * size excludes decimal prec; realsz includes it.
721 realsz = dprec > size ? dprec : size;
724 else if (flags & HEXPREFIX)
727 /* right-adjusting blank padding */
728 if ((flags & (LADJUST|ZEROPAD)) == 0)
729 PAD(width - realsz, blanks);
734 } else if (flags & HEXPREFIX) {
740 /* right-adjusting zero padding */
741 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
742 PAD(width - realsz, zeroes);
744 /* leading zeroes from decimal precision */
745 PAD(dprec - size, zeroes);
747 /* the string or number proper */
750 } else { /* glue together f_p fragments */
751 if (ch >= 'f') { /* 'f' or 'g' */
753 /* kludge for __dtoa irregularity */
755 if (expt < ndig || (flags & ALT) != 0) {
756 PRINT(decimal_point, 1);
757 PAD(ndig - 1, zeroes);
759 } else if (expt <= 0) {
761 PRINT(decimal_point, 1);
764 } else if (expt >= ndig) {
766 PAD(expt - ndig, zeroes);
773 PRINT(cp, ndig-expt);
775 } else { /* 'e' or 'E' */
776 if (ndig > 1 || flags & ALT) {
780 if (_double || (flags & ALT) == 0) {
783 /* __dtoa irregularity */
784 PAD(ndig - 1, zeroes);
787 PRINT(expstr, expsize);
791 /* left-adjusting padding (always blank) */
793 PAD(width - realsz, blanks);
795 /* finally, adjust ret */
796 ret += width > realsz ? width : realsz;
798 FLUSH(); /* copy out the I/O vectors */
803 return (__sferror(fp) ? EOF : ret);
809 cvt(struct _reent *data,double value,int ndigits, int flags, char *sign, int *decpt, int ch, int *length)
812 char *digits, *bp, *rve;
815 mode = 3; /* ndigits after the decimal point */
817 /* To obtain ndigits after the decimal point for the 'e'
818 * and 'E' formats, round to ndigits + 1 significant
821 if (ch == 'e' || ch == 'E') {
824 mode = 2; /* ndigits significant digits */
832 digits = _dtoa_r(data, value, mode, ndigits, decpt, &dsgn, &rve);
833 if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */
834 bp = digits + ndigits;
836 if (*digits == '0' && value)
837 *decpt = -ndigits + 1;
840 if (value == 0) /* kludge for __dtoa irregularity */
845 *length = rve - digits;
850 exponent(char *p0, int exp, int fmtch)
852 register char *p, *t;
866 *--t = (char)to_char(exp % 10);
867 } while ((exp /= 10) > 9);
868 *--t = (char)to_char(exp);
869 for (; t < expbuf + MAXEXP; *p++ = *t++);
873 *p++ = (char)to_char(exp);