This patch remove recursion on Set_Digit and Set_Image_Unsigned
procedure.

Tested on x86_64-pc-linux-gnu, committed on trunk

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.
diff --git a/gcc/ada/libgnat/s-imagei.adb b/gcc/ada/libgnat/s-imagei.adb
--- a/gcc/ada/libgnat/s-imagei.adb
+++ b/gcc/ada/libgnat/s-imagei.adb
@@ -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;


diff --git a/gcc/ada/libgnat/s-imageu.adb b/gcc/ada/libgnat/s-imageu.adb
--- a/gcc/ada/libgnat/s-imageu.adb
+++ b/gcc/ada/libgnat/s-imageu.adb
@@ -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;


Reply via email to