2 Copyright (C) 1993 Free Software Foundation
4 This file is part of the GNU IO Library. This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING. If not, write to the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the executable file might be covered by the GNU General Public License. */
26 * Copyright (c) 1990 Regents of the University of California.
27 * All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. [rescinded 22 July 1999]
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 #if defined(LIBC_SCCS) && !defined(lint)
57 static char sccsid[] = "%W% (Berkeley) %G%";
58 #endif /* LIBC_SCCS and not lint */
61 * Actual printf innards.
63 * This code is large and complicated...
66 #include <sys/types.h>
76 int __cvt_double __P((double number, register int prec, int flags, int *signp, int fmtch, char *startp, char *endp));
80 * Define FLOATING_POINT to get floating point.
82 #ifndef NO_FLOATING_POINT
83 #define FLOATING_POINT
86 /* end of configuration stuff */
90 * Helper "class" for `fprintf to unbuffered': creates a
91 * temporary buffer. */
95 struct _IO_FILE_plus _f;
96 _IO_FILE *_put_stream;
100 _IO_helper_overflow (fp, c)
104 _IO_FILE *target = ((struct helper_file*)fp)->_put_stream;
105 int used = fp->_IO_write_ptr - fp->_IO_write_base;
108 _IO_sputn(target, fp->_IO_write_base, used);
109 fp->_IO_write_ptr -= used;
111 return _IO_putc (c, fp);
114 static struct _IO_jump_t _IO_helper_jumps = {
116 JUMP_INIT(finish, _IO_default_finish),
117 JUMP_INIT(overflow, _IO_helper_overflow),
118 JUMP_INIT(underflow, _IO_default_underflow),
119 JUMP_INIT(uflow, _IO_default_uflow),
120 JUMP_INIT(pbackfail, _IO_default_pbackfail),
121 JUMP_INIT(xsputn, _IO_default_xsputn),
122 JUMP_INIT(xsgetn, _IO_default_xsgetn),
123 JUMP_INIT(seekoff, _IO_default_seekoff),
124 JUMP_INIT(seekpos, _IO_default_seekpos),
125 JUMP_INIT(setbuf, _IO_default_setbuf),
126 JUMP_INIT(sync, _IO_default_sync),
127 JUMP_INIT(doallocate, _IO_default_doallocate),
128 JUMP_INIT(read, _IO_default_read),
129 JUMP_INIT(write, _IO_default_write),
130 JUMP_INIT(seek, _IO_default_seek),
131 JUMP_INIT(close, _IO_default_close),
132 JUMP_INIT(stat, _IO_default_stat)
136 helper_vfprintf (fp, fmt0, ap)
141 char buf[_IO_BUFSIZ];
142 struct helper_file helper;
143 register _IO_FILE *hp = (_IO_FILE*)&helper;
144 int result, to_flush;
146 /* initialize helper */
147 helper._put_stream = fp;
148 hp->_IO_write_base = buf;
149 hp->_IO_write_ptr = buf;
150 hp->_IO_write_end = buf+_IO_BUFSIZ;
151 hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS;
152 _IO_JUMPS(hp) = &_IO_helper_jumps;
154 /* Now print to helper instead. */
155 result = _IO_vfprintf(hp, fmt0, ap);
157 /* Now flush anything from the helper to the fp. */
158 if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0)
160 if (_IO_sputn(fp, hp->_IO_write_base, to_flush) != to_flush)
166 #ifdef FLOATING_POINT
169 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
171 extern double modf __P((double, double*));
173 #else /* no FLOATING_POINT */
177 #endif /* FLOATING_POINT */
181 * Macros for converting digits to letters and vice versa
183 #define to_digit(c) ((c) - '0')
184 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
185 #define to_char(n) ((n) + '0')
188 * Flags used during conversion.
190 #define LONGINT 0x01 /* long integer */
191 #define LONGDBL 0x02 /* long double; unimplemented */
192 #define SHORTINT 0x04 /* short integer */
193 #define ALT 0x08 /* alternate form */
194 #define LADJUST 0x10 /* left adjustment */
195 #define ZEROPAD 0x20 /* zero (as opposed to blank) pad */
196 #define HEXPREFIX 0x40 /* add 0x or 0X prefix */
199 _IO_vfprintf (fp, fmt0, ap)
204 register const char *fmt; /* format string */
205 register int ch; /* character from fmt */
206 register int n; /* handy integer (short term usage) */
207 register char *cp; /* handy char pointer (short term usage) */
208 const char *fmark; /* for remembering a place in fmt */
209 register int flags; /* flags as above */
210 int ret; /* return value accumulator */
211 int width; /* width from format (%8d), or 0 */
212 int prec; /* precision from format (%.3d), or -1 */
213 char sign; /* sign prefix (' ', '+', '-', or \0) */
214 #ifdef FLOATING_POINT
215 int softsign; /* temporary negative sign for floats */
216 double _double; /* double precision arguments %[eEfgG] */
218 int fpprec; /* `extra' floating precision in [eEfgG] */
221 unsigned long _ulong; /* integer arguments %[diouxX] */
222 enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
223 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
224 int dpad; /* extra 0 padding needed for integers */
225 int fieldsz; /* field size expanded by sign, dpad etc */
226 /* The initialization of 'size' is to suppress a warning that
227 'size' might be used unitialized. It seems gcc can't
228 quite grok this spaghetti code ... */
229 int size = 0; /* size of converted field or string */
230 char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
231 char ox[2]; /* space for 0x hex-prefix */
234 * BEWARE, these `goto error' on error, and PAD uses `n'.
236 #define PRINT(ptr, len) \
237 do { if (_IO_sputn(fp,ptr, len) != len) goto error; } while (0)
238 #define PAD_SP(howmany) if (_IO_padn(fp, ' ', howmany) < (howmany)) goto error;
239 #define PAD_0(howmany) if (_IO_padn(fp, '0', howmany) < (howmany)) goto error;
242 * To extend shorts properly, we need both signed and unsigned
243 * argument extraction methods.
246 (flags&LONGINT ? va_arg(ap, long) : \
247 flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
248 (long)va_arg(ap, int))
250 (flags&LONGINT ? va_arg(ap, unsigned long) : \
251 flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \
252 (unsigned long)va_arg(ap, unsigned int))
254 /* optimise stderr (and other unbuffered Unix files) */
255 if (fp->_IO_file_flags & _IO_UNBUFFERED)
256 return helper_vfprintf(fp, fmt0, ap);
262 * Scan the format for conversions (`%' character).
265 for (fmark = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
267 if ((n = fmt - fmark) != 0) {
273 fmt++; /* skip over '%' */
277 #if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
285 reswitch: switch (ch) {
288 * ``If the space and + flags both appear, the space
289 * flag will be ignored.''
300 * ``A negative field width argument is taken as a
301 * - flag followed by a positive field width.''
303 * They don't exclude field widths read from args.
305 if ((width = va_arg(ap, int)) >= 0)
311 flags &= ~ZEROPAD; /* '-' disables '0' */
317 if ((ch = *fmt++) == '*') {
319 prec = n < 0 ? -1 : n;
323 while (is_digit(ch)) {
324 n = 10 * n + to_digit(ch);
327 prec = n < 0 ? -1 : n;
331 * ``Note that 0 is taken as a flag, not as the
332 * beginning of a field width.''
335 if (!(flags & LADJUST))
336 flags |= ZEROPAD; /* '-' disables '0' */
338 case '1': case '2': case '3': case '4':
339 case '5': case '6': case '7': case '8': case '9':
342 n = 10 * n + to_digit(ch);
344 } while (is_digit(ch));
347 #ifdef FLOATING_POINT
359 *(cp = buf) = va_arg(ap, int);
369 if ((long)_ulong < 0) {
375 #ifdef FLOATING_POINT
382 _double = va_arg(ap, double);
388 fmt_flags |= _IO_SHOWPOINT;
390 fmt_flags |= _IO_LEFT;
391 else if (flags & ZEROPAD)
392 fmt_flags |= _IO_INTERNAL, fill = '0';
393 n = _IO_outfloat(_double, fp, ch, width,
394 prec < 0 ? DEFPREC : prec,
395 fmt_flags, sign, fill);
404 * don't do unrealistic precision; just pad it with
405 * zeroes later, so buffer size stays rational.
407 if (prec > MAXFRACT) {
408 if ((ch != 'g' && ch != 'G') || (flags&ALT))
409 fpprec = prec - MAXFRACT;
411 } else if (prec == -1)
413 /* __cvt_double may have to round up before the
414 "start" of its buffer, i.e.
415 ``intf("%.2f", (double)9.999);'';
416 if the first character is still NUL, it did.
417 softsign avoids negative 0 if _double < 0 but
418 no significant digits will be shown. */
421 size = __cvt_double(_double, prec, flags, &softsign,
422 ch, cp, buf + sizeof(buf));
429 #endif /* FLOATING_POINT */
432 *va_arg(ap, long *) = ret;
433 else if (flags & SHORTINT)
434 *va_arg(ap, short *) = ret;
436 *va_arg(ap, int *) = ret;
437 continue; /* no output */
447 * ``The argument shall be a pointer to void. The
448 * value of the pointer is converted to a sequence
449 * of printable characters, in an implementation-
454 _ulong = (unsigned long)va_arg(ap, void *);
460 if ((cp = va_arg(ap, char *)) == NULL)
464 * can't use strlen; can only look for the
465 * NUL in the first `prec' characters, and
466 * strlen() will go further.
468 char *p = (char*)memchr(cp, 0, prec);
491 /* leading 0x/X only if non-zero */
492 if (flags & ALT && _ulong != 0)
495 /* unsigned conversions */
498 * ``... diouXx conversions ... if a precision is
499 * specified, the 0 flag will be ignored.''
502 number: if ((dprec = prec) >= 0)
506 * ``The result of converting a zero value with an
507 * explicit precision of zero is no characters.''
511 if (_ulong != 0 || prec != 0) {
512 char *xdigs; /* digits for [xX] conversion */
514 * unsigned mod is hard, and unsigned mod
515 * by a constant is easier than that by
516 * a variable; hence this switch.
521 *--cp = to_char(_ulong & 7);
524 /* handle octal leading 0 */
525 if (flags & ALT && *cp != '0')
530 /* many numbers are 1 digit */
531 while (_ulong >= 10) {
532 *--cp = to_char(_ulong % 10);
535 *--cp = to_char(_ulong);
540 xdigs = "0123456789ABCDEF";
541 else /* ch == 'x' || ch == 'p' */
542 xdigs = "0123456789abcdef";
544 *--cp = xdigs[_ulong & 15];
550 cp = "bug in vform: bad base";
554 size = buf + BUF - cp;
557 default: /* "%?" prints ?, unless ? is NUL */
560 /* pretend it was %c with argument ch */
569 * All reasonable formats wind up here. At this point,
570 * `cp' points to a string which (if not flags&LADJUST)
571 * should be padded out to `width' places. If
572 * flags&ZEROPAD, it should first be prefixed by any
573 * sign or other prefix; otherwise, it should be blank
574 * padded before the prefix is emitted. After any
575 * left-hand padding and prefixing, emit zeroes
576 * required by a decimal [diouxX] precision, then print
577 * the string proper, then emit zeroes required by any
578 * leftover floating precision; finally, if LADJUST,
583 * compute actual size, so we know how much to pad.
585 #if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
586 fieldsz = size + fpprec;
596 else if (flags & HEXPREFIX)
600 /* right-adjusting blank padding */
601 if ((flags & (LADJUST|ZEROPAD)) == 0)
602 PAD_SP(width - fieldsz);
607 } else if (flags & HEXPREFIX) {
613 /* right-adjusting zero padding */
614 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
615 PAD_0(width - fieldsz);
617 /* leading zeroes from decimal precision */
620 /* the string or number proper */
623 #if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
624 /* trailing f.p. zeroes */
628 /* left-adjusting padding (always blank) */
630 PAD_SP(width - fieldsz);
632 /* finally, adjust ret */
633 ret += width > fieldsz ? width : fieldsz;
643 #if defined(FLOATING_POINT) && !defined(_IO_USE_DTOA)
645 static char *exponent(register char *p, register int exp, int fmtch)
660 *--t = to_char(exp % 10);
661 } while ((exp /= 10) > 9);
663 for (; t < expbuf + MAXEXP; *p++ = *t++);
672 static char * round(double fract, int *exp,
673 register char *start, register char *end,
679 (void)modf(fract * 10, &tmp);
690 if (exp) { /* e/E; increment exponent */
694 else { /* f; add extra digit */
701 /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
702 else if (*signp == '-')
714 int __cvt_double(double number, register int prec, int flags, int *signp,
715 int fmtch, char *startp, char *endp)
717 register char *p, *t;
718 register double fract;
719 int dotrim = 0, expcnt, gformat = 0;
729 fract = modf(number, &integer);
731 /* get an extra slot for rounding. */
735 * get integer portion of number; put into the end of the buffer; the
736 * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
738 for (p = endp - 1; p >= startp && integer; ++expcnt) {
739 tmp = modf(integer / 10, &integer);
740 *p-- = to_char((int)((tmp + .01) * 10));
745 /* reverse integer into beginning of buffer */
747 for (; ++p < endp; *t++ = *p);
751 * if precision required or alternate flag set, add in a
754 if (prec || flags&ALT)
756 /* if requires more precision and some fraction left */
760 fract = modf(fract * 10, &tmp);
761 *t++ = to_char((int)tmp);
762 } while (--prec && fract);
764 startp = round(fract, (int *)NULL, startp,
765 t - 1, (char)0, signp);
767 for (; prec--; *t++ = '0');
771 eformat: if (expcnt) {
773 if (prec || flags&ALT)
775 /* if requires more precision and some integer left */
776 for (; prec && ++p < endp; --prec)
779 * if done precision and more of the integer component,
780 * round using it; adjust fract so we don't re-round
783 if (!prec && ++p < endp) {
785 startp = round((double)0, &expcnt, startp,
788 /* adjust expcnt for digit in front of decimal */
791 /* until first fractional digit, decrement exponent */
793 /* adjust expcnt for digit in front of decimal */
794 for (expcnt = -1;; --expcnt) {
795 fract = modf(fract * 10, &tmp);
799 *t++ = to_char((int)tmp);
800 if (prec || flags&ALT)
805 if (prec || flags&ALT)
808 /* if requires more precision and some fraction left */
812 fract = modf(fract * 10, &tmp);
813 *t++ = to_char((int)tmp);
814 } while (--prec && fract);
816 startp = round(fract, &expcnt, startp,
817 t - 1, (char)0, signp);
819 /* if requires more precision */
820 for (; prec--; *t++ = '0');
822 /* unless alternate flag, trim any g/G format trailing 0's */
823 if (gformat && !(flags&ALT)) {
824 while (t > startp && *--t == '0');
829 t = exponent(t, expcnt, fmtch);
833 /* a precision of 0 is treated as a precision of 1. */
837 * ``The style used depends on the value converted; style e
838 * will be used only if the exponent resulting from the
839 * conversion is less than -4 or greater than the precision.''
842 if (expcnt > prec || (!expcnt && fract && fract < .0001)) {
844 * g/G format counts "significant digits, not digits of
845 * precision; for the e/E format, this just causes an
846 * off-by-one problem, i.e. g/G considers the digit
847 * before the decimal point significant and e/E doesn't
848 * count it as precision.
851 fmtch -= 2; /* G->E, g->e */
856 * reverse integer into beginning of buffer,
857 * note, decrement precision
860 for (; ++p < endp; *t++ = *p, --prec);
864 * if precision required or alternate flag set, add in a
865 * decimal point. If no digits yet, add in leading 0.
867 if (prec || flags&ALT) {
873 /* if requires more precision and some fraction left */
876 /* If no integer part, don't count initial
877 * zeros as significant digits. */
879 fract = modf(fract * 10, &tmp);
880 *t++ = to_char((int)tmp);
881 } while(!tmp && !expcnt);
882 while (--prec && fract) {
883 fract = modf(fract * 10, &tmp);
884 *t++ = to_char((int)tmp);
888 startp = round(fract, (int *)NULL, startp,
889 t - 1, (char)0, signp);
891 /* alternate format, adds 0's for precision, else trim 0's */
893 for (; prec--; *t++ = '0');
895 while (t > startp && *--t == '0');
903 #endif /* defined(FLOATING_POINT) && !defined(_IO_USE_DTOA) */