2 * *****************************************************************************
4 * SPDX-License-Identifier: BSD-2-Clause
6 * Copyright (c) 2018-2023 Gavin D. Howard and contributors.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * * Redistributions of source code must retain the above copyright notice, this
12 * list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright notice,
15 * this list of conditions and the following disclaimer in the documentation
16 * and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
30 * *****************************************************************************
32 * Code to execute bc programs.
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.
57 bc_program_type_num(BcResult* r, BcNum* n)
61 // This should have already been taken care of.
62 assert(r->t != BC_RESULT_VOID);
66 if (BC_ERR(!BC_PROG_NUM(r, n))) bc_err(BC_ERR_EXEC_TYPE);
73 * @param r The result to check.
74 * @param t The type that the result should be.
77 bc_program_type_match(BcResult* r, BcType t)
79 if (BC_ERR((r->t != BC_RESULT_ARRAY) != (!t))) bc_err(BC_ERR_EXEC_TYPE);
84 * Pulls an index out of a bytecode vector and updates the index into the vector
85 * to point to the spot after the index. For more details on bytecode indices,
86 * see the development manual (manuals/development.md#bytecode-indices).
87 * @param code The bytecode vector.
88 * @param bgn An in/out parameter; the index into the vector that will be
90 * @return The index at @a bgn in the bytecode vector.
93 bc_program_index(const char* restrict code, size_t* restrict bgn)
95 uchar amt = (uchar) code[(*bgn)++], i = 0;
98 for (; i < amt; ++i, ++(*bgn))
100 size_t temp = ((size_t) ((int) (uchar) code[*bgn]) & UCHAR_MAX);
101 res |= (temp << (i * CHAR_BIT));
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.
114 bc_program_string(BcProgram* p, const BcNum* n)
116 return *((char**) bc_vec_item(&p->strs, n->scale));
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.
125 * @param p The program.
128 bc_program_prepGlobals(BcProgram* p)
132 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
134 bc_vec_push(p->globals_v + i, p->globals + i);
137 #if BC_ENABLE_EXTRA_MATH
138 bc_rand_push(&p->rng);
139 #endif // BC_ENABLE_EXTRA_MATH
143 * Pops globals stacks on returning from a function, or in the case of reset,
144 * pops all but one item on each global stack.
145 * @param p The program.
146 * @param reset True if all but one item on each stack should be popped, false
150 bc_program_popGlobals(BcProgram* p, bool reset)
154 BC_SIG_ASSERT_LOCKED;
156 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
158 BcVec* v = p->globals_v + i;
159 bc_vec_npop(v, reset ? v->len - 1 : 1);
160 p->globals[i] = BC_PROG_GLOBAL(v);
163 #if BC_ENABLE_EXTRA_MATH
164 bc_rand_pop(&p->rng, reset);
165 #endif // BC_ENABLE_EXTRA_MATH
169 * Derefeneces an array reference and returns a pointer to the real array.
170 * @param p The program.
171 * @param vec The reference vector.
172 * @return A pointer to the desired array.
175 bc_program_dereference(const BcProgram* p, BcVec* vec)
178 size_t vidx, nidx, i = 0;
180 // We want to be sure we have a reference vector.
181 assert(vec->size == sizeof(uchar));
183 // Get the index of the vector in arrs, then the index of the original
184 // referenced vector.
185 vidx = bc_program_index(vec->v, &i);
186 nidx = bc_program_index(vec->v, &i);
188 v = bc_vec_item(bc_vec_item(&p->arrs, vidx), nidx);
190 // We want to be sure we do *not* have a reference vector.
191 assert(v->size != sizeof(uchar));
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.
206 bc_program_pushBigdig(BcProgram* p, BcBigDig dig, BcResultType type)
214 bc_num_createFromBigdig(&res.d.n, dig);
215 bc_vec_push(&p->results, &res);
221 bc_program_addString(BcProgram* p, const char* str)
225 BC_SIG_ASSERT_LOCKED;
227 if (bc_map_insert(&p->str_map, str, p->strs.len, &idx))
230 BcId* id = bc_vec_item(&p->str_map, idx);
235 // Push an empty string on the proper vector.
236 str_ptr = bc_vec_pushEmpty(&p->strs);
238 // We reuse the string in the ID (allocated by bc_map_insert()), because
244 BcId* id = bc_vec_item(&p->str_map, idx);
252 bc_program_search(BcProgram* p, const char* name, bool var)
258 BC_SIG_ASSERT_LOCKED;
260 // Grab the right vector and map.
261 v = var ? &p->vars : &p->arrs;
262 map = var ? &p->var_map : &p->arr_map;
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.
268 if (bc_map_insert(map, name, v->len, &i))
270 BcVec* temp = bc_vec_pushEmpty(v);
271 bc_array_init(temp, var);
274 return ((BcId*) bc_vec_item(map, i))->idx;
278 * Returns the correct variable or array stack for the type.
279 * @param p The program.
280 * @param idx The index of the variable or array in the variable or array
282 * @param type The type of vector to return.
283 * @return A pointer to the variable or array stack.
286 bc_program_vec(const BcProgram* p, size_t idx, BcType type)
288 const BcVec* v = (type == BC_TYPE_VAR) ? &p->vars : &p->arrs;
289 return bc_vec_item(v, idx);
293 * Returns a pointer to the BcNum corresponding to the result. There is one
294 * case, however, where this returns a pointer to a BcVec: if the type of the
295 * result is array. In that case, the pointer is casted to a pointer to BcNum,
296 * but is never used. The function that calls this expecting an array casts the
297 * pointer back. This function is called a lot and needs to be as fast as
299 * @param p The program.
300 * @param r The result whose number will be returned.
301 * @return The BcNum corresponding to the result.
304 bc_program_num(BcProgram* p, BcResult* r)
309 // Windows made it an error to not initialize this, so shut it up.
310 // I don't want to do this on other platforms because this procedure
311 // is one of the most heavily-used, and eliminating the initialization
312 // is a performance win.
320 case BC_RESULT_IBASE:
321 case BC_RESULT_SCALE:
322 case BC_RESULT_OBASE:
323 #if BC_ENABLE_EXTRA_MATH
325 #endif // BC_ENABLE_EXTRA_MATH
332 case BC_RESULT_ARRAY:
333 case BC_RESULT_ARRAY_ELEM:
336 BcType type = (r->t == BC_RESULT_VAR) ? BC_TYPE_VAR : BC_TYPE_ARRAY;
338 // Get the correct variable or array vector.
339 v = bc_program_vec(p, r->d.loc.loc, type);
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)
347 size_t idx = r->d.loc.idx;
349 v = bc_vec_item(v, r->d.loc.stack_idx);
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
358 if (v->size == sizeof(uchar)) v = bc_program_dereference(p, v);
361 // We want to be sure we got a valid array of numbers.
362 assert(v->size == sizeof(BcNum));
364 // The bc spec says that if an element is accessed that does not
365 // exist, it should be preinitialized to 0. Well, if we access
366 // an element *way* out there, we have to preinitialize all
367 // elements between the current last element and the actual
372 bc_array_expand(v, bc_vm_growSize(idx, 1));
376 n = bc_vec_item(v, idx);
378 // This is either a number (for a var) or an array (for an array).
379 // Because bc_vec_top() and bc_vec_item() return a void*, we don't
386 n = bc_vec_item(v, r->d.loc.stack_idx);
411 // We should never get here; this is taken care of earlier because a
412 // result is expected.
428 // This is here in GCC to quiet the "maybe-uninitialized" warning.
440 * Prepares an operand for use.
441 * @param p The program.
442 * @param r An out parameter; this is set to the pointer to the result that
444 * @param n An out parameter; this is set to the pointer to the number that
446 * @param idx The index of the result from the top of the results stack.
449 bc_program_operand(BcProgram* p, BcResult** r, BcNum** n, size_t idx)
451 *r = bc_vec_item_rev(&p->results, idx);
454 if (BC_ERR((*r)->t == BC_RESULT_VOID)) bc_err(BC_ERR_EXEC_VOID_VAL);
457 *n = bc_program_num(p, *r);
461 * Prepares the operands of a binary operator.
462 * @param p The program.
463 * @param l An out parameter; this is set to the pointer to the result for
465 * @param ln An out parameter; this is set to the pointer to the number for
467 * @param r An out parameter; this is set to the pointer to the result for
469 * @param rn An out parameter; this is set to the pointer to the number for
471 * @param idx The starting index where the operands are in the results stack,
472 * starting from the top.
475 bc_program_binPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
476 BcNum** rn, size_t idx)
480 assert(p != NULL && l != NULL && ln != NULL && r != NULL && rn != NULL);
482 #ifndef BC_PROG_NO_STACK_CHECK
483 // Check the stack for dc.
486 if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 2)))
488 bc_err(BC_ERR_EXEC_STACK);
491 #endif // BC_PROG_NO_STACK_CHECK
493 assert(BC_PROG_STACK(&p->results, idx + 2));
496 bc_program_operand(p, l, ln, idx + 1);
497 bc_program_operand(p, r, rn, idx);
502 // bc_program_operand() checked these for us.
503 assert(lt != BC_RESULT_VOID && (*r)->t != BC_RESULT_VOID);
506 // We run this again under these conditions in case any vector has been
507 // reallocated out from under the BcNums or arrays we had. In other words,
508 // this is to fix pointer invalidation.
509 if (lt == (*r)->t && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM))
511 *ln = bc_program_num(p, *l);
514 if (BC_ERR(lt == BC_RESULT_STR)) bc_err(BC_ERR_EXEC_TYPE);
518 * Prepares the operands of a binary operator and type checks them. This is
519 * separate from bc_program_binPrep() because some places want this, others want
520 * bc_program_binPrep().
521 * @param p The program.
522 * @param l An out parameter; this is set to the pointer to the result for
524 * @param ln An out parameter; this is set to the pointer to the number for
526 * @param r An out parameter; this is set to the pointer to the result for
528 * @param rn An out parameter; this is set to the pointer to the number for
530 * @param idx The starting index where the operands are in the results stack,
531 * starting from the top.
534 bc_program_binOpPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
535 BcNum** rn, size_t idx)
537 bc_program_binPrep(p, l, ln, r, rn, idx);
538 bc_program_type_num(*l, *ln);
539 bc_program_type_num(*r, *rn);
543 * Prepares the operands of an assignment operator.
544 * @param p The program.
545 * @param l An out parameter; this is set to the pointer to the result for the
547 * @param ln An out parameter; this is set to the pointer to the number for the
549 * @param r An out parameter; this is set to the pointer to the result for the
551 * @param rn An out parameter; this is set to the pointer to the number for the
555 bc_program_assignPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
558 BcResultType lt, min;
561 // This is the min non-allowable result type. dc allows strings.
562 min = BC_RESULT_TEMP - ((unsigned int) (BC_IS_BC));
564 // Prepare the operands.
565 bc_program_binPrep(p, l, ln, r, rn, 0);
569 // Typecheck the left.
570 if (BC_ERR(lt >= min && lt <= BC_RESULT_ONE)) bc_err(BC_ERR_EXEC_TYPE);
572 // Strings can be assigned to variables. We are already good if we are
573 // assigning a string.
574 good = ((*r)->t == BC_RESULT_STR && lt <= BC_RESULT_ARRAY_ELEM);
576 assert(BC_PROG_STR(*rn) || (*r)->t != BC_RESULT_STR);
578 // If not, type check for a number.
579 if (!good) bc_program_type_num(*r, *rn);
583 * Prepares a single operand and type checks it. This is separate from
584 * bc_program_operand() because different places want one or the other.
585 * @param p The program.
586 * @param r An out parameter; this is set to the pointer to the result that
588 * @param n An out parameter; this is set to the pointer to the number that
590 * @param idx The index of the result from the top of the results stack.
593 bc_program_prep(BcProgram* p, BcResult** r, BcNum** n, size_t idx)
595 assert(p != NULL && r != NULL && n != NULL);
597 #ifndef BC_PROG_NO_STACK_CHECK
598 // Check the stack for dc.
601 if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 1)))
603 bc_err(BC_ERR_EXEC_STACK);
606 #endif // BC_PROG_NO_STACK_CHECK
608 assert(BC_PROG_STACK(&p->results, idx + 1));
610 bc_program_operand(p, r, n, idx);
612 // dc does not allow strings in this case.
613 bc_program_type_num(*r, *n);
617 * Prepares and returns a clean result for the result of an operation.
618 * @param p The program.
619 * @return A clean result.
622 bc_program_prepResult(BcProgram* p)
624 BcResult* res = bc_vec_pushEmpty(&p->results);
626 bc_result_clear(res);
632 * Prepares a constant for use. This parses the constant into a number and then
633 * pushes that number onto the results stack.
634 * @param p The program.
635 * @param code The bytecode vector that we will pull the index of the constant
637 * @param bgn An in/out parameter; marks the start of the index in the
638 * bytecode vector and will be updated to point to after the index.
641 bc_program_const(BcProgram* p, const char* code, size_t* bgn)
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);
646 BcConst* c = bc_vec_item(&p->consts, bc_program_index(code, bgn));
647 BcBigDig base = BC_PROG_IBASE(p);
649 // Only reparse if the base changed.
652 // Allocate if we haven't yet.
653 if (c->num.num == NULL)
655 // The plus 1 is in case of overflow with lack of clamping.
656 size_t len = strlen(c->val) + (BC_DIGIT_CLAMP == 0);
659 bc_num_init(&c->num, BC_NUM_RDX(len));
662 // We need to zero an already existing number.
663 else bc_num_zero(&c->num);
665 // bc_num_parse() should only do operations that cannot fail.
666 bc_num_parse(&c->num, c->val, base);
673 bc_num_createCopy(&r->d.n, &c->num);
679 * Executes a binary operator operation.
680 * @param p The program.
681 * @param inst The instruction corresponding to the binary operator to execute.
684 bc_program_op(BcProgram* p, uchar inst)
691 size_t idx = inst - BC_INST_POWER;
693 res = bc_program_prepResult(p);
695 bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, 1);
699 // Initialize the number with enough space, using the correct
700 // BcNumBinaryOpReq function. This looks weird because it is executing an
701 // item of an array. Rest assured that item is a function.
702 bc_num_init(&res->d.n, bc_program_opReqs[idx](n1, n2, BC_PROG_SCALE(p)));
706 assert(BC_NUM_RDX_VALID(n1));
707 assert(BC_NUM_RDX_VALID(n2));
709 // Run the operation. This also executes an item of an array.
710 bc_program_ops[idx](n1, n2, &res->d.n, BC_PROG_SCALE(p));
712 bc_program_retire(p, 1, 2);
716 * Executes a read() or ? command.
717 * @param p The program.
720 bc_program_read(BcProgram* p)
727 BcFunc* f = bc_vec_item(&p->fns, BC_PROG_READ);
729 // If we are already executing a read, that is an error. So look for a read
731 for (i = 0; i < p->stack.len; ++i)
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);
739 // Save the filename because we are going to overwrite it.
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.
745 vm->mode = BC_MODE_FILE;
747 if (!BC_PARSE_IS_INITED(&vm->read_prs, p))
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
754 bc_parse_init(&vm->read_prs, p, BC_PROG_READ);
756 // We need a separate input buffer; that's why it is also in the BcVm
758 bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE);
762 // This needs to be updated because the parser could have been used
764 bc_parse_updateFunc(&vm->read_prs, BC_PROG_READ);
766 // The read buffer also needs to be emptied or else it will still
767 // contain previous read expressions.
768 bc_vec_empty(&vm->read_buf);
771 BC_SETJMP_LOCKED(vm, exec_err);
775 // Set up the lexer and the read function.
776 bc_lex_file(&vm->read_prs.l, bc_program_stdin_name);
777 bc_vec_popAll(&f->code);
780 if (!BC_R) s = bc_read_line(&vm->read_buf, "");
781 else s = bc_read_line(&vm->read_buf, BC_VM_READ_PROMPT);
783 // We should *not* have run into EOF.
784 if (s == BC_STATUS_EOF) bc_err(BC_ERR_EXEC_READ_EXPR);
786 // Parse *one* expression, so mode should not be stdin.
787 bc_parse_text(&vm->read_prs, vm->read_buf.v, BC_MODE_FILE);
789 vm->expr(&vm->read_prs, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL);
792 // We *must* have a valid expression. A semicolon cannot end an expression,
794 if (BC_ERR(vm->read_prs.l.t != BC_LEX_NLINE &&
795 vm->read_prs.l.t != BC_LEX_EOF))
797 bc_err(BC_ERR_EXEC_READ_EXPR);
801 // Push on the globals stack if necessary.
802 if (BC_G) bc_program_prepGlobals(p);
805 // Set up a new BcInstPtr.
806 ip.func = BC_PROG_READ;
808 ip.len = p->results.len;
810 // Update this pointer, just in case.
811 f = bc_vec_item(&p->fns, BC_PROG_READ);
813 // We want a return instruction to simplify things.
814 bc_vec_pushByte(&f->code, vm->read_ret);
816 // This lock is here to make sure dc's tail calls are the same length.
818 bc_vec_push(&p->stack, &ip);
821 // We need a new tail call entry for dc.
825 bc_vec_push(&p->tail_calls, &temp);
831 vm->mode = (uchar) mode;
836 #if BC_ENABLE_EXTRA_MATH
840 * @param p The program.
843 bc_program_rand(BcProgram* p)
845 BcRand rand = bc_rand_int(&p->rng);
847 bc_program_pushBigdig(p, (BcBigDig) rand, BC_RESULT_TEMP);
850 // This is just to ensure that the generated number is correct. I also use
851 // braces because I declare every local at the top of the scope.
853 BcResult* r = bc_vec_top(&p->results);
854 assert(BC_NUM_RDX_VALID_NP(r->d.n));
858 #endif // BC_ENABLE_EXTRA_MATH
861 * Prints a series of characters, without escapes.
862 * @param str The string (series of characters).
865 bc_program_printChars(const char* str)
868 size_t len = vm->nchars + strlen(str);
871 BC_SIG_TRYLOCK(lock);
873 bc_file_puts(&vm->fout, bc_flush_save, str);
875 // We need to update the number of characters, so we find the last newline
876 // and set the characters accordingly.
877 nl = strrchr(str, '\n');
879 if (nl != NULL) len = strlen(nl + 1);
881 vm->nchars = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len;
883 BC_SIG_TRYUNLOCK(lock);
887 * Prints a string with escapes.
888 * @param str The string.
891 bc_program_printString(const char* restrict str)
893 size_t i, len = strlen(str);
896 // This is to ensure a nul byte is printed for dc's stream operation.
897 if (!len && BC_IS_DC)
899 bc_vm_putchar('\0', bc_flush_save);
904 // Loop over the characters, processing escapes and printing the rest.
905 for (i = 0; i < len; ++i)
909 // If we have an escape...
910 if (c == '\\' && i != len - 1)
914 // Get the escape character and its companion.
916 ptr = strchr(bc_program_esc_chars, c);
918 // If we have a companion character...
921 // We need to specially handle a newline.
925 vm->nchars = UINT16_MAX;
929 // Grab the actual character.
930 c = bc_program_esc_seqs[(size_t) (ptr - bc_program_esc_chars)];
934 // Just print the backslash if there is no companion character.
935 // The following character will be printed later after the outer
937 bc_vm_putchar('\\', bc_flush_save);
941 bc_vm_putchar(c, bc_flush_save);
946 * Executes a print. This function handles all printing except streaming.
947 * @param p The program.
948 * @param inst The instruction for the type of print we are doing.
949 * @param idx The index of the result that we are printing.
952 bc_program_print(BcProgram* p, uchar inst, size_t idx)
957 bool pop = (inst != BC_INST_PRINT);
961 #ifndef BC_PROG_NO_STACK_CHECK
964 if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 1)))
966 bc_err(BC_ERR_EXEC_STACK);
969 #endif // BC_PROG_NO_STACK_CHECK
971 assert(BC_PROG_STACK(&p->results, idx + 1));
973 r = bc_vec_item_rev(&p->results, idx);
976 // If we have a void value, that's not necessarily an error. It is if pop is
977 // true because that means that we are executing a print statement, but
978 // attempting to do a print on a lone void value is allowed because that's
979 // exactly how we want void values used.
980 if (r->t == BC_RESULT_VOID)
982 if (BC_ERR(pop)) bc_err(BC_ERR_EXEC_VOID_VAL);
983 bc_vec_pop(&p->results);
988 n = bc_program_num(p, r);
990 // If we have a number...
991 if (BC_PROG_NUM(r, n))
994 assert(inst != BC_INST_PRINT_STR);
998 bc_num_print(n, BC_PROG_OBASE(p), !pop);
1001 // Need to store the number in last.
1002 if (BC_IS_BC) bc_num_copy(&p->last, n);
1003 #endif // BC_ENABLED
1007 // We want to flush any stuff in the stdout buffer first.
1008 bc_file_flush(&vm->fout, bc_flush_save);
1009 str = bc_program_string(p, n);
1012 if (inst == BC_INST_PRINT_STR) bc_program_printChars(str);
1014 #endif // BC_ENABLED
1016 bc_program_printString(str);
1018 // Need to print a newline only in this case.
1019 if (inst == BC_INST_PRINT) bc_vm_putchar('\n', bc_flush_err);
1023 // bc always pops. This macro makes sure that happens.
1024 if (BC_PROGRAM_POP(pop)) bc_vec_pop(&p->results);
1028 bc_program_negate(BcResult* r, BcNum* n)
1030 bc_num_copy(&r->d.n, n);
1031 if (BC_NUM_NONZERO(&r->d.n)) BC_NUM_NEG_TGL_NP(r->d.n);
1035 bc_program_not(BcResult* r, BcNum* n)
1037 if (!bc_num_cmpZero(n)) bc_num_one(&r->d.n);
1040 #if BC_ENABLE_EXTRA_MATH
1042 bc_program_trunc(BcResult* r, BcNum* n)
1044 bc_num_copy(&r->d.n, n);
1045 bc_num_truncate(&r->d.n, n->scale);
1047 #endif // BC_ENABLE_EXTRA_MATH
1050 * Runs a unary operation.
1051 * @param p The program.
1052 * @param inst The unary operation.
1055 bc_program_unary(BcProgram* p, uchar inst)
1061 res = bc_program_prepResult(p);
1063 bc_program_prep(p, &ptr, &num, 1);
1067 bc_num_init(&res->d.n, num->len);
1071 // This calls a function that is in an array.
1072 bc_program_unarys[inst - BC_INST_NEG](res, num);
1073 bc_program_retire(p, 1, 1);
1077 * Executes a logical operator.
1078 * @param p The program.
1079 * @param inst The operator.
1082 bc_program_logical(BcProgram* p, uchar inst)
1092 res = bc_program_prepResult(p);
1094 // All logical operators (except boolean not, which is taken care of by
1095 // bc_program_unary()), are binary operators.
1096 bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, 1);
1098 // Boolean and and or are not short circuiting. This is why; they can be
1099 // implemented much easier this way.
1100 if (inst == BC_INST_BOOL_AND)
1102 cond = (bc_num_cmpZero(n1) && bc_num_cmpZero(n2));
1104 else if (inst == BC_INST_BOOL_OR)
1106 cond = (bc_num_cmpZero(n1) || bc_num_cmpZero(n2));
1110 // We have a relational operator, so do a comparison.
1111 cmp = bc_num_cmp(n1, n2);
1115 case BC_INST_REL_EQ:
1121 case BC_INST_REL_LE:
1127 case BC_INST_REL_GE:
1133 case BC_INST_REL_NE:
1139 case BC_INST_REL_LT:
1145 case BC_INST_REL_GT:
1153 // There is a bug if we get here.
1162 bc_num_init(&res->d.n, BC_NUM_DEF_SIZE);
1166 if (cond) bc_num_one(&res->d.n);
1168 bc_program_retire(p, 1, 2);
1172 * Assigns a string to a variable.
1173 * @param p The program.
1174 * @param num The location of the string as a BcNum.
1175 * @param v The stack for the variable.
1176 * @param push Whether to push the string or not. To push means to move the
1177 * string from the results stack and push it onto the variable
1181 bc_program_assignStr(BcProgram* p, BcNum* num, BcVec* v, bool push)
1185 assert(BC_PROG_STACK(&p->results, 1 + !push));
1186 assert(num != NULL && num->num == NULL && num->cap == 0);
1188 // If we are not pushing onto the variable stack, we need to replace the
1189 // top of the variable stack.
1190 if (!push) bc_vec_pop(v);
1192 bc_vec_npop(&p->results, 1 + !push);
1194 n = bc_vec_pushEmpty(v);
1196 // We can just copy because the num should not have allocated anything.
1198 memcpy(n, num, sizeof(BcNum));
1202 * Copies a value to a variable. This is used for storing in dc as well as to
1203 * set function parameters to arguments in bc.
1204 * @param p The program.
1205 * @param idx The index of the variable or array to copy to.
1206 * @param t The type to copy to. This could be a variable or an array.
1209 bc_program_copyToVar(BcProgram* p, size_t idx, BcType t)
1211 BcResult *ptr = NULL, r;
1214 bool var = (t == BC_TYPE_VAR);
1217 // Check the stack for dc.
1220 if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
1224 assert(BC_PROG_STACK(&p->results, 1));
1226 bc_program_operand(p, &ptr, &n, 0);
1229 // Get the variable for a bc function call.
1232 // Type match the result.
1233 bc_program_type_match(ptr, t);
1235 #endif // BC_ENABLED
1237 vec = bc_program_vec(p, idx, t);
1239 // We can shortcut in dc if it's assigning a string by using
1240 // bc_program_assignStr().
1241 if (ptr->t == BC_RESULT_STR)
1243 assert(BC_PROG_STR(n));
1245 if (BC_ERR(!var)) bc_err(BC_ERR_EXEC_TYPE);
1247 bc_program_assignStr(p, n, vec, true);
1254 // Just create and copy for a normal variable.
1260 memcpy(&r.d.n, n, sizeof(BcNum));
1262 else bc_num_createCopy(&r.d.n, n);
1266 // If we get here, we are handling an array. This is one place we need
1267 // to cast the number from bc_program_num() to a vector.
1268 BcVec* v = (BcVec*) n;
1277 // True if we are using a reference.
1278 ref = (v->size == sizeof(BcNum) && t == BC_TYPE_REF);
1280 // True if we already have a reference vector. This is slightly
1281 // (okay, a lot; it just doesn't look that way) different from
1282 // above. The above means that we need to construct a reference
1283 // vector, whereas this means that we have one and we might have to
1284 // *dereference* it.
1285 ref_size = (v->size == sizeof(uchar));
1287 // If we *should* have a reference.
1288 if (ref || (ref_size && t == BC_TYPE_REF))
1290 // Create a new reference vector.
1291 bc_vec_init(rv, sizeof(uchar), BC_DTOR_NONE);
1293 // If this is true, then we need to construct a reference.
1296 // Make sure the pointer was not invalidated.
1297 vec = bc_program_vec(p, idx, t);
1299 // Push the indices onto the reference vector. This takes
1300 // care of last; it ensures the reference goes to the right
1302 bc_vec_pushIndex(rv, ptr->d.loc.loc);
1303 bc_vec_pushIndex(rv, ptr->d.loc.stack_idx);
1305 // If we get here, we are copying a ref to a ref. Just push a
1306 // copy of all of the bytes.
1307 else bc_vec_npush(rv, v->len * sizeof(uchar), v->v);
1309 // Push the reference vector onto the array stack and pop the
1311 bc_vec_push(vec, &r.d);
1312 bc_vec_pop(&p->results);
1314 // We need to return early to avoid executing code that we must
1319 // If we get here, we have a reference, but we need an array, so
1320 // dereference the array.
1321 else if (ref_size && t != BC_TYPE_REF)
1323 v = bc_program_dereference(p, v);
1326 #endif // BC_ENABLED
1328 // If we get here, we need to copy the array because in bc, all
1329 // arguments are passed by value. Yes, this is expensive.
1330 bc_array_init(rv, true);
1331 bc_array_copy(rv, v);
1334 // Push the vector onto the array stack and pop the source.
1335 bc_vec_push(vec, &r.d);
1336 bc_vec_pop(&p->results);
1342 bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val)
1349 #endif // BC_ENABLED
1351 assert(!scale || !obase);
1353 // Scale needs handling separate from ibase and obase.
1356 // Set the min and max.
1358 max = vm->maxes[BC_PROG_GLOBALS_SCALE];
1361 // Get a pointer to the stack.
1362 v = p->globals_v + BC_PROG_GLOBALS_SCALE;
1363 #endif // BC_ENABLED
1365 // Get a pointer to the current value.
1366 ptr_t = p->globals + BC_PROG_GLOBALS_SCALE;
1370 // Set the min and max.
1371 min = BC_NUM_MIN_BASE;
1372 if (BC_ENABLE_EXTRA_MATH && obase && (BC_IS_DC || !BC_IS_POSIX))
1376 max = vm->maxes[obase + BC_PROG_GLOBALS_IBASE];
1379 // Get a pointer to the stack.
1380 v = p->globals_v + BC_PROG_GLOBALS_IBASE + obase;
1381 #endif // BC_ENABLED
1383 // Get a pointer to the current value.
1384 ptr_t = p->globals + BC_PROG_GLOBALS_IBASE + obase;
1388 if (BC_ERR(val > max || val < min))
1392 // This grabs the right error.
1393 if (scale) e = BC_ERR_EXEC_SCALE;
1394 else if (obase) e = BC_ERR_EXEC_OBASE;
1395 else e = BC_ERR_EXEC_IBASE;
1397 bc_verr(e, min, max);
1401 // Set the top of the stack.
1402 ptr = bc_vec_top(v);
1404 #endif // BC_ENABLED
1406 // Set the actual global variable.
1410 #if BC_ENABLE_EXTRA_MATH
1412 bc_program_assignSeed(BcProgram* p, BcNum* val)
1414 bc_num_rng(val, &p->rng);
1416 #endif // BC_ENABLE_EXTRA_MATH
1419 * Executes an assignment operator.
1420 * @param p The program.
1421 * @param inst The assignment operator to execute.
1424 bc_program_assign(BcProgram* p, uchar inst)
1426 // The local use_val is true when the assigned value needs to be copied.
1432 bool ob, sc, use_val = BC_INST_USE_VAL(inst);
1434 bc_program_assignPrep(p, &left, &l, &right, &r);
1436 // Assigning to a string should be impossible simply because of the parse.
1437 assert(left->t != BC_RESULT_STR);
1439 // If we are assigning a string...
1440 if (right->t == BC_RESULT_STR)
1442 assert(BC_PROG_STR(r));
1445 if (inst != BC_INST_ASSIGN && inst != BC_INST_ASSIGN_NO_VAL)
1447 bc_err(BC_ERR_EXEC_TYPE);
1449 #endif // BC_ENABLED
1451 // If we are assigning to an array element...
1452 if (left->t == BC_RESULT_ARRAY_ELEM)
1456 // We need to free the number and clear it.
1460 memcpy(l, r, sizeof(BcNum));
1462 // Now we can pop the results.
1463 bc_vec_npop(&p->results, 2);
1469 // If we get here, we are assigning to a variable, which we can use
1470 // bc_program_assignStr() for.
1471 BcVec* v = bc_program_vec(p, left->d.loc.loc, BC_TYPE_VAR);
1472 bc_program_assignStr(p, r, v, false);
1477 // If this is true, the value is going to be used again, so we want to
1478 // push a temporary with the string.
1479 if (inst == BC_INST_ASSIGN)
1481 res.t = BC_RESULT_STR;
1483 memcpy(&res.d.n, r, sizeof(BcNum));
1484 bc_vec_push(&p->results, &res);
1487 #endif // BC_ENABLED
1489 // By using bc_program_assignStr(), we short-circuited this, so return.
1493 // If we have a normal assignment operator, not a math one...
1494 if (BC_INST_IS_ASSIGN(inst))
1496 // Assigning to a variable that has a string here is fine because there
1497 // is no math done on it.
1499 // BC_RESULT_TEMP, BC_RESULT_IBASE, BC_RESULT_OBASE, BC_RESULT_SCALE,
1500 // and BC_RESULT_SEED all have temporary copies. Because that's the
1501 // case, we can free the left and just move the value over. We set the
1502 // type of right to BC_RESULT_ZERO in order to prevent it from being
1503 // freed. We also don't have to worry about BC_RESULT_STR because it's
1504 // take care of above.
1505 if (right->t == BC_RESULT_TEMP || right->t >= BC_RESULT_IBASE)
1511 memcpy(l, r, sizeof(BcNum));
1512 right->t = BC_RESULT_ZERO;
1517 else bc_num_copy(l, r);
1522 // If we get here, we are doing a math assignment (+=, -=, etc.). So
1523 // we need to prepare for a binary operator.
1524 BcBigDig scale = BC_PROG_SCALE(p);
1526 // At this point, the left side could still be a string because it could
1527 // be a variable that has the string. If that's the case, we have a type
1529 if (BC_PROG_STR(l)) bc_err(BC_ERR_EXEC_TYPE);
1531 // Get the right type of assignment operator, whether val is used or
1532 // NO_VAL for performance.
1535 inst -= (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER);
1538 assert(BC_NUM_RDX_VALID(l));
1539 assert(BC_NUM_RDX_VALID(r));
1541 // Run the actual operation. We do not need worry about reallocating l
1542 // because bc_num_binary() does that behind the scenes for us.
1543 bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, scale);
1545 #endif // BC_ENABLED
1547 ob = (left->t == BC_RESULT_OBASE);
1548 sc = (left->t == BC_RESULT_SCALE);
1550 // The globals need special handling, especially the non-seed ones. The
1551 // first part of the if statement handles them.
1552 if (ob || sc || left->t == BC_RESULT_IBASE)
1554 // Get the actual value.
1555 BcBigDig val = bc_num_bigdig(l);
1557 bc_program_assignBuiltin(p, sc, ob, val);
1559 #if BC_ENABLE_EXTRA_MATH
1560 // To assign to steed, let bc_num_rng() do its magic.
1561 else if (left->t == BC_RESULT_SEED) bc_program_assignSeed(p, l);
1562 #endif // BC_ENABLE_EXTRA_MATH
1566 // If we needed to use the value, then we need to copy it. Otherwise, we can
1567 // pop indiscriminately. Oh, and the copy should be a BC_RESULT_TEMP.
1570 bc_num_createCopy(&res.d.n, l);
1571 res.t = BC_RESULT_TEMP;
1572 bc_vec_npop(&p->results, 2);
1573 bc_vec_push(&p->results, &res);
1575 else bc_vec_npop(&p->results, 2);
1581 * Pushes a variable's value onto the results stack.
1582 * @param p The program.
1583 * @param code The bytecode vector to pull the variable's index out of.
1584 * @param bgn An in/out parameter; the start of the index in the bytecode
1585 * vector, and will be updated to point after the index on return.
1586 * @param pop True if the variable's value should be popped off its stack.
1587 * This is only used in dc.
1588 * @param copy True if the variable's value should be copied to the results
1589 * stack. This is only used in dc.
1592 bc_program_pushVar(BcProgram* p, const char* restrict code,
1593 size_t* restrict bgn, bool pop, bool copy)
1596 size_t idx = bc_program_index(code, bgn);
1599 // Set the result appropriately.
1600 r.t = BC_RESULT_VAR;
1603 // Get the stack for the variable. This is used in both bc and dc.
1604 v = bc_program_vec(p, idx, BC_TYPE_VAR);
1605 r.d.loc.stack_idx = v->len - 1;
1608 // If this condition is true, then we have the hard case, where we have to
1609 // adjust dc registers.
1610 if (BC_IS_DC && (pop || copy))
1612 // Get the number at the top at the top of the stack.
1613 BcNum* num = bc_vec_top(v);
1615 // Ensure there are enough elements on the stack.
1616 if (BC_ERR(!BC_PROG_STACK(v, 2 - copy)))
1618 const char* name = bc_map_name(&p->var_map, idx);
1619 bc_verr(BC_ERR_EXEC_STACK_REGISTER, name);
1622 assert(BC_PROG_STACK(v, 2 - copy));
1624 // If the top of the stack is actually a number...
1625 if (!BC_PROG_STR(num))
1629 // Create a copy to go onto the results stack as appropriate.
1630 r.t = BC_RESULT_TEMP;
1631 bc_num_createCopy(&r.d.n, num);
1633 // If we are not actually copying, we need to do a replace, so pop.
1634 if (!copy) bc_vec_pop(v);
1636 bc_vec_push(&p->results, &r);
1644 // Set the string result. We can just memcpy because all of the
1645 // fields in the num should be cleared.
1647 memcpy(&r.d.n, num, sizeof(BcNum));
1648 r.t = BC_RESULT_STR;
1651 // If we are not actually copying, we need to do a replace, so pop.
1652 if (!copy) bc_vec_pop(v);
1654 #endif // DC_ENABLED
1656 bc_vec_push(&p->results, &r);
1660 * Pushes an array or an array element onto the results stack.
1661 * @param p The program.
1662 * @param code The bytecode vector to pull the variable's index out of.
1663 * @param bgn An in/out parameter; the start of the index in the bytecode
1664 * vector, and will be updated to point after the index on return.
1665 * @param inst The instruction; whether to push an array or an array element.
1668 bc_program_pushArray(BcProgram* p, const char* restrict code,
1669 size_t* restrict bgn, uchar inst)
1677 // Get the index of the array.
1678 r.d.loc.loc = bc_program_index(code, bgn);
1680 // We need the array to get its length.
1681 v = bc_program_vec(p, r.d.loc.loc, BC_TYPE_ARRAY);
1684 r.d.loc.stack_idx = v->len - 1;
1686 // Doing an array is easy; just set the result type and finish.
1687 if (inst == BC_INST_ARRAY)
1689 r.t = BC_RESULT_ARRAY;
1690 bc_vec_push(&p->results, &r);
1694 // Grab the top element of the results stack for the array index.
1695 bc_program_prep(p, &operand, &num, 0);
1696 temp = bc_num_bigdig(num);
1699 r.t = BC_RESULT_ARRAY_ELEM;
1700 r.d.loc.idx = (size_t) temp;
1704 // Pop the index and push the element.
1705 bc_vec_pop(&p->results);
1706 bc_vec_push(&p->results, &r);
1714 * Executes an increment or decrement operator. This only handles postfix
1715 * inc/dec because the parser translates prefix inc/dec into an assignment where
1716 * the value is used.
1717 * @param p The program.
1718 * @param inst The instruction; whether to do an increment or decrement.
1721 bc_program_incdec(BcProgram* p, uchar inst)
1723 BcResult *ptr, res, copy;
1727 bc_program_prep(p, &ptr, &num, 0);
1731 // We need a copy from *before* the operation.
1732 copy.t = BC_RESULT_TEMP;
1733 bc_num_createCopy(©.d.n, num);
1735 BC_SETJMP_LOCKED(vm, exit);
1739 // Create the proper assignment.
1740 res.t = BC_RESULT_ONE;
1741 inst2 = BC_INST_ASSIGN_PLUS_NO_VAL + (inst & 0x01);
1743 bc_vec_push(&p->results, &res);
1744 bc_program_assign(p, inst2);
1748 bc_vec_push(&p->results, ©);
1754 // No need to free the copy here because we pushed it onto the stack.
1759 bc_num_free(©.d.n);
1760 BC_LONGJMP_CONT(vm);
1764 * Executes a function call for bc.
1765 * @param p The program.
1766 * @param code The bytecode vector to pull the number of arguments and the
1767 * function index out of.
1768 * @param bgn An in/out parameter; the start of the indices in the bytecode
1769 * vector, and will be updated to point after the indices on
1773 bc_program_call(BcProgram* p, const char* restrict code, size_t* restrict bgn)
1782 // Pull the number of arguments out of the bytecode vector.
1783 nargs = bc_program_index(code, bgn);
1785 // Set up instruction pointer.
1787 ip.func = bc_program_index(code, bgn);
1788 f = bc_vec_item(&p->fns, ip.func);
1791 if (BC_ERR(!f->code.len)) bc_verr(BC_ERR_EXEC_UNDEF_FUNC, f->name);
1792 if (BC_ERR(nargs != f->nparams))
1794 bc_verr(BC_ERR_EXEC_PARAMS, f->nparams, nargs);
1797 // Set the length of the results stack. We discount the argument, of course.
1798 ip.len = p->results.len - nargs;
1800 assert(BC_PROG_STACK(&p->results, nargs));
1802 // Prepare the globals' stacks.
1803 if (BC_G) bc_program_prepGlobals(p);
1805 // Push the arguments onto the stacks of their respective parameters.
1806 for (i = 0; i < nargs; ++i)
1808 arg = bc_vec_top(&p->results);
1809 if (BC_ERR(arg->t == BC_RESULT_VOID)) bc_err(BC_ERR_EXEC_VOID_VAL);
1811 // Get the corresponding parameter.
1812 a = bc_vec_item(&f->autos, nargs - 1 - i);
1814 // Actually push the value onto the parameter's stack.
1815 bc_program_copyToVar(p, a->idx, a->type);
1820 // Push zeroes onto the stacks of the auto variables.
1821 for (; i < f->autos.len; ++i)
1823 // Get the auto and its stack.
1824 a = bc_vec_item(&f->autos, i);
1825 v = bc_program_vec(p, a->idx, a->type);
1827 // If a variable, just push a 0; otherwise, push an array.
1828 if (a->type == BC_TYPE_VAR)
1830 BcNum* n = bc_vec_pushEmpty(v);
1831 bc_num_init(n, BC_NUM_DEF_SIZE);
1837 assert(a->type == BC_TYPE_ARRAY);
1839 v2 = bc_vec_pushEmpty(v);
1840 bc_array_init(v2, true);
1844 // Push the instruction pointer onto the execution stack.
1845 bc_vec_push(&p->stack, &ip);
1851 * Executes a return instruction.
1852 * @param p The program.
1853 * @param inst The return instruction. bc can return void, and we need to know
1857 bc_program_return(BcProgram* p, uchar inst)
1864 // Get the instruction pointer.
1865 ip = bc_vec_top(&p->stack);
1867 // Get the difference between the actual number of results and the number of
1868 // results the caller expects.
1869 nresults = p->results.len - ip->len;
1871 // If this isn't true, there was a missing call somewhere.
1872 assert(BC_PROG_STACK(&p->stack, 2));
1874 // If this isn't true, the parser screwed by giving us no value when we
1875 // expected one, or giving us a value when we expected none.
1876 assert(BC_PROG_STACK(&p->results, ip->len + (inst == BC_INST_RET)));
1878 // Get the function we are returning from.
1879 f = bc_vec_item(&p->fns, ip->func);
1881 res = bc_program_prepResult(p);
1883 // If we are returning normally...
1884 if (inst == BC_INST_RET)
1889 // Prepare and copy the return value.
1890 bc_program_operand(p, &operand, &num, 1);
1892 if (BC_PROG_STR(num))
1894 // We need to set this because otherwise, it will be a
1895 // BC_RESULT_TEMP, and BC_RESULT_TEMP needs an actual number to make
1896 // it easier to do type checking.
1897 res->t = BC_RESULT_STR;
1900 memcpy(&res->d.n, num, sizeof(BcNum));
1906 bc_num_createCopy(&res->d.n, num);
1909 // Void is easy; set the result.
1910 else if (inst == BC_INST_RET_VOID) res->t = BC_RESULT_VOID;
1915 // If we get here, the instruction is for returning a zero, so do that.
1916 bc_num_init(&res->d.n, BC_NUM_DEF_SIZE);
1921 // We need to pop items off of the stacks of arguments and autos as well.
1922 for (i = 0; i < f->autos.len; ++i)
1924 BcAuto* a = bc_vec_item(&f->autos, i);
1925 BcVec* v = bc_program_vec(p, a->idx, a->type);
1932 // When we retire, pop all of the unused results.
1933 bc_program_retire(p, 1, nresults);
1935 // Pop the globals, if necessary.
1936 if (BC_G) bc_program_popGlobals(p, false);
1938 // Pop the stack. This is what causes the function to actually "return."
1939 bc_vec_pop(&p->stack);
1943 #endif // BC_ENABLED
1946 * Executes a builtin function.
1947 * @param p The program.
1948 * @param inst The builtin to execute.
1951 bc_program_builtin(BcProgram* p, uchar inst)
1956 bool len = (inst == BC_INST_LENGTH);
1958 // Ensure we have a valid builtin.
1959 #if BC_ENABLE_EXTRA_MATH
1960 assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IRAND);
1961 #else // BC_ENABLE_EXTRA_MATH
1962 assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IS_STRING);
1963 #endif // BC_ENABLE_EXTRA_MATH
1965 #ifndef BC_PROG_NO_STACK_CHECK
1966 // Check stack for dc.
1967 if (BC_IS_DC && BC_ERR(!BC_PROG_STACK(&p->results, 1)))
1969 bc_err(BC_ERR_EXEC_STACK);
1971 #endif // BC_PROG_NO_STACK_CHECK
1973 assert(BC_PROG_STACK(&p->results, 1));
1975 res = bc_program_prepResult(p);
1977 bc_program_operand(p, &opd, &num, 1);
1979 assert(num != NULL);
1981 // We need to ensure that strings and arrays aren't passed to most builtins.
1982 // The scale function can take strings in dc.
1983 if (!len && (inst != BC_INST_SCALE_FUNC || BC_IS_BC) &&
1984 inst != BC_INST_IS_NUMBER && inst != BC_INST_IS_STRING)
1986 bc_program_type_num(opd, num);
1989 // Square root is easy.
1990 if (inst == BC_INST_SQRT) bc_num_sqrt(num, &res->d.n, BC_PROG_SCALE(p));
1992 // Absolute value is easy.
1993 else if (inst == BC_INST_ABS)
1997 bc_num_createCopy(&res->d.n, num);
2001 BC_NUM_NEG_CLR_NP(res->d.n);
2004 // Testing for number or string is easy.
2005 else if (inst == BC_INST_IS_NUMBER || inst == BC_INST_IS_STRING)
2012 bc_num_init(&res->d.n, BC_NUM_DEF_SIZE);
2016 // Test if the number is a string.
2017 is_str = BC_PROG_STR(num);
2019 // This confusing condition simply means that the instruction must be
2020 // true if is_str is, or it must be false if is_str is. Otherwise, the
2021 // returned value is false (0).
2022 cond = ((inst == BC_INST_IS_STRING) == is_str);
2023 if (cond) bc_num_one(&res->d.n);
2026 #if BC_ENABLE_EXTRA_MATH
2029 else if (inst == BC_INST_IRAND)
2033 bc_num_init(&res->d.n, num->len - BC_NUM_RDX_VAL(num));
2037 bc_num_irand(num, &res->d.n, &p->rng);
2040 #endif // BC_ENABLE_EXTRA_MATH
2042 // Everything else is...not easy.
2047 // Well, scale() is easy, but length() is not.
2050 // If we are bc and we have an array...
2051 if (opd->t == BC_RESULT_ARRAY)
2053 // Yes, this is one place where we need to cast the number from
2054 // bc_program_num() to a vector.
2055 BcVec* v = (BcVec*) num;
2057 // XXX: If this is changed, you should also change the similar
2058 // code in bc_program_asciify().
2061 // Dereference the array, if necessary.
2062 if (BC_IS_BC && v->size == sizeof(uchar))
2064 v = bc_program_dereference(p, v);
2066 #endif // BC_ENABLED
2068 assert(v->size == sizeof(BcNum));
2070 val = (BcBigDig) v->len;
2074 // If the item is a string...
2075 if (!BC_PROG_NUM(opd, num))
2079 // Get the string, then get the length.
2080 str = bc_program_string(p, num);
2081 val = (BcBigDig) strlen(str);
2085 // Calculate the length of the number.
2086 val = (BcBigDig) bc_num_len(num);
2090 // Like I said; scale() is actually easy. It just also needs the integer
2091 // conversion that length() does.
2092 else if (BC_IS_BC || BC_PROG_NUM(opd, num))
2094 val = (BcBigDig) bc_num_scale(num);
2099 // Create the result.
2100 bc_num_createFromBigdig(&res->d.n, val);
2105 bc_program_retire(p, 1, 1);
2109 * Executes a divmod.
2110 * @param p The program.
2113 bc_program_divmod(BcProgram* p)
2123 // We grow first to avoid pointer invalidation.
2124 bc_vec_grow(&p->results, 2);
2126 // We don't need to update the pointer because
2127 // the capacity is enough due to the line above.
2128 res2 = bc_program_prepResult(p);
2129 res = bc_program_prepResult(p);
2131 // Prepare the operands.
2132 bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, 2);
2134 req = bc_num_mulReq(n1, n2, BC_PROG_SCALE(p));
2138 // Initialize the results.
2139 bc_num_init(&res->d.n, req);
2140 bc_num_init(&res2->d.n, req);
2145 bc_num_divmod(n1, n2, &res2->d.n, &res->d.n, BC_PROG_SCALE(p));
2147 bc_program_retire(p, 2, 2);
2151 * Executes modular exponentiation.
2152 * @param p The program.
2155 bc_program_modexp(BcProgram* p)
2168 if (BC_IS_DC && BC_ERR(!BC_PROG_STACK(&p->results, 3)))
2170 bc_err(BC_ERR_EXEC_STACK);
2173 #endif // DC_ENABLED
2175 assert(BC_PROG_STACK(&p->results, 3));
2177 res = bc_program_prepResult(p);
2179 // Get the first operand and typecheck.
2180 bc_program_operand(p, &r1, &n1, 3);
2181 bc_program_type_num(r1, n1);
2183 // Get the last two operands.
2184 bc_program_binOpPrep(p, &r2, &n2, &r3, &n3, 1);
2186 // Make sure that the values have their pointers updated, if necessary.
2187 // Only array elements are possible because this is dc.
2188 if (r1->t == BC_RESULT_ARRAY_ELEM && (r1->t == r2->t || r1->t == r3->t))
2190 n1 = bc_program_num(p, r1);
2195 bc_num_init(&res->d.n, n3->len);
2199 bc_num_modexp(n1, n2, n3, &res->d.n);
2201 bc_program_retire(p, 1, 3);
2205 * Asciifies a number for dc. This is a helper for bc_program_asciify().
2206 * @param p The program.
2207 * @param n The number to asciify.
2210 bc_program_asciifyNum(BcProgram* p, BcNum* n)
2212 bc_num_copy(&p->asciify, n);
2214 // We want to clear the scale and sign for easy mod later.
2215 bc_num_truncate(&p->asciify, p->asciify.scale);
2216 BC_NUM_NEG_CLR(&p->asciify);
2218 // This is guaranteed to not have a divide by 0
2219 // because strmb is equal to 256.
2220 bc_num_mod(&p->asciify, &p->strmb, &p->asciify, 0);
2222 // This is also guaranteed to not error because num is in the range
2223 // [0, UCHAR_MAX], which is definitely in range for a BcBigDig. And
2224 // it is not negative.
2225 return (uchar) bc_num_bigdig2(&p->asciify);
2229 * Executes the "asciify" command in bc and dc.
2230 * @param p The program.
2233 bc_program_asciify(BcProgram* p)
2240 // This is in the outer scope because it has to be freed after a jump.
2242 #endif // BC_ENABLED
2245 if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
2247 assert(BC_PROG_STACK(&p->results, 1));
2249 // Get the top of the results stack.
2250 bc_program_operand(p, &r, &n, 0);
2253 assert(BC_IS_BC || r->t != BC_RESULT_ARRAY);
2256 // Handle arrays in bc specially.
2257 if (r->t == BC_RESULT_ARRAY)
2259 // Yes, this is one place where we need to cast the number from
2260 // bc_program_num() to a vector.
2261 BcVec* v = (BcVec*) n;
2264 // XXX: If this is changed, you should also change the similar code in
2265 // bc_program_builtin().
2267 // Dereference the array, if necessary.
2268 if (v->size == sizeof(uchar))
2270 v = bc_program_dereference(p, v);
2273 assert(v->size == sizeof(BcNum));
2275 // Allocate the string and set the jump for it.
2277 temp_str = bc_vm_malloc(v->len + 1);
2278 BC_SETJMP_LOCKED(vm, exit);
2281 // Convert the array.
2282 for (i = 0; i < v->len; ++i)
2284 BcNum* num = (BcNum*) bc_vec_item(v, i);
2286 if (BC_PROG_STR(num))
2288 temp_str[i] = (bc_program_string(p, num))[0];
2292 temp_str[i] = (char) bc_program_asciifyNum(p, num);
2296 temp_str[v->len] = '\0';
2298 // Store the string in the slab and map, and free the temp string.
2300 idx = bc_program_addString(p, temp_str);
2306 #endif // BC_ENABLED
2312 if (BC_PROG_NUM(r, n)) c = bc_program_asciifyNum(p, n);
2315 // Get the string itself, then the first character.
2316 str2 = bc_program_string(p, n);
2317 c = (uchar) str2[0];
2320 // Fill the resulting string.
2324 // Add the string to the data structures.
2326 idx = bc_program_addString(p, str);
2331 res.t = BC_RESULT_STR;
2332 bc_num_clear(&res.d.n);
2333 res.d.n.scale = idx;
2336 bc_vec_pop(&p->results);
2337 bc_vec_push(&p->results, &res);
2344 #endif // BC_ENABLED
2348 * Streams a number or a string to stdout.
2349 * @param p The program.
2352 bc_program_printStream(BcProgram* p)
2358 if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
2360 assert(BC_PROG_STACK(&p->results, 1));
2362 // Get the top of the results stack.
2363 bc_program_operand(p, &r, &n, 0);
2367 // Stream appropriately.
2368 if (BC_PROG_NUM(r, n)) bc_num_stream(n);
2369 else bc_program_printChars(bc_program_string(p, n));
2372 bc_vec_pop(&p->results);
2378 * Gets the length of a register in dc and pushes it onto the results stack.
2379 * @param p The program.
2380 * @param code The bytecode vector to pull the register's index out of.
2381 * @param bgn An in/out parameter; the start of the index in the bytecode
2382 * vector, and will be updated to point after the index on return.
2385 bc_program_regStackLen(BcProgram* p, const char* restrict code,
2386 size_t* restrict bgn)
2388 size_t idx = bc_program_index(code, bgn);
2389 BcVec* v = bc_program_vec(p, idx, BC_TYPE_VAR);
2391 bc_program_pushBigdig(p, (BcBigDig) v->len, BC_RESULT_TEMP);
2395 * Pushes the length of the results stack onto the results stack.
2396 * @param p The program.
2399 bc_program_stackLen(BcProgram* p)
2401 bc_program_pushBigdig(p, (BcBigDig) p->results.len, BC_RESULT_TEMP);
2405 * Pops a certain number of elements off the execution stack.
2406 * @param p The program.
2407 * @param inst The instruction to tell us how many. There is one to pop up to
2408 * 2, and one to pop the amount equal to the number at the top of
2409 * the results stack.
2412 bc_program_nquit(BcProgram* p, uchar inst)
2419 // Ensure that the tail calls stack is correct.
2420 assert(p->stack.len == p->tail_calls.len);
2422 // Get the number of executions to pop.
2423 if (inst == BC_INST_QUIT) val = 2;
2426 bc_program_prep(p, &opnd, &num, 0);
2427 val = bc_num_bigdig(num);
2429 bc_vec_pop(&p->results);
2432 // Loop over the tail call stack and adjust the quit value appropriately.
2433 for (i = 0; val && i < p->tail_calls.len; ++i)
2435 // Get the number of tail calls for this one.
2436 size_t calls = *((size_t*) bc_vec_item_rev(&p->tail_calls, i)) + 1;
2438 // Adjust the value.
2439 if (calls >= val) val = 0;
2440 else val -= (BcBigDig) calls;
2443 // If we don't have enough executions, just quit.
2444 if (i == p->stack.len)
2446 vm->status = BC_STATUS_QUIT;
2451 // We can always pop the last item we reached on the tail call stack
2452 // because these are for tail calls. That means that any executions that
2453 // we would not have quit in that position on the stack would have quit
2456 bc_vec_npop(&p->stack, i);
2457 bc_vec_npop(&p->tail_calls, i);
2463 * Pushes the depth of the execution stack onto the stack.
2464 * @param p The program.
2467 bc_program_execStackLen(BcProgram* p)
2469 size_t i, amt, len = p->tail_calls.len;
2473 for (i = 0; i < len; ++i)
2475 amt += *((size_t*) bc_vec_item(&p->tail_calls, i));
2478 bc_program_pushBigdig(p, (BcBigDig) amt, BC_RESULT_TEMP);
2483 * @param p The program.
2484 * @param code The bytecode vector to pull the register's index out of.
2485 * @param bgn An in/out parameter; the start of the index in the bytecode
2486 * vector, and will be updated to point after the index on return.
2487 * @param cond True if the execution is conditional, false otherwise.
2488 * @param len The number of bytes in the bytecode vector.
2491 bc_program_execStr(BcProgram* p, const char* restrict code,
2492 size_t* restrict bgn, bool cond, size_t len)
2501 assert(p->stack.len == p->tail_calls.len);
2504 if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
2506 assert(BC_PROG_STACK(&p->results, 1));
2509 bc_program_operand(p, &r, &n, 0);
2511 // If execution is conditional...
2516 // These are volatile to quiet warnings on GCC about clobbering with
2518 volatile size_t else_idx;
2519 volatile size_t idx;
2521 // Get the index of the "then" var and "else" var.
2522 then_idx = bc_program_index(code, bgn);
2523 else_idx = bc_program_index(code, bgn);
2525 // Figure out if we should execute.
2526 exec = (r->d.n.len != 0);
2528 idx = exec ? then_idx : else_idx;
2531 BC_SETJMP_LOCKED(vm, exit);
2533 // If we are supposed to execute, execute. If else_idx == SIZE_MAX, that
2534 // means there was no else clause, so if execute is false and else does
2535 // not exist, we don't execute. The goto skips all of the setup for the
2537 if (exec || (else_idx != SIZE_MAX))
2539 n = bc_vec_top(bc_program_vec(p, idx, BC_TYPE_VAR));
2543 if (BC_ERR(!BC_PROG_STR(n))) bc_err(BC_ERR_EXEC_TYPE);
2550 // In non-conditional situations, only the top of stack can be executed,
2551 // and in those cases, variables are not allowed to be "on the stack";
2552 // they are only put on the stack to be assigned to.
2553 assert(r->t != BC_RESULT_VAR);
2555 if (r->t != BC_RESULT_STR) return;
2558 assert(BC_PROG_STR(n));
2561 str = bc_program_string(p, n);
2563 // Get the function index and function.
2565 fidx = bc_program_insertFunc(p, str);
2567 f = bc_vec_item(&p->fns, fidx);
2569 // If the function has not been parsed yet...
2574 if (!BC_PARSE_IS_INITED(&vm->read_prs, p))
2576 bc_parse_init(&vm->read_prs, p, fidx);
2578 // Initialize this too because bc_vm_shutdown() expects them to be
2579 // initialized togther.
2580 bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE);
2582 // This needs to be updated because the parser could have been used
2584 else bc_parse_updateFunc(&vm->read_prs, fidx);
2586 bc_lex_file(&vm->read_prs.l, vm->file);
2588 BC_SETJMP_LOCKED(vm, err);
2592 // Parse. Only one expression is needed, so stdin isn't used.
2593 bc_parse_text(&vm->read_prs, str, BC_MODE_FILE);
2596 vm->expr(&vm->read_prs, BC_PARSE_NOCALL);
2600 // We can just assert this here because
2601 // dc should parse everything until EOF.
2602 assert(vm->read_prs.l.t == BC_LEX_EOF);
2607 // Set the instruction pointer.
2609 ip.len = p->results.len;
2615 bc_vec_pop(&p->results);
2617 // Tail call processing. This condition means that there is more on the
2618 // execution stack, and we are at the end of the bytecode vector, and the
2619 // last instruction is just a BC_INST_POP_EXEC, which would return.
2620 if (p->stack.len > 1 && *bgn == len - 1 && code[*bgn] == BC_INST_POP_EXEC)
2622 size_t* call_ptr = bc_vec_top(&p->tail_calls);
2624 // Add one to the tail call.
2627 // Pop the execution stack before pushing the new instruction pointer
2629 bc_vec_pop(&p->stack);
2631 // If not a tail call, just push a new one.
2632 else bc_vec_push(&p->tail_calls, &ip.idx);
2634 // Push the new function onto the execution stack and return.
2635 bc_vec_push(&p->stack, &ip);
2644 f = bc_vec_item(&p->fns, fidx);
2646 // Make sure to erase the bytecode vector so dc knows it is not parsed.
2647 bc_vec_popAll(&f->code);
2650 bc_vec_pop(&p->results);
2651 BC_LONGJMP_CONT(vm);
2655 * Prints every item on the results stack, one per line.
2656 * @param p The program.
2659 bc_program_printStack(BcProgram* p)
2663 for (idx = 0; idx < p->results.len; ++idx)
2665 bc_program_print(p, BC_INST_PRINT, idx);
2668 #endif // DC_ENABLED
2671 * Pushes the value of a global onto the results stack.
2672 * @param p The program.
2673 * @param inst Which global to push, as an instruction.
2676 bc_program_pushGlobal(BcProgram* p, uchar inst)
2680 // Make sure the instruction is valid.
2681 assert(inst >= BC_INST_IBASE && inst <= BC_INST_SCALE);
2684 t = inst - BC_INST_IBASE + BC_RESULT_IBASE;
2685 bc_program_pushBigdig(p, p->globals[inst - BC_INST_IBASE], t);
2689 * Pushes the value of a global setting onto the stack.
2690 * @param p The program.
2691 * @param inst Which global setting to push, as an instruction.
2694 bc_program_globalSetting(BcProgram* p, uchar inst)
2698 // Make sure the instruction is valid.
2700 assert((inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO) ||
2701 (BC_IS_DC && inst == BC_INST_EXTENDED_REGISTERS));
2703 assert(inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO);
2704 #endif // DC_ENABLED
2706 if (inst == BC_INST_LINE_LENGTH)
2708 val = (BcBigDig) vm->line_len;
2711 else if (inst == BC_INST_GLOBAL_STACKS)
2715 #endif // BC_ENABLED
2717 else if (inst == BC_INST_EXTENDED_REGISTERS)
2721 #endif // DC_ENABLED
2722 else val = (BC_Z != 0);
2725 bc_program_pushBigdig(p, val, BC_RESULT_TEMP);
2728 #if BC_ENABLE_EXTRA_MATH
2731 * Pushes the value of seed on the stack.
2732 * @param p The program.
2735 bc_program_pushSeed(BcProgram* p)
2739 res = bc_program_prepResult(p);
2740 res->t = BC_RESULT_SEED;
2744 // We need 2*BC_RAND_NUM_SIZE because of the size of the state.
2745 bc_num_init(&res->d.n, 2 * BC_RAND_NUM_SIZE);
2749 bc_num_createFromRNG(&res->d.n, &p->rng);
2752 #endif // BC_ENABLE_EXTRA_MATH
2755 * Adds a function to the fns array. The function's ID must have already been
2756 * inserted into the map.
2757 * @param p The program.
2758 * @param id_ptr The ID of the function as inserted into the map.
2761 bc_program_addFunc(BcProgram* p, BcId* id_ptr)
2765 BC_SIG_ASSERT_LOCKED;
2768 f = bc_vec_pushEmpty(&p->fns);
2769 bc_func_init(f, id_ptr->name);
2773 bc_program_insertFunc(BcProgram* p, const char* name)
2779 BC_SIG_ASSERT_LOCKED;
2781 assert(p != NULL && name != NULL);
2783 // Insert into the map and get the resulting ID.
2784 new = bc_map_insert(&p->fn_map, name, p->fns.len, &idx);
2785 id_ptr = (BcId*) bc_vec_item(&p->fn_map, idx);
2788 // If the function is new...
2791 // Add the function to the fns array.
2792 bc_program_addFunc(p, id_ptr);
2795 // bc has to reset the function because it's about to be redefined.
2798 BcFunc* func = bc_vec_item(&p->fns, idx);
2799 bc_func_reset(func);
2801 #endif // BC_ENABLED
2808 bc_program_free(BcProgram* p)
2812 #endif // BC_ENABLED
2814 BC_SIG_ASSERT_LOCKED;
2819 // Free the globals stacks.
2820 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
2822 bc_vec_free(p->globals_v + i);
2824 #endif // BC_ENABLED
2826 bc_vec_free(&p->fns);
2827 bc_vec_free(&p->fn_map);
2828 bc_vec_free(&p->vars);
2829 bc_vec_free(&p->var_map);
2830 bc_vec_free(&p->arrs);
2831 bc_vec_free(&p->arr_map);
2832 bc_vec_free(&p->results);
2833 bc_vec_free(&p->stack);
2834 bc_vec_free(&p->consts);
2835 bc_vec_free(&p->const_map);
2836 bc_vec_free(&p->strs);
2837 bc_vec_free(&p->str_map);
2839 bc_num_free(&p->asciify);
2842 if (BC_IS_BC) bc_num_free(&p->last);
2843 #endif // BC_ENABLED
2845 #if BC_ENABLE_EXTRA_MATH
2846 bc_rand_free(&p->rng);
2847 #endif // BC_ENABLE_EXTRA_MATH
2850 if (BC_IS_DC) bc_vec_free(&p->tail_calls);
2851 #endif // DC_ENABLED
2856 bc_program_init(BcProgram* p)
2861 BC_SIG_ASSERT_LOCKED;
2865 // We want this clear.
2867 memset(&ip, 0, sizeof(BcInstPtr));
2869 // Setup the globals stacks and the current values.
2870 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
2872 BcBigDig val = i == BC_PROG_GLOBALS_SCALE ? 0 : BC_BASE;
2875 bc_vec_init(p->globals_v + i, sizeof(BcBigDig), BC_DTOR_NONE);
2876 bc_vec_push(p->globals_v + i, &val);
2877 #endif // BC_ENABLED
2879 p->globals[i] = val;
2886 bc_vec_init(&p->tail_calls, sizeof(size_t), BC_DTOR_NONE);
2888 // We want an item for the main function on the tail call stack.
2890 bc_vec_push(&p->tail_calls, &i);
2892 #endif // DC_ENABLED
2894 bc_num_setup(&p->strmb, p->strmb_num, BC_NUM_BIGDIG_LOG10);
2895 bc_num_bigdig2num(&p->strmb, BC_NUM_STREAM_BASE);
2897 bc_num_init(&p->asciify, BC_NUM_DEF_SIZE);
2899 #if BC_ENABLE_EXTRA_MATH
2900 // We need to initialize srand() just in case /dev/urandom and /dev/random
2901 // are not available.
2902 srand((unsigned int) time(NULL));
2903 bc_rand_init(&p->rng);
2904 #endif // BC_ENABLE_EXTRA_MATH
2907 if (BC_IS_BC) bc_num_init(&p->last, BC_NUM_DEF_SIZE);
2908 #endif // BC_ENABLED
2911 bc_vec_init(&p->fns, sizeof(BcFunc), BC_DTOR_FUNC);
2913 bc_vec_init(&p->fns, sizeof(BcFunc), BC_DTOR_NONE);
2915 bc_map_init(&p->fn_map);
2916 bc_program_insertFunc(p, bc_func_main);
2917 bc_program_insertFunc(p, bc_func_read);
2919 bc_vec_init(&p->vars, sizeof(BcVec), BC_DTOR_VEC);
2920 bc_map_init(&p->var_map);
2922 bc_vec_init(&p->arrs, sizeof(BcVec), BC_DTOR_VEC);
2923 bc_map_init(&p->arr_map);
2925 bc_vec_init(&p->results, sizeof(BcResult), BC_DTOR_RESULT);
2927 // Push the first instruction pointer onto the execution stack.
2928 bc_vec_init(&p->stack, sizeof(BcInstPtr), BC_DTOR_NONE);
2929 bc_vec_push(&p->stack, &ip);
2931 bc_vec_init(&p->consts, sizeof(BcConst), BC_DTOR_CONST);
2932 bc_map_init(&p->const_map);
2933 bc_vec_init(&p->strs, sizeof(char*), BC_DTOR_NONE);
2934 bc_map_init(&p->str_map);
2938 bc_program_printStackTrace(BcProgram* p)
2940 size_t i, max_digits;
2942 max_digits = bc_vm_numDigits(p->stack.len - 1);
2944 for (i = 0; i < p->stack.len; ++i)
2946 BcInstPtr* ip = bc_vec_item_rev(&p->stack, i);
2947 BcFunc* f = bc_vec_item(&p->fns, ip->func);
2950 digits = bc_vm_numDigits(i);
2952 bc_file_puts(&vm->ferr, bc_flush_none, " ");
2954 for (j = 0; j < max_digits - digits; ++j)
2956 bc_file_putchar(&vm->ferr, bc_flush_none, ' ');
2959 bc_file_printf(&vm->ferr, "%zu: %s", i, f->name);
2962 if (BC_IS_BC && ip->func != BC_PROG_MAIN && ip->func != BC_PROG_READ)
2964 bc_file_puts(&vm->ferr, bc_flush_none, "()");
2966 #endif // BC_ENABLED
2968 bc_file_putchar(&vm->ferr, bc_flush_none, '\n');
2973 bc_program_reset(BcProgram* p)
2978 BC_SIG_ASSERT_LOCKED;
2980 // Pop all but the last execution and all results.
2981 bc_vec_npop(&p->stack, p->stack.len - 1);
2982 bc_vec_popAll(&p->results);
2985 // We need to pop tail calls too.
2986 if (BC_IS_DC) bc_vec_npop(&p->tail_calls, p->tail_calls.len - 1);
2987 #endif // DC_ENABLED
2990 // Clear the globals' stacks.
2991 if (BC_G) bc_program_popGlobals(p, true);
2992 #endif // BC_ENABLED
2994 // Clear the bytecode vector of the main function.
2995 f = bc_vec_item(&p->fns, BC_PROG_MAIN);
2996 bc_vec_npop(&f->code, f->code.len);
2998 // Reset the instruction pointer.
2999 ip = bc_vec_top(&p->stack);
3001 memset(ip, 0, sizeof(BcInstPtr));
3003 if (BC_SIG_INTERRUPT(vm))
3005 // Write the ready message for a signal.
3006 bc_file_printf(&vm->fout, "%s", bc_program_ready_msg);
3007 bc_file_flush(&vm->fout, bc_flush_err);
3010 // Clear the signal.
3015 bc_program_exec(BcProgram* p)
3027 #endif // BC_ENABLED
3028 #if !BC_HAS_COMPUTED_GOTO
3030 size_t jmp_bufs_len;
3032 #endif // !BC_HAS_COMPUTED_GOTO
3034 #if BC_HAS_COMPUTED_GOTO
3037 #pragma GCC diagnostic ignored "-Wpedantic"
3041 #pragma clang diagnostic ignored "-Wgnu-label-as-value"
3045 BC_PROG_LBLS_ASSERT;
3048 #pragma clang diagnostic warning "-Wgnu-label-as-value"
3052 #pragma GCC diagnostic warning "-Wpedantic"
3055 // BC_INST_INVALID is a marker for the end so that we don't have to have an
3057 func = (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN);
3058 bc_vec_pushByte(&func->code, BC_INST_INVALID);
3059 #endif // BC_HAS_COMPUTED_GOTO
3063 ip = bc_vec_top(&p->stack);
3064 func = (BcFunc*) bc_vec_item(&p->fns, ip->func);
3065 code = func->code.v;
3067 #if !BC_HAS_COMPUTED_GOTO
3070 jmp_bufs_len = vm->jmp_bufs.len;
3073 // This loop is the heart of the execution engine. It *is* the engine. For
3074 // computed goto, it is ignored.
3075 while (ip->idx < func->code.len)
3076 #endif // !BC_HAS_COMPUTED_GOTO
3078 BC_SIG_ASSERT_NOT_LOCKED;
3080 #if BC_HAS_COMPUTED_GOTO
3083 #pragma GCC diagnostic ignored "-Wpedantic"
3087 #pragma clang diagnostic ignored "-Wgnu-label-as-value"
3090 BC_PROG_JUMP(inst, code, ip);
3092 #else // BC_HAS_COMPUTED_GOTO
3094 // Get the next instruction and increment the index.
3095 inst = (uchar) code[(ip->idx)++];
3097 #endif // BC_HAS_COMPUTED_GOTO
3100 bc_file_printf(&vm->ferr, "inst: %s\n", bc_inst_names[inst]);
3101 bc_file_flush(&vm->ferr, bc_flush_none);
3102 #endif // BC_DEBUG_CODE
3104 #if !BC_HAS_COMPUTED_GOTO
3106 #endif // !BC_HAS_COMPUTED_GOTO
3109 // This just sets up the condition for the unconditional jump below,
3110 // which checks the condition, if necessary.
3112 BC_PROG_LBL(BC_INST_JUMP_ZERO):
3115 bc_program_prep(p, &ptr, &num, 0);
3117 cond = !bc_num_cmpZero(num);
3118 bc_vec_pop(&p->results);
3120 BC_PROG_DIRECT_JUMP(BC_INST_JUMP)
3126 BC_PROG_LBL(BC_INST_JUMP):
3129 idx = bc_program_index(code, &ip->idx);
3131 // If a jump is required...
3132 if (inst == BC_INST_JUMP || cond)
3134 // Get the address to jump to.
3135 size_t* addr = bc_vec_item(&func->labels, idx);
3137 // If this fails, then the parser failed to set up the
3138 // labels correctly.
3139 assert(*addr != SIZE_MAX);
3141 // Set the new address.
3145 BC_PROG_JUMP(inst, code, ip);
3149 BC_PROG_LBL(BC_INST_CALL):
3154 bc_program_call(p, code, &ip->idx);
3156 // Because we changed the execution stack and where we are
3157 // executing, we have to update all of this.
3159 ip = bc_vec_top(&p->stack);
3160 func = bc_vec_item(&p->fns, ip->func);
3161 code = func->code.v;
3164 BC_PROG_JUMP(inst, code, ip);
3168 BC_PROG_LBL(BC_INST_INC):
3169 BC_PROG_LBL(BC_INST_DEC):
3172 bc_program_incdec(p, inst);
3173 BC_PROG_JUMP(inst, code, ip);
3177 BC_PROG_LBL(BC_INST_HALT):
3180 vm->status = BC_STATUS_QUIT;
3182 // Just jump out. The jump series will take care of everything.
3185 BC_PROG_JUMP(inst, code, ip);
3189 BC_PROG_LBL(BC_INST_RET):
3190 BC_PROG_LBL(BC_INST_RET0):
3191 BC_PROG_LBL(BC_INST_RET_VOID):
3194 bc_program_return(p, inst);
3196 // Because we changed the execution stack and where we are
3197 // executing, we have to update all of this.
3199 ip = bc_vec_top(&p->stack);
3200 func = bc_vec_item(&p->fns, ip->func);
3201 code = func->code.v;
3204 BC_PROG_JUMP(inst, code, ip);
3206 #endif // BC_ENABLED
3209 BC_PROG_LBL(BC_INST_BOOL_OR):
3210 BC_PROG_LBL(BC_INST_BOOL_AND):
3211 BC_PROG_LBL(BC_INST_REL_EQ):
3212 BC_PROG_LBL(BC_INST_REL_LE):
3213 BC_PROG_LBL(BC_INST_REL_GE):
3214 BC_PROG_LBL(BC_INST_REL_NE):
3215 BC_PROG_LBL(BC_INST_REL_LT):
3216 BC_PROG_LBL(BC_INST_REL_GT):
3219 bc_program_logical(p, inst);
3220 BC_PROG_JUMP(inst, code, ip);
3224 BC_PROG_LBL(BC_INST_READ):
3227 // We want to flush output before
3228 // this in case there is a prompt.
3229 bc_file_flush(&vm->fout, bc_flush_save);
3233 // Because we changed the execution stack and where we are
3234 // executing, we have to update all of this.
3236 ip = bc_vec_top(&p->stack);
3237 func = bc_vec_item(&p->fns, ip->func);
3238 code = func->code.v;
3241 BC_PROG_JUMP(inst, code, ip);
3244 #if BC_ENABLE_EXTRA_MATH
3246 BC_PROG_LBL(BC_INST_RAND):
3250 BC_PROG_JUMP(inst, code, ip);
3252 #endif // BC_ENABLE_EXTRA_MATH
3255 BC_PROG_LBL(BC_INST_MAXIBASE):
3256 BC_PROG_LBL(BC_INST_MAXOBASE):
3257 BC_PROG_LBL(BC_INST_MAXSCALE):
3258 #if BC_ENABLE_EXTRA_MATH
3259 BC_PROG_LBL(BC_INST_MAXRAND):
3260 #endif // BC_ENABLE_EXTRA_MATH
3263 BcBigDig dig = vm->maxes[inst - BC_INST_MAXIBASE];
3264 bc_program_pushBigdig(p, dig, BC_RESULT_TEMP);
3265 BC_PROG_JUMP(inst, code, ip);
3269 BC_PROG_LBL(BC_INST_LINE_LENGTH):
3271 BC_PROG_LBL(BC_INST_GLOBAL_STACKS):
3272 #endif // BC_ENABLED
3274 BC_PROG_LBL(BC_INST_EXTENDED_REGISTERS):
3276 BC_PROG_LBL(BC_INST_LEADING_ZERO):
3279 bc_program_globalSetting(p, inst);
3280 BC_PROG_JUMP(inst, code, ip);
3284 BC_PROG_LBL(BC_INST_VAR):
3287 bc_program_pushVar(p, code, &ip->idx, false, false);
3288 BC_PROG_JUMP(inst, code, ip);
3292 BC_PROG_LBL(BC_INST_ARRAY_ELEM):
3293 BC_PROG_LBL(BC_INST_ARRAY):
3296 bc_program_pushArray(p, code, &ip->idx, inst);
3297 BC_PROG_JUMP(inst, code, ip);
3301 BC_PROG_LBL(BC_INST_IBASE):
3302 BC_PROG_LBL(BC_INST_SCALE):
3303 BC_PROG_LBL(BC_INST_OBASE):
3306 bc_program_pushGlobal(p, inst);
3307 BC_PROG_JUMP(inst, code, ip);
3310 #if BC_ENABLE_EXTRA_MATH
3312 BC_PROG_LBL(BC_INST_SEED):
3315 bc_program_pushSeed(p);
3316 BC_PROG_JUMP(inst, code, ip);
3318 #endif // BC_ENABLE_EXTRA_MATH
3321 BC_PROG_LBL(BC_INST_LENGTH):
3322 BC_PROG_LBL(BC_INST_SCALE_FUNC):
3323 BC_PROG_LBL(BC_INST_SQRT):
3324 BC_PROG_LBL(BC_INST_ABS):
3325 BC_PROG_LBL(BC_INST_IS_NUMBER):
3326 BC_PROG_LBL(BC_INST_IS_STRING):
3327 #if BC_ENABLE_EXTRA_MATH
3328 BC_PROG_LBL(BC_INST_IRAND):
3329 #endif // BC_ENABLE_EXTRA_MATH
3332 bc_program_builtin(p, inst);
3333 BC_PROG_JUMP(inst, code, ip);
3337 BC_PROG_LBL(BC_INST_ASCIIFY):
3340 bc_program_asciify(p);
3342 // Because we changed the execution stack and where we are
3343 // executing, we have to update all of this.
3345 ip = bc_vec_top(&p->stack);
3346 func = bc_vec_item(&p->fns, ip->func);
3347 code = func->code.v;
3350 BC_PROG_JUMP(inst, code, ip);
3354 BC_PROG_LBL(BC_INST_NUM):
3357 bc_program_const(p, code, &ip->idx);
3358 BC_PROG_JUMP(inst, code, ip);
3362 BC_PROG_LBL(BC_INST_ZERO):
3363 BC_PROG_LBL(BC_INST_ONE):
3365 BC_PROG_LBL(BC_INST_LAST):
3366 #endif // BC_ENABLED
3369 r.t = BC_RESULT_ZERO + (inst - BC_INST_ZERO);
3370 bc_vec_push(&p->results, &r);
3371 BC_PROG_JUMP(inst, code, ip);
3375 BC_PROG_LBL(BC_INST_PRINT):
3376 BC_PROG_LBL(BC_INST_PRINT_POP):
3378 BC_PROG_LBL(BC_INST_PRINT_STR):
3379 #endif // BC_ENABLED
3382 bc_program_print(p, inst, 0);
3384 // We want to flush right away to save the output for history,
3385 // if history must preserve it when taking input.
3386 bc_file_flush(&vm->fout, bc_flush_save);
3388 BC_PROG_JUMP(inst, code, ip);
3392 BC_PROG_LBL(BC_INST_STR):
3395 // Set up the result and push.
3396 r.t = BC_RESULT_STR;
3397 bc_num_clear(&r.d.n);
3398 r.d.n.scale = bc_program_index(code, &ip->idx);
3399 bc_vec_push(&p->results, &r);
3400 BC_PROG_JUMP(inst, code, ip);
3404 BC_PROG_LBL(BC_INST_POWER):
3405 BC_PROG_LBL(BC_INST_MULTIPLY):
3406 BC_PROG_LBL(BC_INST_DIVIDE):
3407 BC_PROG_LBL(BC_INST_MODULUS):
3408 BC_PROG_LBL(BC_INST_PLUS):
3409 BC_PROG_LBL(BC_INST_MINUS):
3410 #if BC_ENABLE_EXTRA_MATH
3411 BC_PROG_LBL(BC_INST_PLACES):
3412 BC_PROG_LBL(BC_INST_LSHIFT):
3413 BC_PROG_LBL(BC_INST_RSHIFT):
3414 #endif // BC_ENABLE_EXTRA_MATH
3417 bc_program_op(p, inst);
3418 BC_PROG_JUMP(inst, code, ip);
3422 BC_PROG_LBL(BC_INST_NEG):
3423 BC_PROG_LBL(BC_INST_BOOL_NOT):
3424 #if BC_ENABLE_EXTRA_MATH
3425 BC_PROG_LBL(BC_INST_TRUNC):
3426 #endif // BC_ENABLE_EXTRA_MATH
3429 bc_program_unary(p, inst);
3430 BC_PROG_JUMP(inst, code, ip);
3435 BC_PROG_LBL(BC_INST_ASSIGN_POWER):
3436 BC_PROG_LBL(BC_INST_ASSIGN_MULTIPLY):
3437 BC_PROG_LBL(BC_INST_ASSIGN_DIVIDE):
3438 BC_PROG_LBL(BC_INST_ASSIGN_MODULUS):
3439 BC_PROG_LBL(BC_INST_ASSIGN_PLUS):
3440 BC_PROG_LBL(BC_INST_ASSIGN_MINUS):
3441 #if BC_ENABLE_EXTRA_MATH
3442 BC_PROG_LBL(BC_INST_ASSIGN_PLACES):
3443 BC_PROG_LBL(BC_INST_ASSIGN_LSHIFT):
3444 BC_PROG_LBL(BC_INST_ASSIGN_RSHIFT):
3445 #endif // BC_ENABLE_EXTRA_MATH
3446 BC_PROG_LBL(BC_INST_ASSIGN):
3447 BC_PROG_LBL(BC_INST_ASSIGN_POWER_NO_VAL):
3448 BC_PROG_LBL(BC_INST_ASSIGN_MULTIPLY_NO_VAL):
3449 BC_PROG_LBL(BC_INST_ASSIGN_DIVIDE_NO_VAL):
3450 BC_PROG_LBL(BC_INST_ASSIGN_MODULUS_NO_VAL):
3451 BC_PROG_LBL(BC_INST_ASSIGN_PLUS_NO_VAL):
3452 BC_PROG_LBL(BC_INST_ASSIGN_MINUS_NO_VAL):
3453 #if BC_ENABLE_EXTRA_MATH
3454 BC_PROG_LBL(BC_INST_ASSIGN_PLACES_NO_VAL):
3455 BC_PROG_LBL(BC_INST_ASSIGN_LSHIFT_NO_VAL):
3456 BC_PROG_LBL(BC_INST_ASSIGN_RSHIFT_NO_VAL):
3457 #endif // BC_ENABLE_EXTRA_MATH
3458 #endif // BC_ENABLED
3459 BC_PROG_LBL(BC_INST_ASSIGN_NO_VAL):
3462 bc_program_assign(p, inst);
3463 BC_PROG_JUMP(inst, code, ip);
3467 BC_PROG_LBL(BC_INST_POP):
3470 #ifndef BC_PROG_NO_STACK_CHECK
3471 // dc must do a stack check, but bc does not.
3474 if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
3476 bc_err(BC_ERR_EXEC_STACK);
3479 #endif // BC_PROG_NO_STACK_CHECK
3481 assert(BC_PROG_STACK(&p->results, 1));
3483 bc_vec_pop(&p->results);
3485 BC_PROG_JUMP(inst, code, ip);
3489 BC_PROG_LBL(BC_INST_SWAP):
3495 if (BC_ERR(!BC_PROG_STACK(&p->results, 2)))
3497 bc_err(BC_ERR_EXEC_STACK);
3500 assert(BC_PROG_STACK(&p->results, 2));
3502 // Get the two items.
3503 ptr = bc_vec_item_rev(&p->results, 0);
3504 ptr2 = bc_vec_item_rev(&p->results, 1);
3506 // Swap. It's just easiest to do it this way.
3508 memcpy(&r, ptr, sizeof(BcResult));
3510 memcpy(ptr, ptr2, sizeof(BcResult));
3512 memcpy(ptr2, &r, sizeof(BcResult));
3514 BC_PROG_JUMP(inst, code, ip);
3518 BC_PROG_LBL(BC_INST_MODEXP):
3521 bc_program_modexp(p);
3522 BC_PROG_JUMP(inst, code, ip);
3526 BC_PROG_LBL(BC_INST_DIVMOD):
3529 bc_program_divmod(p);
3530 BC_PROG_JUMP(inst, code, ip);
3534 BC_PROG_LBL(BC_INST_PRINT_STREAM):
3537 bc_program_printStream(p);
3538 BC_PROG_JUMP(inst, code, ip);
3543 BC_PROG_LBL(BC_INST_POP_EXEC):
3546 // If this fails, the dc parser got something wrong.
3547 assert(BC_PROG_STACK(&p->stack, 2));
3549 // Pop the execution stack and tail call stack.
3550 bc_vec_pop(&p->stack);
3551 bc_vec_pop(&p->tail_calls);
3553 // Because we changed the execution stack and where we are
3554 // executing, we have to update all of this.
3556 ip = bc_vec_top(&p->stack);
3557 func = bc_vec_item(&p->fns, ip->func);
3558 code = func->code.v;
3561 BC_PROG_JUMP(inst, code, ip);
3565 BC_PROG_LBL(BC_INST_EXECUTE):
3566 BC_PROG_LBL(BC_INST_EXEC_COND):
3569 cond = (inst == BC_INST_EXEC_COND);
3571 bc_program_execStr(p, code, &ip->idx, cond, func->code.len);
3573 // Because we changed the execution stack and where we are
3574 // executing, we have to update all of this.
3576 ip = bc_vec_top(&p->stack);
3577 func = bc_vec_item(&p->fns, ip->func);
3578 code = func->code.v;
3581 BC_PROG_JUMP(inst, code, ip);
3585 BC_PROG_LBL(BC_INST_PRINT_STACK):
3588 bc_program_printStack(p);
3589 BC_PROG_JUMP(inst, code, ip);
3593 BC_PROG_LBL(BC_INST_CLEAR_STACK):
3596 bc_vec_popAll(&p->results);
3597 BC_PROG_JUMP(inst, code, ip);
3601 BC_PROG_LBL(BC_INST_REG_STACK_LEN):
3604 bc_program_regStackLen(p, code, &ip->idx);
3605 BC_PROG_JUMP(inst, code, ip);
3609 BC_PROG_LBL(BC_INST_STACK_LEN):
3612 bc_program_stackLen(p);
3613 BC_PROG_JUMP(inst, code, ip);
3617 BC_PROG_LBL(BC_INST_DUPLICATE):
3621 if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
3623 bc_err(BC_ERR_EXEC_STACK);
3626 assert(BC_PROG_STACK(&p->results, 1));
3628 // Get the top of the stack.
3629 ptr = bc_vec_top(&p->results);
3634 bc_result_copy(&r, ptr);
3635 bc_vec_push(&p->results, &r);
3639 BC_PROG_JUMP(inst, code, ip);
3643 BC_PROG_LBL(BC_INST_LOAD):
3644 BC_PROG_LBL(BC_INST_PUSH_VAR):
3647 bool copy = (inst == BC_INST_LOAD);
3648 bc_program_pushVar(p, code, &ip->idx, true, copy);
3649 BC_PROG_JUMP(inst, code, ip);
3653 BC_PROG_LBL(BC_INST_PUSH_TO_VAR):
3656 idx = bc_program_index(code, &ip->idx);
3657 bc_program_copyToVar(p, idx, BC_TYPE_VAR);
3658 BC_PROG_JUMP(inst, code, ip);
3662 BC_PROG_LBL(BC_INST_QUIT):
3663 BC_PROG_LBL(BC_INST_NQUIT):
3666 bc_program_nquit(p, inst);
3668 // Because we changed the execution stack and where we are
3669 // executing, we have to update all of this.
3671 ip = bc_vec_top(&p->stack);
3672 func = bc_vec_item(&p->fns, ip->func);
3673 code = func->code.v;
3676 BC_PROG_JUMP(inst, code, ip);
3680 BC_PROG_LBL(BC_INST_EXEC_STACK_LEN):
3683 bc_program_execStackLen(p);
3684 BC_PROG_JUMP(inst, code, ip);
3686 #endif // DC_ENABLED
3688 #if BC_HAS_COMPUTED_GOTO
3690 BC_PROG_LBL(BC_INST_INVALID):
3695 #else // BC_HAS_COMPUTED_GOTO
3699 #if BC_DEBUG && !BC_CLANG
3701 #endif // BC_DEBUG && !BC_CLANG
3703 #endif // BC_HAS_COMPUTED_GOTO
3706 #if BC_HAS_COMPUTED_GOTO
3709 #pragma clang diagnostic warning "-Wgnu-label-as-value"
3713 #pragma GCC diagnostic warning "-Wpedantic"
3716 #else // BC_HAS_COMPUTED_GOTO
3719 // This is to allow me to use a debugger to see the last instruction,
3720 // which will point to which function was the problem. But it's also a
3721 // good smoke test for error handling changes.
3722 assert(jmp_bufs_len == vm->jmp_bufs.len);
3725 #endif // BC_HAS_COMPUTED_GOTO
3731 // This is here just to print a stack trace on interrupts. This is for
3732 // finding infinite loops.
3733 if (BC_SIG_INTERRUPT(vm))
3737 bc_file_putchar(&vm->ferr, bc_flush_none, '\n');
3739 bc_program_printStackTrace(p);
3741 s = bc_file_flushErr(&vm->ferr, bc_flush_err);
3742 if (BC_ERR(s != BC_STATUS_SUCCESS && vm->status == BC_STATUS_SUCCESS))
3744 vm->status = (sig_atomic_t) s;
3748 BC_LONGJMP_CONT(vm);
3752 #if BC_ENABLED && DC_ENABLED
3754 bc_program_printStackDebug(BcProgram* p)
3756 bc_file_puts(&vm->fout, bc_flush_err, "-------------- Stack ----------\n");
3757 bc_program_printStack(p);
3758 bc_file_puts(&vm->fout, bc_flush_err, "-------------- Stack End ------\n");
3762 bc_program_printIndex(const char* restrict code, size_t* restrict bgn)
3764 uchar byte, i, bytes = (uchar) code[(*bgn)++];
3767 for (byte = 1, i = 0; byte && i < bytes; ++i)
3769 byte = (uchar) code[(*bgn)++];
3770 if (byte) val |= ((ulong) byte) << (CHAR_BIT * i);
3773 bc_vm_printf(" (%lu) ", val);
3777 bc_program_printStr(const BcProgram* p, const char* restrict code,
3778 size_t* restrict bgn)
3780 size_t idx = bc_program_index(code, bgn);
3783 s = *((char**) bc_vec_item(p->strs, idx));
3785 bc_vm_printf(" (\"%s\") ", s);
3789 bc_program_printInst(const BcProgram* p, const char* restrict code,
3790 size_t* restrict bgn)
3792 uchar inst = (uchar) code[(*bgn)++];
3794 bc_vm_printf("Inst[%zu]: %s [%lu]; ", *bgn - 1, bc_inst_names[inst],
3795 (unsigned long) inst);
3797 if (inst == BC_INST_VAR || inst == BC_INST_ARRAY_ELEM ||
3798 inst == BC_INST_ARRAY)
3800 bc_program_printIndex(code, bgn);
3802 else if (inst == BC_INST_STR) bc_program_printStr(p, code, bgn);
3803 else if (inst == BC_INST_NUM)
3805 size_t idx = bc_program_index(code, bgn);
3806 BcConst* c = bc_vec_item(p->consts, idx);
3807 bc_vm_printf("(%s)", c->val);
3809 else if (inst == BC_INST_CALL ||
3810 (inst > BC_INST_STR && inst <= BC_INST_JUMP_ZERO))
3812 bc_program_printIndex(code, bgn);
3813 if (inst == BC_INST_CALL) bc_program_printIndex(code, bgn);
3816 bc_vm_putchar('\n', bc_flush_err);
3820 bc_program_code(const BcProgram* p)
3827 for (i = 0; i < p->fns.len; ++i)
3829 ip.idx = ip.len = 0;
3832 f = bc_vec_item(&p->fns, ip.func);
3835 bc_vm_printf("func[%zu]:\n", ip.func);
3836 while (ip.idx < f->code.len)
3838 bc_program_printInst(p, code, &ip.idx);
3840 bc_file_puts(&vm->fout, bc_flush_err, "\n\n");
3843 #endif // BC_ENABLED && DC_ENABLED
3844 #endif // BC_DEBUG_CODE