File 3243-Print-large-bignums-in-base-16-instead-of-in-interna.patch of Package erlang

From b3038094d5d15ef66fb76ae370208f1d3665a668 Mon Sep 17 00:00:00 2001
From: Rickard Green <rickard@erlang.org>
Date: Fri, 8 Jan 2021 16:53:51 +0100
Subject: [PATCH 3/3] Print large bignums in base 16 instead of in internal
 representation

---
 lib/erl_interface/src/misc/ei_printterm.c | 47 +++++++++++++++++------
 lib/erl_interface/test/ei_print_SUITE.erl | 43 ++++++---------------
 2 files changed, 47 insertions(+), 43 deletions(-)

diff --git a/lib/erl_interface/src/misc/ei_printterm.c b/lib/erl_interface/src/misc/ei_printterm.c
index 3a464377b1..0bad730095 100644
--- a/lib/erl_interface/src/misc/ei_printterm.c
+++ b/lib/erl_interface/src/misc/ei_printterm.c
@@ -90,6 +90,7 @@ static char *ei_big_to_str(erlang_big *b)
     unsigned int no_digits;
     unsigned short *sp;
     int i;
+    int printed;
 
     /* Number of 16-bit digits */
     no_digits = (b->arity + 1) / 2;
@@ -110,26 +111,48 @@ static char *ei_big_to_str(erlang_big *b)
         return buf;
     }
 
+    /* big nums this large gets printed in base 16... */
     buf_len = (!!b->is_neg /* "-" */
-               + 9 /* "#integer(" */
-               + 10 /* %d */
-               + 5 /* ") = {" */
-               + 6*no_digits /* 16-bit digits + ","s */
-               + 1 /* "}" */
+               + 3 /* "16#" */
+               + 4*no_digits /* 16-bit digits in base 16 */
                + 1); /* \0 */
     if ( (buf=malloc(buf_len)) == NULL) return NULL;
 
     s = buf;
     if ( b->is_neg ) 
-        s += sprintf(s,"-");
+        *(s++) = '-';
+    *(s++) = '1';
+    *(s++) = '6';
+    *(s++) = '#';
+
+    sp = b->digits;
+    printed = 0;
+    for (i = no_digits - 1; i >= 0; i--) {
+        unsigned short val = sp[i];
+        int j;
+
+        for (j = 3; j >= 0; j--) {
+            char c = (char) ((val >> (j*4)) & 0xf);
+            if (c < 10)
+                c += '0';
+            else
+                c += 'A' - 10;
+            
+            if (printed)
+                *(s++) = c;
+            else if (c != '0') {
+                *(s++) = c;
+                printed = !0;
+            }
+        }
+    }
 
-    s += sprintf(s,"#integer(%d) = {", no_digits);
-    for(sp = b->digits, i = 0; i < no_digits; i++) {
-        s += sprintf(s, "%d", (int) sp[i]);
-        if (i + 1 != no_digits)
-            *(s++) = ',';
+    if (!printed) {
+        /* very strange to encode zero like this... */
+        *(s++) = '0';
     }
-    *(s++) = '}';
+        
+
     *s = '\0';
     return buf;
 }
diff --git a/lib/erl_interface/test/ei_print_SUITE.erl b/lib/erl_interface/test/ei_print_SUITE.erl
index c0c2b40891..43d74066a2 100644
--- a/lib/erl_interface/test/ei_print_SUITE.erl
+++ b/lib/erl_interface/test/ei_print_SUITE.erl
@@ -216,6 +216,8 @@ integers(Config) ->
     test_integers(Port, 16#feeddeaddeadbeef - 1000, 16#feeddeaddeadbeef + 1000),
     test_integers(Port, -16#feeddeaddeadbeef - 1000, -16#feeddeaddeadbeef + 1000),
     test_integers(Port, (1 bsl 64) - 1000, (1 bsl 64) + 1000),
+    test_integers(Port, 16#addfeeddeaddeadbeef - 1000, 16#addfeeddeaddeadbeef + 1000),
+    test_integers(Port, -16#addfeeddeaddeadbeef - 1000, -16#addfeeddeaddeadbeef + 1000),
     test_integers(Port, -(1 bsl 64) - 1000, -(1 bsl 64) + 1000),
     test_integers(Port, (1 bsl 8192) - 1000, (1 bsl 8192) + 1000),
     test_integers(Port, -(1 bsl 8192) - 1000, -(1 bsl 8192) + 1000),
@@ -228,19 +230,21 @@ integers(Config) ->
 
 test_integer(Port, Int, Print) when is_integer(Int) ->
     Res = send_term_get_printed(Port, Int),
-    Exp = try
-              _ = list_to_integer(Res),
-              integer_to_list(Int)
-          catch
-              _:_ ->
-                  bignum_string(Int)
-          end,
     case Print of
         true ->
             io:format("Res: ~s~n", [Res]);
         false ->
             ok
     end,
+    %% Large bignums are printed in base 16...
+    Exp = case Res of
+              "16#" ++ _ ->
+                  "16#" ++ integer_to_list(Int, 16);
+              "-16#" ++ _ ->
+                  "-16#" ++ integer_to_list(-1*Int, 16);
+              _ ->
+                  integer_to_list(Int)
+           end,
     case Exp =:= Res of
         true ->
             ok;
@@ -249,33 +253,10 @@ test_integer(Port, Int, Print) when is_integer(Int) ->
             ct:fail({Exp, Res})
     end.
 
-bignum_string(Int) ->
-    {AbsInt, Sign} = case Int < 0 of
-                         true -> {-1*Int, "-"};
-                         false -> {Int, ""}
-                     end,
-    Digits = bignum_digits(AbsInt, []),
-    NoDigits = length(Digits),
-    lists:flatten([Sign, "#integer(",
-                   integer_to_list(NoDigits),
-                   ") = {",
-                   lists:foldl(fun (Digit, []) ->
-                                       [integer_to_list(Digit), $}];
-                                   (Digit, Acc) ->
-                                       [integer_to_list(Digit), $, | Acc]
-                               end,
-                               [],
-                               Digits)]).
-
-bignum_digits(0, Acc) ->
-    Acc;
-bignum_digits(Int, Acc) ->
-    bignum_digits(Int bsr 16, [Int band 16#ffff | Acc]).
-    
 test_integers(Port, FromInt, ToInt) ->
     test_integers(Port, FromInt, ToInt, true).
 
-test_integers(Port, FromInt, ToInt, _Print) when FromInt > ToInt ->
+test_integers(_Port, FromInt, ToInt, _Print) when FromInt > ToInt ->
     ok;
 test_integers(Port, FromInt, ToInt, Print) ->
     ok = test_integer(Port, FromInt, Print),
-- 
2.26.2

openSUSE Build Service is sponsored by