Ricky W. Butler wrote:
[...] x := 0.5000000000000E+00; writeln(' x = ',x:10:3); [...]
incorrectly prints out
x = 5.000
[...]
Thanks for pointing us to this serious bug. I fixed it immediately but needed some time for testing.
Here ist the patch to the GPC source file `gpc-lex.c' to fix the bug:
8< -------------------------------------------------------------
diff -r -U3 -p -N -X /usr/local/bin/gpcdiff.exclude gpc-old/p/gpc-lex.c gpc/p/gpc-lex.c --- gpc-old/p/gpc-lex.c Tue Jul 20 08:24:10 1999 +++ gpc/p/gpc-lex.c Tue Jul 20 12:02:34 1999 @@ -2044,7 +2044,6 @@ yylex () c = getc (finput); if ((c == '+') || (c == '-')) { - *p++ = c; if (c == '-') esign = -1; c = getc (finput); @@ -2053,11 +2052,15 @@ yylex () error ("real constant exponent has no digits"); while (isdigit (c)) { - expon = 10*expon+c-'0'; + expon = 10 * expon + c - '0'; c = getc (finput); } - expon = esign*expon+adjust_exp; - expon *= esign; + expon = esign * expon + adjust_exp; + if (expon < 0) + { + *p++ = '-'; + expon = - expon; + } exp_store_loc = p; store_exp (expon); p = exp_store_loc;
8< -------------------------------------------------------------
And here is the program I used to generate the program to test for further bugs of the same type.
8< -------------------------------------------------------------
Program GenRick;
Const Tests = 10000;
Var i, j, FieldWidth, digits: Integer;
begin writeln ( 'Program Rick1a;' ); writeln; writeln ( 'Var' ); writeln ( ' x, y, a: Real;' ); writeln ( ' S: String ( 137 );' ); writeln ( ' i: Integer;' ); writeln ( ' OK: Boolean = true;' ); writeln; writeln ( 'begin' ); for i:= 1 to Tests do begin write ( ' x:= ' ); case Random ( 3 ) of 1: write ( '+' ); 2: write ( '-' ); end (* case *); for j:= 0 to Random ( 10 ) do write ( succ ( '0', Random ( 10 ) ) ); if Random ( 1 ) = 0 then begin write ( '.' ); for j:= 0 to Random ( 10 ) do write ( succ ( '0', Random ( 10 ) ) ); end (* if *); case Random ( 3 ) of 1: begin write ( 'e' ); case Random ( 3 ) of 1: write ( '+' ); 2: write ( '-' ); end (* case *); for j:= 0 to Random ( 2 ) do write ( succ ( '0', Random ( 10 ) ) ); end (* 1 *); 2: begin write ( 'E' ); case Random ( 3 ) of 1: write ( '+' ); 2: write ( '-' ); end (* case *); for j:= 0 to Random ( 2 ) do write ( succ ( '0', Random ( 10 ) ) ); end (* 2 *); end (* case *); writeln ( ';' ); case Random ( 7 ) of 0..3: begin FieldWidth:= Random ( 42 ); digits:= Random ( 13 ); writeln ( ' WriteStr ( S, x : ', FieldWidth, ' : ', digits, ' );' ); writeln ( ' a:= 5;' ); writeln ( ' for i:= 1 to ', digits, ' do' ); writeln ( ' a:= 0.1 * a;' ); end (* 0..3 *); 4, 5: begin FieldWidth:= Random ( 42 ); digits:= min ( 10, FieldWidth - 7 ); writeln ( ' WriteStr ( S, x : ', FieldWidth, ' );' ); writeln ( ' a:= abs ( x );' ); writeln ( ' for i:= 1 to ', digits, ' do' ); writeln ( ' a:= 0.1 * a;' ); end (* 4, 5 *); 6: begin writeln ( ' WriteStr ( S, x );' ); writeln ( ' a:= 1E-10 * abs ( x );' ); end (* 6 *); end (* case *); writeln ( ' ReadStr ( S, y );' ); writeln ( ' if abs ( x - y ) > a then' ); writeln ( ' begin' ); writeln ( ' OK:= false;' ); writeln ( ' writeln ( ''failed: '', x, '' '', y, '' '', abs ( x - y ), '' '', a, '' '', S );' ); writeln ( ' end (* if *);' ); end (* for *); writeln ( ' if OK then' ); writeln ( ' writeln ( ''OK'' )' ); writeln ( 'end.' ) end.
8< -------------------------------------------------------------
Hope this helps,
Peter