From d26be6f09dd9fb8394f3a28ee539c7dad0ea2d6d Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Sun, 12 Mar 1995 13:26:49 +0000 Subject: [PATCH] Obtained from: 1.1.5. Originally by jtc. Cosmetically changed for this commit by bde. Fix bugs in floating point formatting. The 4.4lite version is similar to revision 1.3 in old-cvs and is missing all of jtc's fixes in revision 1.4 in old-cvs. Revision 1.2 in ncvs fixed one of the old bugs but introduced at least one new one (for %.0e). old-cvs log: revision 1.4 date: 1993/11/04 19:38:22; author: jtc; state: Exp; lines: +33 -20 My work from NetBSD to make printf() & friends ANSI C compliant. Fixes several bugs in floating point formatting: 1. Trailing zeros were being stripped with %e format. 2. %g/%G formats incorrect. 3. Lots of other nits. --- lib/libc/stdio/vfprintf.c | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c index ebd772fa30c7..65a1eb4566be 100644 --- a/lib/libc/stdio/vfprintf.c +++ b/lib/libc/stdio/vfprintf.c @@ -502,19 +502,20 @@ reswitch: switch (ch) { base = 10; goto number; #ifdef FLOATING_POINT - case 'e': /* anomalous precision */ + case 'e': case 'E': - prec = (prec == -1) ? - DEFPREC + 1 : prec + 1; - /* FALLTHROUGH */ - case 'f': /* always print trailing zeroes */ - if (prec != 0) - flags |= ALT; + case 'f': + goto fp_begin; case 'g': case 'G': - if (prec == -1) + if (prec == 0) + prec = 1; +fp_begin: if (prec == -1) prec = DEFPREC; -fp_begin: _double = va_arg(ap, double); + if (flags & LONGDBL) + _double = (double)va_arg(ap, long double); + else + _double = va_arg(ap, double); /* do this before tricky precision changes */ if (isinf(_double)) { if (_double < 0) @@ -728,9 +729,8 @@ number: if ((dprec = prec) >= 0) } else { /* glue together f_p fragments */ if (ch >= 'f') { /* 'f' or 'g' */ if (_double == 0) { - /* kludge for __dtoa irregularity */ - if (prec == 0 || - (flags & ALT) == 0) { + /* kludge for __dtoa irregularity */ + if (prec == 0 && (flags & ALT) == 0) { PRINT("0", 1); } else { PRINT("0.", 2); @@ -799,9 +799,16 @@ cvt(value, ndigits, flags, sign, decpt, ch, length) char *digits, *bp, *rve; if (ch == 'f') - mode = 3; + mode = 3; /* ndigits after the decimal point */ else { - mode = 2; + /* + * To obtain ndigits after the decimal point for the 'e' + * and 'E' formats, round to ndigits + 1 significant + * figures. + */ + if (ch == 'e' || ch == 'E') + ndigits++; + mode = 2; /* ndigits significant digits */ } if (value < 0) { value = -value; @@ -809,7 +816,8 @@ cvt(value, ndigits, flags, sign, decpt, ch, length) } else *sign = '\000'; digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); - if (flags & ALT) { /* Print trailing zeros */ + if ((ch != 'g' && ch != 'G') || flags & ALT) { + /* print trailing zeros */ bp = digits + ndigits; if (ch == 'f') { if (*digits == '0' && value)