[Ada] Unrecursify Set_Digit/Set_Image_Unsigned procedure
authorLiaiss Merzougue <merzougue@adacore.com>
Thu, 8 Oct 2020 15:26:11 +0000 (15:26 +0000)
committerPierre-Marie de Rodat <derodat@adacore.com>
Wed, 25 Nov 2020 13:22:25 +0000 (08:22 -0500)
gcc/ada/

* libgnat/s-imagei.adb
(Set_Digits): Rewrite the procedure to remove recursion.
(Image_Integer, Set_Image_Integer): Update assertions and remove
redundant ones.
* libgnat/s-imageu.adb
(Set_Image_Unsigned): Rewrite the procedure to remove recursion.

gcc/ada/libgnat/s-imagei.adb
gcc/ada/libgnat/s-imageu.adb

index c739dfb..36c1f6f 100644 (file)
@@ -56,8 +56,11 @@ package body System.Image_I is
       if V >= 0 then
          S (1) := ' ';
          P := 1;
+         pragma Assert (P < S'Last);
+
       else
          P := 0;
+         pragma Assert (P < S'Last - 1);
       end if;
 
       Set_Image_Integer (V, S, P);
@@ -72,26 +75,31 @@ package body System.Image_I is
       S : in out String;
       P : in out Natural)
    is
+      Nb_Digits : Natural := 0;
+      Value     : Non_Positive := T;
    begin
-      if T <= -10 then
-         Set_Digits (T / 10, S, P);
-         pragma Assert (P >= (S'First - 1) and P < S'Last and
-                        P < Natural'Last);
-         --  No check is done since, as documented in the Set_Image_Integer
-         --  specification, the caller guarantees that S is long enough to
-         --  hold the result.
-         P := P + 1;
-         S (P) := Character'Val (48 - (T rem 10));
+      pragma Assert (P >= S'First - 1 and P < S'Last);
+      --  No check is done since, as documented in the Set_Image_Integer
+      --  specification, the caller guarantees that S is long enough to
+      --  hold the result.
 
-      else
-         pragma Assert (P >= (S'First - 1) and P < S'Last and
-                        P < Natural'Last);
-         --  No check is done since, as documented in the Set_Image_Integer
-         --  specification, the caller guarantees that S is long enough to
-         --  hold the result.
-         P := P + 1;
-         S (P) := Character'Val (48 - T);
-      end if;
+      --  First we compute the number of characters needed for representing
+      --  the number.
+      loop
+         Value := Value / 10;
+         Nb_Digits := Nb_Digits + 1;
+         exit when Value = 0;
+      end loop;
+
+      Value := T;
+
+      --  We now populate digits from the end of the string to the beginning
+      for J in reverse  1 .. Nb_Digits loop
+         S (P + J) := Character'Val (48 - (Value rem 10));
+         Value := Value / 10;
+      end loop;
+
+      P := P + Nb_Digits;
    end Set_Digits;
 
    -----------------------
@@ -108,8 +116,7 @@ package body System.Image_I is
          Set_Digits (-V, S, P);
 
       else
-         pragma Assert (P >= (S'First - 1) and P < S'Last and
-                        P < Natural'Last);
+         pragma Assert (P >= S'First - 1 and P < S'Last);
          --  No check is done since, as documented in the specification,
          --  the caller guarantees that S is long enough to hold the result.
          P := P + 1;
index c995d55..8ffb8f0 100644 (file)
@@ -56,24 +56,31 @@ package body System.Image_U is
       S : in out String;
       P : in out Natural)
    is
+      Nb_Digits : Natural := 0;
+      Value     : Uns := V;
    begin
-      if V >= 10 then
-         Set_Image_Unsigned (V / 10, S, P);
-         pragma Assert (P >= (S'First - 1) and P < S'Last and
-                        P < Natural'Last);
-         --  No check is done since, as documented in the specification,
-         --  the caller guarantees that S is long enough to hold the result.
-         P := P + 1;
-         S (P) := Character'Val (48 + (V rem 10));
+      pragma Assert (P >= S'First - 1 and then P < S'Last and then
+                     P < Natural'Last);
+      --  No check is done since, as documented in the specification, the
+      --  caller guarantees that S is long enough to hold the result.
 
-      else
-         pragma Assert (P >= (S'First - 1) and P < S'Last and
-                        P < Natural'Last);
-         --  No check is done since, as documented in the specification,
-         --  the caller guarantees that S is long enough to hold the result.
-         P := P + 1;
-         S (P) := Character'Val (48 + V);
-      end if;
+      --  First we compute the number of characters needed for representing
+      --  the number.
+      loop
+         Value := Value / 10;
+         Nb_Digits := Nb_Digits + 1;
+         exit when Value = 0;
+      end loop;
+
+      Value := V;
+
+      --  We now populate digits from the end of the string to the beginning
+      for J in reverse  1 .. Nb_Digits loop
+         S (P + J) := Character'Val (48 + (Value rem 10));
+         Value := Value / 10;
+      end loop;
+
+      P := P + Nb_Digits;
    end Set_Image_Unsigned;
 
 end System.Image_U;