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 _IO_helper_overflow (fp
, c
)
91 _IO_FILE
*target
= ((struct helper_file
*)fp
)->_put_stream
;
92 int used
= fp
->_IO_write_ptr
- fp
->_IO_write_base
;
95 _IO_sputn(target
, fp
->_IO_write_base
, used
);
96 fp
->_IO_write_ptr
-= used
;
98 return _IO_putc (c
, fp
);
101 static struct _IO_jump_t _IO_helper_jumps
= {
103 JUMP_INIT(finish
, _IO_default_finish
),
104 JUMP_INIT(overflow
, _IO_helper_overflow
),
105 JUMP_INIT(underflow
, _IO_default_underflow
),
106 JUMP_INIT(uflow
, _IO_default_uflow
),
107 JUMP_INIT(pbackfail
, _IO_default_pbackfail
),
108 JUMP_INIT(xsputn
, _IO_default_xsputn
),
109 JUMP_INIT(xsgetn
, _IO_default_xsgetn
),
110 JUMP_INIT(seekoff
, _IO_default_seekoff
),
111 JUMP_INIT(seekpos
, _IO_default_seekpos
),
112 JUMP_INIT(setbuf
, _IO_default_setbuf
),
113 JUMP_INIT(sync
, _IO_default_sync
),
114 JUMP_INIT(doallocate
, _IO_default_doallocate
),
115 JUMP_INIT(read
, _IO_default_read
),
116 JUMP_INIT(write
, _IO_default_write
),
117 JUMP_INIT(seek
, _IO_default_seek
),
118 JUMP_INIT(close
, _IO_default_close
),
119 JUMP_INIT(stat
, _IO_default_stat
)
123 helper_vfprintf (fp
, fmt0
, ap
)
128 char buf
[_IO_BUFSIZ
];
129 struct helper_file helper
;
130 register _IO_FILE
*hp
= (_IO_FILE
*)&helper
;
131 int result
, to_flush
;
133 /* initialize helper */
134 helper
._put_stream
= fp
;
135 hp
->_IO_write_base
= buf
;
136 hp
->_IO_write_ptr
= buf
;
137 hp
->_IO_write_end
= buf
+_IO_BUFSIZ
;
138 hp
->_IO_file_flags
= _IO_MAGIC
|_IO_NO_READS
;
139 _IO_JUMPS(hp
) = &_IO_helper_jumps
;
141 /* Now print to helper instead. */
142 result
= _IO_vfprintf(hp
, fmt0
, ap
);
144 /* Now flush anything from the helper to the fp. */
145 if ((to_flush
= hp
->_IO_write_ptr
- hp
->_IO_write_base
) > 0)
147 if (_IO_sputn(fp
, hp
->_IO_write_base
, to_flush
) != to_flush
)
153 #ifdef FLOATING_POINT
156 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
158 extern double modf
__P((double, double*));
160 #else /* no FLOATING_POINT */
164 #endif /* FLOATING_POINT */
168 * Macros for converting digits to letters and vice versa
170 #define to_digit(c) ((c) - '0')
171 #define is_digit(c) ((unsigned)to_digit(c) <= 9)
172 #define to_char(n) ((n) + '0')
175 * Flags used during conversion.
177 #define LONGINT 0x01 /* long integer */
178 #define LONGDBL 0x02 /* long double; unimplemented */
179 #define SHORTINT 0x04 /* short integer */
180 #define ALT 0x08 /* alternate form */
181 #define LADJUST 0x10 /* left adjustment */
182 #define ZEROPAD 0x20 /* zero (as opposed to blank) pad */
183 #define HEXPREFIX 0x40 /* add 0x or 0X prefix */
186 _IO_vfprintf (fp
, fmt0
, ap
)
191 register const char *fmt
; /* format string */
192 register int ch
; /* character from fmt */
193 register int n
; /* handy integer (short term usage) */
194 register char *cp
; /* handy char pointer (short term usage) */
195 const char *fmark
; /* for remembering a place in fmt */
196 register int flags
; /* flags as above */
197 int ret
; /* return value accumulator */
198 int width
; /* width from format (%8d), or 0 */
199 int prec
; /* precision from format (%.3d), or -1 */
200 char sign
; /* sign prefix (' ', '+', '-', or \0) */
201 #ifdef FLOATING_POINT
202 int softsign
; /* temporary negative sign for floats */
203 double _double
; /* double precision arguments %[eEfgG] */
205 int fpprec
; /* `extra' floating precision in [eEfgG] */
208 unsigned long _ulong
; /* integer arguments %[diouxX] */
209 enum { OCT
, DEC
, HEX
} base
;/* base for [diouxX] conversion */
210 int dprec
; /* a copy of prec if [diouxX], 0 otherwise */
211 int dpad
; /* extra 0 padding needed for integers */
212 int fieldsz
; /* field size expanded by sign, dpad etc */
213 /* The initialization of 'size' is to suppress a warning that
214 'size' might be used unitialized. It seems gcc can't
215 quite grok this spaghetti code ... */
216 int size
= 0; /* size of converted field or string */
217 char buf
[BUF
]; /* space for %c, %[diouxX], %[eEfgG] */
218 char ox
[2]; /* space for 0x hex-prefix */
221 * BEWARE, these `goto error' on error, and PAD uses `n'.
223 #define PRINT(ptr, len) \
224 do { if (_IO_sputn(fp,ptr, len) != len) goto error; } while (0)
225 #define PAD_SP(howmany) if (_IO_padn(fp, ' ', howmany) < (howmany)) goto error;
226 #define PAD_0(howmany) if (_IO_padn(fp, '0', howmany) < (howmany)) goto error;
229 * To extend shorts properly, we need both signed and unsigned
230 * argument extraction methods.
233 (flags&LONGINT ? va_arg(ap, long) : \
234 flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
235 (long)va_arg(ap, int))
237 (flags&LONGINT ? va_arg(ap, unsigned long) : \
238 flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \
239 (unsigned long)va_arg(ap, unsigned int))
241 /* optimise stderr (and other unbuffered Unix files) */
242 if (fp
->_IO_file_flags
& _IO_UNBUFFERED
)
243 return helper_vfprintf(fp
, fmt0
, ap
);
249 * Scan the format for conversions (`%' character).
252 for (fmark
= fmt
; (ch
= *fmt
) != '\0' && ch
!= '%'; fmt
++)
254 if ((n
= fmt
- fmark
) != 0) {
260 fmt
++; /* skip over '%' */
264 #if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
272 reswitch
: switch (ch
) {
275 * ``If the space and + flags both appear, the space
276 * flag will be ignored.''
287 * ``A negative field width argument is taken as a
288 * - flag followed by a positive field width.''
290 * They don't exclude field widths read from args.
292 if ((width
= va_arg(ap
, int)) >= 0)
298 flags
&= ~ZEROPAD
; /* '-' disables '0' */
304 if ((ch
= *fmt
++) == '*') {
306 prec
= n
< 0 ? -1 : n
;
310 while (is_digit(ch
)) {
311 n
= 10 * n
+ to_digit(ch
);
314 prec
= n
< 0 ? -1 : n
;
318 * ``Note that 0 is taken as a flag, not as the
319 * beginning of a field width.''
322 if (!(flags
& LADJUST
))
323 flags
|= ZEROPAD
; /* '-' disables '0' */
325 case '1': case '2': case '3': case '4':
326 case '5': case '6': case '7': case '8': case '9':
329 n
= 10 * n
+ to_digit(ch
);
331 } while (is_digit(ch
));
334 #ifdef FLOATING_POINT
346 *(cp
= buf
) = va_arg(ap
, int);
356 if ((long)_ulong
< 0) {
362 #ifdef FLOATING_POINT
369 _double
= va_arg(ap
, double);
375 fmt_flags
|= _IO_SHOWPOINT
;
377 fmt_flags
|= _IO_LEFT
;
378 else if (flags
& ZEROPAD
)
379 fmt_flags
|= _IO_INTERNAL
, fill
= '0';
380 n
= _IO_outfloat(_double
, fp
, ch
, width
,
381 prec
< 0 ? DEFPREC
: prec
,
382 fmt_flags
, sign
, fill
);
391 * don't do unrealistic precision; just pad it with
392 * zeroes later, so buffer size stays rational.
394 if (prec
> MAXFRACT
) {
395 if ((ch
!= 'g' && ch
!= 'G') || (flags
&ALT
))
396 fpprec
= prec
- MAXFRACT
;
398 } else if (prec
== -1)
400 /* __cvt_double may have to round up before the
401 "start" of its buffer, i.e.
402 ``intf("%.2f", (double)9.999);'';
403 if the first character is still NUL, it did.
404 softsign avoids negative 0 if _double < 0 but
405 no significant digits will be shown. */
408 size
= __cvt_double(_double
, prec
, flags
, &softsign
,
409 ch
, cp
, buf
+ sizeof(buf
));
416 #endif /* FLOATING_POINT */
419 *va_arg(ap
, long *) = ret
;
420 else if (flags
& SHORTINT
)
421 *va_arg(ap
, short *) = ret
;
423 *va_arg(ap
, int *) = ret
;
424 continue; /* no output */
434 * ``The argument shall be a pointer to void. The
435 * value of the pointer is converted to a sequence
436 * of printable characters, in an implementation-
441 _ulong
= (unsigned long)va_arg(ap
, void *);
447 if ((cp
= va_arg(ap
, char *)) == NULL
)
451 * can't use strlen; can only look for the
452 * NUL in the first `prec' characters, and
453 * strlen() will go further.
455 char *p
= (char*)memchr(cp
, 0, prec
);
478 /* leading 0x/X only if non-zero */
479 if (flags
& ALT
&& _ulong
!= 0)
482 /* unsigned conversions */
485 * ``... diouXx conversions ... if a precision is
486 * specified, the 0 flag will be ignored.''
489 number
: if ((dprec
= prec
) >= 0)
493 * ``The result of converting a zero value with an
494 * explicit precision of zero is no characters.''
498 if (_ulong
!= 0 || prec
!= 0) {
499 char *xdigs
; /* digits for [xX] conversion */
501 * unsigned mod is hard, and unsigned mod
502 * by a constant is easier than that by
503 * a variable; hence this switch.
508 *--cp
= to_char(_ulong
& 7);
511 /* handle octal leading 0 */
512 if (flags
& ALT
&& *cp
!= '0')
517 /* many numbers are 1 digit */
518 while (_ulong
>= 10) {
519 *--cp
= to_char(_ulong
% 10);
522 *--cp
= to_char(_ulong
);
527 xdigs
= "0123456789ABCDEF";
528 else /* ch == 'x' || ch == 'p' */
529 xdigs
= "0123456789abcdef";
531 *--cp
= xdigs
[_ulong
& 15];
537 cp
= "bug in vform: bad base";
541 size
= buf
+ BUF
- cp
;
544 default: /* "%?" prints ?, unless ? is NUL */
547 /* pretend it was %c with argument ch */
556 * All reasonable formats wind up here. At this point,
557 * `cp' points to a string which (if not flags&LADJUST)
558 * should be padded out to `width' places. If
559 * flags&ZEROPAD, it should first be prefixed by any
560 * sign or other prefix; otherwise, it should be blank
561 * padded before the prefix is emitted. After any
562 * left-hand padding and prefixing, emit zeroes
563 * required by a decimal [diouxX] precision, then print
564 * the string proper, then emit zeroes required by any
565 * leftover floating precision; finally, if LADJUST,
570 * compute actual size, so we know how much to pad.
572 #if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
573 fieldsz
= size
+ fpprec
;
583 else if (flags
& HEXPREFIX
)
587 /* right-adjusting blank padding */
588 if ((flags
& (LADJUST
|ZEROPAD
)) == 0)
589 PAD_SP(width
- fieldsz
);
594 } else if (flags
& HEXPREFIX
) {
600 /* right-adjusting zero padding */
601 if ((flags
& (LADJUST
|ZEROPAD
)) == ZEROPAD
)
602 PAD_0(width
- fieldsz
);
604 /* leading zeroes from decimal precision */
607 /* the string or number proper */
610 #if defined(FLOATING_POINT) && !defined (_IO_USE_DTOA)
611 /* trailing f.p. zeroes */
615 /* left-adjusting padding (always blank) */
617 PAD_SP(width
- fieldsz
);
619 /* finally, adjust ret */
620 ret
+= width
> fieldsz
? width
: fieldsz
;
630 #if defined(FLOATING_POINT) && !defined(_IO_USE_DTOA)
632 static char *exponent(register char *p
, register int exp
, int fmtch
)
647 *--t
= to_char(exp
% 10);
648 } while ((exp
/= 10) > 9);
650 for (; t
< expbuf
+ MAXEXP
; *p
++ = *t
++);
659 static char * round(double fract
, int *exp
,
660 register char *start
, register char *end
,
666 (void)modf(fract
* 10, &tmp
);
677 if (exp
) { /* e/E; increment exponent */
681 else { /* f; add extra digit */
688 /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
689 else if (*signp
== '-')
701 int __cvt_double(double number
, register int prec
, int flags
, int *signp
,
702 int fmtch
, char *startp
, char *endp
)
704 register char *p
, *t
;
705 register double fract
;
706 int dotrim
= 0, expcnt
, gformat
= 0;
716 fract
= modf(number
, &integer
);
718 /* get an extra slot for rounding. */
722 * get integer portion of number; put into the end of the buffer; the
723 * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
725 for (p
= endp
- 1; p
>= startp
&& integer
; ++expcnt
) {
726 tmp
= modf(integer
/ 10, &integer
);
727 *p
-- = to_char((int)((tmp
+ .01) * 10));
732 /* reverse integer into beginning of buffer */
734 for (; ++p
< endp
; *t
++ = *p
);
738 * if precision required or alternate flag set, add in a
741 if (prec
|| flags
&ALT
)
743 /* if requires more precision and some fraction left */
747 fract
= modf(fract
* 10, &tmp
);
748 *t
++ = to_char((int)tmp
);
749 } while (--prec
&& fract
);
751 startp
= round(fract
, (int *)NULL
, startp
,
752 t
- 1, (char)0, signp
);
754 for (; prec
--; *t
++ = '0');
758 eformat
: if (expcnt
) {
760 if (prec
|| flags
&ALT
)
762 /* if requires more precision and some integer left */
763 for (; prec
&& ++p
< endp
; --prec
)
766 * if done precision and more of the integer component,
767 * round using it; adjust fract so we don't re-round
770 if (!prec
&& ++p
< endp
) {
772 startp
= round((double)0, &expcnt
, startp
,
775 /* adjust expcnt for digit in front of decimal */
778 /* until first fractional digit, decrement exponent */
780 /* adjust expcnt for digit in front of decimal */
781 for (expcnt
= -1;; --expcnt
) {
782 fract
= modf(fract
* 10, &tmp
);
786 *t
++ = to_char((int)tmp
);
787 if (prec
|| flags
&ALT
)
792 if (prec
|| flags
&ALT
)
795 /* if requires more precision and some fraction left */
799 fract
= modf(fract
* 10, &tmp
);
800 *t
++ = to_char((int)tmp
);
801 } while (--prec
&& fract
);
803 startp
= round(fract
, &expcnt
, startp
,
804 t
- 1, (char)0, signp
);
806 /* if requires more precision */
807 for (; prec
--; *t
++ = '0');
809 /* unless alternate flag, trim any g/G format trailing 0's */
810 if (gformat
&& !(flags
&ALT
)) {
811 while (t
> startp
&& *--t
== '0');
816 t
= exponent(t
, expcnt
, fmtch
);
820 /* a precision of 0 is treated as a precision of 1. */
824 * ``The style used depends on the value converted; style e
825 * will be used only if the exponent resulting from the
826 * conversion is less than -4 or greater than the precision.''
829 if (expcnt
> prec
|| (!expcnt
&& fract
&& fract
< .0001)) {
831 * g/G format counts "significant digits, not digits of
832 * precision; for the e/E format, this just causes an
833 * off-by-one problem, i.e. g/G considers the digit
834 * before the decimal point significant and e/E doesn't
835 * count it as precision.
838 fmtch
-= 2; /* G->E, g->e */
843 * reverse integer into beginning of buffer,
844 * note, decrement precision
847 for (; ++p
< endp
; *t
++ = *p
, --prec
);
851 * if precision required or alternate flag set, add in a
852 * decimal point. If no digits yet, add in leading 0.
854 if (prec
|| flags
&ALT
) {
860 /* if requires more precision and some fraction left */
863 /* If no integer part, don't count initial
864 * zeros as significant digits. */
866 fract
= modf(fract
* 10, &tmp
);
867 *t
++ = to_char((int)tmp
);
868 } while(!tmp
&& !expcnt
);
869 while (--prec
&& fract
) {
870 fract
= modf(fract
* 10, &tmp
);
871 *t
++ = to_char((int)tmp
);
875 startp
= round(fract
, (int *)NULL
, startp
,
876 t
- 1, (char)0, signp
);
878 /* alternate format, adds 0's for precision, else trim 0's */
880 for (; prec
--; *t
++ = '0');
882 while (t
> startp
&& *--t
== '0');
890 #endif /* defined(FLOATING_POINT) && !defined(_IO_USE_DTOA) */