GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
Copyright 2018, 2020 - 2025 Joel Svensson svenssonjoel@yahoo.se |
||
3 |
2022 Benjamin Vedder |
||
4 |
|||
5 |
This program is free software: you can redistribute it and/or modify |
||
6 |
it under the terms of the GNU General Public License as published by |
||
7 |
the Free Software Foundation, either version 3 of the License, or |
||
8 |
(at your option) any later version. |
||
9 |
|||
10 |
This program is distributed in the hope that it will be useful, |
||
11 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
13 |
GNU General Public License for more details. |
||
14 |
|||
15 |
You should have received a copy of the GNU General Public License |
||
16 |
along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
17 |
*/ |
||
18 |
|||
19 |
#include <stdio.h> |
||
20 |
#include <string.h> |
||
21 |
#include <ctype.h> |
||
22 |
#include <inttypes.h> |
||
23 |
#include <lbm_types.h> |
||
24 |
#include <lbm_custom_type.h> |
||
25 |
|||
26 |
#include "print.h" |
||
27 |
#include "heap.h" |
||
28 |
#include "symrepr.h" |
||
29 |
#include "stack.h" |
||
30 |
#include "lbm_channel.h" |
||
31 |
|||
32 |
#define PRINT 1 |
||
33 |
#define PRINT_SPACE 2 |
||
34 |
#define START_LIST 3 |
||
35 |
#define CONTINUE_LIST 4 |
||
36 |
#define END_LIST 5 |
||
37 |
#define PRINT_DOT 6 |
||
38 |
#define START_ARRAY 7 |
||
39 |
#define CONTINUE_ARRAY 8 |
||
40 |
#define END_ARRAY 9 |
||
41 |
|||
42 |
static lbm_stack_t print_stack = { NULL, 0, 0}; |
||
43 |
static bool print_has_stack = false; |
||
44 |
|||
45 |
const char *failed_str = "Error: print failed\n"; |
||
46 |
|||
47 |
555110 |
static int push_n(lbm_stack_t *s, lbm_uint *values, lbm_uint n) { |
|
48 |
✓✗ | 555110 |
if (s->sp + n < s->size) { |
49 |
✓✓ | 1673282 |
for (lbm_uint i = 0; i < n; i ++) { |
50 |
1118172 |
s->data[s->sp+i] = values[i]; |
|
51 |
} |
||
52 |
555110 |
s->sp+=n; |
|
53 |
555110 |
return 1; |
|
54 |
} |
||
55 |
return 0; |
||
56 |
} |
||
57 |
|||
58 |
5320 |
bool lbm_value_is_printable_string(lbm_value v, char **str) { |
|
59 |
5320 |
bool is_a_string = false; |
|
60 |
✓✓ | 5320 |
if (lbm_is_array_r(v)) { |
61 |
4424 |
lbm_array_header_t *array = (lbm_array_header_t*)lbm_car(v); |
|
62 |
// TODO: Potential null deref. |
||
63 |
// Highly unlikely that array is a recognizable NULL though. |
||
64 |
// If it is incorrect, it is most likely arbitrary. |
||
65 |
4424 |
char *c_data = (char *)array->data; |
|
66 |
✓✓ | 4424 |
if (array->size >= 1) { // nonzero length |
67 |
3976 |
unsigned int i = 0; |
|
68 |
3976 |
is_a_string = true; |
|
69 |
✓✗ | 7196 |
for (i = 0; i < array->size; i ++) { |
70 |
✓✓ | 7196 |
if (c_data[i] == 0) break; |
71 |
✓✓✓✓ ✗✓ |
4732 |
if (!isprint((unsigned char)c_data[i]) && ((c_data[i] < 8) || c_data[i] > 13)) { |
72 |
1512 |
is_a_string = false; |
|
73 |
1512 |
break; |
|
74 |
} |
||
75 |
} |
||
76 |
✓✓✓✓ ✓✗ |
3976 |
if (i > 0 && i != array->size-1 && c_data[i-1] != 0) is_a_string = false; |
77 |
✓✓ | 3976 |
if (is_a_string) { |
78 |
2464 |
*str = (char*)array->data; |
|
79 |
} |
||
80 |
} |
||
81 |
} |
||
82 |
5320 |
return is_a_string; |
|
83 |
} |
||
84 |
|||
85 |
|||
86 |
21756 |
int lbm_print_init(lbm_uint print_stack_size) { |
|
87 |
|||
88 |
✗✓ | 21756 |
if (print_stack_size == 0) |
89 |
return 0; |
||
90 |
|||
91 |
21756 |
lbm_uint *print_stack_storage = (lbm_uint*)lbm_malloc(print_stack_size * sizeof(lbm_uint)); |
|
92 |
✗✓ | 21756 |
if (!print_stack_storage) return 0; |
93 |
|||
94 |
✓✗ | 21756 |
if (lbm_stack_create(&print_stack, print_stack_storage, print_stack_size)) { |
95 |
21756 |
print_has_stack = true; |
|
96 |
21756 |
return 1; |
|
97 |
} |
||
98 |
return 0; |
||
99 |
} |
||
100 |
|||
101 |
#define EMIT_BUFFER_SIZE 30 |
||
102 |
|||
103 |
#define EMIT_FAILED -1 |
||
104 |
#define EMIT_OK 0 |
||
105 |
|||
106 |
407722 |
static int print_emit_string(lbm_char_channel_t *chan, char* str) { |
|
107 |
✓✓ | 407722 |
if (str == NULL) return EMIT_FAILED; |
108 |
✓✓ | 2090740 |
while (*str != 0) { |
109 |
1683092 |
int r = lbm_channel_write(chan, *str); |
|
110 |
1683092 |
str++; |
|
111 |
✓✓ | 1683092 |
if (r != CHANNEL_SUCCESS) return EMIT_FAILED; |
112 |
} |
||
113 |
407648 |
return EMIT_OK; |
|
114 |
} |
||
115 |
|||
116 |
180704 |
static int print_emit_char(lbm_char_channel_t *chan, char c) { |
|
117 |
|||
118 |
180704 |
int r = lbm_channel_write(chan, c); |
|
119 |
✓✓ | 180704 |
if (r != CHANNEL_SUCCESS) return EMIT_FAILED; |
120 |
180616 |
return EMIT_OK; |
|
121 |
} |
||
122 |
|||
123 |
|||
124 |
1596 |
static int emit_escape(lbm_char_channel_t *chan, char c) { |
|
125 |
✗✗✗✗ ✗✓ |
1596 |
switch(c) { |
126 |
case '"': return print_emit_string(chan, "\\\""); |
||
127 |
case '\n': return print_emit_string(chan, "\\n"); |
||
128 |
case '\r': return print_emit_string(chan, "\\r"); |
||
129 |
case '\t': return print_emit_string(chan, "\\t"); |
||
130 |
case '\\': return print_emit_string(chan, "\\\\"); |
||
131 |
1596 |
default: |
|
132 |
1596 |
return print_emit_char(chan, c); |
|
133 |
} |
||
134 |
} |
||
135 |
|||
136 |
2212 |
static int print_emit_string_value(lbm_char_channel_t *chan, char* str) { |
|
137 |
✗✓ | 2212 |
if (str == NULL) return EMIT_FAILED; |
138 |
✓✓ | 3808 |
while (*str != 0) { |
139 |
1596 |
int r = emit_escape(chan, *str++); |
|
140 |
✗✓ | 1596 |
if (r != EMIT_OK) return r; |
141 |
} |
||
142 |
2212 |
return EMIT_OK; |
|
143 |
} |
||
144 |
|||
145 |
262305 |
static int print_emit_symbol(lbm_char_channel_t *chan, lbm_value sym) { |
|
146 |
262305 |
char *str_ptr = (char*)lbm_get_name_by_symbol(lbm_dec_sym(sym)); |
|
147 |
262305 |
return print_emit_string(chan, str_ptr); |
|
148 |
} |
||
149 |
|||
150 |
41749 |
static int print_emit_i(lbm_char_channel_t *chan, lbm_int v) { |
|
151 |
char buf[EMIT_BUFFER_SIZE]; |
||
152 |
41749 |
snprintf(buf, EMIT_BUFFER_SIZE, "%"PRI_INT, v); |
|
153 |
41749 |
return print_emit_string(chan, buf); |
|
154 |
} |
||
155 |
|||
156 |
21624 |
static int print_emit_u(lbm_char_channel_t *chan, lbm_uint v, bool ps) { |
|
157 |
char buf[EMIT_BUFFER_SIZE]; |
||
158 |
✓✗ | 21624 |
snprintf(buf, EMIT_BUFFER_SIZE, "%"PRI_UINT"%s", v, ps ? "u" : ""); |
159 |
21624 |
return print_emit_string(chan, buf); |
|
160 |
} |
||
161 |
|||
162 |
13048 |
static int print_emit_byte(lbm_char_channel_t *chan, uint8_t v, bool ps) { |
|
163 |
char buf[EMIT_BUFFER_SIZE]; |
||
164 |
✓✓ | 13048 |
snprintf(buf, EMIT_BUFFER_SIZE, "%u%s", v, ps ? "b" : ""); |
165 |
13048 |
return print_emit_string(chan, buf); |
|
166 |
} |
||
167 |
|||
168 |
420 |
static int print_emit_float(lbm_char_channel_t *chan, float v, bool ps) { |
|
169 |
char buf[EMIT_BUFFER_SIZE]; |
||
170 |
✓✗ | 420 |
snprintf(buf, EMIT_BUFFER_SIZE, "%"PRI_FLOAT"%s", (double)v, ps ? "f32" : ""); |
171 |
420 |
return print_emit_string(chan, buf); |
|
172 |
} |
||
173 |
|||
174 |
336 |
static int print_emit_double(lbm_char_channel_t *chan, double v, bool ps) { |
|
175 |
char buf[EMIT_BUFFER_SIZE]; |
||
176 |
✓✗ | 336 |
snprintf(buf, EMIT_BUFFER_SIZE, "%lf%s", v, ps ? "f64" : ""); |
177 |
336 |
return print_emit_string(chan, buf); |
|
178 |
} |
||
179 |
|||
180 |
112 |
static int print_emit_u32(lbm_char_channel_t *chan, uint32_t v, bool ps) { |
|
181 |
char buf[EMIT_BUFFER_SIZE]; |
||
182 |
✓✗ | 112 |
snprintf(buf,EMIT_BUFFER_SIZE, "%"PRIu32"%s", v, ps ? "u32" : ""); |
183 |
112 |
return print_emit_string(chan, buf); |
|
184 |
} |
||
185 |
|||
186 |
112 |
static int print_emit_i32(lbm_char_channel_t *chan, int32_t v, bool ps) { |
|
187 |
char buf[EMIT_BUFFER_SIZE]; |
||
188 |
✓✗ | 112 |
snprintf(buf,EMIT_BUFFER_SIZE, "%"PRId32"%s", v, ps ? "i32" : ""); |
189 |
112 |
return print_emit_string(chan, buf); |
|
190 |
} |
||
191 |
|||
192 |
112 |
static int print_emit_u64(lbm_char_channel_t *chan, uint64_t v, bool ps) { |
|
193 |
char buf[EMIT_BUFFER_SIZE]; |
||
194 |
✓✗ | 112 |
snprintf(buf,EMIT_BUFFER_SIZE, "%"PRIu64"%s", v, ps ? "u64" : ""); |
195 |
112 |
return print_emit_string(chan, buf); |
|
196 |
} |
||
197 |
|||
198 |
112 |
static int print_emit_i64(lbm_char_channel_t *chan, int64_t v, bool ps) { |
|
199 |
char buf[EMIT_BUFFER_SIZE]; |
||
200 |
✓✗ | 112 |
snprintf(buf,EMIT_BUFFER_SIZE, "%"PRId64"%s", v, ps ? "i64" : ""); |
201 |
112 |
return print_emit_string(chan, buf); |
|
202 |
} |
||
203 |
|||
204 |
51428 |
static int print_emit_continuation(lbm_char_channel_t *chan, lbm_value v) { |
|
205 |
char buf[EMIT_BUFFER_SIZE]; |
||
206 |
51428 |
lbm_uint cont = (v & ~LBM_CONTINUATION_INTERNAL) >> LBM_ADDRESS_SHIFT; |
|
207 |
51428 |
snprintf(buf, EMIT_BUFFER_SIZE, "CONT[" "%"PRI_UINT"]", cont); |
|
208 |
51428 |
return print_emit_string(chan, buf); |
|
209 |
} |
||
210 |
|||
211 |
168 |
static int print_emit_custom(lbm_char_channel_t *chan, lbm_value v) { |
|
212 |
168 |
lbm_uint *custom = (lbm_uint*)lbm_car(v); |
|
213 |
int r; // NULL checks works against SYM_NIL. |
||
214 |
✓✓✓✗ |
168 |
if (custom && custom[CUSTOM_TYPE_DESCRIPTOR]) { |
215 |
56 |
r = print_emit_string(chan, (char*)custom[CUSTOM_TYPE_DESCRIPTOR]); |
|
216 |
} else { |
||
217 |
112 |
r = print_emit_string(chan, "INVALID_CUSTOM_TYPE"); |
|
218 |
} |
||
219 |
168 |
return r; |
|
220 |
} |
||
221 |
|||
222 |
56 |
static int print_emit_defrag_mem(lbm_char_channel_t *chan, lbm_value v) { |
|
223 |
(void) v; |
||
224 |
56 |
return print_emit_string(chan, "DM"); |
|
225 |
} |
||
226 |
|||
227 |
12192 |
static int print_emit_channel(lbm_char_channel_t *chan, lbm_value v) { |
|
228 |
(void) v; |
||
229 |
12192 |
return print_emit_string(chan, "~CHANNEL~"); |
|
230 |
} |
||
231 |
|||
232 |
1820 |
static int print_emit_array_data(lbm_char_channel_t *chan, lbm_array_header_t *array) { |
|
233 |
|||
234 |
1820 |
int r = print_emit_char(chan, '['); |
|
235 |
|||
236 |
✓✗ | 1820 |
if (r == EMIT_OK) { |
237 |
|||
238 |
✓✓ | 14588 |
for (unsigned int i = 0; i < array->size; i ++) { |
239 |
|||
240 |
12768 |
char *c_data = (char*)array->data; |
|
241 |
12768 |
r = print_emit_byte(chan, (uint8_t)c_data[i], false); |
|
242 |
|||
243 |
✓✗✓✓ |
12768 |
if (r == EMIT_OK && i != array->size - 1) { |
244 |
11396 |
r = print_emit_char(chan, ' '); |
|
245 |
} |
||
246 |
} |
||
247 |
|||
248 |
✗✓ | 1820 |
if (r != EMIT_OK) return r; |
249 |
1820 |
return print_emit_char(chan, ']'); |
|
250 |
} |
||
251 |
return r; |
||
252 |
} |
||
253 |
|||
254 |
4256 |
static int print_emit_bytearray(lbm_char_channel_t *chan, lbm_value v) { |
|
255 |
4256 |
int r = 0; |
|
256 |
char *str; |
||
257 |
✓✓ | 4256 |
if (lbm_is_array_r(v)) { |
258 |
✓✓ | 4032 |
if (lbm_value_is_printable_string(v, &str)) { |
259 |
2212 |
r = print_emit_char(chan, '"'); |
|
260 |
✓✗ | 2212 |
if (r == EMIT_OK) { |
261 |
2212 |
r = print_emit_string_value(chan, str); |
|
262 |
✓✗ | 2212 |
if (r == EMIT_OK) { |
263 |
2212 |
r = print_emit_char(chan, '"'); |
|
264 |
} |
||
265 |
} |
||
266 |
} else { |
||
267 |
1820 |
lbm_array_header_t *array = (lbm_array_header_t*)lbm_car(v); |
|
268 |
1820 |
r= print_emit_array_data(chan, array); |
|
269 |
} |
||
270 |
} else { |
||
271 |
224 |
r = print_emit_string(chan, "[INVALID_ARRAY]"); |
|
272 |
} |
||
273 |
4256 |
return r; |
|
274 |
} |
||
275 |
|||
276 |
|||
277 |
333150 |
static int lbm_print_internal(lbm_char_channel_t *chan, lbm_value v) { |
|
278 |
|||
279 |
333150 |
lbm_stack_clear(&print_stack); |
|
280 |
333150 |
lbm_value start_print[2] = {v, PRINT}; |
|
281 |
333150 |
push_n(&print_stack, start_print, 2); |
|
282 |
333150 |
bool chan_full = false; |
|
283 |
lbm_value curr; |
||
284 |
lbm_uint instr; |
||
285 |
333150 |
int r = EMIT_FAILED; |
|
286 |
|||
287 |
✓✓✓✗ |
1275574 |
while (!lbm_stack_is_empty(&print_stack) && !chan_full) { |
288 |
609390 |
lbm_pop(&print_stack, &instr); |
|
289 |
✓✓✓✓ ✓✓✗✓ ✓✗ |
609390 |
switch (instr) { |
290 |
56 |
case START_ARRAY: { |
|
291 |
56 |
lbm_pop(&print_stack, &curr); |
|
292 |
56 |
int res = 1; |
|
293 |
56 |
r = print_emit_char(chan, '['); |
|
294 |
56 |
lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(curr); |
|
295 |
56 |
lbm_uint size = arr->size / sizeof(lbm_value); |
|
296 |
56 |
lbm_value *arrdata = (lbm_value*)arr->data; |
|
297 |
✓✗ | 56 |
if (size >= 1) { |
298 |
56 |
lbm_value continuation[5] = |
|
299 |
{1, // next index |
||
300 |
56 |
(lbm_uint) arr, |
|
301 |
CONTINUE_ARRAY, |
||
302 |
56 |
arrdata[0], // first elt |
|
303 |
PRINT}; |
||
304 |
✓✗✓✗ |
56 |
res = res && push_n(&print_stack, continuation, 5); |
305 |
} else { |
||
306 |
res = res && lbm_push(&print_stack, END_LIST); |
||
307 |
} |
||
308 |
✗✓ | 56 |
if (!res) { |
309 |
return EMIT_FAILED; |
||
310 |
} |
||
311 |
56 |
break; |
|
312 |
} |
||
313 |
168 |
case CONTINUE_ARRAY: { |
|
314 |
lbm_uint arr_ptr; |
||
315 |
lbm_array_header_t *arr; |
||
316 |
lbm_uint ix; |
||
317 |
168 |
int res = 1; |
|
318 |
168 |
lbm_pop_2(&print_stack, &arr_ptr, &ix); |
|
319 |
168 |
arr = (lbm_array_header_t *)arr_ptr; |
|
320 |
168 |
lbm_value *arrdata = (lbm_value*)arr->data; |
|
321 |
✓✓ | 168 |
if (ix < (arr->size / sizeof(lbm_value))) { |
322 |
112 |
r = print_emit_char(chan, ' '); |
|
323 |
112 |
lbm_value continuation[5] = |
|
324 |
112 |
{ix + 1, |
|
325 |
112 |
(lbm_uint) arr, |
|
326 |
CONTINUE_ARRAY, |
||
327 |
112 |
arrdata[ix], |
|
328 |
PRINT}; |
||
329 |
✓✗✓✗ |
112 |
res = res && push_n(&print_stack, continuation, 5); |
330 |
} else { |
||
331 |
✓✗✓✗ |
56 |
res = res && lbm_push(&print_stack, END_ARRAY); |
332 |
} |
||
333 |
✗✓ | 168 |
if (!res) { |
334 |
return EMIT_FAILED; |
||
335 |
} |
||
336 |
168 |
break; |
|
337 |
} |
||
338 |
56 |
case END_ARRAY: { |
|
339 |
56 |
r = print_emit_char(chan, ']'); |
|
340 |
56 |
break; |
|
341 |
} |
||
342 |
50644 |
case START_LIST: { |
|
343 |
50644 |
lbm_pop(&print_stack, &curr); |
|
344 |
50644 |
r = print_emit_char(chan, '('); |
|
345 |
✗✓ | 50644 |
if (r != EMIT_OK) return r; |
346 |
50644 |
lbm_value car_val = lbm_car(curr); |
|
347 |
50644 |
lbm_value cdr_val = lbm_cdr(curr); |
|
348 |
50644 |
int res = 1; |
|
349 |
✓✓✗✓ |
58728 |
if (lbm_type_of(cdr_val) == LBM_TYPE_CONS || |
350 |
8084 |
lbm_type_of(cdr_val) == (LBM_TYPE_CONS | LBM_PTR_TO_CONSTANT_BIT)) { |
|
351 |
42560 |
lbm_value cont[2] = {cdr_val, CONTINUE_LIST}; |
|
352 |
✓✗✓✗ |
42560 |
res = res && push_n(&print_stack, cont, 2); |
353 |
✓✓✓✓ |
8084 |
} else if (lbm_type_of(cdr_val) == LBM_TYPE_SYMBOL && |
354 |
cdr_val == ENC_SYM_NIL) { |
||
355 |
✓✗✓✗ |
4360 |
res = res && lbm_push(&print_stack, END_LIST); |
356 |
} else { |
||
357 |
3724 |
lbm_value cont[4] = {END_LIST, cdr_val, PRINT, PRINT_DOT}; |
|
358 |
✓✗✓✗ |
3724 |
res = res && push_n(&print_stack, cont, 4); |
359 |
} |
||
360 |
50644 |
lbm_value cont[2] = {car_val, PRINT}; |
|
361 |
✓✗✓✗ |
50644 |
res = res && push_n(&print_stack, cont,2); |
362 |
✗✓ | 50644 |
if (!res) { |
363 |
return EMIT_FAILED; |
||
364 |
} |
||
365 |
50644 |
break; |
|
366 |
} |
||
367 |
58308 |
case CONTINUE_LIST: { |
|
368 |
58308 |
int res = 1; |
|
369 |
58308 |
lbm_pop(&print_stack, &curr); |
|
370 |
|||
371 |
✗✓ | 58308 |
if (lbm_type_of(curr) == LBM_TYPE_SYMBOL && |
372 |
curr == ENC_SYM_NIL) { |
||
373 |
58304 |
break; |
|
374 |
} |
||
375 |
|||
376 |
58308 |
lbm_value car_val = lbm_car(curr); |
|
377 |
58308 |
lbm_value cdr_val = lbm_cdr(curr); |
|
378 |
|||
379 |
58308 |
r = print_emit_char(chan, ' '); |
|
380 |
✓✓ | 58308 |
if (r != EMIT_OK) { |
381 |
4 |
return r; |
|
382 |
} |
||
383 |
✓✓✗✓ |
100748 |
if (lbm_type_of(cdr_val) == LBM_TYPE_CONS || |
384 |
42444 |
lbm_type_of(cdr_val) == (LBM_TYPE_CONS | LBM_PTR_TO_CONSTANT_BIT)) { |
|
385 |
15860 |
lbm_value cont[2] = {cdr_val, CONTINUE_LIST}; |
|
386 |
✓✗✓✗ |
15860 |
res = res && push_n(&print_stack, cont, 2); |
387 |
✓✗✓✗ |
42444 |
} else if (lbm_type_of(cdr_val) == LBM_TYPE_SYMBOL && |
388 |
cdr_val == ENC_SYM_NIL) { |
||
389 |
✓✗✓✗ |
42444 |
res = res && lbm_push(&print_stack, END_LIST); |
390 |
} else { |
||
391 |
lbm_value cont[4] = {END_LIST, cdr_val, PRINT, PRINT_DOT}; |
||
392 |
res = res && push_n(&print_stack, cont, 4); |
||
393 |
} |
||
394 |
58304 |
lbm_value cont[2] = {car_val, PRINT}; |
|
395 |
✓✗✓✗ |
58304 |
res = res && push_n(&print_stack, cont, 2); |
396 |
✗✓ | 58304 |
if (!res) { |
397 |
return EMIT_FAILED; |
||
398 |
} |
||
399 |
58304 |
break; |
|
400 |
} |
||
401 |
50472 |
case END_LIST: |
|
402 |
50472 |
r = print_emit_char(chan, ')'); |
|
403 |
✓✓ | 50472 |
if (r != EMIT_OK) return r; |
404 |
50388 |
break; |
|
405 |
case PRINT_SPACE: |
||
406 |
r = print_emit_char(chan, ' '); |
||
407 |
if (r != EMIT_OK) return r; |
||
408 |
break; |
||
409 |
3724 |
case PRINT_DOT: |
|
410 |
3724 |
r = print_emit_string(chan, " . "); |
|
411 |
✓✓ | 3724 |
if (r != EMIT_OK) return r; |
412 |
3696 |
break; |
|
413 |
445962 |
case PRINT: |
|
414 |
445962 |
lbm_pop(&print_stack, &curr); |
|
415 |
|||
416 |
445962 |
lbm_type t = lbm_type_of(curr); |
|
417 |
✓✓ | 445962 |
if (lbm_is_ptr(curr)) |
418 |
120004 |
t = t & LBM_PTR_TO_CONSTANT_MASK; // print constants normally |
|
419 |
|||
420 |
switch(t) { |
||
421 |
50644 |
case LBM_TYPE_CONS: { |
|
422 |
50644 |
lbm_value cont[2] = {curr, START_LIST}; |
|
423 |
50644 |
int res = push_n(&print_stack, cont, 2); |
|
424 |
✗✓ | 50644 |
if (!res) { |
425 |
print_emit_string(chan," ..."); |
||
426 |
return EMIT_OK; |
||
427 |
} |
||
428 |
50644 |
break; |
|
429 |
} |
||
430 |
262305 |
case LBM_TYPE_SYMBOL: |
|
431 |
262305 |
r = print_emit_symbol(chan, curr); |
|
432 |
262305 |
break; |
|
433 |
41749 |
case LBM_TYPE_I: |
|
434 |
41749 |
r = print_emit_i(chan, lbm_dec_i(curr)); |
|
435 |
41749 |
break; |
|
436 |
21624 |
case LBM_TYPE_U: |
|
437 |
21624 |
r = print_emit_u(chan, lbm_dec_u(curr), true); |
|
438 |
21624 |
break; |
|
439 |
280 |
case LBM_TYPE_CHAR: |
|
440 |
280 |
r = print_emit_byte(chan, (uint8_t)lbm_dec_char(curr), true); |
|
441 |
280 |
break; |
|
442 |
420 |
case LBM_TYPE_FLOAT: |
|
443 |
420 |
r = print_emit_float(chan, lbm_dec_float(curr), true); |
|
444 |
420 |
break; |
|
445 |
336 |
case LBM_TYPE_DOUBLE: |
|
446 |
336 |
r = print_emit_double(chan, lbm_dec_double(curr), true); |
|
447 |
336 |
break; |
|
448 |
112 |
case LBM_TYPE_U32: |
|
449 |
112 |
r = print_emit_u32(chan, lbm_dec_u32(curr), true); |
|
450 |
112 |
break; |
|
451 |
112 |
case LBM_TYPE_I32: |
|
452 |
112 |
r = print_emit_i32(chan, lbm_dec_i32(curr), true); |
|
453 |
112 |
break; |
|
454 |
112 |
case LBM_TYPE_U64: |
|
455 |
112 |
r = print_emit_u64(chan, lbm_dec_u64(curr), true); |
|
456 |
112 |
break; |
|
457 |
112 |
case LBM_TYPE_I64: |
|
458 |
112 |
r = print_emit_i64(chan, lbm_dec_i64(curr), true); |
|
459 |
112 |
break; |
|
460 |
51428 |
case LBM_CONTINUATION_INTERNAL_TYPE: |
|
461 |
51428 |
r = print_emit_continuation(chan, curr); |
|
462 |
51428 |
break; |
|
463 |
168 |
case LBM_TYPE_CUSTOM: |
|
464 |
168 |
r = print_emit_custom(chan, curr); |
|
465 |
168 |
break; |
|
466 |
12192 |
case LBM_TYPE_CHANNEL: |
|
467 |
12192 |
r = print_emit_channel(chan, curr); |
|
468 |
12192 |
break; |
|
469 |
4256 |
case LBM_TYPE_ARRAY: |
|
470 |
4256 |
r = print_emit_bytearray(chan, curr); |
|
471 |
4256 |
break; |
|
472 |
56 |
case LBM_TYPE_DEFRAG_MEM: |
|
473 |
56 |
r = print_emit_defrag_mem(chan, curr); |
|
474 |
56 |
break; |
|
475 |
56 |
case LBM_TYPE_LISPARRAY: { |
|
476 |
56 |
lbm_value cont[2] = {curr, START_ARRAY}; |
|
477 |
56 |
int res = push_n(&print_stack, cont, 2); |
|
478 |
✗✓ | 56 |
if (!res) { |
479 |
print_emit_string(chan, " ..."); |
||
480 |
return EMIT_OK; |
||
481 |
} |
||
482 |
56 |
break; |
|
483 |
} |
||
484 |
default: |
||
485 |
return EMIT_FAILED; |
||
486 |
} |
||
487 |
942424 |
} |
|
488 |
} |
||
489 |
333034 |
return r; |
|
490 |
} |
||
491 |
|||
492 |
333150 |
int lbm_print_value(char *buf, unsigned int len, lbm_value v) { |
|
493 |
|||
494 |
lbm_string_channel_state_t st; |
||
495 |
lbm_char_channel_t chan; |
||
496 |
|||
497 |
333150 |
memset(buf, 0, len); |
|
498 |
333150 |
lbm_create_string_char_channel_size(&st, &chan, buf, len); |
|
499 |
✓✓ | 333150 |
if (lbm_print_internal(&chan,v) == EMIT_OK) |
500 |
333020 |
return 1; |
|
501 |
130 |
return 0; |
|
502 |
} |
Generated by: GCOVR (Version 4.2) |