Skip to content

Commit ff800f7

Browse files
committed
term_funprint: support bigint
Signed-off-by: Davide Bettio <davide@uninstall.it>
1 parent e210b05 commit ff800f7

File tree

3 files changed

+64
-17
lines changed

3 files changed

+64
-17
lines changed

src/libAtomVM/nifs.c

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "externalterm.h"
4545
#include "globalcontext.h"
4646
#include "interop.h"
47+
#include "intn.h"
4748
#include "mailbox.h"
4849
#include "memory.h"
4950
#include "module.h"
@@ -2185,8 +2186,10 @@ static term nif_erlang_atom_to_list_1(Context *ctx, int argc, term argv[])
21852186
}
21862187

21872188
static term integer_to_buf(Context *ctx, int argc, term argv[], char *tmp_buf, size_t tmp_buf_size,
2188-
char **int_buf, size_t *int_len)
2189+
char **int_buf, size_t *int_len, bool *needs_cleanup)
21892190
{
2191+
*needs_cleanup = false;
2192+
21902193
term value = argv[0];
21912194
avm_int_t base = 10;
21922195
VALIDATE_VALUE(value, term_is_any_integer);
@@ -2225,8 +2228,13 @@ static term integer_to_buf(Context *ctx, int argc, term argv[], char *tmp_buf, s
22252228
break;
22262229
}
22272230
#endif
2228-
default:
2229-
abort();
2231+
default: {
2232+
size_t boxed_size = term_intn_size(value);
2233+
size_t digits_per_term = sizeof(term) / sizeof(intn_digit_t);
2234+
intn_digit_t *dest_buf = (void *) term_intn_data(value);
2235+
*int_buf = intn_to_string(dest_buf, boxed_size * digits_per_term, base, int_len);
2236+
*needs_cleanup = true;
2237+
}
22302238
}
22312239
}
22322240

@@ -2235,17 +2243,14 @@ static term integer_to_buf(Context *ctx, int argc, term argv[], char *tmp_buf, s
22352243

22362244
static term nif_erlang_integer_to_binary_2(Context *ctx, int argc, term argv[])
22372245
{
2238-
#ifdef INT64_TO_A_BUF_LEN
22392246
size_t tmp_buf_size = INT64_WRITE_TO_ASCII_BUF_LEN;
2240-
#else
2241-
size_t tmp_buf_size = INTPTR_WRITE_TO_ASCII_BUF_LEN;
2242-
#endif
22432247
char tmp_buf[tmp_buf_size];
22442248

22452249
char *int_buf;
22462250
size_t int_len;
2251+
bool needs_cleanup;
22472252
term maybe_fail_ret
2248-
= integer_to_buf(ctx, argc, argv, tmp_buf, tmp_buf_size, &int_buf, &int_len);
2253+
= integer_to_buf(ctx, argc, argv, tmp_buf, tmp_buf_size, &int_buf, &int_len, &needs_cleanup);
22492254
if (UNLIKELY(term_is_invalid_term(maybe_fail_ret))) {
22502255
return maybe_fail_ret;
22512256
}
@@ -2255,27 +2260,36 @@ static term nif_erlang_integer_to_binary_2(Context *ctx, int argc, term argv[])
22552260
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
22562261
}
22572262

2258-
return term_from_literal_binary(int_buf, int_len, &ctx->heap, ctx->global);
2263+
term ret = term_from_literal_binary(int_buf, int_len, &ctx->heap, ctx->global);
2264+
2265+
if (needs_cleanup) {
2266+
free(int_buf);
2267+
}
2268+
2269+
return ret;
22592270
}
22602271

22612272
static term nif_erlang_integer_to_list_2(Context *ctx, int argc, term argv[])
22622273
{
2263-
#ifdef INT64_TO_A_BUF_LEN
22642274
size_t tmp_buf_size = INT64_WRITE_TO_ASCII_BUF_LEN;
2265-
#else
2266-
size_t tmp_buf_size = INTPTR_WRITE_TO_ASCII_BUF_LEN;
2267-
#endif
22682275
char tmp_buf[tmp_buf_size];
22692276

22702277
char *int_buf;
22712278
size_t int_len;
2279+
bool needs_cleanup;
22722280
term maybe_fail_ret
2273-
= integer_to_buf(ctx, argc, argv, tmp_buf, tmp_buf_size, &int_buf, &int_len);
2281+
= integer_to_buf(ctx, argc, argv, tmp_buf, tmp_buf_size, &int_buf, &int_len, &needs_cleanup);
22742282
if (UNLIKELY(term_is_invalid_term(maybe_fail_ret))) {
22752283
return maybe_fail_ret;
22762284
}
22772285

2278-
return make_list_from_ascii_buf((uint8_t *) int_buf, int_len, ctx);
2286+
term ret = make_list_from_ascii_buf((uint8_t *) int_buf, int_len, ctx);
2287+
2288+
if (needs_cleanup) {
2289+
free(int_buf);
2290+
}
2291+
2292+
return ret;
22792293
}
22802294

22812295
static int format_float(term value, int scientific, int decimals, int compact, char *out_buf, int outbuf_len)

src/libAtomVM/term.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "atom.h"
2424
#include "atom_table.h"
25+
#include "intn.h"
2526
#include "context.h"
2627
#include "interop.h"
2728
#include "module.h"
@@ -393,8 +394,20 @@ int term_funprint(PrinterFun *fun, term t, const GlobalContext *global)
393394
case 2:
394395
return fun->print(fun, AVM_INT64_FMT, term_unbox_int64(t));
395396
#endif
396-
default:
397-
AVM_ABORT();
397+
default: {
398+
size_t digits_per_term = sizeof(term) / sizeof(intn_digit_t);
399+
size_t boxed_size = term_intn_size(t);
400+
const intn_digit_t *intn_data = (const intn_digit_t *) term_intn_data(t);
401+
size_t unused_s_len;
402+
char *s
403+
= intn_to_string(intn_data, boxed_size * digits_per_term, 10, &unused_s_len);
404+
if (IS_NULL_PTR(s)) {
405+
return -1;
406+
}
407+
int print_res = fun->print(fun, "%s", s);
408+
free(s);
409+
return print_res;
410+
}
398411
}
399412

400413
} else if (term_is_float(t)) {

src/libAtomVM/term.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,26 @@ static inline size_t term_boxed_integer_size(avm_int64_t value)
870870
}
871871
}
872872

873+
static inline term term_create_uninitialized_intn(size_t n, Heap *heap)
874+
{
875+
term *boxed_int = memory_heap_alloc(heap, 1 + n);
876+
boxed_int[0] = (n << 6) | TERM_BOXED_POSITIVE_INTEGER; // OR sign bit
877+
878+
return ((term) boxed_int) | TERM_BOXED_VALUE_TAG;
879+
}
880+
881+
static inline void *term_intn_data(term t)
882+
{
883+
const term *boxed_value = term_to_const_term_ptr(t);
884+
return (void *) (boxed_value + 1);
885+
}
886+
887+
static inline size_t term_intn_size(term t)
888+
{
889+
const term *boxed_value = term_to_const_term_ptr(t);
890+
return term_get_size_from_boxed_header(boxed_value[0]);
891+
}
892+
873893
static inline term term_from_catch_label(unsigned int module_index, unsigned int label)
874894
{
875895
return (term) ((module_index << 24) | (label << 6) | TERM_CATCH_TAG);

0 commit comments

Comments
 (0)