Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 15 Jan 1995 14:45:11 -0500
From:      "Paul F. Werkowski" <pw@snoopy.MV.COM>
To:        freebsd-hackers@freefall.cdrom.com
Subject:   old vfprintf bug back again in 2.x
Message-ID:  <199501151945.OAA07055@snoopy.mv.com>

next in thread | raw e-mail | index | archive | help


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)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199501151945.OAA07055>