Skip to content

Commit 79220c2

Browse files
committed
Merge pull request atomvm#494 from bettio/add-new-term-print-function
Add new term print function These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents afea246 + ccdbd6a commit 79220c2

File tree

4 files changed

+264
-40
lines changed

4 files changed

+264
-40
lines changed

src/libAtomVM/globalcontext.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ typedef struct Module Module;
5858

5959
struct Module;
6060

61-
typedef struct
61+
struct GlobalContext
6262
{
6363
struct ListHead ready_processes;
6464
struct ListHead waiting_processes;
@@ -83,7 +83,7 @@ typedef struct
8383
uint64_t ref_ticks;
8484

8585
void *platform_data;
86-
} GlobalContext;
86+
};
8787

8888
/**
8989
* @brief Creates a new GlobalContext

src/libAtomVM/term.c

Lines changed: 205 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,108 @@
2828

2929
#include <ctype.h>
3030
#include <inttypes.h>
31+
#include <stdarg.h>
32+
#include <stddef.h>
3133
#include <stdio.h>
3234

35+
//TODO use macro from utils
36+
#ifndef CONTAINER_OF
37+
#define CONTAINER_OF(ptr, type, member) \
38+
((type *) (((char *) (ptr)) - offsetof(type, member)))
39+
#endif
40+
41+
struct FprintfFun
42+
{
43+
PrinterFun base;
44+
FILE *stream;
45+
};
46+
47+
struct SnprintfFun
48+
{
49+
PrinterFun base;
50+
int size;
51+
char *buf;
52+
};
53+
3354
const term empty_tuple = 0;
3455

56+
int fprintf_printer(PrinterFun *fun, const char *fmt, ...)
57+
{
58+
int ret;
59+
60+
va_list args;
61+
va_start(args, fmt);
62+
63+
FILE *stream = CONTAINER_OF(fun, struct FprintfFun, base)->stream;
64+
ret = vfprintf(stream, fmt, args);
65+
66+
va_end(args);
67+
68+
return ret;
69+
}
70+
71+
int snprintf_printer(PrinterFun *fun, const char *fmt, ...)
72+
{
73+
int ret;
74+
75+
va_list args;
76+
va_start(args, fmt);
77+
78+
struct SnprintfFun *snpf = CONTAINER_OF(fun, struct SnprintfFun, base);
79+
ret = vsnprintf(snpf->buf, snpf->size, fmt, args);
80+
snpf->buf += ret;
81+
snpf->size -= ret;
82+
83+
va_end(args);
84+
85+
return ret;
86+
}
87+
3588
void term_display(FILE *fd, term t, const Context *ctx)
89+
{
90+
term_fprint(fd, t, ctx->global);
91+
}
92+
93+
int term_fprint(FILE *stream, term t, const GlobalContext *global)
94+
{
95+
struct FprintfFun fprintf_fun = {
96+
.base = {
97+
.print = fprintf_printer
98+
},
99+
.stream = stream
100+
};
101+
102+
return term_funprint(&fprintf_fun.base, t, global);
103+
}
104+
105+
int term_snprint(char *buf, size_t size, term t, const GlobalContext *global)
106+
{
107+
struct SnprintfFun snprintf_fun = {
108+
.base = {
109+
.print = snprintf_printer
110+
},
111+
.buf = buf,
112+
.size = size
113+
};
114+
115+
return term_funprint(&snprintf_fun.base, t, global);
116+
}
117+
118+
int term_funprint(PrinterFun *fun, term t, const GlobalContext *global)
36119
{
37120
if (term_is_atom(t)) {
38121
int atom_index = term_to_atom_index(t);
39-
AtomString atom_string = (AtomString) valueshashtable_get_value(ctx->global->atoms_ids_table, atom_index, (unsigned long) NULL);
40-
fprintf(fd, "%.*s", (int) atom_string_len(atom_string), (char *) atom_string_data(atom_string));
122+
AtomString atom_string = (AtomString) valueshashtable_get_value(
123+
global->atoms_ids_table, atom_index, (unsigned long) NULL);
124+
return fun->print(fun, "%.*s", (int) atom_string_len(atom_string),
125+
(char *) atom_string_data(atom_string));
41126

42127
} else if (term_is_integer(t)) {
43128
avm_int_t iv = term_to_int(t);
44-
fprintf(fd, AVM_INT_FMT, iv);
129+
return fun->print(fun, AVM_INT_FMT, iv);
45130

46131
} else if (term_is_nil(t)) {
47-
fprintf(fd, "[]");
132+
return fun->print(fun, "[]");
48133

49134
} else if (term_is_nonempty_list(t)) {
50135
int is_printable = 1;
@@ -63,33 +148,55 @@ void term_display(FILE *fd, term t, const Context *ctx)
63148
int ok;
64149
char *printable = interop_list_to_string(t, &ok);
65150
if (LIKELY(ok)) {
66-
fprintf(fd, "\"%s\"", printable);
151+
int ret = fun->print(fun, "\"%s\"", printable);
67152
free(printable);
153+
return ret;
68154
} else {
69-
fprintf(fd, "???");
155+
return fun->print(fun, "???");
70156
}
71157

72158
} else {
73-
fputc('[', fd);
159+
int ret = fun->print(fun, "[");
160+
if (UNLIKELY(ret < 0)) {
161+
return ret;
162+
}
74163
int display_separator = 0;
75164
while (term_is_nonempty_list(t)) {
76165
if (display_separator) {
77-
fputc(',', fd);
166+
ret += fun->print(fun, ",");
78167
} else {
79168
display_separator = 1;
80169
}
81170

82-
term_display(fd, term_get_list_head(t), ctx);
171+
int printed = term_funprint(fun, term_get_list_head(t), global);
172+
if (UNLIKELY(printed < 0)) {
173+
return printed;
174+
}
175+
ret += printed;
83176
t = term_get_list_tail(t);
84177
}
85178
if (!term_is_nil(t)) {
86-
fputc('|', fd);
87-
term_display(fd, t, ctx);
179+
int printed = fun->print(fun, "|");
180+
if (UNLIKELY(printed < 0)) {
181+
return printed;
182+
}
183+
ret += printed;
184+
185+
printed = term_funprint(fun, t, global);
186+
if (UNLIKELY(printed < 0)) {
187+
return printed;
188+
}
189+
ret += printed;
190+
}
191+
int printed = fun->print(fun, "]");
192+
if (UNLIKELY(printed < 0)) {
193+
return printed;
88194
}
89-
fputc(']', fd);
195+
ret += printed;
196+
return ret;
90197
}
91198
} else if (term_is_pid(t)) {
92-
fprintf(fd, "<0.%i.0>", term_to_local_process_id(t));
199+
return fun->print(fun, "<0.%i.0>", term_to_local_process_id(t));
93200

94201
} else if (term_is_function(t)) {
95202
const term *boxed_value = term_to_const_term_ptr(t);
@@ -101,35 +208,77 @@ void term_display(FILE *fd, term t, const Context *ctx)
101208
#else
102209
"#Fun<erl_eval.%lu.%llu>";
103210
#endif
104-
fprintf(fd, format, fun_index, (unsigned long) fun_module);
211+
return fun->print(fun, format, fun_index, (unsigned long) fun_module);
105212

106213
} else if (term_is_tuple(t)) {
107-
fputc('{', fd);
214+
int ret = fun->print(fun, "{");
215+
if (UNLIKELY(ret < 0)) {
216+
return ret;
217+
}
108218

109219
int tuple_size = term_get_tuple_arity(t);
110220
for (int i = 0; i < tuple_size; i++) {
111221
if (i != 0) {
112-
fputc(',', fd);
222+
int printed = fun->print(fun, ",");
223+
if (UNLIKELY(printed < 0)) {
224+
return printed;
225+
}
226+
ret += printed;
113227
}
114-
term_display(fd, term_get_tuple_element(t, i), ctx);
228+
int printed = term_funprint(fun, term_get_tuple_element(t, i), global);
229+
if (UNLIKELY(printed < 0)) {
230+
return printed;
231+
}
232+
ret += printed;
115233
}
116234

117-
fputc('}', fd);
235+
int printed = fun->print(fun, "}");
236+
if (UNLIKELY(printed < 0)) {
237+
return printed;
238+
}
239+
ret += printed;
240+
return ret;
118241

119242
} else if (term_is_map(t)) {
120-
fprintf(fd, "#{");
243+
int ret = fun->print(fun, "#{");
244+
if (UNLIKELY(ret < 0)) {
245+
return ret;
246+
}
121247

122248
int map_size = term_get_map_size(t);
123249
for (int i = 0; i < map_size; i++) {
124250
if (i != 0) {
125-
fputc(',', fd);
251+
int printed = fun->print(fun, ",");
252+
if (UNLIKELY(printed < 0)) {
253+
return printed;
254+
}
255+
ret += printed;
256+
}
257+
int printed = term_funprint(fun, term_get_map_key(t, i), global);
258+
if (UNLIKELY(printed < 0)) {
259+
return printed;
126260
}
127-
term_display(fd, term_get_map_key(t, i), ctx);
128-
fprintf(fd, "=>");
129-
term_display(fd, term_get_map_value(t, i), ctx);
261+
ret += printed;
262+
263+
printed = fun->print(fun, "=>");
264+
if (UNLIKELY(printed < 0)) {
265+
return printed;
266+
}
267+
ret += printed;
268+
269+
printed = term_funprint(fun, term_get_map_value(t, i), global);
270+
if (UNLIKELY(printed < 0)) {
271+
return printed;
272+
}
273+
ret += printed;
130274
}
131275

132-
fputc('}', fd);
276+
int printed = fun->print(fun, "}");
277+
if (UNLIKELY(printed < 0)) {
278+
return printed;
279+
}
280+
ret += printed;
281+
return ret;
133282

134283
} else if (term_is_binary(t)) {
135284
int len = term_binary_size(t);
@@ -143,24 +292,45 @@ void term_display(FILE *fd, term t, const Context *ctx)
143292
}
144293
}
145294

146-
fprintf(fd, "<<");
295+
int ret = fun->print(fun, "<<");
296+
if (UNLIKELY(ret < 0)) {
297+
return ret;
298+
}
299+
147300
if (is_printable) {
148-
fprintf(fd, "\"%.*s\"", len, binary_data);
301+
int printed = fun->print(fun, "\"%.*s\"", len, binary_data);
302+
if (UNLIKELY(printed < 0)) {
303+
return printed;
304+
}
305+
ret += printed;
149306

150307
} else {
151308
int display_separator = 0;
152309
for (int i = 0; i < len; i++) {
153310
if (display_separator) {
154-
fputc(',', fd);
311+
int printed = fun->print(fun, ",");
312+
if (UNLIKELY(printed < 0)) {
313+
return printed;
314+
}
315+
ret += printed;
155316
} else {
156317
display_separator = 1;
157318
}
158319

159320
uint8_t c = (uint8_t) binary_data[i];
160-
fprintf(fd, "%i", (int) c);
321+
int printed = fun->print(fun, "%i", (int) c);
322+
if (UNLIKELY(printed < 0)) {
323+
return printed;
324+
}
325+
ret += printed;
161326
}
162327
}
163-
fprintf(fd, ">>");
328+
int printed = fun->print(fun, ">>");
329+
if (UNLIKELY(printed < 0)) {
330+
return printed;
331+
}
332+
ret += printed;
333+
return ret;
164334

165335
} else if (term_is_reference(t)) {
166336
const char *format =
@@ -169,30 +339,28 @@ void term_display(FILE *fd, term t, const Context *ctx)
169339
#else
170340
"#Ref<0.0.0.%lu>";
171341
#endif
172-
fprintf(fd, format, term_to_ref_ticks(t));
342+
return fun->print(fun, format, term_to_ref_ticks(t));
173343

174344
} else if (term_is_boxed_integer(t)) {
175345
int size = term_boxed_size(t);
176346
switch (size) {
177347
case 1:
178-
fprintf(fd, AVM_INT_FMT, term_unbox_int(t));
179-
break;
348+
return fun->print(fun, AVM_INT_FMT, term_unbox_int(t));
180349

181350
#if BOXED_TERMS_REQUIRED_FOR_INT64 == 2
182351
case 2:
183-
fprintf(fd, AVM_INT64_FMT, term_unbox_int64(t));
184-
break;
352+
return fun->print(fun, AVM_INT64_FMT, term_unbox_int64(t));
185353
#endif
186-
187354
default:
188355
AVM_ABORT();
189356
}
190357

191358
} else if (term_is_float(t)) {
192359
avm_float_t f = term_to_float(t);
193-
fprintf(fd, AVM_FLOAT_FMT, f);
360+
return fun->print(fun, AVM_FLOAT_FMT, f);
361+
194362
} else {
195-
fprintf(fd, "Unknown term type: %" TERM_U_FMT, t);
363+
return fun->print(fun, "Unknown term type: %" TERM_U_FMT, t);
196364
}
197365
}
198366

0 commit comments

Comments
 (0)