summaryrefslogtreecommitdiff
path: root/gcc/ada/s-valrea.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/s-valrea.adb')
-rw-r--r--gcc/ada/s-valrea.adb78
1 files changed, 67 insertions, 11 deletions
diff --git a/gcc/ada/s-valrea.adb b/gcc/ada/s-valrea.adb
index 7d93472a538..28f687e8ca2 100644
--- a/gcc/ada/s-valrea.adb
+++ b/gcc/ada/s-valrea.adb
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2000 Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2003 Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -81,6 +81,17 @@ package body System.Val_Real is
After_Point : Natural := 0;
-- Set to 1 after the point
+ Num_Saved_Zeroes : Natural := 0;
+ -- This counts zeroes after the decimal point. A non-zero value means
+ -- that this number of previously scanned digits are zero. if the end
+ -- of the number is reached, these zeroes are simply discarded, which
+ -- ensures that trailing zeroes after the point never affect the value
+ -- (which might otherwise happen as a result of rounding). With this
+ -- processing in place, we can ensure that, for example, we get the
+ -- same exact result from 1.0E+49 and 1.0000000E+49. This is not
+ -- necessarily required in a case like this where the result is not
+ -- a machine number, but it is certainly a desirable behavior.
+
procedure Scanf;
-- Scans integer literal value starting at current character position.
-- For each digit encountered, Uval is multiplied by 10.0, and the new
@@ -96,9 +107,36 @@ package body System.Val_Real is
begin
loop
Digit := Character'Pos (Str (P)) - Character'Pos ('0');
- Uval := Uval * 10.0 + Long_Long_Float (Digit);
P := P + 1;
- Scale := Scale - After_Point;
+
+ -- Save up trailing zeroes after the decimal point
+
+ if Digit = 0 and After_Point = 1 then
+ Num_Saved_Zeroes := Num_Saved_Zeroes + 1;
+
+ -- Here for a non-zero digit
+
+ else
+ -- First deal with any previously saved zeroes
+
+ if Num_Saved_Zeroes /= 0 then
+ while Num_Saved_Zeroes > Maxpow loop
+ Uval := Uval * Powten (Maxpow);
+ Num_Saved_Zeroes := Num_Saved_Zeroes - Maxpow;
+ Scale := Scale - Maxpow;
+ end loop;
+
+ Uval := Uval * Powten (Num_Saved_Zeroes);
+ Scale := Scale - Num_Saved_Zeroes;
+
+ Num_Saved_Zeroes := 0;
+ end if;
+
+ -- Accumulate new digit
+
+ Uval := Uval * 10.0 + Long_Long_Float (Digit);
+ Scale := Scale - After_Point;
+ end if;
-- Done if end of input field
@@ -197,16 +235,36 @@ package body System.Val_Real is
raise Constraint_Error;
end if;
- P := P + 1;
- Fdigit := Long_Long_Float (Digit);
+ -- Save up trailing zeroes after the decimal point
+
+ if Digit = 0 and After_Point = 1 then
+ Num_Saved_Zeroes := Num_Saved_Zeroes + 1;
+
+ -- Here for a non-zero digit
- if Fdigit >= Base then
- Bad_Base := True;
else
- Scale := Scale - After_Point;
- Uval := Uval * Base + Fdigit;
+ -- First deal with any previously saved zeroes
+
+ if Num_Saved_Zeroes /= 0 then
+ Uval := Uval * Base ** Num_Saved_Zeroes;
+ Scale := Scale - Num_Saved_Zeroes;
+ Num_Saved_Zeroes := 0;
+ end if;
+
+ -- Now accumulate the new digit
+
+ Fdigit := Long_Long_Float (Digit);
+
+ if Fdigit >= Base then
+ Bad_Base := True;
+ else
+ Scale := Scale - After_Point;
+ Uval := Uval * Base + Fdigit;
+ end if;
end if;
+ P := P + 1;
+
if P > Max then
raise Constraint_Error;
@@ -276,7 +334,6 @@ package body System.Val_Real is
-- For base 10, use power of ten table, repeatedly if necessary.
elsif Scale > 0 then
-
while Scale > Maxpow loop
Uval := Uval * Powten (Maxpow);
Scale := Scale - Maxpow;
@@ -287,7 +344,6 @@ package body System.Val_Real is
end if;
elsif Scale < 0 then
-
while (-Scale) > Maxpow loop
Uval := Uval / Powten (Maxpow);
Scale := Scale + Maxpow;