program.c (78bc019d220e05abb5b12f678f9b4a847019bbcc) program.c (d101cdd6edd782f6ec56eef63ed91abd77a8b317)
1/*
2 * *****************************************************************************
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
1/*
2 * *****************************************************************************
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * Copyright (c) 2018-2021 Gavin D. Howard and contributors.
6 * Copyright (c) 2018-2023 Gavin D. Howard and contributors.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright notice,

--- 29 unchanged lines hidden (view full) ---

44#include <time.h>
45
46#include <read.h>
47#include <parse.h>
48#include <program.h>
49#include <vm.h>
50
51/**
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright notice,

--- 29 unchanged lines hidden (view full) ---

44#include <time.h>
45
46#include <read.h>
47#include <parse.h>
48#include <program.h>
49#include <vm.h>
50
51/**
52 * Quickly sets the const and strs vector pointers in the program. This is a
53 * convenience function.
54 * @param p The program.
55 * @param f The new function.
56 */
57static inline void
58bc_program_setVecs(BcProgram* p, BcFunc* f)
59{
60 BC_SIG_ASSERT_LOCKED;
61 p->consts = &f->consts;
62 p->strs = &f->strs;
63}
64
65/**
66 * Does a type check for something that expects a number.
67 * @param r The result that will be checked.
68 * @param n The result's number.
69 */
70static inline void
71bc_program_type_num(BcResult* r, BcNum* n)
72{
73#if BC_ENABLED

--- 45 unchanged lines hidden (view full) ---

119}
120
121/**
122 * Returns a string from a result and its number.
123 * @param p The program.
124 * @param n The number tied to the result.
125 * @return The string corresponding to the result and number.
126 */
52 * Does a type check for something that expects a number.
53 * @param r The result that will be checked.
54 * @param n The result's number.
55 */
56static inline void
57bc_program_type_num(BcResult* r, BcNum* n)
58{
59#if BC_ENABLED

--- 45 unchanged lines hidden (view full) ---

105}
106
107/**
108 * Returns a string from a result and its number.
109 * @param p The program.
110 * @param n The number tied to the result.
111 * @return The string corresponding to the result and number.
112 */
127static char*
113static inline char*
128bc_program_string(BcProgram* p, const BcNum* n)
129{
114bc_program_string(BcProgram* p, const BcNum* n)
115{
130 BcFunc* f = bc_vec_item(&p->fns, n->rdx);
131 return *((char**) bc_vec_item(&f->strs, n->scale));
116 return *((char**) bc_vec_item(&p->strs, n->scale));
132}
133
134#if BC_ENABLED
135
136/**
137 * Prepares the globals for a function call. This is only called when global
138 * stacks are on because it pushes a copy of the current globals onto each of
139 * their respective stacks.

--- 62 unchanged lines hidden (view full) ---

202
203 v = bc_vec_item(bc_vec_item(&p->arrs, vidx), nidx);
204
205 // We want to be sure we do *not* have a reference vector.
206 assert(v->size != sizeof(uchar));
207
208 return v;
209}
117}
118
119#if BC_ENABLED
120
121/**
122 * Prepares the globals for a function call. This is only called when global
123 * stacks are on because it pushes a copy of the current globals onto each of
124 * their respective stacks.

--- 62 unchanged lines hidden (view full) ---

187
188 v = bc_vec_item(bc_vec_item(&p->arrs, vidx), nidx);
189
190 // We want to be sure we do *not* have a reference vector.
191 assert(v->size != sizeof(uchar));
192
193 return v;
194}
195
210#endif // BC_ENABLED
211
212/**
213 * Creates a BcNum from a BcBigDig and pushes onto the results stack. This is a
214 * convenience function.
215 * @param p The program.
216 * @param dig The BcBigDig to push onto the results stack.
217 * @param type The type that the pushed result should be.

--- 9 unchanged lines hidden (view full) ---

227
228 bc_num_createFromBigdig(&res.d.n, dig);
229 bc_vec_push(&p->results, &res);
230
231 BC_SIG_UNLOCK;
232}
233
234size_t
196#endif // BC_ENABLED
197
198/**
199 * Creates a BcNum from a BcBigDig and pushes onto the results stack. This is a
200 * convenience function.
201 * @param p The program.
202 * @param dig The BcBigDig to push onto the results stack.
203 * @param type The type that the pushed result should be.

--- 9 unchanged lines hidden (view full) ---

213
214 bc_num_createFromBigdig(&res.d.n, dig);
215 bc_vec_push(&p->results, &res);
216
217 BC_SIG_UNLOCK;
218}
219
220size_t
235bc_program_addString(BcProgram* p, const char* str, size_t fidx)
221bc_program_addString(BcProgram* p, const char* str)
236{
222{
237 BcFunc* f;
238 char** str_ptr;
239 BcVec* slabs;
223 size_t idx;
240
241 BC_SIG_ASSERT_LOCKED;
242
224
225 BC_SIG_ASSERT_LOCKED;
226
243 // Push an empty string on the proper vector.
244 f = bc_vec_item(&p->fns, fidx);
245 str_ptr = bc_vec_pushEmpty(&f->strs);
227 if (bc_map_insert(&p->str_map, str, p->strs.len, &idx))
228 {
229 char** str_ptr;
230 BcId* id = bc_vec_item(&p->str_map, idx);
246
231
247 // Figure out which slab vector to use.
248 slabs = fidx == BC_PROG_MAIN || fidx == BC_PROG_READ ?
249 &vm.main_slabs :
250 &vm.other_slabs;
232 // Get the index.
233 idx = id->idx;
251
234
252 *str_ptr = bc_slabvec_strdup(slabs, str);
235 // Push an empty string on the proper vector.
236 str_ptr = bc_vec_pushEmpty(&p->strs);
253
237
254 return f->strs.len - 1;
238 // We reuse the string in the ID (allocated by bc_map_insert()), because
239 // why not?
240 *str_ptr = id->name;
241 }
242 else
243 {
244 BcId* id = bc_vec_item(&p->str_map, idx);
245 idx = id->idx;
246 }
247
248 return idx;
255}
256
257size_t
249}
250
251size_t
258bc_program_search(BcProgram* p, const char* id, bool var)
252bc_program_search(BcProgram* p, const char* name, bool var)
259{
260 BcVec* v;
261 BcVec* map;
262 size_t i;
263
264 BC_SIG_ASSERT_LOCKED;
265
266 // Grab the right vector and map.
267 v = var ? &p->vars : &p->arrs;
268 map = var ? &p->var_map : &p->arr_map;
269
270 // We do an insert because the variable might not exist yet. This is because
271 // the parser calls this function. If the insert succeeds, we create a stack
272 // for the variable/array. But regardless, bc_map_insert() gives us the
273 // index of the item in i.
253{
254 BcVec* v;
255 BcVec* map;
256 size_t i;
257
258 BC_SIG_ASSERT_LOCKED;
259
260 // Grab the right vector and map.
261 v = var ? &p->vars : &p->arrs;
262 map = var ? &p->var_map : &p->arr_map;
263
264 // We do an insert because the variable might not exist yet. This is because
265 // the parser calls this function. If the insert succeeds, we create a stack
266 // for the variable/array. But regardless, bc_map_insert() gives us the
267 // index of the item in i.
274 if (bc_map_insert(map, id, v->len, &i))
268 if (bc_map_insert(map, name, v->len, &i))
275 {
276 BcVec* temp = bc_vec_pushEmpty(v);
277 bc_array_init(temp, var);
278 }
279
280 return ((BcId*) bc_vec_item(map, i))->idx;
281}
282

--- 64 unchanged lines hidden (view full) ---

347 // Surprisingly enough, the hard case is *not* returning an array;
348 // it's returning an array element. This is because we have to dig
349 // deeper to get *to* the element. That's what the code inside this
350 // if statement does.
351 if (r->t == BC_RESULT_ARRAY_ELEM)
352 {
353 size_t idx = r->d.loc.idx;
354
269 {
270 BcVec* temp = bc_vec_pushEmpty(v);
271 bc_array_init(temp, var);
272 }
273
274 return ((BcId*) bc_vec_item(map, i))->idx;
275}
276

--- 64 unchanged lines hidden (view full) ---

341 // Surprisingly enough, the hard case is *not* returning an array;
342 // it's returning an array element. This is because we have to dig
343 // deeper to get *to* the element. That's what the code inside this
344 // if statement does.
345 if (r->t == BC_RESULT_ARRAY_ELEM)
346 {
347 size_t idx = r->d.loc.idx;
348
355 v = bc_vec_top(v);
349 v = bc_vec_item(v, r->d.loc.stack_idx);
356
357#if BC_ENABLED
358 // If this is true, we have a reference vector, so dereference
359 // it. The reason we don't need to worry about it for returning
360 // a straight array is because we only care about references
361 // when we access elements of an array that is a reference. That
362 // is this code, so in essence, this line takes care of arrays
363 // as well.

--- 13 unchanged lines hidden (view full) ---

377 BC_SIG_LOCK;
378 bc_array_expand(v, bc_vm_growSize(idx, 1));
379 BC_SIG_UNLOCK;
380 }
381
382 n = bc_vec_item(v, idx);
383 }
384 // This is either a number (for a var) or an array (for an array).
350
351#if BC_ENABLED
352 // If this is true, we have a reference vector, so dereference
353 // it. The reason we don't need to worry about it for returning
354 // a straight array is because we only care about references
355 // when we access elements of an array that is a reference. That
356 // is this code, so in essence, this line takes care of arrays
357 // as well.

--- 13 unchanged lines hidden (view full) ---

371 BC_SIG_LOCK;
372 bc_array_expand(v, bc_vm_growSize(idx, 1));
373 BC_SIG_UNLOCK;
374 }
375
376 n = bc_vec_item(v, idx);
377 }
378 // This is either a number (for a var) or an array (for an array).
385 // Because bc_vec_top() returns a void*, we don't need to cast.
386 else n = bc_vec_top(v);
379 // Because bc_vec_top() and bc_vec_item() return a void*, we don't
380 // need to cast.
381 else
382 {
383#if BC_ENABLED
384 if (BC_IS_BC)
385 {
386 n = bc_vec_item(v, r->d.loc.stack_idx);
387 }
388 else
389#endif // BC_ENABLED
390 {
391 n = bc_vec_top(v);
392 }
393 }
387
388 break;
389 }
390
391 case BC_RESULT_ZERO:
392 {
394
395 break;
396 }
397
398 case BC_RESULT_ZERO:
399 {
393 n = &vm.zero;
400 n = &vm->zero;
394 break;
395 }
396
397 case BC_RESULT_ONE:
398 {
401 break;
402 }
403
404 case BC_RESULT_ONE:
405 {
399 n = &vm.one;
406 n = &vm->one;
400 break;
401 }
402
403#if BC_ENABLED
404 // We should never get here; this is taken care of earlier because a
405 // result is expected.
406 case BC_RESULT_VOID:
407#ifndef NDEBUG
408 {
409 abort();
407 break;
408 }
409
410#if BC_ENABLED
411 // We should never get here; this is taken care of earlier because a
412 // result is expected.
413 case BC_RESULT_VOID:
414#ifndef NDEBUG
415 {
416 abort();
417 // Fallthrough
410 }
411#endif // NDEBUG
418 }
419#endif // NDEBUG
412 // Fallthrough
413 case BC_RESULT_LAST:
414 {
415 n = &p->last;
416 break;
417 }
418#endif // BC_ENABLED
420 case BC_RESULT_LAST:
421 {
422 n = &p->last;
423 break;
424 }
425#endif // BC_ENABLED
426
427#if BC_GCC
428 // This is here in GCC to quiet the "maybe-uninitialized" warning.
429 default:
430 {
431 abort();
432 }
433#endif // BC_GCC
419 }
420
421 return n;
422}
423
424/**
425 * Prepares an operand for use.
426 * @param p The program.

--- 109 unchanged lines hidden (view full) ---

536 * @param rn An out parameter; this is set to the pointer to the number for the
537 * right operand.
538 */
539static void
540bc_program_assignPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
541 BcNum** rn)
542{
543 BcResultType lt, min;
434 }
435
436 return n;
437}
438
439/**
440 * Prepares an operand for use.
441 * @param p The program.

--- 109 unchanged lines hidden (view full) ---

551 * @param rn An out parameter; this is set to the pointer to the number for the
552 * right operand.
553 */
554static void
555bc_program_assignPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
556 BcNum** rn)
557{
558 BcResultType lt, min;
559 bool good;
544
545 // This is the min non-allowable result type. dc allows strings.
546 min = BC_RESULT_TEMP - ((unsigned int) (BC_IS_BC));
547
548 // Prepare the operands.
549 bc_program_binPrep(p, l, ln, r, rn, 0);
550
551 lt = (*l)->t;
552
553 // Typecheck the left.
554 if (BC_ERR(lt >= min && lt <= BC_RESULT_ONE)) bc_err(BC_ERR_EXEC_TYPE);
555
556 // Strings can be assigned to variables. We are already good if we are
557 // assigning a string.
560
561 // This is the min non-allowable result type. dc allows strings.
562 min = BC_RESULT_TEMP - ((unsigned int) (BC_IS_BC));
563
564 // Prepare the operands.
565 bc_program_binPrep(p, l, ln, r, rn, 0);
566
567 lt = (*l)->t;
568
569 // Typecheck the left.
570 if (BC_ERR(lt >= min && lt <= BC_RESULT_ONE)) bc_err(BC_ERR_EXEC_TYPE);
571
572 // Strings can be assigned to variables. We are already good if we are
573 // assigning a string.
558 bool good = ((*r)->t == BC_RESULT_STR && lt <= BC_RESULT_ARRAY_ELEM);
574 good = ((*r)->t == BC_RESULT_STR && lt <= BC_RESULT_ARRAY_ELEM);
559
560 assert(BC_PROG_STR(*rn) || (*r)->t != BC_RESULT_STR);
561
562 // If not, type check for a number.
563 if (!good) bc_program_type_num(*r, *rn);
564}
565
566/**

--- 55 unchanged lines hidden (view full) ---

622 * bytecode vector and will be updated to point to after the index.
623 */
624static void
625bc_program_const(BcProgram* p, const char* code, size_t* bgn)
626{
627 // I lied. I actually push the result first. I can do this because the
628 // result will be popped on error. I also get the constant itself.
629 BcResult* r = bc_program_prepResult(p);
575
576 assert(BC_PROG_STR(*rn) || (*r)->t != BC_RESULT_STR);
577
578 // If not, type check for a number.
579 if (!good) bc_program_type_num(*r, *rn);
580}
581
582/**

--- 55 unchanged lines hidden (view full) ---

638 * bytecode vector and will be updated to point to after the index.
639 */
640static void
641bc_program_const(BcProgram* p, const char* code, size_t* bgn)
642{
643 // I lied. I actually push the result first. I can do this because the
644 // result will be popped on error. I also get the constant itself.
645 BcResult* r = bc_program_prepResult(p);
630 BcConst* c = bc_vec_item(p->consts, bc_program_index(code, bgn));
646 BcConst* c = bc_vec_item(&p->consts, bc_program_index(code, bgn));
631 BcBigDig base = BC_PROG_IBASE(p);
632
633 // Only reparse if the base changed.
634 if (c->base != base)
635 {
636 // Allocate if we haven't yet.
637 if (c->num.num == NULL)
638 {
647 BcBigDig base = BC_PROG_IBASE(p);
648
649 // Only reparse if the base changed.
650 if (c->base != base)
651 {
652 // Allocate if we haven't yet.
653 if (c->num.num == NULL)
654 {
655 // The plus 1 is in case of overflow with lack of clamping.
656 size_t len = strlen(c->val) + (BC_DIGIT_CLAMP == 0);
657
639 BC_SIG_LOCK;
658 BC_SIG_LOCK;
640 bc_num_init(&c->num, BC_NUM_RDX(strlen(c->val)));
659 bc_num_init(&c->num, BC_NUM_RDX(len));
641 BC_SIG_UNLOCK;
642 }
660 BC_SIG_UNLOCK;
661 }
662 // We need to zero an already existing number.
663 else bc_num_zero(&c->num);
643
644 // bc_num_parse() should only do operations that cannot fail.
645 bc_num_parse(&c->num, c->val, base);
646
647 c->base = base;
648 }
649
650 BC_SIG_LOCK;

--- 46 unchanged lines hidden (view full) ---

697 */
698static void
699bc_program_read(BcProgram* p)
700{
701 BcStatus s;
702 BcInstPtr ip;
703 size_t i;
704 const char* file;
664
665 // bc_num_parse() should only do operations that cannot fail.
666 bc_num_parse(&c->num, c->val, base);
667
668 c->base = base;
669 }
670
671 BC_SIG_LOCK;

--- 46 unchanged lines hidden (view full) ---

718 */
719static void
720bc_program_read(BcProgram* p)
721{
722 BcStatus s;
723 BcInstPtr ip;
724 size_t i;
725 const char* file;
705 bool is_stdin;
726 BcMode mode;
706 BcFunc* f = bc_vec_item(&p->fns, BC_PROG_READ);
707
708 // If we are already executing a read, that is an error. So look for a read
709 // and barf.
710 for (i = 0; i < p->stack.len; ++i)
711 {
712 BcInstPtr* ip_ptr = bc_vec_item(&p->stack, i);
713 if (ip_ptr->func == BC_PROG_READ) bc_err(BC_ERR_EXEC_REC_READ);
714 }
715
716 BC_SIG_LOCK;
717
718 // Save the filename because we are going to overwrite it.
727 BcFunc* f = bc_vec_item(&p->fns, BC_PROG_READ);
728
729 // If we are already executing a read, that is an error. So look for a read
730 // and barf.
731 for (i = 0; i < p->stack.len; ++i)
732 {
733 BcInstPtr* ip_ptr = bc_vec_item(&p->stack, i);
734 if (ip_ptr->func == BC_PROG_READ) bc_err(BC_ERR_EXEC_REC_READ);
735 }
736
737 BC_SIG_LOCK;
738
739 // Save the filename because we are going to overwrite it.
719 file = vm.file;
720 is_stdin = vm.is_stdin;
740 file = vm->file;
741 mode = vm->mode;
721
722 // It is a parse error if there needs to be more than one line, so we unset
723 // this to tell the lexer to not request more. We set it back later.
742
743 // It is a parse error if there needs to be more than one line, so we unset
744 // this to tell the lexer to not request more. We set it back later.
724 vm.is_stdin = false;
745 vm->mode = BC_MODE_FILE;
725
746
726 if (!BC_PARSE_IS_INITED(&vm.read_prs, p))
747 if (!BC_PARSE_IS_INITED(&vm->read_prs, p))
727 {
728 // We need to parse, but we don't want to use the existing parser
729 // because it has state it needs to keep. (It could have a partial parse
730 // state.) So we create a new parser. This parser is in the BcVm struct
731 // so that it is not local, which means that a longjmp() could change
732 // it.
748 {
749 // We need to parse, but we don't want to use the existing parser
750 // because it has state it needs to keep. (It could have a partial parse
751 // state.) So we create a new parser. This parser is in the BcVm struct
752 // so that it is not local, which means that a longjmp() could change
753 // it.
733 bc_parse_init(&vm.read_prs, p, BC_PROG_READ);
754 bc_parse_init(&vm->read_prs, p, BC_PROG_READ);
734
735 // We need a separate input buffer; that's why it is also in the BcVm
736 // struct.
755
756 // We need a separate input buffer; that's why it is also in the BcVm
757 // struct.
737 bc_vec_init(&vm.read_buf, sizeof(char), BC_DTOR_NONE);
758 bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE);
738 }
739 // This needs to be updated because the parser could have been used
740 // somewhere else
759 }
760 // This needs to be updated because the parser could have been used
761 // somewhere else
741 else bc_parse_updateFunc(&vm.read_prs, BC_PROG_READ);
762 else bc_parse_updateFunc(&vm->read_prs, BC_PROG_READ);
742
763
743 BC_SETJMP_LOCKED(exec_err);
764 BC_SETJMP_LOCKED(vm, exec_err);
744
745 BC_SIG_UNLOCK;
746
747 // Set up the lexer and the read function.
765
766 BC_SIG_UNLOCK;
767
768 // Set up the lexer and the read function.
748 bc_lex_file(&vm.read_prs.l, bc_program_stdin_name);
769 bc_lex_file(&vm->read_prs.l, bc_program_stdin_name);
749 bc_vec_popAll(&f->code);
750
751 // Read a line.
770 bc_vec_popAll(&f->code);
771
772 // Read a line.
752 if (!BC_R) s = bc_read_line(&vm.read_buf, "");
753 else s = bc_read_line(&vm.read_buf, BC_IS_BC ? "read> " : "?> ");
773 if (!BC_R) s = bc_read_line(&vm->read_buf, "");
774 else s = bc_read_line(&vm->read_buf, BC_VM_READ_PROMPT);
754
755 // We should *not* have run into EOF.
756 if (s == BC_STATUS_EOF) bc_err(BC_ERR_EXEC_READ_EXPR);
757
775
776 // We should *not* have run into EOF.
777 if (s == BC_STATUS_EOF) bc_err(BC_ERR_EXEC_READ_EXPR);
778
758 // Parse *one* expression, so is_stdin should be false.
759 bc_parse_text(&vm.read_prs, vm.read_buf.v, false, false);
779 // Parse *one* expression, so mode should not be stdin.
780 bc_parse_text(&vm->read_prs, vm->read_buf.v, BC_MODE_FILE);
760 BC_SIG_LOCK;
781 BC_SIG_LOCK;
761 vm.expr(&vm.read_prs, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL);
782 vm->expr(&vm->read_prs, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL);
762 BC_SIG_UNLOCK;
763
764 // We *must* have a valid expression. A semicolon cannot end an expression,
765 // although EOF can.
783 BC_SIG_UNLOCK;
784
785 // We *must* have a valid expression. A semicolon cannot end an expression,
786 // although EOF can.
766 if (BC_ERR(vm.read_prs.l.t != BC_LEX_NLINE &&
767 vm.read_prs.l.t != BC_LEX_EOF))
787 if (BC_ERR(vm->read_prs.l.t != BC_LEX_NLINE &&
788 vm->read_prs.l.t != BC_LEX_EOF))
768 {
769 bc_err(BC_ERR_EXEC_READ_EXPR);
770 }
771
772#if BC_ENABLED
773 // Push on the globals stack if necessary.
774 if (BC_G) bc_program_prepGlobals(p);
775#endif // BC_ENABLED
776
777 // Set up a new BcInstPtr.
778 ip.func = BC_PROG_READ;
779 ip.idx = 0;
780 ip.len = p->results.len;
781
782 // Update this pointer, just in case.
783 f = bc_vec_item(&p->fns, BC_PROG_READ);
784
785 // We want a return instruction to simplify things.
789 {
790 bc_err(BC_ERR_EXEC_READ_EXPR);
791 }
792
793#if BC_ENABLED
794 // Push on the globals stack if necessary.
795 if (BC_G) bc_program_prepGlobals(p);
796#endif // BC_ENABLED
797
798 // Set up a new BcInstPtr.
799 ip.func = BC_PROG_READ;
800 ip.idx = 0;
801 ip.len = p->results.len;
802
803 // Update this pointer, just in case.
804 f = bc_vec_item(&p->fns, BC_PROG_READ);
805
806 // We want a return instruction to simplify things.
786 bc_vec_pushByte(&f->code, vm.read_ret);
807 bc_vec_pushByte(&f->code, vm->read_ret);
787
788 // This lock is here to make sure dc's tail calls are the same length.
789 BC_SIG_LOCK;
790 bc_vec_push(&p->stack, &ip);
791
792#if DC_ENABLED
793 // We need a new tail call entry for dc.
794 if (BC_IS_DC)
795 {
796 size_t temp = 0;
797 bc_vec_push(&p->tail_calls, &temp);
798 }
799#endif // DC_ENABLED
800
801exec_err:
802 BC_SIG_MAYLOCK;
808
809 // This lock is here to make sure dc's tail calls are the same length.
810 BC_SIG_LOCK;
811 bc_vec_push(&p->stack, &ip);
812
813#if DC_ENABLED
814 // We need a new tail call entry for dc.
815 if (BC_IS_DC)
816 {
817 size_t temp = 0;
818 bc_vec_push(&p->tail_calls, &temp);
819 }
820#endif // DC_ENABLED
821
822exec_err:
823 BC_SIG_MAYLOCK;
803 vm.is_stdin = is_stdin;
804 vm.file = file;
805 BC_LONGJMP_CONT;
824 vm->mode = (uchar) mode;
825 vm->file = file;
826 BC_LONGJMP_CONT(vm);
806}
807
808#if BC_ENABLE_EXTRA_MATH
809
810/**
811 * Execute a rand().
812 * @param p The program.
813 */

--- 18 unchanged lines hidden (view full) ---

832/**
833 * Prints a series of characters, without escapes.
834 * @param str The string (series of characters).
835 */
836static void
837bc_program_printChars(const char* str)
838{
839 const char* nl;
827}
828
829#if BC_ENABLE_EXTRA_MATH
830
831/**
832 * Execute a rand().
833 * @param p The program.
834 */

--- 18 unchanged lines hidden (view full) ---

853/**
854 * Prints a series of characters, without escapes.
855 * @param str The string (series of characters).
856 */
857static void
858bc_program_printChars(const char* str)
859{
860 const char* nl;
840 size_t len = vm.nchars + strlen(str);
861 size_t len = vm->nchars + strlen(str);
841 sig_atomic_t lock;
842
843 BC_SIG_TRYLOCK(lock);
844
862 sig_atomic_t lock;
863
864 BC_SIG_TRYLOCK(lock);
865
845 bc_file_puts(&vm.fout, bc_flush_save, str);
866 bc_file_puts(&vm->fout, bc_flush_save, str);
846
847 // We need to update the number of characters, so we find the last newline
848 // and set the characters accordingly.
849 nl = strrchr(str, '\n');
850
851 if (nl != NULL) len = strlen(nl + 1);
852
867
868 // We need to update the number of characters, so we find the last newline
869 // and set the characters accordingly.
870 nl = strrchr(str, '\n');
871
872 if (nl != NULL) len = strlen(nl + 1);
873
853 vm.nchars = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len;
874 vm->nchars = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len;
854
855 BC_SIG_TRYUNLOCK(lock);
856}
857
858/**
859 * Prints a string with escapes.
860 * @param str The string.
861 */

--- 27 unchanged lines hidden (view full) ---

889
890 // If we have a companion character...
891 if (ptr != NULL)
892 {
893 // We need to specially handle a newline.
894 if (c == 'n')
895 {
896 BC_SIG_LOCK;
875
876 BC_SIG_TRYUNLOCK(lock);
877}
878
879/**
880 * Prints a string with escapes.
881 * @param str The string.
882 */

--- 27 unchanged lines hidden (view full) ---

910
911 // If we have a companion character...
912 if (ptr != NULL)
913 {
914 // We need to specially handle a newline.
915 if (c == 'n')
916 {
917 BC_SIG_LOCK;
897 vm.nchars = UINT16_MAX;
918 vm->nchars = UINT16_MAX;
898 BC_SIG_UNLOCK;
899 }
900
901 // Grab the actual character.
902 c = bc_program_esc_seqs[(size_t) (ptr - bc_program_esc_chars)];
903 }
904 else
905 {

--- 66 unchanged lines hidden (view full) ---

972#if BC_ENABLED
973 // Need to store the number in last.
974 if (BC_IS_BC) bc_num_copy(&p->last, n);
975#endif // BC_ENABLED
976 }
977 else
978 {
979 // We want to flush any stuff in the stdout buffer first.
919 BC_SIG_UNLOCK;
920 }
921
922 // Grab the actual character.
923 c = bc_program_esc_seqs[(size_t) (ptr - bc_program_esc_chars)];
924 }
925 else
926 {

--- 66 unchanged lines hidden (view full) ---

993#if BC_ENABLED
994 // Need to store the number in last.
995 if (BC_IS_BC) bc_num_copy(&p->last, n);
996#endif // BC_ENABLED
997 }
998 else
999 {
1000 // We want to flush any stuff in the stdout buffer first.
980 bc_file_flush(&vm.fout, bc_flush_save);
1001 bc_file_flush(&vm->fout, bc_flush_save);
981 str = bc_program_string(p, n);
982
983#if BC_ENABLED
984 if (inst == BC_INST_PRINT_STR) bc_program_printChars(str);
985 else
986#endif // BC_ENABLED
987 {
988 bc_program_printString(str);
989
990 // Need to print a newline only in this case.
991 if (inst == BC_INST_PRINT) bc_vm_putchar('\n', bc_flush_err);
992 }
993 }
994
1002 str = bc_program_string(p, n);
1003
1004#if BC_ENABLED
1005 if (inst == BC_INST_PRINT_STR) bc_program_printChars(str);
1006 else
1007#endif // BC_ENABLED
1008 {
1009 bc_program_printString(str);
1010
1011 // Need to print a newline only in this case.
1012 if (inst == BC_INST_PRINT) bc_vm_putchar('\n', bc_flush_err);
1013 }
1014 }
1015
995 // bc always pops.
996 if (BC_IS_BC || pop) bc_vec_pop(&p->results);
1016 // bc always pops. This macro makes sure that happens.
1017 if (BC_PROGRAM_POP(pop)) bc_vec_pop(&p->results);
997}
998
999void
1000bc_program_negate(BcResult* r, BcNum* n)
1001{
1002 bc_num_copy(&r->d.n, n);
1003 if (BC_NUM_NONZERO(&r->d.n)) BC_NUM_NEG_TGL_NP(r->d.n);
1004}

