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