[Ada] Fix invalid JSON real numbers generated with -gnatRj
gcc/ada/ * urealp.ads (UR_Write_To_JSON): Declare. * urealp.adb (Decimal_Exponent_Hi): Treat numbers in base 10 specially and rewrite handling of numbers in other bases. (Decimal_Exponent_Lo): Likewise. (Normalize): Minor tweak. (UR_Write_To_JSON): New wrapper procedure around UR_Write. * repinfo.adb (List_Type_Info): When the output is to JSON, call UR_Write_To_JSON instead of UR_Write.
This commit is contained in:
parent
05447313c9
commit
08c9ef089f
3 changed files with 126 additions and 20 deletions
|
@ -2030,7 +2030,7 @@ package body Repinfo is
|
|||
if List_Representation_Info_To_JSON then
|
||||
Write_Line (",");
|
||||
Write_Str (" ""Small"": ");
|
||||
UR_Write (Small_Value (Ent));
|
||||
UR_Write_To_JSON (Small_Value (Ent));
|
||||
else
|
||||
Write_Str ("for ");
|
||||
List_Name (Ent);
|
||||
|
@ -2052,9 +2052,9 @@ package body Repinfo is
|
|||
if List_Representation_Info_To_JSON then
|
||||
Write_Line (",");
|
||||
Write_Str (" ""Range"": [ ");
|
||||
UR_Write (Realval (Low_Bound (R)));
|
||||
UR_Write_To_JSON (Realval (Low_Bound (R)));
|
||||
Write_Str (", ");
|
||||
UR_Write (Realval (High_Bound (R)));
|
||||
UR_Write_To_JSON (Realval (High_Bound (R)));
|
||||
Write_Str (" ]");
|
||||
else
|
||||
Write_Str ("for ");
|
||||
|
|
|
@ -174,16 +174,30 @@ package body Urealp is
|
|||
return UI_Decimal_Digits_Hi (Val.Num) -
|
||||
UI_Decimal_Digits_Lo (Val.Den);
|
||||
|
||||
-- For based numbers, just subtract the decimal exponent from the
|
||||
-- high estimate of the number of digits in the numerator and add
|
||||
-- one to accommodate possible round off errors for non-decimal
|
||||
-- bases. For example:
|
||||
-- For based numbers, get the maximum number of digits in the numerator
|
||||
-- minus one and the either exact or floor value of the decimal exponent
|
||||
-- of the denominator, and subtract. For example:
|
||||
|
||||
-- 1_500_000 / 10**4 = 1.50E-2
|
||||
-- 321 / 10**3 = 3.21E-1
|
||||
-- 435 / 5**7 = 5.57E-3
|
||||
|
||||
else -- Val.Rbase /= 0
|
||||
return UI_Decimal_Digits_Hi (Val.Num) -
|
||||
Equivalent_Decimal_Exponent (Val) + 1;
|
||||
else
|
||||
declare
|
||||
E : Int;
|
||||
|
||||
begin
|
||||
if Val.Rbase = 10 then
|
||||
E := UI_To_Int (Val.Den);
|
||||
|
||||
else
|
||||
E := Equivalent_Decimal_Exponent (Val);
|
||||
if E < 0 then
|
||||
E := E - 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
return UI_Decimal_Digits_Hi (Val.Num) - 1 - E;
|
||||
end;
|
||||
end if;
|
||||
end Decimal_Exponent_Hi;
|
||||
|
||||
|
@ -213,16 +227,30 @@ package body Urealp is
|
|||
return UI_Decimal_Digits_Lo (Val.Num) -
|
||||
UI_Decimal_Digits_Hi (Val.Den) - 1;
|
||||
|
||||
-- For based numbers, just subtract the decimal exponent from the
|
||||
-- low estimate of the number of digits in the numerator and subtract
|
||||
-- one to accommodate possible round off errors for non-decimal
|
||||
-- bases. For example:
|
||||
-- For based numbers, get the minimum number of digits in the numerator
|
||||
-- minus one and the either exact or ceil value of the decimal exponent
|
||||
-- of the denominator, and subtract. For example:
|
||||
|
||||
-- 1_500_000 / 10**4 = 1.50E-2
|
||||
-- 321 / 10**3 = 3.21E-1
|
||||
-- 435 / 5**7 = 5.57E-3
|
||||
|
||||
else -- Val.Rbase /= 0
|
||||
return UI_Decimal_Digits_Lo (Val.Num) -
|
||||
Equivalent_Decimal_Exponent (Val) - 1;
|
||||
else
|
||||
declare
|
||||
E : Int;
|
||||
|
||||
begin
|
||||
if Val.Rbase = 10 then
|
||||
E := UI_To_Int (Val.Den);
|
||||
|
||||
else
|
||||
E := Equivalent_Decimal_Exponent (Val);
|
||||
if E > 0 then
|
||||
E := E + 1;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
return UI_Decimal_Digits_Lo (Val.Num) - 1 - E;
|
||||
end;
|
||||
end if;
|
||||
end Decimal_Exponent_Lo;
|
||||
|
||||
|
@ -374,7 +402,7 @@ package body Urealp is
|
|||
Tmp : Uint;
|
||||
Num : Uint;
|
||||
Den : Uint;
|
||||
M : constant Uintp.Save_Mark := Uintp.Mark;
|
||||
M : constant Uintp.Save_Mark := Mark;
|
||||
|
||||
begin
|
||||
-- Start by setting J to the greatest of the absolute values of the
|
||||
|
@ -1486,6 +1514,80 @@ package body Urealp is
|
|||
end if;
|
||||
end UR_Write;
|
||||
|
||||
----------------------
|
||||
-- UR_Write_To_JSON --
|
||||
----------------------
|
||||
|
||||
-- We defer to the implementation of UR_Write in all cases, either directly
|
||||
-- for values that are naturally written in a JSON compatible format, or by
|
||||
-- first computing a decimal approxixmation for other values.
|
||||
|
||||
procedure UR_Write_To_JSON (Real : Ureal) is
|
||||
Val : constant Ureal_Entry := Ureals.Table (Real);
|
||||
Imrk : constant Uintp.Save_Mark := Mark;
|
||||
Rmrk : constant Urealp.Save_Mark := Mark;
|
||||
|
||||
T : Ureal;
|
||||
|
||||
begin
|
||||
-- Zero is zero
|
||||
|
||||
if Val.Num = 0 then
|
||||
T := Real;
|
||||
|
||||
-- For constants with a denominator of zero, the value is simply the
|
||||
-- numerator value, since we are dividing by base**0, which is 1.
|
||||
|
||||
elsif Val.Den = 0 then
|
||||
T := Real;
|
||||
|
||||
-- Small powers of 2 get written in decimal fixed-point format
|
||||
|
||||
elsif Val.Rbase = 2
|
||||
and then Val.Den <= 3
|
||||
and then Val.Den >= -16
|
||||
then
|
||||
T := Real;
|
||||
|
||||
-- Constants in base 10 can be written in normal Ada literal style
|
||||
|
||||
elsif Val.Rbase = 10 then
|
||||
T := Real;
|
||||
|
||||
-- Rationals where numerator is divisible by denominator can be output
|
||||
-- as literals after we do the division. This includes the common case
|
||||
-- where the denominator is 1.
|
||||
|
||||
elsif Val.Rbase = 0 and then Val.Num mod Val.Den = 0 then
|
||||
T := Real;
|
||||
|
||||
-- For other constants, compute an approxixmation in base 10
|
||||
|
||||
else
|
||||
declare
|
||||
A : constant Ureal := UR_Abs (Real);
|
||||
-- The absolute value
|
||||
|
||||
E : constant Uint :=
|
||||
(if A < Ureal_1
|
||||
then UI_From_Int (3 - Decimal_Exponent_Lo (Real))
|
||||
else Uint_3);
|
||||
-- The exponent for at least 3 digits after the decimal point
|
||||
|
||||
Num : constant Uint :=
|
||||
UR_To_Uint (UR_Mul (A, UR_Exponentiate (Ureal_10, E)));
|
||||
-- The numerator appropriately rounded
|
||||
|
||||
begin
|
||||
T := UR_From_Components (Num, E, 10, Val.Negative);
|
||||
end;
|
||||
end if;
|
||||
|
||||
UR_Write (T);
|
||||
Release (Imrk);
|
||||
Release (Rmrk);
|
||||
end UR_Write_To_JSON;
|
||||
|
||||
-------------
|
||||
-- Ureal_0 --
|
||||
-------------
|
||||
|
|
|
@ -288,6 +288,10 @@ package Urealp is
|
|||
-- In the case where an expression is output, if Brackets is set to True,
|
||||
-- the expression is surrounded by square brackets.
|
||||
|
||||
procedure UR_Write_To_JSON (Real : Ureal);
|
||||
-- Writes value of Real to standard output in the JSON data interchange
|
||||
-- format specified by the ECMA-404 standard, for the -gnatRj output.
|
||||
|
||||
procedure pr (Real : Ureal);
|
||||
pragma Export (Ada, pr);
|
||||
-- Writes value of Real to standard output with a terminating line return,
|
||||
|
|
Loading…
Add table
Reference in a new issue