The -gnatR output contains information about fixed-point types declared
in the program and it comprises real numbers, which are displayed using
a custom format specific to the compiler, which is not always compatible
with the JSON data interchange format.
The change also fixes an off-by-one bug in Decimal_Exponent_Lo and also
tweaks Decimal_Exponent_Hi for the sake of consistency.
Tested on x86_64-pc-linux-gnu, committed on trunk
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.
diff --git a/gcc/ada/repinfo.adb b/gcc/ada/repinfo.adb
--- a/gcc/ada/repinfo.adb
+++ b/gcc/ada/repinfo.adb
@@ -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 ");
diff --git a/gcc/ada/urealp.adb b/gcc/ada/urealp.adb
--- a/gcc/ada/urealp.adb
+++ b/gcc/ada/urealp.adb
@@ -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 --
-------------
diff --git a/gcc/ada/urealp.ads b/gcc/ada/urealp.ads
--- a/gcc/ada/urealp.ads
+++ b/gcc/ada/urealp.ads
@@ -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,