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 are permitted
30 * provided that the above copyright notice and this paragraph are
31 * duplicated in all such forms and that any documentation,
32 * advertising materials, and other materials related to such
33 * distribution and use acknowledge that the software was developed
34 * by the University of California, Berkeley. The name of the
35 * University may not be used to endorse or promote products derived
36 * from this software without specific prior written permission.
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
38 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
39 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
43 #if defined(LIBC_SCCS) && !defined(lint)
44 static char sccsid[] = "%W% (Berkeley) %G%";
45 #endif /* LIBC_SCCS and not lint */
48 * Actual printf innards.
50 * This code is large and complicated...
53 #include <sys/types.h>
63 int __cvt_double __P((double number, register int prec, int flags, int *signp, int fmtch, char *startp, char *endp));
67 * Define FLOATING_POINT to get floating point.
69 #ifndef NO_FLOATING_POINT
70 #define FLOATING_POINT
73 /* end of configuration stuff */
77 * Helper "class" for `fprintf to unbuffered': creates a
78 * temporary buffer. */
82 struct _IO_FILE_plus _f;
83 _IO_FILE *_put_stream;
87 DEFUN(_IO_helper_overflow, (fp, c),
88 _IO_FILE *fp AND int c)
90 _IO_FILE *target = ((struct helper_file*)fp)->_put_stream;
91 int used = fp->_IO_write_ptr - fp->_IO_write_base;
94 _IO_sputn(target, fp->_IO_write_base, used);
95 fp->_IO_write_ptr -= used;
97 return _IO_putc (c, fp);
100 static struct _IO_jump_t _IO_helper_jumps = {
102 JUMP_INIT(finish, _IO_default_finish),
103 JUMP_INIT(overflow, _IO_helper_overflow),
104 JUMP_INIT(underflow, _IO_default_underflow),
105 JUMP_INIT(uflow, _IO_default_uflow),
106 JUMP_INIT(pbackfail, _IO_default_pbackfail),
107 JUMP_INIT(xsputn, _IO_default_xsputn),
108 JUMP_INIT(xsgetn, _IO_default_xsgetn),
109 JUMP_INIT(seekoff, _IO_default_seekoff),
110 JUMP_INIT(seekpos, _IO_default_seekpos),
111 JUMP_INIT(setbuf, _IO_default_setbuf),
112 JUMP_INIT(sync, _IO_default_sync),
113 JUMP_INIT(doallocate, _IO_default_doallocate),
114 JUMP_INIT(read, _IO_default_read),
115 JUMP_INIT(write, _IO_default_write),
116 JUMP_INIT(seek, _IO_default_seek),
117 JUMP_INIT(close, _IO_default_close),
118 JUMP_INIT(stat, _IO_default_stat)
122 DEFUN(helper_vfprintf, (fp, fmt0, ap),
123 register _IO_FILE* fp AND char const *fmt0 AND _IO_va_list ap)
125 char buf[_IO_BUFSIZ];
126 struct helper_file helper;
127 register _IO_FILE *hp = (_IO_FILE*)&helper;
128 int result, to_flush;
130 /* initialize helper */
131 helper._put_stream = fp;
132 hp->_IO_write_base = buf;
133 hp->_IO_write_ptr = buf;
134 hp->_IO_write_end = buf+_IO_BUFSIZ;
135 hp->_IO_file_flags = _IO_MAGIC|_IO_NO_READS;
136 _IO_JUMPS(hp) = &_IO_helper_jumps;
138 /* Now print to helper instead. */
139 result = _IO_vfprintf(hp, fmt0, ap);
141 /* Now flush anything from the helper to the fp. */
142 if ((to_flush = hp->_IO_write_ptr - hp->_IO_write_base) > 0)
144 if (_IO_sputn(fp, hp->_IO_write_base, to_flush) != to_flush)
150 #ifdef FLOATING_POINT
153 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
155 extern double modf __P((double, double*));
157 #else /* no FLOATING_POINT */
161 #endif /* FLOATING_POINT */
165 * Macros for converting digits to letters and vice versa
167 #define to_digit(c) ((c) - '0')
168 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
169 #define to_char(n) ((n) + '0')
172 * Flags used during conversion.
174 #define LONGINT 0x01 /* long integer */
175 #define LONGDBL 0x02 /* long double; unimplemented */
176 #define SHORTINT 0x04 /* short integer */
177 #define ALT 0x08 /* alternate form */
178 #define LADJUST 0x10 /* left adjustment */
179 #define ZEROPAD 0x20 /* zero (as opposed to blank) pad */
180 #define HEXPREFIX 0x40 /* add 0x or 0X prefix */
183 DEFUN(_IO_vfprintf, (fp, fmt0, ap),
184 register _IO_FILE* fp AND char const *fmt0 AND _IO_va_list ap)
186 register const char *fmt; /* format string */
187 register int ch; /* character from fmt */
188 register int n; /* handy integer (short term usage) */
189 register char *cp; /* handy char pointer (short term usage) */
190 const char *fmark; /* for remembering a place in fmt */
191 register int flags; /* flags as above */
192 int ret; /* return value accumulator */
193 int width; /* width from format (%8d), or 0 */
194 int prec; /* precision from format (%.3d), or -1 */
195 char sign; /* sign prefix (' ', '+', '-', or \0) */
196 #ifdef FLOATING_POINT
197 int softsign; /* temporary negative sign for floats */
198 double _double; /* double precision arguments %[eEfgG] */
200 int fpprec; /* `extra' floating precision in [eEfgG] */
203 unsigned long _ulong; /* integer arguments %[diouxX] */
204 enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
205 int dprec; /* a copy of prec if [diouxX], 0 otherwise */
206 int dpad; /* extra 0 padding needed for integers */
207 int fieldsz; /* field size expanded by sign, dpad etc */
208 /* The initialization of 'size' is to suppress a warning that
209 'size' might be used unitialized. It seems gcc can't
210 quite grok this spaghetti code ... */
211 int size = 0; /* size of converted field or string */
212 char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
213 char ox[2]; /* space for 0x hex-prefix */
216 * BEWARE, these `goto error' on error, and PAD uses `n'.
218 #define PRINT(ptr, len) \
219 do { if (_IO_sputn(fp,ptr, len) != len) goto error; } while (0)
220 #define PAD_SP(howmany) if (_IO_padn(fp, ' ', howmany) < (howmany)) goto error;
221 #define PAD_0(howmany) if (_IO_padn(fp, '0', howmany) < (howmany)) goto error;
224 * To extend shorts properly, we need both signed and unsigned
225 * argument extraction methods.
228 (flags&LONGINT ? va_arg(ap, long) : \
229 flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
230 (long)va_arg(ap, int))
232 (flags&LONGINT ? va_arg(ap, unsigned long) : \
233 flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \
234 (unsigned long)va_arg(ap, unsigned int))
236 /* optimise stderr (and other unbuffered Unix files) */
237 if (fp->_IO_file_flags & _IO_UNBUFFERED)
238 return helper_vfprintf(fp, fmt0, ap);
244 * Scan the format for conversions (`%' character).
247 for (fmark = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
249 if ((n = fmt - fmark) != 0) {
255 fmt++; /* skip over '%' */
259 #if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
267 reswitch: switch (ch) {
270 * ``If the space and + flags both appear, the space
271 * flag will be ignored.''
282 * ``A negative field width argument is taken as a
283 * - flag followed by a positive field width.''
285 * They don't exclude field widths read from args.
287 if ((width = va_arg(ap, int)) >= 0)
293 flags &= ~ZEROPAD; /* '-' disables '0' */
299 if ((ch = *fmt++) == '*') {
301 prec = n < 0 ? -1 : n;
305 while (is_digit(ch)) {
306 n = 10 * n + to_digit(ch);
309 prec = n < 0 ? -1 : n;
313 * ``Note that 0 is taken as a flag, not as the
314 * beginning of a field width.''
317 if (!(flags & LADJUST))
318 flags |= ZEROPAD; /* '-' disables '0' */
320 case '1': case '2': case '3': case '4':
321 case '5': case '6': case '7': case '8': case '9':
324 n = 10 * n + to_digit(ch);
326 } while (is_digit(ch));
329 #ifdef FLOATING_POINT
341 *(cp = buf) = va_arg(ap, int);
351 if ((long)_ulong < 0) {
357 #ifdef FLOATING_POINT
364 _double = va_arg(ap, double);
370 fmt_flags |= _IO_SHOWPOINT;
372 fmt_flags |= _IO_LEFT;
373 else if (flags & ZEROPAD)
374 fmt_flags |= _IO_INTERNAL, fill = '0';
375 n = _IO_outfloat(_double, fp, ch, width,
376 prec < 0 ? DEFPREC : prec,
377 fmt_flags, sign, fill);
386 * don't do unrealistic precision; just pad it with
387 * zeroes later, so buffer size stays rational.
389 if (prec > MAXFRACT) {
390 if ((ch != 'g' && ch != 'G') || (flags&ALT))
391 fpprec = prec - MAXFRACT;
393 } else if (prec == -1)
395 /* __cvt_double may have to round up before the
396 "start" of its buffer, i.e.
397 ``intf("%.2f", (double)9.999);'';
398 if the first character is still NUL, it did.
399 softsign avoids negative 0 if _double < 0 but
400 no significant digits will be shown. */
403 size = __cvt_double(_double, prec, flags, &softsign,
404 ch, cp, buf + sizeof(buf));
411 #endif /* FLOATING_POINT */
414 *va_arg(ap, long *) = ret;
415 else if (flags & SHORTINT)
416 *va_arg(ap, short *) = ret;
418 *va_arg(ap, int *) = ret;
419 continue; /* no output */
429 * ``The argument shall be a pointer to void. The
430 * value of the pointer is converted to a sequence
431 * of printable characters, in an implementation-
436 _ulong = (unsigned long)va_arg(ap, void *);
442 if ((cp = va_arg(ap, char *)) == NULL)
446 * can't use strlen; can only look for the
447 * NUL in the first `prec' characters, and
448 * strlen() will go further.
450 char *p = (char*)memchr(cp, 0, prec);
473 /* leading 0x/X only if non-zero */
474 if (flags & ALT && _ulong != 0)
477 /* unsigned conversions */
480 * ``... diouXx conversions ... if a precision is
481 * specified, the 0 flag will be ignored.''
484 number: if ((dprec = prec) >= 0)
488 * ``The result of converting a zero value with an
489 * explicit precision of zero is no characters.''
493 if (_ulong != 0 || prec != 0) {
494 char *xdigs; /* digits for [xX] conversion */
496 * unsigned mod is hard, and unsigned mod
497 * by a constant is easier than that by
498 * a variable; hence this switch.
503 *--cp = to_char(_ulong & 7);
506 /* handle octal leading 0 */
507 if (flags & ALT && *cp != '0')
512 /* many numbers are 1 digit */
513 while (_ulong >= 10) {
514 *--cp = to_char(_ulong % 10);
517 *--cp = to_char(_ulong);
522 xdigs = "0123456789ABCDEF";
523 else /* ch == 'x' || ch == 'p' */
524 xdigs = "0123456789abcdef";
526 *--cp = xdigs[_ulong & 15];
532 cp = "bug in vform: bad base";
536 size = buf + BUF - cp;
539 default: /* "%?" prints ?, unless ? is NUL */
542 /* pretend it was %c with argument ch */
551 * All reasonable formats wind up here. At this point,
552 * `cp' points to a string which (if not flags&LADJUST)
553 * should be padded out to `width' places. If
554 * flags&ZEROPAD, it should first be prefixed by any
555 * sign or other prefix; otherwise, it should be blank
556 * padded before the prefix is emitted. After any
557 * left-hand padding and prefixing, emit zeroes
558 * required by a decimal [diouxX] precision, then print
559 * the string proper, then emit zeroes required by any
560 * leftover floating precision; finally, if LADJUST,
565 * compute actual size, so we know how much to pad.
567 #if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
568 fieldsz = size + fpprec;
578 else if (flags & HEXPREFIX)
582 /* right-adjusting blank padding */
583 if ((flags & (LADJUST|ZEROPAD)) == 0)
584 PAD_SP(width - fieldsz);
589 } else if (flags & HEXPREFIX) {
595 /* right-adjusting zero padding */
596 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
597 PAD_0(width - fieldsz);
599 /* leading zeroes from decimal precision */
602 /* the string or number proper */
605 #if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
606 /* trailing f.p. zeroes */
610 /* left-adjusting padding (always blank) */
612 PAD_SP(width - fieldsz);
614 /* finally, adjust ret */
615 ret += width > fieldsz ? width : fieldsz;
625 #if defined(FLOATING_POINT) && !defined(_IO_USE_DTOA)
627 static char *exponent(register char *p, register int exp, int fmtch)
642 *--t = to_char(exp % 10);
643 } while ((exp /= 10) > 9);
645 for (; t < expbuf + MAXEXP; *p++ = *t++);
654 static char * round(double fract, int *exp,
655 register char *start, register char *end,
661 (void)modf(fract * 10, &tmp);
672 if (exp) { /* e/E; increment exponent */
676 else { /* f; add extra digit */
683 /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
684 else if (*signp == '-')
696 int __cvt_double(double number, register int prec, int flags, int *signp,
697 int fmtch, char *startp, char *endp)
699 register char *p, *t;
700 register double fract;
701 int dotrim = 0, expcnt, gformat = 0;
711 fract = modf(number, &integer);
713 /* get an extra slot for rounding. */
717 * get integer portion of number; put into the end of the buffer; the
718 * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
720 for (p = endp - 1; p >= startp && integer; ++expcnt) {
721 tmp = modf(integer / 10, &integer);
722 *p-- = to_char((int)((tmp + .01) * 10));
727 /* reverse integer into beginning of buffer */
729 for (; ++p < endp; *t++ = *p);
733 * if precision required or alternate flag set, add in a
736 if (prec || flags&ALT)
738 /* if requires more precision and some fraction left */
742 fract = modf(fract * 10, &tmp);
743 *t++ = to_char((int)tmp);
744 } while (--prec && fract);
746 startp = round(fract, (int *)NULL, startp,
747 t - 1, (char)0, signp);
749 for (; prec--; *t++ = '0');
753 eformat: if (expcnt) {
755 if (prec || flags&ALT)
757 /* if requires more precision and some integer left */
758 for (; prec && ++p < endp; --prec)
761 * if done precision and more of the integer component,
762 * round using it; adjust fract so we don't re-round
765 if (!prec && ++p < endp) {
767 startp = round((double)0, &expcnt, startp,
770 /* adjust expcnt for digit in front of decimal */
773 /* until first fractional digit, decrement exponent */
775 /* adjust expcnt for digit in front of decimal */
776 for (expcnt = -1;; --expcnt) {
777 fract = modf(fract * 10, &tmp);
781 *t++ = to_char((int)tmp);
782 if (prec || flags&ALT)
787 if (prec || flags&ALT)
790 /* if requires more precision and some fraction left */
794 fract = modf(fract * 10, &tmp);
795 *t++ = to_char((int)tmp);
796 } while (--prec && fract);
798 startp = round(fract, &expcnt, startp,
799 t - 1, (char)0, signp);
801 /* if requires more precision */
802 for (; prec--; *t++ = '0');
804 /* unless alternate flag, trim any g/G format trailing 0's */
805 if (gformat && !(flags&ALT)) {
806 while (t > startp && *--t == '0');
811 t = exponent(t, expcnt, fmtch);
815 /* a precision of 0 is treated as a precision of 1. */
819 * ``The style used depends on the value converted; style e
820 * will be used only if the exponent resulting from the
821 * conversion is less than -4 or greater than the precision.''
824 if (expcnt > prec || (!expcnt && fract && fract < .0001)) {
826 * g/G format counts "significant digits, not digits of
827 * precision; for the e/E format, this just causes an
828 * off-by-one problem, i.e. g/G considers the digit
829 * before the decimal point significant and e/E doesn't
830 * count it as precision.
833 fmtch -= 2; /* G->E, g->e */
838 * reverse integer into beginning of buffer,
839 * note, decrement precision
842 for (; ++p < endp; *t++ = *p, --prec);
846 * if precision required or alternate flag set, add in a
847 * decimal point. If no digits yet, add in leading 0.
849 if (prec || flags&ALT) {
855 /* if requires more precision and some fraction left */
858 /* If no integer part, don't count initial
859 * zeros as significant digits. */
861 fract = modf(fract * 10, &tmp);
862 *t++ = to_char((int)tmp);
863 } while(!tmp && !expcnt);
864 while (--prec && fract) {
865 fract = modf(fract * 10, &tmp);
866 *t++ = to_char((int)tmp);
870 startp = round(fract, (int *)NULL, startp,
871 t - 1, (char)0, signp);
873 /* alternate format, adds 0's for precision, else trim 0's */
875 for (; prec--; *t++ = '0');
877 while (t > startp && *--t == '0');
885 #endif /* defined(FLOATING_POINT) && !defined(_IO_USE_DTOA) */