From owner-freebsd-hackers Tue Jan 17 09:16:28 1995 Return-Path: hackers-owner Received: (from root@localhost) by freefall.cdrom.com (8.6.9/8.6.6) id JAA10511 for hackers-outgoing; Tue, 17 Jan 1995 09:16:28 -0800 Received: from snoopy.mv.com (snoopy.mv.com [199.125.64.182]) by freefall.cdrom.com (8.6.9/8.6.6) with ESMTP id JAA10500 for ; Tue, 17 Jan 1995 09:16:18 -0800 Received: (from pw@localhost) by snoopy.mv.com (8.6.9/8.6.6) id OAA07055; Sun, 15 Jan 1995 14:45:11 -0500 Date: Sun, 15 Jan 1995 14:45:11 -0500 From: "Paul F. Werkowski" Message-Id: <199501151945.OAA07055@snoopy.mv.com> To: freebsd-hackers@freefall.cdrom.com Subject: old vfprintf bug back again in 2.x Sender: hackers-owner@FreeBSD.org Precedence: bulk A bug that was lurking in lib/libc/stdio/vfprintf.c prior to FreeBSD 1.1 is now again hiding in the 2.0 and -current source. The bug is demonstrated by this code: int main() { int FPRC = 16; double d = 0; printf( "%*.*e\n",FPRC+7,FPRC,d); } which results in 0e+00 instead of the correct 0.0000000000000000e+00 This breaks the AKCL (now GCL) compile/load feature. I looked at the considerable differences between the 1.1 and 2.0 versions of vfprintf and think I have reproduced the previous fixes. At least the modified version passes the GCL test. Perhaps some official bug fixer can look at this and commit to current /usr/src/lib/libc/stdio/? Paul *** vfprintf.c.dist Fri May 27 00:57:31 1994 --- vfprintf.c Sun Jan 15 14:38:03 1995 *************** *** 502,521 **** base = 10; goto number; #ifdef FLOATING_POINT ! case 'e': /* anomalous precision */ case 'E': ! prec = (prec == -1) ? ! DEFPREC + 1 : prec + 1; ! /* FALLTHROUGH */ ! goto fp_begin; ! case 'f': /* always print trailing zeroes */ ! if (prec != 0) ! flags |= ALT; case 'g': case 'G': ! if (prec == -1) prec = DEFPREC; ! fp_begin: _double = va_arg(ap, double); /* do this before tricky precision changes */ if (isinf(_double)) { if (_double < 0) --- 502,524 ---- base = 10; goto number; #ifdef FLOATING_POINT ! case 'e': case 'E': ! case 'f': case 'g': case 'G': ! if (prec == -1) { prec = DEFPREC; ! } else if ((ch == 'g' || ch == 'G') && prec == 0) { ! prec = 1; ! } ! ! 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) *************** *** 802,808 **** if (ch == 'f') mode = 3; else { ! mode = 2; } if (value < 0) { value = -value; --- 805,818 ---- if (ch == 'f') mode = 3; else { ! /* 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; *************** *** 810,816 **** } else *sign = '\000'; digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); ! if (flags & ALT) { /* Print trailing zeros */ bp = digits + ndigits; if (ch == 'f') { if (*digits == '0' && value) --- 820,826 ---- } else *sign = '\000'; digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); ! if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */ bp = digits + ndigits; if (ch == 'f') { if (*digits == '0' && value)