--- 163 unchanged lines hidden (view full) ---

1168 // We can just copy because the num should not have allocated anything.
1169 // NOLINTNEXTLINE
1170 memcpy(n, num, sizeof(BcNum));
1171}
1172
1173/**
1174 * Copies a value to a variable. This is used for storing in dc as well as to
1175 * set function parameters to arguments in bc.
1018}
1019
1020void
1021bc_program_negate(BcResult* r, BcNum* n)
1022{
1023 bc_num_copy(&r->d.n, n);
1024 if (BC_NUM_NONZERO(&r->d.n)) BC_NUM_NEG_TGL_NP(r->d.n);
1025}

--- 163 unchanged lines hidden (view full) ---

1189 // We can just copy because the num should not have allocated anything.
1190 // NOLINTNEXTLINE
1191 memcpy(n, num, sizeof(BcNum));
1192}
1193
1194/**
1195 * Copies a value to a variable. This is used for storing in dc as well as to
1196 * set function parameters to arguments in bc.
1176 * @param p The program.
1177 * @param idx The index of the variable or array to copy to.
1178 * @param t The type to copy to. This could be a variable or an array.
1179 * @param last Whether to grab the last item on the variable stack or not (for
1180 * bc function parameters). This is important because if a new
1181 * value has been pushed to the variable already, we need to grab
1182 * the value pushed before. This happens when you have a parameter
1183 * named something like "x", and a variable "x" is passed to
1184 * another parameter.
1197 * @param p The program.
1198 * @param idx The index of the variable or array to copy to.
1199 * @param t The type to copy to. This could be a variable or an array.
1185 */
1186static void
1200 */
1201static void
1187bc_program_copyToVar(BcProgram* p, size_t idx, BcType t, bool last)
1202bc_program_copyToVar(BcProgram* p, size_t idx, BcType t)
1188{
1189 BcResult *ptr = NULL, r;
1190 BcVec* vec;
1191 BcNum* n = NULL;
1192 bool var = (t == BC_TYPE_VAR);
1193
1194#if DC_ENABLED
1195 // Check the stack for dc.

--- 8 unchanged lines hidden (view full) ---

1204 bc_program_operand(p, &ptr, &n, 0);
1205
1206#if BC_ENABLED
1207 // Get the variable for a bc function call.
1208 if (BC_IS_BC)
1209 {
1210 // Type match the result.
1211 bc_program_type_match(ptr, t);
1203{
1204 BcResult *ptr = NULL, r;
1205 BcVec* vec;
1206 BcNum* n = NULL;
1207 bool var = (t == BC_TYPE_VAR);
1208
1209#if DC_ENABLED
1210 // Check the stack for dc.

--- 8 unchanged lines hidden (view full) ---

1219 bc_program_operand(p, &ptr, &n, 0);
1220
1221#if BC_ENABLED
1222 // Get the variable for a bc function call.
1223 if (BC_IS_BC)
1224 {
1225 // Type match the result.
1226 bc_program_type_match(ptr, t);
1212
1213 // Get the variable or array, taking care to get the real item. We take
1214 // care of last with arrays later.
1215 if (!last && var)
1216 {
1217 n = bc_vec_item_rev(bc_program_vec(p, ptr->d.loc.loc, t), 1);
1218 }
1219 }
1220#endif // BC_ENABLED
1221
1222 vec = bc_program_vec(p, idx, t);
1223
1224 // We can shortcut in dc if it's assigning a string by using
1225 // bc_program_assignStr().
1226 if (ptr->t == BC_RESULT_STR)

--- 25 unchanged lines hidden (view full) ---

1252 // to cast the number from bc_program_num() to a vector.
1253 BcVec* v = (BcVec*) n;
1254 BcVec* rv = &r.d.v;
1255
1256#if BC_ENABLED
1257
1258 if (BC_IS_BC)
1259 {
1227 }
1228#endif // BC_ENABLED
1229
1230 vec = bc_program_vec(p, idx, t);
1231
1232 // We can shortcut in dc if it's assigning a string by using
1233 // bc_program_assignStr().
1234 if (ptr->t == BC_RESULT_STR)

--- 25 unchanged lines hidden (view full) ---

1260 // to cast the number from bc_program_num() to a vector.
1261 BcVec* v = (BcVec*) n;
1262 BcVec* rv = &r.d.v;
1263
1264#if BC_ENABLED
1265
1266 if (BC_IS_BC)
1267 {
1260 BcVec* parent;
1261 bool ref, ref_size;
1262
1268 bool ref, ref_size;
1269
1263 // We need to figure out if the parameter is a reference or not and
1264 // construct the reference vector, if necessary. So this gets the
1265 // parent stack for the array.
1266 parent = bc_program_vec(p, ptr->d.loc.loc, t);
1267 assert(parent != NULL);
1268
1269 // This takes care of last for arrays. Mostly.
1270 if (!last) v = bc_vec_item_rev(parent, !last);
1271 assert(v != NULL);
1272
1273 // True if we are using a reference.
1274 ref = (v->size == sizeof(BcNum) && t == BC_TYPE_REF);
1275
1276 // True if we already have a reference vector. This is slightly
1277 // (okay, a lot; it just doesn't look that way) different from
1278 // above. The above means that we need to construct a reference
1279 // vector, whereas this means that we have one and we might have to
1280 // *dereference* it.
1281 ref_size = (v->size == sizeof(uchar));
1282
1283 // If we *should* have a reference.
1284 if (ref || (ref_size && t == BC_TYPE_REF))
1285 {
1286 // Create a new reference vector.
1287 bc_vec_init(rv, sizeof(uchar), BC_DTOR_NONE);
1288
1289 // If this is true, then we need to construct a reference.
1290 if (ref)
1291 {
1270 // True if we are using a reference.
1271 ref = (v->size == sizeof(BcNum) && t == BC_TYPE_REF);
1272
1273 // True if we already have a reference vector. This is slightly
1274 // (okay, a lot; it just doesn't look that way) different from
1275 // above. The above means that we need to construct a reference
1276 // vector, whereas this means that we have one and we might have to
1277 // *dereference* it.
1278 ref_size = (v->size == sizeof(uchar));
1279
1280 // If we *should* have a reference.
1281 if (ref || (ref_size && t == BC_TYPE_REF))
1282 {
1283 // Create a new reference vector.
1284 bc_vec_init(rv, sizeof(uchar), BC_DTOR_NONE);
1285
1286 // If this is true, then we need to construct a reference.
1287 if (ref)
1288 {
1292 assert(parent->len >= (size_t) (!last + 1));
1293
1294 // Make sure the pointer was not invalidated.
1295 vec = bc_program_vec(p, idx, t);
1296
1297 // Push the indices onto the reference vector. This takes
1298 // care of last; it ensures the reference goes to the right
1299 // place.
1300 bc_vec_pushIndex(rv, ptr->d.loc.loc);
1289 // Make sure the pointer was not invalidated.
1290 vec = bc_program_vec(p, idx, t);
1291
1292 // Push the indices onto the reference vector. This takes
1293 // care of last; it ensures the reference goes to the right
1294 // place.
1295 bc_vec_pushIndex(rv, ptr->d.loc.loc);
1301 bc_vec_pushIndex(rv, parent->len - !last - 1);
1296 bc_vec_pushIndex(rv, ptr->d.loc.stack_idx);
1302 }
1303 // If we get here, we are copying a ref to a ref. Just push a
1304 // copy of all of the bytes.
1305 else bc_vec_npush(rv, v->len * sizeof(uchar), v->v);
1306
1307 // Push the reference vector onto the array stack and pop the
1308 // source.
1309 bc_vec_push(vec, &r.d);

--- 24 unchanged lines hidden (view full) ---

1334 bc_vec_pop(&p->results);
1335
1336 BC_SIG_UNLOCK;
1337}
1338
1339void
1340bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val)
1341{
1297 }
1298 // If we get here, we are copying a ref to a ref. Just push a
1299 // copy of all of the bytes.
1300 else bc_vec_npush(rv, v->len * sizeof(uchar), v->v);
1301
1302 // Push the reference vector onto the array stack and pop the
1303 // source.
1304 bc_vec_push(vec, &r.d);

--- 24 unchanged lines hidden (view full) ---

1329 bc_vec_pop(&p->results);
1330
1331 BC_SIG_UNLOCK;
1332}
1333
1334void
1335bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val)
1336{
1342 BcVec* v;
1343 BcBigDig* ptr;
1344 BcBigDig* ptr_t;
1345 BcBigDig max, min;
1337 BcBigDig* ptr_t;
1338 BcBigDig max, min;
1339#if BC_ENABLED
1340 BcVec* v;
1341 BcBigDig* ptr;
1342#endif // BC_ENABLED
1346
1347 assert(!scale || !obase);
1348
1349 // Scale needs handling separate from ibase and obase.
1350 if (scale)
1351 {
1352 // Set the min and max.
1353 min = 0;
1343
1344 assert(!scale || !obase);
1345
1346 // Scale needs handling separate from ibase and obase.
1347 if (scale)
1348 {
1349 // Set the min and max.
1350 min = 0;
1354 max = vm.maxes[BC_PROG_GLOBALS_SCALE];
1351 max = vm->maxes[BC_PROG_GLOBALS_SCALE];
1355
1352
1356 // Get a pointer to the stack and to the current value.
1353#if BC_ENABLED
1354 // Get a pointer to the stack.
1357 v = p->globals_v + BC_PROG_GLOBALS_SCALE;
1355 v = p->globals_v + BC_PROG_GLOBALS_SCALE;
1356#endif // BC_ENABLED
1357
1358 // Get a pointer to the current value.
1358 ptr_t = p->globals + BC_PROG_GLOBALS_SCALE;
1359 }
1360 else
1361 {
1362 // Set the min and max.
1363 min = BC_NUM_MIN_BASE;
1364 if (BC_ENABLE_EXTRA_MATH && obase && (BC_IS_DC || !BC_IS_POSIX))
1365 {
1366 min = 0;
1367 }
1359 ptr_t = p->globals + BC_PROG_GLOBALS_SCALE;
1360 }
1361 else
1362 {
1363 // Set the min and max.
1364 min = BC_NUM_MIN_BASE;
1365 if (BC_ENABLE_EXTRA_MATH && obase && (BC_IS_DC || !BC_IS_POSIX))
1366 {
1367 min = 0;
1368 }
1368 max = vm.maxes[obase + BC_PROG_GLOBALS_IBASE];
1369 max = vm->maxes[obase + BC_PROG_GLOBALS_IBASE];
1369
1370
1370 // Get a pointer to the stack and to the current value.
1371#if BC_ENABLED
1372 // Get a pointer to the stack.
1371 v = p->globals_v + BC_PROG_GLOBALS_IBASE + obase;
1373 v = p->globals_v + BC_PROG_GLOBALS_IBASE + obase;
1374#endif // BC_ENABLED
1375
1376 // Get a pointer to the current value.
1372 ptr_t = p->globals + BC_PROG_GLOBALS_IBASE + obase;
1373 }
1374
1375 // Check for error.
1376 if (BC_ERR(val > max || val < min))
1377 {
1378 BcErr e;
1379
1380 // This grabs the right error.
1381 if (scale) e = BC_ERR_EXEC_SCALE;
1382 else if (obase) e = BC_ERR_EXEC_OBASE;
1383 else e = BC_ERR_EXEC_IBASE;
1384
1385 bc_verr(e, min, max);
1386 }
1387
1377 ptr_t = p->globals + BC_PROG_GLOBALS_IBASE + obase;
1378 }
1379
1380 // Check for error.
1381 if (BC_ERR(val > max || val < min))
1382 {
1383 BcErr e;
1384
1385 // This grabs the right error.
1386 if (scale) e = BC_ERR_EXEC_SCALE;
1387 else if (obase) e = BC_ERR_EXEC_OBASE;
1388 else e = BC_ERR_EXEC_IBASE;
1389
1390 bc_verr(e, min, max);
1391 }
1392
1388 // Set the top of the stack and the actual global value.
1393#if BC_ENABLED
1394 // Set the top of the stack.
1389 ptr = bc_vec_top(v);
1390 *ptr = val;
1395 ptr = bc_vec_top(v);
1396 *ptr = val;
1397#endif // BC_ENABLED
1398
1399 // Set the actual global variable.
1391 *ptr_t = val;
1392}
1393
1394#if BC_ENABLE_EXTRA_MATH
1395void
1396bc_program_assignSeed(BcProgram* p, BcNum* val)
1397{
1398 bc_num_rng(val, &p->rng);

--- 174 unchanged lines hidden (view full) ---

1573 * stack. This is only used in dc.
1574 */
1575static void
1576bc_program_pushVar(BcProgram* p, const char* restrict code,
1577 size_t* restrict bgn, bool pop, bool copy)
1578{
1579 BcResult r;
1580 size_t idx = bc_program_index(code, bgn);
1400 *ptr_t = val;
1401}
1402
1403#if BC_ENABLE_EXTRA_MATH
1404void
1405bc_program_assignSeed(BcProgram* p, BcNum* val)
1406{
1407 bc_num_rng(val, &p->rng);

--- 174 unchanged lines hidden (view full) ---

1582 * stack. This is only used in dc.
1583 */
1584static void
1585bc_program_pushVar(BcProgram* p, const char* restrict code,
1586 size_t* restrict bgn, bool pop, bool copy)
1587{
1588 BcResult r;
1589 size_t idx = bc_program_index(code, bgn);
1590 BcVec* v;
1581
1582 // Set the result appropriately.
1583 r.t = BC_RESULT_VAR;
1584 r.d.loc.loc = idx;
1585
1591
1592 // Set the result appropriately.
1593 r.t = BC_RESULT_VAR;
1594 r.d.loc.loc = idx;
1595
1596 // Get the stack for the variable. This is used in both bc and dc.
1597 v = bc_program_vec(p, idx, BC_TYPE_VAR);
1598 r.d.loc.stack_idx = v->len - 1;
1599
1586#if DC_ENABLED
1587 // If this condition is true, then we have the hard case, where we have to
1588 // adjust dc registers.
1589 if (BC_IS_DC && (pop || copy))
1590 {
1600#if DC_ENABLED
1601 // If this condition is true, then we have the hard case, where we have to
1602 // adjust dc registers.
1603 if (BC_IS_DC && (pop || copy))
1604 {
1591 // Get the stack for the variable and the number at the top.
1592 BcVec* v = bc_program_vec(p, idx, BC_TYPE_VAR);
1605 // Get the number at the top at the top of the stack.
1593 BcNum* num = bc_vec_top(v);
1594
1595 // Ensure there are enough elements on the stack.
1596 if (BC_ERR(!BC_PROG_STACK(v, 2 - copy)))
1597 {
1598 const char* name = bc_map_name(&p->var_map, idx);
1599 bc_verr(BC_ERR_EXEC_STACK_REGISTER, name);
1600 }

--- 46 unchanged lines hidden (view full) ---

1647static void
1648bc_program_pushArray(BcProgram* p, const char* restrict code,
1649 size_t* restrict bgn, uchar inst)
1650{
1651 BcResult r;
1652 BcResult* operand;
1653 BcNum* num;
1654 BcBigDig temp;
1606 BcNum* num = bc_vec_top(v);
1607
1608 // Ensure there are enough elements on the stack.
1609 if (BC_ERR(!BC_PROG_STACK(v, 2 - copy)))
1610 {
1611 const char* name = bc_map_name(&p->var_map, idx);
1612 bc_verr(BC_ERR_EXEC_STACK_REGISTER, name);
1613 }

--- 46 unchanged lines hidden (view full) ---

1660static void
1661bc_program_pushArray(BcProgram* p, const char* restrict code,
1662 size_t* restrict bgn, uchar inst)
1663{
1664 BcResult r;
1665 BcResult* operand;
1666 BcNum* num;
1667 BcBigDig temp;
1668 BcVec* v;
1655
1656 // Get the index of the array.
1657 r.d.loc.loc = bc_program_index(code, bgn);
1658
1669
1670 // Get the index of the array.
1671 r.d.loc.loc = bc_program_index(code, bgn);
1672
1673 // We need the array to get its length.
1674 v = bc_program_vec(p, r.d.loc.loc, BC_TYPE_ARRAY);
1675 assert(v != NULL);
1676
1677 r.d.loc.stack_idx = v->len - 1;
1678
1659 // Doing an array is easy; just set the result type and finish.
1660 if (inst == BC_INST_ARRAY)
1661 {
1662 r.t = BC_RESULT_ARRAY;
1663 bc_vec_push(&p->results, &r);
1664 return;
1665 }
1666

--- 33 unchanged lines hidden (view full) ---

1700 bc_program_prep(p, &ptr, &num, 0);
1701
1702 BC_SIG_LOCK;
1703
1704 // We need a copy from *before* the operation.
1705 copy.t = BC_RESULT_TEMP;
1706 bc_num_createCopy(&copy.d.n, num);
1707
1679 // Doing an array is easy; just set the result type and finish.
1680 if (inst == BC_INST_ARRAY)
1681 {
1682 r.t = BC_RESULT_ARRAY;
1683 bc_vec_push(&p->results, &r);
1684 return;
1685 }
1686

--- 33 unchanged lines hidden (view full) ---

1720 bc_program_prep(p, &ptr, &num, 0);
1721
1722 BC_SIG_LOCK;
1723
1724 // We need a copy from *before* the operation.
1725 copy.t = BC_RESULT_TEMP;
1726 bc_num_createCopy(&copy.d.n, num);
1727
1708 BC_SETJMP_LOCKED(exit);
1728 BC_SETJMP_LOCKED(vm, exit);
1709
1710 BC_SIG_UNLOCK;
1711
1712 // Create the proper assignment.
1713 res.t = BC_RESULT_ONE;
1714 inst2 = BC_INST_ASSIGN_PLUS_NO_VAL + (inst & 0x01);
1715
1716 bc_vec_push(&p->results, &res);
1717 bc_program_assign(p, inst2);
1718
1719 BC_SIG_LOCK;
1720
1721 bc_vec_push(&p->results, &copy);
1722
1729
1730 BC_SIG_UNLOCK;
1731
1732 // Create the proper assignment.
1733 res.t = BC_RESULT_ONE;
1734 inst2 = BC_INST_ASSIGN_PLUS_NO_VAL + (inst & 0x01);
1735
1736 bc_vec_push(&p->results, &res);
1737 bc_program_assign(p, inst2);
1738
1739 BC_SIG_LOCK;
1740
1741 bc_vec_push(&p->results, &copy);
1742
1723 BC_UNSETJMP;
1743 BC_UNSETJMP(vm);
1724
1725 BC_SIG_UNLOCK;
1726
1727 // No need to free the copy here because we pushed it onto the stack.
1728 return;
1729
1730exit:
1731 BC_SIG_MAYLOCK;
1732 bc_num_free(&copy.d.n);
1744
1745 BC_SIG_UNLOCK;
1746
1747 // No need to free the copy here because we pushed it onto the stack.
1748 return;
1749
1750exit:
1751 BC_SIG_MAYLOCK;
1752 bc_num_free(&copy.d.n);
1733 BC_LONGJMP_CONT;
1753 BC_LONGJMP_CONT(vm);
1734}
1735
1736/**
1737 * Executes a function call for bc.
1738 * @param p The program.
1739 * @param code The bytecode vector to pull the number of arguments and the
1740 * function index out of.
1741 * @param bgn An in/out parameter; the start of the indices in the bytecode

--- 31 unchanged lines hidden (view full) ---

1773 assert(BC_PROG_STACK(&p->results, nargs));
1774
1775 // Prepare the globals' stacks.
1776 if (BC_G) bc_program_prepGlobals(p);
1777
1778 // Push the arguments onto the stacks of their respective parameters.
1779 for (i = 0; i < nargs; ++i)
1780 {
1754}
1755
1756/**
1757 * Executes a function call for bc.
1758 * @param p The program.
1759 * @param code The bytecode vector to pull the number of arguments and the
1760 * function index out of.
1761 * @param bgn An in/out parameter; the start of the indices in the bytecode

--- 31 unchanged lines hidden (view full) ---

1793 assert(BC_PROG_STACK(&p->results, nargs));
1794
1795 // Prepare the globals' stacks.
1796 if (BC_G) bc_program_prepGlobals(p);
1797
1798 // Push the arguments onto the stacks of their respective parameters.
1799 for (i = 0; i < nargs; ++i)
1800 {
1781 size_t j;
1782 bool last = true;
1783
1784 arg = bc_vec_top(&p->results);
1785 if (BC_ERR(arg->t == BC_RESULT_VOID)) bc_err(BC_ERR_EXEC_VOID_VAL);
1786
1787 // Get the corresponding parameter.
1788 a = bc_vec_item(&f->autos, nargs - 1 - i);
1789
1801 arg = bc_vec_top(&p->results);
1802 if (BC_ERR(arg->t == BC_RESULT_VOID)) bc_err(BC_ERR_EXEC_VOID_VAL);
1803
1804 // Get the corresponding parameter.
1805 a = bc_vec_item(&f->autos, nargs - 1 - i);
1806
1790 // If I have already pushed to a var, I need to make sure I
1791 // get the previous version, not the already pushed one. This condition
1792 // must be true for that to even be possible.
1793 if (arg->t == BC_RESULT_VAR || arg->t == BC_RESULT_ARRAY)
1794 {
1795 // Loop through all of the previous parameters.
1796 for (j = 0; j < i && last; ++j)
1797 {
1798 BcAuto* aptr = bc_vec_item(&f->autos, nargs - 1 - j);
1799
1800 // This condition is true if there is a previous parameter with
1801 // the same name *and* type because variables and arrays do not
1802 // interfere with each other.
1803 last = (arg->d.loc.loc != aptr->idx ||
1804 (!aptr->type) != (arg->t == BC_RESULT_VAR));
1805 }
1806 }
1807
1808 // Actually push the value onto the parameter's stack.
1807 // Actually push the value onto the parameter's stack.
1809 bc_program_copyToVar(p, a->idx, a->type, last);
1808 bc_program_copyToVar(p, a->idx, a->type);
1810 }
1811
1812 BC_SIG_LOCK;
1813
1814 // Push zeroes onto the stacks of the auto variables.
1815 for (; i < f->autos.len; ++i)
1816 {
1817 // Get the auto and its stack.

--- 130 unchanged lines hidden (view full) ---

1948 BcResult* res;
1949 BcNum* num;
1950 bool len = (inst == BC_INST_LENGTH);
1951
1952 // Ensure we have a valid builtin.
1953#if BC_ENABLE_EXTRA_MATH
1954 assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IRAND);
1955#else // BC_ENABLE_EXTRA_MATH
1809 }
1810
1811 BC_SIG_LOCK;
1812
1813 // Push zeroes onto the stacks of the auto variables.
1814 for (; i < f->autos.len; ++i)
1815 {
1816 // Get the auto and its stack.

--- 130 unchanged lines hidden (view full) ---

1947 BcResult* res;
1948 BcNum* num;
1949 bool len = (inst == BC_INST_LENGTH);
1950
1951 // Ensure we have a valid builtin.
1952#if BC_ENABLE_EXTRA_MATH
1953 assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IRAND);
1954#else // BC_ENABLE_EXTRA_MATH
1956 assert(inst >= BC_INST_LENGTH && inst <= BC_INST_ABS);
1955 assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IS_STRING);
1957#endif // BC_ENABLE_EXTRA_MATH
1958
1959#ifndef BC_PROG_NO_STACK_CHECK
1960 // Check stack for dc.
1961 if (BC_IS_DC && BC_ERR(!BC_PROG_STACK(&p->results, 1)))
1962 {
1963 bc_err(BC_ERR_EXEC_STACK);
1964 }

--- 4 unchanged lines hidden (view full) ---

1969 res = bc_program_prepResult(p);
1970
1971 bc_program_operand(p, &opd, &num, 1);
1972
1973 assert(num != NULL);
1974
1975 // We need to ensure that strings and arrays aren't passed to most builtins.
1976 // The scale function can take strings in dc.
1956#endif // BC_ENABLE_EXTRA_MATH
1957
1958#ifndef BC_PROG_NO_STACK_CHECK
1959 // Check stack for dc.
1960 if (BC_IS_DC && BC_ERR(!BC_PROG_STACK(&p->results, 1)))
1961 {
1962 bc_err(BC_ERR_EXEC_STACK);
1963 }

--- 4 unchanged lines hidden (view full) ---

1968 res = bc_program_prepResult(p);
1969
1970 bc_program_operand(p, &opd, &num, 1);
1971
1972 assert(num != NULL);
1973
1974 // We need to ensure that strings and arrays aren't passed to most builtins.
1975 // The scale function can take strings in dc.
1977 if (!len && (inst != BC_INST_SCALE_FUNC || BC_IS_BC))
1976 if (!len && (inst != BC_INST_SCALE_FUNC || BC_IS_BC) &&
1977 inst != BC_INST_IS_NUMBER && inst != BC_INST_IS_STRING)
1978 {
1979 bc_program_type_num(opd, num);
1980 }
1981
1982 // Square root is easy.
1983 if (inst == BC_INST_SQRT) bc_num_sqrt(num, &res->d.n, BC_PROG_SCALE(p));
1984
1985 // Absolute value is easy.
1986 else if (inst == BC_INST_ABS)
1987 {
1988 BC_SIG_LOCK;
1989
1990 bc_num_createCopy(&res->d.n, num);
1991
1992 BC_SIG_UNLOCK;
1993
1994 BC_NUM_NEG_CLR_NP(res->d.n);
1995 }
1978 {
1979 bc_program_type_num(opd, num);
1980 }
1981
1982 // Square root is easy.
1983 if (inst == BC_INST_SQRT) bc_num_sqrt(num, &res->d.n, BC_PROG_SCALE(p));
1984
1985 // Absolute value is easy.
1986 else if (inst == BC_INST_ABS)
1987 {
1988 BC_SIG_LOCK;
1989
1990 bc_num_createCopy(&res->d.n, num);
1991
1992 BC_SIG_UNLOCK;
1993
1994 BC_NUM_NEG_CLR_NP(res->d.n);
1995 }
1996
1997 // Testing for number or string is easy.
1998 else if (inst == BC_INST_IS_NUMBER || inst == BC_INST_IS_STRING)
1999 {
2000 bool cond;
2001 bool is_str;
2002
2003 BC_SIG_LOCK;
2004
2005 bc_num_init(&res->d.n, BC_NUM_DEF_SIZE);
2006
2007 BC_SIG_UNLOCK;
2008
2009 // Test if the number is a string.
2010 is_str = BC_PROG_STR(num);
2011
2012 // This confusing condition simply means that the instruction must be
2013 // true if is_str is, or it must be false if is_str is. Otherwise, the
2014 // returned value is false (0).
2015 cond = ((inst == BC_INST_IS_STRING) == is_str);
2016 if (cond) bc_num_one(&res->d.n);
2017 }
2018
1996#if BC_ENABLE_EXTRA_MATH
2019#if BC_ENABLE_EXTRA_MATH
2020
1997 // irand() is easy.
1998 else if (inst == BC_INST_IRAND)
1999 {
2000 BC_SIG_LOCK;
2001
2002 bc_num_init(&res->d.n, num->len - BC_NUM_RDX_VAL(num));
2003
2004 BC_SIG_UNLOCK;
2005
2006 bc_num_irand(num, &res->d.n, &p->rng);
2007 }
2021 // irand() is easy.
2022 else if (inst == BC_INST_IRAND)
2023 {
2024 BC_SIG_LOCK;
2025
2026 bc_num_init(&res->d.n, num->len - BC_NUM_RDX_VAL(num));
2027
2028 BC_SIG_UNLOCK;
2029
2030 bc_num_irand(num, &res->d.n, &p->rng);
2031 }
2032
2008#endif // BC_ENABLE_EXTRA_MATH
2009
2010 // Everything else is...not easy.
2011 else
2012 {
2013 BcBigDig val = 0;
2014
2015 // Well, scale() is easy, but length() is not.
2016 if (len)
2017 {
2018 // If we are bc and we have an array...
2019 if (opd->t == BC_RESULT_ARRAY)
2020 {
2021 // Yes, this is one place where we need to cast the number from
2022 // bc_program_num() to a vector.
2023 BcVec* v = (BcVec*) num;
2024
2033#endif // BC_ENABLE_EXTRA_MATH
2034
2035 // Everything else is...not easy.
2036 else
2037 {
2038 BcBigDig val = 0;
2039
2040 // Well, scale() is easy, but length() is not.
2041 if (len)
2042 {
2043 // If we are bc and we have an array...
2044 if (opd->t == BC_RESULT_ARRAY)
2045 {
2046 // Yes, this is one place where we need to cast the number from
2047 // bc_program_num() to a vector.
2048 BcVec* v = (BcVec*) num;
2049
2050 // XXX: If this is changed, you should also change the similar
2051 // code in bc_program_asciify().
2052
2025#if BC_ENABLED
2026 // Dereference the array, if necessary.
2027 if (BC_IS_BC && v->size == sizeof(uchar))
2028 {
2029 v = bc_program_dereference(p, v);
2030 }
2031#endif // BC_ENABLED
2032

--- 136 unchanged lines hidden (view full) ---

2169/**
2170 * Asciifies a number for dc. This is a helper for bc_program_asciify().
2171 * @param p The program.
2172 * @param n The number to asciify.
2173 */
2174static uchar
2175bc_program_asciifyNum(BcProgram* p, BcNum* n)
2176{
2053#if BC_ENABLED
2054 // Dereference the array, if necessary.
2055 if (BC_IS_BC && v->size == sizeof(uchar))
2056 {
2057 v = bc_program_dereference(p, v);
2058 }
2059#endif // BC_ENABLED
2060

--- 136 unchanged lines hidden (view full) ---

2197/**
2198 * Asciifies a number for dc. This is a helper for bc_program_asciify().
2199 * @param p The program.
2200 * @param n The number to asciify.
2201 */
2202static uchar
2203bc_program_asciifyNum(BcProgram* p, BcNum* n)
2204{
2177 BcNum num;
2178 BcBigDig val;
2205 bc_num_copy(&p->asciify, n);
2179
2206
2180#ifndef NDEBUG
2181 // This is entirely to satisfy a useless scan-build error.
2182 val = 0;
2183#endif // NDEBUG
2184
2185 bc_num_clear(&num);
2186
2187 BC_SETJMP(num_err);
2188
2189 BC_SIG_LOCK;
2190
2191 bc_num_createCopy(&num, n);
2192
2193 BC_SIG_UNLOCK;
2194
2195 // We want to clear the scale and sign for easy mod later.
2207 // We want to clear the scale and sign for easy mod later.
2196 bc_num_truncate(&num, num.scale);
2197 BC_NUM_NEG_CLR_NP(num);
2208 bc_num_truncate(&p->asciify, p->asciify.scale);
2209 BC_NUM_NEG_CLR(&p->asciify);
2198
2199 // This is guaranteed to not have a divide by 0
2200 // because strmb is equal to 256.
2210
2211 // This is guaranteed to not have a divide by 0
2212 // because strmb is equal to 256.
2201 bc_num_mod(&num, &p->strmb, &num, 0);
2213 bc_num_mod(&p->asciify, &p->strmb, &p->asciify, 0);
2202
2203 // This is also guaranteed to not error because num is in the range
2204 // [0, UCHAR_MAX], which is definitely in range for a BcBigDig. And
2205 // it is not negative.
2214
2215 // This is also guaranteed to not error because num is in the range
2216 // [0, UCHAR_MAX], which is definitely in range for a BcBigDig. And
2217 // it is not negative.
2206 val = bc_num_bigdig2(&num);
2207
2208num_err:
2209 BC_SIG_MAYLOCK;
2210 bc_num_free(&num);
2211 BC_LONGJMP_CONT;
2212 return (uchar) val;
2218 return (uchar) bc_num_bigdig2(&p->asciify);
2213}
2214
2215/**
2219}
2220
2221/**
2216 * Executes the "asciify" command in dc.
2217 * @param p The program.
2218 * @param fidx The index of the current function.
2222 * Executes the "asciify" command in bc and dc.
2223 * @param p The program.
2219 */
2220static void
2224 */
2225static void
2221bc_program_asciify(BcProgram* p, size_t fidx)
2226bc_program_asciify(BcProgram* p)
2222{
2223 BcResult *r, res;
2224 BcNum* n;
2227{
2228 BcResult *r, res;
2229 BcNum* n;
2225 char str[2];
2226 char* str2;
2227 uchar c;
2228 size_t idx;
2230 uchar c;
2231 size_t idx;
2232#if BC_ENABLED
2233 // This is in the outer scope because it has to be freed after a jump.
2234 char* temp_str;
2235#endif // BC_ENABLED
2229
2230 // Check the stack.
2231 if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
2232
2233 assert(BC_PROG_STACK(&p->results, 1));
2234
2235 // Get the top of the results stack.
2236 bc_program_operand(p, &r, &n, 0);
2237
2238 assert(n != NULL);
2236
2237 // Check the stack.
2238 if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
2239
2240 assert(BC_PROG_STACK(&p->results, 1));
2241
2242 // Get the top of the results stack.
2243 bc_program_operand(p, &r, &n, 0);
2244
2245 assert(n != NULL);
2246 assert(BC_IS_BC || r->t != BC_RESULT_ARRAY);
2239
2247
2240 // Asciify.
2241 if (BC_PROG_NUM(r, n)) c = bc_program_asciifyNum(p, n);
2242 else
2248#if BC_ENABLED
2249 // Handle arrays in bc specially.
2250 if (r->t == BC_RESULT_ARRAY)
2243 {
2251 {
2244 // Get the string itself, then the first character.
2245 str2 = bc_program_string(p, n);
2246 c = (uchar) str2[0];
2252 // Yes, this is one place where we need to cast the number from
2253 // bc_program_num() to a vector.
2254 BcVec* v = (BcVec*) n;
2255 size_t i;
2256
2257 // XXX: If this is changed, you should also change the similar code in
2258 // bc_program_builtin().
2259
2260 // Dereference the array, if necessary.
2261 if (v->size == sizeof(uchar))
2262 {
2263 v = bc_program_dereference(p, v);
2264 }
2265
2266 assert(v->size == sizeof(BcNum));
2267
2268 // Allocate the string and set the jump for it.
2269 BC_SIG_LOCK;
2270 temp_str = bc_vm_malloc(v->len + 1);
2271 BC_SETJMP_LOCKED(vm, exit);
2272 BC_SIG_UNLOCK;
2273
2274 // Convert the array.
2275 for (i = 0; i < v->len; ++i)
2276 {
2277 BcNum* num = (BcNum*) bc_vec_item(v, i);
2278
2279 if (BC_PROG_STR(num))
2280 {
2281 temp_str[i] = (bc_program_string(p, num))[0];
2282 }
2283 else
2284 {
2285 temp_str[i] = (char) bc_program_asciifyNum(p, num);
2286 }
2287 }
2288
2289 temp_str[v->len] = '\0';
2290
2291 // Store the string in the slab and map, and free the temp string.
2292 BC_SIG_LOCK;
2293 idx = bc_program_addString(p, temp_str);
2294 free(temp_str);
2295 BC_UNSETJMP(vm);
2296 BC_SIG_UNLOCK;
2247 }
2297 }
2298 else
2299#endif // BC_ENABLED
2300 {
2301 char str[2];
2302 char* str2;
2248
2303
2249 // Fill the resulting string.
2250 str[0] = (char) c;
2251 str[1] = '\0';
2304 // Asciify.
2305 if (BC_PROG_NUM(r, n)) c = bc_program_asciifyNum(p, n);
2306 else
2307 {
2308 // Get the string itself, then the first character.
2309 str2 = bc_program_string(p, n);
2310 c = (uchar) str2[0];
2311 }
2252
2312
2253 // Add the string to the data structures.
2254 BC_SIG_LOCK;
2255 idx = bc_program_addString(p, str, fidx);
2256 BC_SIG_UNLOCK;
2313 // Fill the resulting string.
2314 str[0] = (char) c;
2315 str[1] = '\0';
2257
2316
2317 // Add the string to the data structures.
2318 BC_SIG_LOCK;
2319 idx = bc_program_addString(p, str);
2320 BC_SIG_UNLOCK;
2321 }
2322
2258 // Set the result
2259 res.t = BC_RESULT_STR;
2260 bc_num_clear(&res.d.n);
2323 // Set the result
2324 res.t = BC_RESULT_STR;
2325 bc_num_clear(&res.d.n);
2261 res.d.n.rdx = fidx;
2262 res.d.n.scale = idx;
2263
2264 // Pop and push.
2265 bc_vec_pop(&p->results);
2266 bc_vec_push(&p->results, &res);
2326 res.d.n.scale = idx;
2327
2328 // Pop and push.
2329 bc_vec_pop(&p->results);
2330 bc_vec_push(&p->results, &res);
2331
2332 return;
2333
2334#if BC_ENABLED
2335exit:
2336 free(temp_str);
2337#endif // BC_ENABLED
2267}
2268
2269/**
2270 * Streams a number or a string to stdout.
2271 * @param p The program.
2272 */
2273static void
2274bc_program_printStream(BcProgram* p)

--- 85 unchanged lines hidden (view full) ---

2360 // Adjust the value.
2361 if (calls >= val) val = 0;
2362 else val -= (BcBigDig) calls;
2363 }
2364
2365 // If we don't have enough executions, just quit.
2366 if (i == p->stack.len)
2367 {
2338}
2339
2340/**
2341 * Streams a number or a string to stdout.
2342 * @param p The program.
2343 */
2344static void
2345bc_program_printStream(BcProgram* p)

--- 85 unchanged lines hidden (view full) ---

2431 // Adjust the value.
2432 if (calls >= val) val = 0;
2433 else val -= (BcBigDig) calls;
2434 }
2435
2436 // If we don't have enough executions, just quit.
2437 if (i == p->stack.len)
2438 {
2368 vm.status = BC_STATUS_QUIT;
2439 vm->status = BC_STATUS_QUIT;
2369 BC_JMP;
2370 }
2371 else
2372 {
2373 // We can always pop the last item we reached on the tail call stack
2374 // because these are for tail calls. That means that any executions that
2375 // we would not have quit in that position on the stack would have quit
2376 // anyway.

--- 52 unchanged lines hidden (view full) ---

2429
2430 // Get the operand.
2431 bc_program_operand(p, &r, &n, 0);
2432
2433 // If execution is conditional...
2434 if (cond)
2435 {
2436 bool exec;
2440 BC_JMP;
2441 }
2442 else
2443 {
2444 // We can always pop the last item we reached on the tail call stack
2445 // because these are for tail calls. That means that any executions that
2446 // we would not have quit in that position on the stack would have quit
2447 // anyway.

--- 52 unchanged lines hidden (view full) ---

2500
2501 // Get the operand.
2502 bc_program_operand(p, &r, &n, 0);
2503
2504 // If execution is conditional...
2505 if (cond)
2506 {
2507 bool exec;
2437 size_t idx, then_idx, else_idx;
2508 size_t then_idx;
2509 // These are volatile to quiet warnings on GCC about clobbering with
2510 // longjmp().
2511 volatile size_t else_idx;
2512 volatile size_t idx;
2438
2439 // Get the index of the "then" var and "else" var.
2440 then_idx = bc_program_index(code, bgn);
2441 else_idx = bc_program_index(code, bgn);
2442
2443 // Figure out if we should execute.
2444 exec = (r->d.n.len != 0);
2445
2446 idx = exec ? then_idx : else_idx;
2447
2448 BC_SIG_LOCK;
2513
2514 // Get the index of the "then" var and "else" var.
2515 then_idx = bc_program_index(code, bgn);
2516 else_idx = bc_program_index(code, bgn);
2517
2518 // Figure out if we should execute.
2519 exec = (r->d.n.len != 0);
2520
2521 idx = exec ? then_idx : else_idx;
2522
2523 BC_SIG_LOCK;
2449 BC_SETJMP_LOCKED(exit);
2524 BC_SETJMP_LOCKED(vm, exit);
2450
2451 // If we are supposed to execute, execute. If else_idx == SIZE_MAX, that
2452 // means there was no else clause, so if execute is false and else does
2453 // not exist, we don't execute. The goto skips all of the setup for the
2454 // execution.
2455 if (exec || (else_idx != SIZE_MAX))
2456 {
2457 n = bc_vec_top(bc_program_vec(p, idx, BC_TYPE_VAR));
2458 }
2459 else goto exit;
2460
2461 if (BC_ERR(!BC_PROG_STR(n))) bc_err(BC_ERR_EXEC_TYPE);
2462
2525
2526 // If we are supposed to execute, execute. If else_idx == SIZE_MAX, that
2527 // means there was no else clause, so if execute is false and else does
2528 // not exist, we don't execute. The goto skips all of the setup for the
2529 // execution.
2530 if (exec || (else_idx != SIZE_MAX))
2531 {
2532 n = bc_vec_top(bc_program_vec(p, idx, BC_TYPE_VAR));
2533 }
2534 else goto exit;
2535
2536 if (BC_ERR(!BC_PROG_STR(n))) bc_err(BC_ERR_EXEC_TYPE);
2537
2463 BC_UNSETJMP;
2538 BC_UNSETJMP(vm);
2464 BC_SIG_UNLOCK;
2465 }
2466 else
2467 {
2468 // In non-conditional situations, only the top of stack can be executed,
2469 // and in those cases, variables are not allowed to be "on the stack";
2470 // they are only put on the stack to be assigned to.
2471 assert(r->t != BC_RESULT_VAR);

--- 12 unchanged lines hidden (view full) ---

2484 BC_SIG_UNLOCK;
2485 f = bc_vec_item(&p->fns, fidx);
2486
2487 // If the function has not been parsed yet...
2488 if (!f->code.len)
2489 {
2490 BC_SIG_LOCK;
2491
2539 BC_SIG_UNLOCK;
2540 }
2541 else
2542 {
2543 // In non-conditional situations, only the top of stack can be executed,
2544 // and in those cases, variables are not allowed to be "on the stack";
2545 // they are only put on the stack to be assigned to.
2546 assert(r->t != BC_RESULT_VAR);

--- 12 unchanged lines hidden (view full) ---

2559 BC_SIG_UNLOCK;
2560 f = bc_vec_item(&p->fns, fidx);
2561
2562 // If the function has not been parsed yet...
2563 if (!f->code.len)
2564 {
2565 BC_SIG_LOCK;
2566
2492 if (!BC_PARSE_IS_INITED(&vm.read_prs, p))
2567 if (!BC_PARSE_IS_INITED(&vm->read_prs, p))
2493 {
2568 {
2494 bc_parse_init(&vm.read_prs, p, fidx);
2569 bc_parse_init(&vm->read_prs, p, fidx);
2495
2496 // Initialize this too because bc_vm_shutdown() expects them to be
2497 // initialized togther.
2570
2571 // Initialize this too because bc_vm_shutdown() expects them to be
2572 // initialized togther.
2498 bc_vec_init(&vm.read_buf, sizeof(char), BC_DTOR_NONE);
2573 bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE);
2499 }
2500 // This needs to be updated because the parser could have been used
2501 // somewhere else
2574 }
2575 // This needs to be updated because the parser could have been used
2576 // somewhere else
2502 else bc_parse_updateFunc(&vm.read_prs, fidx);
2577 else bc_parse_updateFunc(&vm->read_prs, fidx);
2503
2578
2504 bc_lex_file(&vm.read_prs.l, vm.file);
2579 bc_lex_file(&vm->read_prs.l, vm->file);
2505
2580
2506 BC_SETJMP_LOCKED(err);
2581 BC_SETJMP_LOCKED(vm, err);
2507
2508 BC_SIG_UNLOCK;
2509
2582
2583 BC_SIG_UNLOCK;
2584
2510 // Parse.
2511 bc_parse_text(&vm.read_prs, str, false, false);
2585 // Parse. Only one expression is needed, so stdin isn't used.
2586 bc_parse_text(&vm->read_prs, str, BC_MODE_FILE);
2512
2513 BC_SIG_LOCK;
2587
2588 BC_SIG_LOCK;
2514 vm.expr(&vm.read_prs, BC_PARSE_NOCALL);
2589 vm->expr(&vm->read_prs, BC_PARSE_NOCALL);
2515
2590
2516 BC_UNSETJMP;
2591 BC_UNSETJMP(vm);
2517
2518 // We can just assert this here because
2519 // dc should parse everything until EOF.
2592
2593 // We can just assert this here because
2594 // dc should parse everything until EOF.
2520 assert(vm.read_prs.l.t == BC_LEX_EOF);
2595 assert(vm->read_prs.l.t == BC_LEX_EOF);
2521
2522 BC_SIG_UNLOCK;
2523 }
2524
2525 // Set the instruction pointer.
2526 ip.idx = 0;
2527 ip.len = p->results.len;
2528 ip.func = fidx;

--- 32 unchanged lines hidden (view full) ---

2561
2562 f = bc_vec_item(&p->fns, fidx);
2563
2564 // Make sure to erase the bytecode vector so dc knows it is not parsed.
2565 bc_vec_popAll(&f->code);
2566
2567exit:
2568 bc_vec_pop(&p->results);
2596
2597 BC_SIG_UNLOCK;
2598 }
2599
2600 // Set the instruction pointer.
2601 ip.idx = 0;
2602 ip.len = p->results.len;
2603 ip.func = fidx;

--- 32 unchanged lines hidden (view full) ---

2636
2637 f = bc_vec_item(&p->fns, fidx);
2638
2639 // Make sure to erase the bytecode vector so dc knows it is not parsed.
2640 bc_vec_popAll(&f->code);
2641
2642exit:
2643 bc_vec_pop(&p->results);
2569 BC_LONGJMP_CONT;
2644 BC_LONGJMP_CONT(vm);
2570}
2571
2572/**
2573 * Prints every item on the results stack, one per line.
2574 * @param p The program.
2575 */
2576static void
2577bc_program_printStack(BcProgram* p)

--- 33 unchanged lines hidden (view full) ---

2611static void
2612bc_program_globalSetting(BcProgram* p, uchar inst)
2613{
2614 BcBigDig val;
2615
2616 // Make sure the instruction is valid.
2617 assert(inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO);
2618
2645}
2646
2647/**
2648 * Prints every item on the results stack, one per line.
2649 * @param p The program.
2650 */
2651static void
2652bc_program_printStack(BcProgram* p)

--- 33 unchanged lines hidden (view full) ---

2686static void
2687bc_program_globalSetting(BcProgram* p, uchar inst)
2688{
2689 BcBigDig val;
2690
2691 // Make sure the instruction is valid.
2692 assert(inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO);
2693
2619 if (inst == BC_INST_LINE_LENGTH) val = (BcBigDig) vm.line_len;
2694 if (inst == BC_INST_LINE_LENGTH) val = (BcBigDig) vm->line_len;
2620#if BC_ENABLED
2621 else if (inst == BC_INST_GLOBAL_STACKS) val = (BC_G != 0);
2622#endif // BC_ENABLED
2623 else val = (BC_Z != 0);
2624
2625 // Push the global.
2626 bc_program_pushBigdig(p, val, BC_RESULT_TEMP);
2627}

--- 28 unchanged lines hidden (view full) ---

2656 * Adds a function to the fns array. The function's ID must have already been
2657 * inserted into the map.
2658 * @param p The program.
2659 * @param id_ptr The ID of the function as inserted into the map.
2660 */
2661static void
2662bc_program_addFunc(BcProgram* p, BcId* id_ptr)
2663{
2695#if BC_ENABLED
2696 else if (inst == BC_INST_GLOBAL_STACKS) val = (BC_G != 0);
2697#endif // BC_ENABLED
2698 else val = (BC_Z != 0);
2699
2700 // Push the global.
2701 bc_program_pushBigdig(p, val, BC_RESULT_TEMP);
2702}

--- 28 unchanged lines hidden (view full) ---

2731 * Adds a function to the fns array. The function's ID must have already been
2732 * inserted into the map.
2733 * @param p The program.
2734 * @param id_ptr The ID of the function as inserted into the map.
2735 */
2736static void
2737bc_program_addFunc(BcProgram* p, BcId* id_ptr)
2738{
2664 BcInstPtr* ip;
2665 BcFunc* f;
2666
2667 BC_SIG_ASSERT_LOCKED;
2668
2669 // Push and init.
2670 f = bc_vec_pushEmpty(&p->fns);
2671 bc_func_init(f, id_ptr->name);
2739 BcFunc* f;
2740
2741 BC_SIG_ASSERT_LOCKED;
2742
2743 // Push and init.
2744 f = bc_vec_pushEmpty(&p->fns);
2745 bc_func_init(f, id_ptr->name);
2672
2673 // This is to make sure pointers are updated if the array was moved.
2674 if (p->stack.len)
2675 {
2676 ip = bc_vec_top(&p->stack);
2677 bc_program_setVecs(p, (BcFunc*) bc_vec_item(&p->fns, ip->func));
2678 }
2679}
2680
2681size_t
2682bc_program_insertFunc(BcProgram* p, const char* name)
2683{
2684 BcId* id_ptr;
2685 bool new;
2686 size_t idx;

--- 24 unchanged lines hidden (view full) ---

2711
2712 return idx;
2713}
2714
2715#ifndef NDEBUG
2716void
2717bc_program_free(BcProgram* p)
2718{
2746}
2747
2748size_t
2749bc_program_insertFunc(BcProgram* p, const char* name)
2750{
2751 BcId* id_ptr;
2752 bool new;
2753 size_t idx;

--- 24 unchanged lines hidden (view full) ---

2778
2779 return idx;
2780}
2781
2782#ifndef NDEBUG
2783void
2784bc_program_free(BcProgram* p)
2785{
2786#if BC_ENABLED
2719 size_t i;
2787 size_t i;
2788#endif // BC_ENABLED
2720
2721 BC_SIG_ASSERT_LOCKED;
2722
2723 assert(p != NULL);
2724
2789
2790 BC_SIG_ASSERT_LOCKED;
2791
2792 assert(p != NULL);
2793
2794#if BC_ENABLED
2725 // Free the globals stacks.
2726 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
2727 {
2728 bc_vec_free(p->globals_v + i);
2729 }
2795 // Free the globals stacks.
2796 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
2797 {
2798 bc_vec_free(p->globals_v + i);
2799 }
2800#endif // BC_ENABLED
2730
2731 bc_vec_free(&p->fns);
2732 bc_vec_free(&p->fn_map);
2733 bc_vec_free(&p->vars);
2734 bc_vec_free(&p->var_map);
2735 bc_vec_free(&p->arrs);
2736 bc_vec_free(&p->arr_map);
2737 bc_vec_free(&p->results);
2738 bc_vec_free(&p->stack);
2801
2802 bc_vec_free(&p->fns);
2803 bc_vec_free(&p->fn_map);
2804 bc_vec_free(&p->vars);
2805 bc_vec_free(&p->var_map);
2806 bc_vec_free(&p->arrs);
2807 bc_vec_free(&p->arr_map);
2808 bc_vec_free(&p->results);
2809 bc_vec_free(&p->stack);
2810 bc_vec_free(&p->consts);
2811 bc_vec_free(&p->const_map);
2812 bc_vec_free(&p->strs);
2813 bc_vec_free(&p->str_map);
2739
2814
2815 bc_num_free(&p->asciify);
2816
2740#if BC_ENABLED
2741 if (BC_IS_BC) bc_num_free(&p->last);
2742#endif // BC_ENABLED
2743
2744#if BC_ENABLE_EXTRA_MATH
2745 bc_rand_free(&p->rng);
2746#endif // BC_ENABLE_EXTRA_MATH
2747

--- 17 unchanged lines hidden (view full) ---

2765 // NOLINTNEXTLINE
2766 memset(&ip, 0, sizeof(BcInstPtr));
2767
2768 // Setup the globals stacks and the current values.
2769 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
2770 {
2771 BcBigDig val = i == BC_PROG_GLOBALS_SCALE ? 0 : BC_BASE;
2772
2817#if BC_ENABLED
2818 if (BC_IS_BC) bc_num_free(&p->last);
2819#endif // BC_ENABLED
2820
2821#if BC_ENABLE_EXTRA_MATH
2822 bc_rand_free(&p->rng);
2823#endif // BC_ENABLE_EXTRA_MATH
2824

--- 17 unchanged lines hidden (view full) ---

2842 // NOLINTNEXTLINE
2843 memset(&ip, 0, sizeof(BcInstPtr));
2844
2845 // Setup the globals stacks and the current values.
2846 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
2847 {
2848 BcBigDig val = i == BC_PROG_GLOBALS_SCALE ? 0 : BC_BASE;
2849
2850#if BC_ENABLED
2773 bc_vec_init(p->globals_v + i, sizeof(BcBigDig), BC_DTOR_NONE);
2774 bc_vec_push(p->globals_v + i, &val);
2851 bc_vec_init(p->globals_v + i, sizeof(BcBigDig), BC_DTOR_NONE);
2852 bc_vec_push(p->globals_v + i, &val);
2853#endif // BC_ENABLED
2775
2776 p->globals[i] = val;
2777 }
2778
2779#if DC_ENABLED
2780 // dc-only setup.
2781 if (BC_IS_DC)
2782 {
2783 bc_vec_init(&p->tail_calls, sizeof(size_t), BC_DTOR_NONE);
2784
2785 // We want an item for the main function on the tail call stack.
2786 i = 0;
2787 bc_vec_push(&p->tail_calls, &i);
2788 }
2789#endif // DC_ENABLED
2790
2791 bc_num_setup(&p->strmb, p->strmb_num, BC_NUM_BIGDIG_LOG10);
2792 bc_num_bigdig2num(&p->strmb, BC_NUM_STREAM_BASE);
2793
2854
2855 p->globals[i] = val;
2856 }
2857
2858#if DC_ENABLED
2859 // dc-only setup.
2860 if (BC_IS_DC)
2861 {
2862 bc_vec_init(&p->tail_calls, sizeof(size_t), BC_DTOR_NONE);
2863
2864 // We want an item for the main function on the tail call stack.
2865 i = 0;
2866 bc_vec_push(&p->tail_calls, &i);
2867 }
2868#endif // DC_ENABLED
2869
2870 bc_num_setup(&p->strmb, p->strmb_num, BC_NUM_BIGDIG_LOG10);
2871 bc_num_bigdig2num(&p->strmb, BC_NUM_STREAM_BASE);
2872
2873 bc_num_init(&p->asciify, BC_NUM_DEF_SIZE);
2874
2794#if BC_ENABLE_EXTRA_MATH
2795 // We need to initialize srand() just in case /dev/urandom and /dev/random
2796 // are not available.
2797 srand((unsigned int) time(NULL));
2798 bc_rand_init(&p->rng);
2799#endif // BC_ENABLE_EXTRA_MATH
2800
2801#if BC_ENABLED

--- 16 unchanged lines hidden (view full) ---

2818 bc_map_init(&p->arr_map);
2819
2820 bc_vec_init(&p->results, sizeof(BcResult), BC_DTOR_RESULT);
2821
2822 // Push the first instruction pointer onto the execution stack.
2823 bc_vec_init(&p->stack, sizeof(BcInstPtr), BC_DTOR_NONE);
2824 bc_vec_push(&p->stack, &ip);
2825
2875#if BC_ENABLE_EXTRA_MATH
2876 // We need to initialize srand() just in case /dev/urandom and /dev/random
2877 // are not available.
2878 srand((unsigned int) time(NULL));
2879 bc_rand_init(&p->rng);
2880#endif // BC_ENABLE_EXTRA_MATH
2881
2882#if BC_ENABLED

--- 16 unchanged lines hidden (view full) ---

2899 bc_map_init(&p->arr_map);
2900
2901 bc_vec_init(&p->results, sizeof(BcResult), BC_DTOR_RESULT);
2902
2903 // Push the first instruction pointer onto the execution stack.
2904 bc_vec_init(&p->stack, sizeof(BcInstPtr), BC_DTOR_NONE);
2905 bc_vec_push(&p->stack, &ip);
2906
2826 // Make sure the pointers are properly set up.
2827 bc_program_setVecs(p, (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN));
2907 bc_vec_init(&p->consts, sizeof(BcConst), BC_DTOR_CONST);
2908 bc_map_init(&p->const_map);
2909 bc_vec_init(&p->strs, sizeof(char*), BC_DTOR_NONE);
2910 bc_map_init(&p->str_map);
2911}
2828
2912
2829 assert(p->consts != NULL && p->strs != NULL);
2913void
2914bc_program_printStackTrace(BcProgram* p)
2915{
2916 size_t i, max_digits;
2917
2918 max_digits = bc_vm_numDigits(p->stack.len - 1);
2919
2920 for (i = 0; i < p->stack.len; ++i)
2921 {
2922 BcInstPtr* ip = bc_vec_item_rev(&p->stack, i);
2923 BcFunc* f = bc_vec_item(&p->fns, ip->func);
2924 size_t j, digits;
2925
2926 digits = bc_vm_numDigits(i);
2927
2928 bc_file_puts(&vm->ferr, bc_flush_none, " ");
2929
2930 for (j = 0; j < max_digits - digits; ++j)
2931 {
2932 bc_file_putchar(&vm->ferr, bc_flush_none, ' ');
2933 }
2934
2935 bc_file_printf(&vm->ferr, "%zu: %s", i, f->name);
2936
2937#if BC_ENABLED
2938 if (BC_IS_BC && ip->func != BC_PROG_MAIN && ip->func != BC_PROG_READ)
2939 {
2940 bc_file_puts(&vm->ferr, bc_flush_none, "()");
2941 }
2942#endif // BC_ENABLED
2943
2944 bc_file_putchar(&vm->ferr, bc_flush_none, '\n');
2945 }
2830}
2831
2832void
2833bc_program_reset(BcProgram* p)
2834{
2835 BcFunc* f;
2836 BcInstPtr* ip;
2837
2838 BC_SIG_ASSERT_LOCKED;
2839
2840 // Pop all but the last execution and all results.
2841 bc_vec_npop(&p->stack, p->stack.len - 1);
2842 bc_vec_popAll(&p->results);
2843
2946}
2947
2948void
2949bc_program_reset(BcProgram* p)
2950{
2951 BcFunc* f;
2952 BcInstPtr* ip;
2953
2954 BC_SIG_ASSERT_LOCKED;
2955
2956 // Pop all but the last execution and all results.
2957 bc_vec_npop(&p->stack, p->stack.len - 1);
2958 bc_vec_popAll(&p->results);
2959
2960#if DC_ENABLED
2961 // We need to pop tail calls too.
2962 if (BC_IS_DC) bc_vec_npop(&p->tail_calls, p->tail_calls.len - 1);
2963#endif // DC_ENABLED
2964
2844#if BC_ENABLED
2845 // Clear the globals' stacks.
2846 if (BC_G) bc_program_popGlobals(p, true);
2847#endif // BC_ENABLED
2848
2849 // Clear the bytecode vector of the main function.
2850 f = bc_vec_item(&p->fns, BC_PROG_MAIN);
2851 bc_vec_npop(&f->code, f->code.len);
2852
2853 // Reset the instruction pointer.
2854 ip = bc_vec_top(&p->stack);
2965#if BC_ENABLED
2966 // Clear the globals' stacks.
2967 if (BC_G) bc_program_popGlobals(p, true);
2968#endif // BC_ENABLED
2969
2970 // Clear the bytecode vector of the main function.
2971 f = bc_vec_item(&p->fns, BC_PROG_MAIN);
2972 bc_vec_npop(&f->code, f->code.len);
2973
2974 // Reset the instruction pointer.
2975 ip = bc_vec_top(&p->stack);
2855 bc_program_setVecs(p, f);
2856 // NOLINTNEXTLINE
2857 memset(ip, 0, sizeof(BcInstPtr));
2858
2976 // NOLINTNEXTLINE
2977 memset(ip, 0, sizeof(BcInstPtr));
2978
2859 // Write the ready message for a signal, and clear the signal.
2860 if (vm.sig)
2979 if (BC_SIG_INTERRUPT(vm))
2861 {
2980 {
2862 bc_file_printf(&vm.fout, "%s", bc_program_ready_msg);
2863 bc_file_flush(&vm.fout, bc_flush_err);
2864 vm.sig = 0;
2981 // Write the ready message for a signal.
2982 bc_file_printf(&vm->fout, "%s", bc_program_ready_msg);
2983 bc_file_flush(&vm->fout, bc_flush_err);
2865 }
2984 }
2985
2986 // Clear the signal.
2987 vm->sig = 0;
2866}
2867
2868void
2869bc_program_exec(BcProgram* p)
2870{
2871 size_t idx;
2872 BcResult r;
2873 BcResult* ptr;

--- 7 unchanged lines hidden (view full) ---

2881#endif // BC_ENABLED
2882#if !BC_HAS_COMPUTED_GOTO
2883#ifndef NDEBUG
2884 size_t jmp_bufs_len;
2885#endif // NDEBUG
2886#endif // !BC_HAS_COMPUTED_GOTO
2887
2888#if BC_HAS_COMPUTED_GOTO
2988}
2989
2990void
2991bc_program_exec(BcProgram* p)
2992{
2993 size_t idx;
2994 BcResult r;
2995 BcResult* ptr;

--- 7 unchanged lines hidden (view full) ---

3003#endif // BC_ENABLED
3004#if !BC_HAS_COMPUTED_GOTO
3005#ifndef NDEBUG
3006 size_t jmp_bufs_len;
3007#endif // NDEBUG
3008#endif // !BC_HAS_COMPUTED_GOTO
3009
3010#if BC_HAS_COMPUTED_GOTO
3011
3012#if BC_GCC
3013#pragma GCC diagnostic ignored "-Wpedantic"
3014#endif // BC_GCC
3015
3016#if BC_CLANG
3017#pragma clang diagnostic ignored "-Wgnu-label-as-value"
3018#endif // BC_CLANG
3019
2889 BC_PROG_LBLS;
2890 BC_PROG_LBLS_ASSERT;
2891
3020 BC_PROG_LBLS;
3021 BC_PROG_LBLS_ASSERT;
3022
3023#if BC_CLANG
3024#pragma clang diagnostic warning "-Wgnu-label-as-value"
3025#endif // BC_CLANG
3026
3027#if BC_GCC
3028#pragma GCC diagnostic warning "-Wpedantic"
3029#endif // BC_GCC
3030
2892 // BC_INST_INVALID is a marker for the end so that we don't have to have an
2893 // execution loop.
2894 func = (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN);
2895 bc_vec_pushByte(&func->code, BC_INST_INVALID);
2896#endif // BC_HAS_COMPUTED_GOTO
2897
3031 // BC_INST_INVALID is a marker for the end so that we don't have to have an
3032 // execution loop.
3033 func = (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN);
3034 bc_vec_pushByte(&func->code, BC_INST_INVALID);
3035#endif // BC_HAS_COMPUTED_GOTO
3036
3037 BC_SETJMP(vm, end);
3038
2898 ip = bc_vec_top(&p->stack);
2899 func = (BcFunc*) bc_vec_item(&p->fns, ip->func);
2900 code = func->code.v;
2901
3039 ip = bc_vec_top(&p->stack);
3040 func = (BcFunc*) bc_vec_item(&p->fns, ip->func);
3041 code = func->code.v;
3042
2902 // Ensure the pointers are correct.
2903 BC_SIG_LOCK;
2904 bc_program_setVecs(p, func);
2905 BC_SIG_UNLOCK;
2906
2907#if !BC_HAS_COMPUTED_GOTO
2908
2909#ifndef NDEBUG
3043#if !BC_HAS_COMPUTED_GOTO
3044
3045#ifndef NDEBUG
2910 jmp_bufs_len = vm.jmp_bufs.len;
3046 jmp_bufs_len = vm->jmp_bufs.len;
2911#endif // NDEBUG
2912
2913 // This loop is the heart of the execution engine. It *is* the engine. For
2914 // computed goto, it is ignored.
2915 while (ip->idx < func->code.len)
2916#endif // !BC_HAS_COMPUTED_GOTO
2917 {
2918 BC_SIG_ASSERT_NOT_LOCKED;
2919
2920#if BC_HAS_COMPUTED_GOTO
2921
3047#endif // NDEBUG
3048
3049 // This loop is the heart of the execution engine. It *is* the engine. For
3050 // computed goto, it is ignored.
3051 while (ip->idx < func->code.len)
3052#endif // !BC_HAS_COMPUTED_GOTO
3053 {
3054 BC_SIG_ASSERT_NOT_LOCKED;
3055
3056#if BC_HAS_COMPUTED_GOTO
3057
3058#if BC_GCC
3059#pragma GCC diagnostic ignored "-Wpedantic"
3060#endif // BC_GCC
3061
3062#if BC_CLANG
3063#pragma clang diagnostic ignored "-Wgnu-label-as-value"
3064#endif // BC_CLANG
3065
2922 BC_PROG_JUMP(inst, code, ip);
2923
2924#else // BC_HAS_COMPUTED_GOTO
2925
2926 // Get the next instruction and increment the index.
2927 inst = (uchar) code[(ip->idx)++];
2928
2929#endif // BC_HAS_COMPUTED_GOTO
2930
2931#if BC_DEBUG_CODE
3066 BC_PROG_JUMP(inst, code, ip);
3067
3068#else // BC_HAS_COMPUTED_GOTO
3069
3070 // Get the next instruction and increment the index.
3071 inst = (uchar) code[(ip->idx)++];
3072
3073#endif // BC_HAS_COMPUTED_GOTO
3074
3075#if BC_DEBUG_CODE
2932 bc_file_printf(&vm.ferr, "inst: %s\n", bc_inst_names[inst]);
2933 bc_file_flush(&vm.ferr, bc_flush_none);
3076 bc_file_printf(&vm->ferr, "inst: %s\n", bc_inst_names[inst]);
3077 bc_file_flush(&vm->ferr, bc_flush_none);
2934#endif // BC_DEBUG_CODE
2935
2936#if !BC_HAS_COMPUTED_GOTO
2937 switch (inst)
2938#endif // !BC_HAS_COMPUTED_GOTO
2939 {
2940#if BC_ENABLED
2941 // This just sets up the condition for the unconditional jump below,

--- 44 unchanged lines hidden (view full) ---

2986 bc_program_call(p, code, &ip->idx);
2987
2988 // Because we changed the execution stack and where we are
2989 // executing, we have to update all of this.
2990 BC_SIG_LOCK;
2991 ip = bc_vec_top(&p->stack);
2992 func = bc_vec_item(&p->fns, ip->func);
2993 code = func->code.v;
3078#endif // BC_DEBUG_CODE
3079
3080#if !BC_HAS_COMPUTED_GOTO
3081 switch (inst)
3082#endif // !BC_HAS_COMPUTED_GOTO
3083 {
3084#if BC_ENABLED
3085 // This just sets up the condition for the unconditional jump below,

--- 44 unchanged lines hidden (view full) ---

3130 bc_program_call(p, code, &ip->idx);
3131
3132 // Because we changed the execution stack and where we are
3133 // executing, we have to update all of this.
3134 BC_SIG_LOCK;
3135 ip = bc_vec_top(&p->stack);
3136 func = bc_vec_item(&p->fns, ip->func);
3137 code = func->code.v;
2994 bc_program_setVecs(p, func);
2995 BC_SIG_UNLOCK;
2996
2997 BC_PROG_JUMP(inst, code, ip);
2998 }
2999
3000 // clang-format off
3001 BC_PROG_LBL(BC_INST_INC):
3002 BC_PROG_LBL(BC_INST_DEC):
3003 // clang-format on
3004 {
3005 bc_program_incdec(p, inst);
3006 BC_PROG_JUMP(inst, code, ip);
3007 }
3008
3009 // clang-format off
3010 BC_PROG_LBL(BC_INST_HALT):
3011 // clang-format on
3012 {
3138 BC_SIG_UNLOCK;
3139
3140 BC_PROG_JUMP(inst, code, ip);
3141 }
3142
3143 // clang-format off
3144 BC_PROG_LBL(BC_INST_INC):
3145 BC_PROG_LBL(BC_INST_DEC):
3146 // clang-format on
3147 {
3148 bc_program_incdec(p, inst);
3149 BC_PROG_JUMP(inst, code, ip);
3150 }
3151
3152 // clang-format off
3153 BC_PROG_LBL(BC_INST_HALT):
3154 // clang-format on
3155 {
3013 vm.status = BC_STATUS_QUIT;
3156 vm->status = BC_STATUS_QUIT;
3014
3015 // Just jump out. The jump series will take care of everything.
3016 BC_JMP;
3017
3018 BC_PROG_JUMP(inst, code, ip);
3019 }
3020
3021 // clang-format off

--- 5 unchanged lines hidden (view full) ---

3027 bc_program_return(p, inst);
3028
3029 // Because we changed the execution stack and where we are
3030 // executing, we have to update all of this.
3031 BC_SIG_LOCK;
3032 ip = bc_vec_top(&p->stack);
3033 func = bc_vec_item(&p->fns, ip->func);
3034 code = func->code.v;
3157
3158 // Just jump out. The jump series will take care of everything.
3159 BC_JMP;
3160
3161 BC_PROG_JUMP(inst, code, ip);
3162 }
3163
3164 // clang-format off

--- 5 unchanged lines hidden (view full) ---

3170 bc_program_return(p, inst);
3171
3172 // Because we changed the execution stack and where we are
3173 // executing, we have to update all of this.
3174 BC_SIG_LOCK;
3175 ip = bc_vec_top(&p->stack);
3176 func = bc_vec_item(&p->fns, ip->func);
3177 code = func->code.v;
3035 bc_program_setVecs(p, func);
3036 BC_SIG_UNLOCK;
3037
3038 BC_PROG_JUMP(inst, code, ip);
3039 }
3040#endif // BC_ENABLED
3041
3042 // clang-format off
3043 BC_PROG_LBL(BC_INST_BOOL_OR):

--- 11 unchanged lines hidden (view full) ---

3055 }
3056
3057 // clang-format off
3058 BC_PROG_LBL(BC_INST_READ):
3059 // clang-format on
3060 {
3061 // We want to flush output before
3062 // this in case there is a prompt.
3178 BC_SIG_UNLOCK;
3179
3180 BC_PROG_JUMP(inst, code, ip);
3181 }
3182#endif // BC_ENABLED
3183
3184 // clang-format off
3185 BC_PROG_LBL(BC_INST_BOOL_OR):

--- 11 unchanged lines hidden (view full) ---

3197 }
3198
3199 // clang-format off
3200 BC_PROG_LBL(BC_INST_READ):
3201 // clang-format on
3202 {
3203 // We want to flush output before
3204 // this in case there is a prompt.
3063 bc_file_flush(&vm.fout, bc_flush_save);
3205 bc_file_flush(&vm->fout, bc_flush_save);
3064
3065 bc_program_read(p);
3066
3067 // Because we changed the execution stack and where we are
3068 // executing, we have to update all of this.
3069 BC_SIG_LOCK;
3070 ip = bc_vec_top(&p->stack);
3071 func = bc_vec_item(&p->fns, ip->func);
3072 code = func->code.v;
3206
3207 bc_program_read(p);
3208
3209 // Because we changed the execution stack and where we are
3210 // executing, we have to update all of this.
3211 BC_SIG_LOCK;
3212 ip = bc_vec_top(&p->stack);
3213 func = bc_vec_item(&p->fns, ip->func);
3214 code = func->code.v;
3073 bc_program_setVecs(p, func);
3074 BC_SIG_UNLOCK;
3075
3076 BC_PROG_JUMP(inst, code, ip);
3077 }
3078
3079#if BC_ENABLE_EXTRA_MATH
3080 // clang-format off
3081 BC_PROG_LBL(BC_INST_RAND):

--- 6 unchanged lines hidden (view full) ---

3088
3089 // clang-format off
3090 BC_PROG_LBL(BC_INST_MAXIBASE):
3091 BC_PROG_LBL(BC_INST_MAXOBASE):
3092 BC_PROG_LBL(BC_INST_MAXSCALE):
3093#if BC_ENABLE_EXTRA_MATH
3094 BC_PROG_LBL(BC_INST_MAXRAND):
3095#endif // BC_ENABLE_EXTRA_MATH
3215 BC_SIG_UNLOCK;
3216
3217 BC_PROG_JUMP(inst, code, ip);
3218 }
3219
3220#if BC_ENABLE_EXTRA_MATH
3221 // clang-format off
3222 BC_PROG_LBL(BC_INST_RAND):

--- 6 unchanged lines hidden (view full) ---

3229
3230 // clang-format off
3231 BC_PROG_LBL(BC_INST_MAXIBASE):
3232 BC_PROG_LBL(BC_INST_MAXOBASE):
3233 BC_PROG_LBL(BC_INST_MAXSCALE):
3234#if BC_ENABLE_EXTRA_MATH
3235 BC_PROG_LBL(BC_INST_MAXRAND):
3236#endif // BC_ENABLE_EXTRA_MATH
3096 // clang-format on
3237 // clang-format on
3097 {
3238 {
3098 BcBigDig dig = vm.maxes[inst - BC_INST_MAXIBASE];
3239 BcBigDig dig = vm->maxes[inst - BC_INST_MAXIBASE];
3099 bc_program_pushBigdig(p, dig, BC_RESULT_TEMP);
3100 BC_PROG_JUMP(inst, code, ip);
3101 }
3102
3103 // clang-format off
3104 BC_PROG_LBL(BC_INST_LINE_LENGTH):
3105#if BC_ENABLED
3106 BC_PROG_LBL(BC_INST_GLOBAL_STACKS):

--- 42 unchanged lines hidden (view full) ---

3149 }
3150#endif // BC_ENABLE_EXTRA_MATH
3151
3152 // clang-format off
3153 BC_PROG_LBL(BC_INST_LENGTH):
3154 BC_PROG_LBL(BC_INST_SCALE_FUNC):
3155 BC_PROG_LBL(BC_INST_SQRT):
3156 BC_PROG_LBL(BC_INST_ABS):
3240 bc_program_pushBigdig(p, dig, BC_RESULT_TEMP);
3241 BC_PROG_JUMP(inst, code, ip);
3242 }
3243
3244 // clang-format off
3245 BC_PROG_LBL(BC_INST_LINE_LENGTH):
3246#if BC_ENABLED
3247 BC_PROG_LBL(BC_INST_GLOBAL_STACKS):

--- 42 unchanged lines hidden (view full) ---

3290 }
3291#endif // BC_ENABLE_EXTRA_MATH
3292
3293 // clang-format off
3294 BC_PROG_LBL(BC_INST_LENGTH):
3295 BC_PROG_LBL(BC_INST_SCALE_FUNC):
3296 BC_PROG_LBL(BC_INST_SQRT):
3297 BC_PROG_LBL(BC_INST_ABS):
3298 BC_PROG_LBL(BC_INST_IS_NUMBER):
3299 BC_PROG_LBL(BC_INST_IS_STRING):
3157#if BC_ENABLE_EXTRA_MATH
3158 BC_PROG_LBL(BC_INST_IRAND):
3159#endif // BC_ENABLE_EXTRA_MATH
3300#if BC_ENABLE_EXTRA_MATH
3301 BC_PROG_LBL(BC_INST_IRAND):
3302#endif // BC_ENABLE_EXTRA_MATH
3160 // clang-format on
3303 // clang-format on
3161 {
3162 bc_program_builtin(p, inst);
3163 BC_PROG_JUMP(inst, code, ip);
3164 }
3165
3166 // clang-format off
3167 BC_PROG_LBL(BC_INST_ASCIIFY):
3168 // clang-format on
3169 {
3304 {
3305 bc_program_builtin(p, inst);
3306 BC_PROG_JUMP(inst, code, ip);
3307 }
3308
3309 // clang-format off
3310 BC_PROG_LBL(BC_INST_ASCIIFY):
3311 // clang-format on
3312 {
3170 bc_program_asciify(p, ip->func);
3313 bc_program_asciify(p);
3171
3172 // Because we changed the execution stack and where we are
3173 // executing, we have to update all of this.
3174 BC_SIG_LOCK;
3175 ip = bc_vec_top(&p->stack);
3176 func = bc_vec_item(&p->fns, ip->func);
3177 code = func->code.v;
3314
3315 // Because we changed the execution stack and where we are
3316 // executing, we have to update all of this.
3317 BC_SIG_LOCK;
3318 ip = bc_vec_top(&p->stack);
3319 func = bc_vec_item(&p->fns, ip->func);
3320 code = func->code.v;
3178 bc_program_setVecs(p, func);
3179 BC_SIG_UNLOCK;
3180
3181 BC_PROG_JUMP(inst, code, ip);
3182 }
3183
3184 // clang-format off
3185 BC_PROG_LBL(BC_INST_NUM):
3186 // clang-format on
3187 {
3188 bc_program_const(p, code, &ip->idx);
3189 BC_PROG_JUMP(inst, code, ip);
3190 }
3191
3192 // clang-format off
3193 BC_PROG_LBL(BC_INST_ZERO):
3194 BC_PROG_LBL(BC_INST_ONE):
3195#if BC_ENABLED
3196 BC_PROG_LBL(BC_INST_LAST):
3197#endif // BC_ENABLED
3321 BC_SIG_UNLOCK;
3322
3323 BC_PROG_JUMP(inst, code, ip);
3324 }
3325
3326 // clang-format off
3327 BC_PROG_LBL(BC_INST_NUM):
3328 // clang-format on
3329 {
3330 bc_program_const(p, code, &ip->idx);
3331 BC_PROG_JUMP(inst, code, ip);
3332 }
3333
3334 // clang-format off
3335 BC_PROG_LBL(BC_INST_ZERO):
3336 BC_PROG_LBL(BC_INST_ONE):
3337#if BC_ENABLED
3338 BC_PROG_LBL(BC_INST_LAST):
3339#endif // BC_ENABLED
3198 // clang-format on
3340 // clang-format on
3199 {
3200 r.t = BC_RESULT_ZERO + (inst - BC_INST_ZERO);
3201 bc_vec_push(&p->results, &r);
3202 BC_PROG_JUMP(inst, code, ip);
3203 }
3204
3205 // clang-format off
3206 BC_PROG_LBL(BC_INST_PRINT):
3207 BC_PROG_LBL(BC_INST_PRINT_POP):
3208#if BC_ENABLED
3209 BC_PROG_LBL(BC_INST_PRINT_STR):
3210#endif // BC_ENABLED
3341 {
3342 r.t = BC_RESULT_ZERO + (inst - BC_INST_ZERO);
3343 bc_vec_push(&p->results, &r);
3344 BC_PROG_JUMP(inst, code, ip);
3345 }
3346
3347 // clang-format off
3348 BC_PROG_LBL(BC_INST_PRINT):
3349 BC_PROG_LBL(BC_INST_PRINT_POP):
3350#if BC_ENABLED
3351 BC_PROG_LBL(BC_INST_PRINT_STR):
3352#endif // BC_ENABLED
3211 // clang-format on
3353 // clang-format on
3212 {
3213 bc_program_print(p, inst, 0);
3214
3215 // We want to flush right away to save the output for history,
3216 // if history must preserve it when taking input.
3354 {
3355 bc_program_print(p, inst, 0);
3356
3357 // We want to flush right away to save the output for history,
3358 // if history must preserve it when taking input.
3217 bc_file_flush(&vm.fout, bc_flush_save);
3359 bc_file_flush(&vm->fout, bc_flush_save);
3218
3219 BC_PROG_JUMP(inst, code, ip);
3220 }
3221
3222 // clang-format off
3223 BC_PROG_LBL(BC_INST_STR):
3224 // clang-format on
3225 {
3226 // Set up the result and push.
3227 r.t = BC_RESULT_STR;
3228 bc_num_clear(&r.d.n);
3360
3361 BC_PROG_JUMP(inst, code, ip);
3362 }
3363
3364 // clang-format off
3365 BC_PROG_LBL(BC_INST_STR):
3366 // clang-format on
3367 {
3368 // Set up the result and push.
3369 r.t = BC_RESULT_STR;
3370 bc_num_clear(&r.d.n);
3229 r.d.n.rdx = bc_program_index(code, &ip->idx);
3230 r.d.n.scale = bc_program_index(code, &ip->idx);
3231 bc_vec_push(&p->results, &r);
3232 BC_PROG_JUMP(inst, code, ip);
3233 }
3234
3235 // clang-format off
3236 BC_PROG_LBL(BC_INST_POWER):
3237 BC_PROG_LBL(BC_INST_MULTIPLY):
3238 BC_PROG_LBL(BC_INST_DIVIDE):
3239 BC_PROG_LBL(BC_INST_MODULUS):
3240 BC_PROG_LBL(BC_INST_PLUS):
3241 BC_PROG_LBL(BC_INST_MINUS):
3242#if BC_ENABLE_EXTRA_MATH
3243 BC_PROG_LBL(BC_INST_PLACES):
3244 BC_PROG_LBL(BC_INST_LSHIFT):
3245 BC_PROG_LBL(BC_INST_RSHIFT):
3246#endif // BC_ENABLE_EXTRA_MATH
3371 r.d.n.scale = bc_program_index(code, &ip->idx);
3372 bc_vec_push(&p->results, &r);
3373 BC_PROG_JUMP(inst, code, ip);
3374 }
3375
3376 // clang-format off
3377 BC_PROG_LBL(BC_INST_POWER):
3378 BC_PROG_LBL(BC_INST_MULTIPLY):
3379 BC_PROG_LBL(BC_INST_DIVIDE):
3380 BC_PROG_LBL(BC_INST_MODULUS):
3381 BC_PROG_LBL(BC_INST_PLUS):
3382 BC_PROG_LBL(BC_INST_MINUS):
3383#if BC_ENABLE_EXTRA_MATH
3384 BC_PROG_LBL(BC_INST_PLACES):
3385 BC_PROG_LBL(BC_INST_LSHIFT):
3386 BC_PROG_LBL(BC_INST_RSHIFT):
3387#endif // BC_ENABLE_EXTRA_MATH
3247 // clang-format on
3388 // clang-format on
3248 {
3249 bc_program_op(p, inst);
3250 BC_PROG_JUMP(inst, code, ip);
3251 }
3252
3253 // clang-format off
3254 BC_PROG_LBL(BC_INST_NEG):
3255 BC_PROG_LBL(BC_INST_BOOL_NOT):
3256#if BC_ENABLE_EXTRA_MATH
3257 BC_PROG_LBL(BC_INST_TRUNC):
3258#endif // BC_ENABLE_EXTRA_MATH
3389 {
3390 bc_program_op(p, inst);
3391 BC_PROG_JUMP(inst, code, ip);
3392 }
3393
3394 // clang-format off
3395 BC_PROG_LBL(BC_INST_NEG):
3396 BC_PROG_LBL(BC_INST_BOOL_NOT):
3397#if BC_ENABLE_EXTRA_MATH
3398 BC_PROG_LBL(BC_INST_TRUNC):
3399#endif // BC_ENABLE_EXTRA_MATH
3259 // clang-format on
3400 // clang-format on
3260 {
3261 bc_program_unary(p, inst);
3262 BC_PROG_JUMP(inst, code, ip);
3263 }
3264
3265 // clang-format off
3266#if BC_ENABLED
3267 BC_PROG_LBL(BC_INST_ASSIGN_POWER):

--- 115 unchanged lines hidden (view full) ---

3383 bc_vec_pop(&p->tail_calls);
3384
3385 // Because we changed the execution stack and where we are
3386 // executing, we have to update all of this.
3387 BC_SIG_LOCK;
3388 ip = bc_vec_top(&p->stack);
3389 func = bc_vec_item(&p->fns, ip->func);
3390 code = func->code.v;
3401 {
3402 bc_program_unary(p, inst);
3403 BC_PROG_JUMP(inst, code, ip);
3404 }
3405
3406 // clang-format off
3407#if BC_ENABLED
3408 BC_PROG_LBL(BC_INST_ASSIGN_POWER):

--- 115 unchanged lines hidden (view full) ---

3524 bc_vec_pop(&p->tail_calls);
3525
3526 // Because we changed the execution stack and where we are
3527 // executing, we have to update all of this.
3528 BC_SIG_LOCK;
3529 ip = bc_vec_top(&p->stack);
3530 func = bc_vec_item(&p->fns, ip->func);
3531 code = func->code.v;
3391 bc_program_setVecs(p, func);
3392 BC_SIG_UNLOCK;
3393
3394 BC_PROG_JUMP(inst, code, ip);
3395 }
3396
3397 // clang-format off
3398 BC_PROG_LBL(BC_INST_EXECUTE):
3399 BC_PROG_LBL(BC_INST_EXEC_COND):

--- 4 unchanged lines hidden (view full) ---

3404 bc_program_execStr(p, code, &ip->idx, cond, func->code.len);
3405
3406 // Because we changed the execution stack and where we are
3407 // executing, we have to update all of this.
3408 BC_SIG_LOCK;
3409 ip = bc_vec_top(&p->stack);
3410 func = bc_vec_item(&p->fns, ip->func);
3411 code = func->code.v;
3532 BC_SIG_UNLOCK;
3533
3534 BC_PROG_JUMP(inst, code, ip);
3535 }
3536
3537 // clang-format off
3538 BC_PROG_LBL(BC_INST_EXECUTE):
3539 BC_PROG_LBL(BC_INST_EXEC_COND):

--- 4 unchanged lines hidden (view full) ---

3544 bc_program_execStr(p, code, &ip->idx, cond, func->code.len);
3545
3546 // Because we changed the execution stack and where we are
3547 // executing, we have to update all of this.
3548 BC_SIG_LOCK;
3549 ip = bc_vec_top(&p->stack);
3550 func = bc_vec_item(&p->fns, ip->func);
3551 code = func->code.v;
3412 bc_program_setVecs(p, func);
3413 BC_SIG_UNLOCK;
3414
3415 BC_PROG_JUMP(inst, code, ip);
3416 }
3417
3418 // clang-format off
3419 BC_PROG_LBL(BC_INST_PRINT_STACK):
3420 // clang-format on

--- 62 unchanged lines hidden (view full) ---

3483 BC_PROG_JUMP(inst, code, ip);
3484 }
3485
3486 // clang-format off
3487 BC_PROG_LBL(BC_INST_PUSH_TO_VAR):
3488 // clang-format on
3489 {
3490 idx = bc_program_index(code, &ip->idx);
3552 BC_SIG_UNLOCK;
3553
3554 BC_PROG_JUMP(inst, code, ip);
3555 }
3556
3557 // clang-format off
3558 BC_PROG_LBL(BC_INST_PRINT_STACK):
3559 // clang-format on

--- 62 unchanged lines hidden (view full) ---

3622 BC_PROG_JUMP(inst, code, ip);
3623 }
3624
3625 // clang-format off
3626 BC_PROG_LBL(BC_INST_PUSH_TO_VAR):
3627 // clang-format on
3628 {
3629 idx = bc_program_index(code, &ip->idx);
3491 bc_program_copyToVar(p, idx, BC_TYPE_VAR, true);
3630 bc_program_copyToVar(p, idx, BC_TYPE_VAR);
3492 BC_PROG_JUMP(inst, code, ip);
3493 }
3494
3495 // clang-format off
3496 BC_PROG_LBL(BC_INST_QUIT):
3497 BC_PROG_LBL(BC_INST_NQUIT):
3498 // clang-format on
3499 {
3500 bc_program_nquit(p, inst);
3501
3502 // Because we changed the execution stack and where we are
3503 // executing, we have to update all of this.
3504 BC_SIG_LOCK;
3505 ip = bc_vec_top(&p->stack);
3506 func = bc_vec_item(&p->fns, ip->func);
3507 code = func->code.v;
3631 BC_PROG_JUMP(inst, code, ip);
3632 }
3633
3634 // clang-format off
3635 BC_PROG_LBL(BC_INST_QUIT):
3636 BC_PROG_LBL(BC_INST_NQUIT):
3637 // clang-format on
3638 {
3639 bc_program_nquit(p, inst);
3640
3641 // Because we changed the execution stack and where we are
3642 // executing, we have to update all of this.
3643 BC_SIG_LOCK;
3644 ip = bc_vec_top(&p->stack);
3645 func = bc_vec_item(&p->fns, ip->func);
3646 code = func->code.v;
3508 bc_program_setVecs(p, func);
3509 BC_SIG_UNLOCK;
3510
3511 BC_PROG_JUMP(inst, code, ip);
3512 }
3513
3514 // clang-format off
3515 BC_PROG_LBL(BC_INST_EXEC_STACK_LEN):
3516 // clang-format on
3517 {
3518 bc_program_execStackLen(p);
3519 BC_PROG_JUMP(inst, code, ip);
3520 }
3521#endif // DC_ENABLED
3522
3523#if BC_HAS_COMPUTED_GOTO
3524 // clang-format off
3525 BC_PROG_LBL(BC_INST_INVALID):
3526 // clang-format on
3527 {
3647 BC_SIG_UNLOCK;
3648
3649 BC_PROG_JUMP(inst, code, ip);
3650 }
3651
3652 // clang-format off
3653 BC_PROG_LBL(BC_INST_EXEC_STACK_LEN):
3654 // clang-format on
3655 {
3656 bc_program_execStackLen(p);
3657 BC_PROG_JUMP(inst, code, ip);
3658 }
3659#endif // DC_ENABLED
3660
3661#if BC_HAS_COMPUTED_GOTO
3662 // clang-format off
3663 BC_PROG_LBL(BC_INST_INVALID):
3664 // clang-format on
3665 {
3528 return;
3666 goto end;
3529 }
3530#else // BC_HAS_COMPUTED_GOTO
3531 default:
3532 {
3533 BC_UNREACHABLE
3667 }
3668#else // BC_HAS_COMPUTED_GOTO
3669 default:
3670 {
3671 BC_UNREACHABLE
3534#ifndef NDEBUG
3672#if !defined(NDEBUG) && !BC_CLANG
3535 abort();
3673 abort();
3536#endif // NDEBUG
3674#endif // !defined(NDEBUG) && !BC_CLANG
3537 }
3538#endif // BC_HAS_COMPUTED_GOTO
3539 }
3540
3675 }
3676#endif // BC_HAS_COMPUTED_GOTO
3677 }
3678
3541#if !BC_HAS_COMPUTED_GOTO
3679#if BC_HAS_COMPUTED_GOTO
3680
3681#if BC_CLANG
3682#pragma clang diagnostic warning "-Wgnu-label-as-value"
3683#endif // BC_CLANG
3684
3685#if BC_GCC
3686#pragma GCC diagnostic warning "-Wpedantic"
3687#endif // BC_GCC
3688
3689#else // BC_HAS_COMPUTED_GOTO
3690
3542#ifndef NDEBUG
3543 // This is to allow me to use a debugger to see the last instruction,
3544 // which will point to which function was the problem. But it's also a
3545 // good smoke test for error handling changes.
3691#ifndef NDEBUG
3692 // This is to allow me to use a debugger to see the last instruction,
3693 // which will point to which function was the problem. But it's also a
3694 // good smoke test for error handling changes.
3546 assert(jmp_bufs_len == vm.jmp_bufs.len);
3695 assert(jmp_bufs_len == vm->jmp_bufs.len);
3547#endif // NDEBUG
3696#endif // NDEBUG
3548#endif // !BC_HAS_COMPUTED_GOTO
3697
3698#endif // BC_HAS_COMPUTED_GOTO
3549 }
3699 }
3700
3701end:
3702 BC_SIG_MAYLOCK;
3703
3704 // This is here just to print a stack trace on interrupts. This is for
3705 // finding infinite loops.
3706 if (BC_SIG_INTERRUPT(vm))
3707 {
3708 BcStatus s;
3709
3710 bc_file_putchar(&vm->ferr, bc_flush_none, '\n');
3711
3712 bc_program_printStackTrace(p);
3713
3714 s = bc_file_flushErr(&vm->ferr, bc_flush_err);
3715 if (BC_ERR(s != BC_STATUS_SUCCESS && vm->status == BC_STATUS_SUCCESS))
3716 {
3717 vm->status = (sig_atomic_t) s;
3718 }
3719 }
3720
3721 BC_LONGJMP_CONT(vm);
3550}
3551
3552#if BC_DEBUG_CODE
3553#if BC_ENABLED && DC_ENABLED
3554void
3555bc_program_printStackDebug(BcProgram* p)
3556{
3722}
3723
3724#if BC_DEBUG_CODE
3725#if BC_ENABLED && DC_ENABLED
3726void
3727bc_program_printStackDebug(BcProgram* p)
3728{
3557 bc_file_puts(&vm.fout, bc_flush_err, "-------------- Stack ----------\n");
3729 bc_file_puts(&vm->fout, bc_flush_err, "-------------- Stack ----------\n");
3558 bc_program_printStack(p);
3730 bc_program_printStack(p);
3559 bc_file_puts(&vm.fout, bc_flush_err, "-------------- Stack End ------\n");
3731 bc_file_puts(&vm->fout, bc_flush_err, "-------------- Stack End ------\n");
3560}
3561
3562static void
3563bc_program_printIndex(const char* restrict code, size_t* restrict bgn)
3564{
3565 uchar byte, i, bytes = (uchar) code[(*bgn)++];
3566 ulong val = 0;
3567

--- 65 unchanged lines hidden (view full) ---

3633 f = bc_vec_item(&p->fns, ip.func);
3634 code = f->code.v;
3635
3636 bc_vm_printf("func[%zu]:\n", ip.func);
3637 while (ip.idx < f->code.len)
3638 {
3639 bc_program_printInst(p, code, &ip.idx);
3640 }
3732}
3733
3734static void
3735bc_program_printIndex(const char* restrict code, size_t* restrict bgn)
3736{
3737 uchar byte, i, bytes = (uchar) code[(*bgn)++];
3738 ulong val = 0;
3739

--- 65 unchanged lines hidden (view full) ---

3805 f = bc_vec_item(&p->fns, ip.func);
3806 code = f->code.v;
3807
3808 bc_vm_printf("func[%zu]:\n", ip.func);
3809 while (ip.idx < f->code.len)
3810 {
3811 bc_program_printInst(p, code, &ip.idx);
3812 }
3641 bc_file_puts(&vm.fout, bc_flush_err, "\n\n");
3813 bc_file_puts(&vm->fout, bc_flush_err, "\n\n");
3642 }
3643}
3644#endif // BC_ENABLED && DC_ENABLED
3645#endif // BC_DEBUG_CODE
3814 }
3815}
3816#endif // BC_ENABLED && DC_ENABLED
3817#endif // BC_DEBUG_CODE