xref: /freebsd/contrib/bc/src/program.c (revision 79d939126a819f31882343b5733c2073452a4218)
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2021 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,
15  *   this list of conditions and the following disclaimer in the documentation
16  *   and/or other materials provided with the distribution.
17  *
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.
29  *
30  * *****************************************************************************
31  *
32  * Code to execute bc programs.
33  *
34  */
35 
36 #include <assert.h>
37 #include <stdbool.h>
38 #include <string.h>
39 
40 #include <setjmp.h>
41 
42 #include <signal.h>
43 
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  */
57 static inline void
58 bc_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  */
70 static inline void
71 bc_program_type_num(BcResult* r, BcNum* n)
72 {
73 #if BC_ENABLED
74 
75 	// This should have already been taken care of.
76 	assert(r->t != BC_RESULT_VOID);
77 
78 #endif // BC_ENABLED
79 
80 	if (BC_ERR(!BC_PROG_NUM(r, n))) bc_err(BC_ERR_EXEC_TYPE);
81 }
82 
83 #if BC_ENABLED
84 
85 /**
86  * Does a type check.
87  * @param r  The result to check.
88  * @param t  The type that the result should be.
89  */
90 static void
91 bc_program_type_match(BcResult* r, BcType t)
92 {
93 	if (BC_ERR((r->t != BC_RESULT_ARRAY) != (!t))) bc_err(BC_ERR_EXEC_TYPE);
94 }
95 #endif // BC_ENABLED
96 
97 /**
98  * Pulls an index out of a bytecode vector and updates the index into the vector
99  * to point to the spot after the index. For more details on bytecode indices,
100  * see the development manual (manuals/development.md#bytecode-indices).
101  * @param code  The bytecode vector.
102  * @param bgn   An in/out parameter; the index into the vector that will be
103  *              updated.
104  * @return      The index at @a bgn in the bytecode vector.
105  */
106 static size_t
107 bc_program_index(const char* restrict code, size_t* restrict bgn)
108 {
109 	uchar amt = (uchar) code[(*bgn)++], i = 0;
110 	size_t res = 0;
111 
112 	for (; i < amt; ++i, ++(*bgn))
113 	{
114 		size_t temp = ((size_t) ((int) (uchar) code[*bgn]) & UCHAR_MAX);
115 		res |= (temp << (i * CHAR_BIT));
116 	}
117 
118 	return res;
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  */
127 static char*
128 bc_program_string(BcProgram* p, const BcNum* n)
129 {
130 	BcFunc* f = bc_vec_item(&p->fns, n->rdx);
131 	return *((char**) bc_vec_item(&f->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.
140  * @param p  The program.
141  */
142 static void
143 bc_program_prepGlobals(BcProgram* p)
144 {
145 	size_t i;
146 
147 	for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
148 	{
149 		bc_vec_push(p->globals_v + i, p->globals + i);
150 	}
151 
152 #if BC_ENABLE_EXTRA_MATH
153 	bc_rand_push(&p->rng);
154 #endif // BC_ENABLE_EXTRA_MATH
155 }
156 
157 /**
158  * Pops globals stacks on returning from a function, or in the case of reset,
159  * pops all but one item on each global stack.
160  * @param p      The program.
161  * @param reset  True if all but one item on each stack should be popped, false
162  *               otherwise.
163  */
164 static void
165 bc_program_popGlobals(BcProgram* p, bool reset)
166 {
167 	size_t i;
168 
169 	BC_SIG_ASSERT_LOCKED;
170 
171 	for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
172 	{
173 		BcVec* v = p->globals_v + i;
174 		bc_vec_npop(v, reset ? v->len - 1 : 1);
175 		p->globals[i] = BC_PROG_GLOBAL(v);
176 	}
177 
178 #if BC_ENABLE_EXTRA_MATH
179 	bc_rand_pop(&p->rng, reset);
180 #endif // BC_ENABLE_EXTRA_MATH
181 }
182 
183 /**
184  * Derefeneces an array reference and returns a pointer to the real array.
185  * @param p    The program.
186  * @param vec  The reference vector.
187  * @return     A pointer to the desired array.
188  */
189 static BcVec*
190 bc_program_dereference(const BcProgram* p, BcVec* vec)
191 {
192 	BcVec* v;
193 	size_t vidx, nidx, i = 0;
194 
195 	// We want to be sure we have a reference vector.
196 	assert(vec->size == sizeof(uchar));
197 
198 	// Get the index of the vector in arrs, then the index of the original
199 	// referenced vector.
200 	vidx = bc_program_index(vec->v, &i);
201 	nidx = bc_program_index(vec->v, &i);
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 }
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.
218  */
219 static void
220 bc_program_pushBigdig(BcProgram* p, BcBigDig dig, BcResultType type)
221 {
222 	BcResult res;
223 
224 	res.t = type;
225 
226 	BC_SIG_LOCK;
227 
228 	bc_num_createFromBigdig(&res.d.n, dig);
229 	bc_vec_push(&p->results, &res);
230 
231 	BC_SIG_UNLOCK;
232 }
233 
234 size_t
235 bc_program_addString(BcProgram* p, const char* str, size_t fidx)
236 {
237 	BcFunc* f;
238 	char** str_ptr;
239 	BcVec* slabs;
240 
241 	BC_SIG_ASSERT_LOCKED;
242 
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);
246 
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;
251 
252 	*str_ptr = bc_slabvec_strdup(slabs, str);
253 
254 	return f->strs.len - 1;
255 }
256 
257 size_t
258 bc_program_search(BcProgram* p, const char* id, 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.
274 	if (bc_map_insert(map, id, 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 
283 /**
284  * Returns the correct variable or array stack for the type.
285  * @param p     The program.
286  * @param idx   The index of the variable or array in the variable or array
287  *              vector.
288  * @param type  The type of vector to return.
289  * @return      A pointer to the variable or array stack.
290  */
291 static inline BcVec*
292 bc_program_vec(const BcProgram* p, size_t idx, BcType type)
293 {
294 	const BcVec* v = (type == BC_TYPE_VAR) ? &p->vars : &p->arrs;
295 	return bc_vec_item(v, idx);
296 }
297 
298 /**
299  * Returns a pointer to the BcNum corresponding to the result. There is one
300  * case, however, where this returns a pointer to a BcVec: if the type of the
301  * result is array. In that case, the pointer is casted to a pointer to BcNum,
302  * but is never used. The function that calls this expecting an array casts the
303  * pointer back. This function is called a lot and needs to be as fast as
304  * possible.
305  * @param p  The program.
306  * @param r  The result whose number will be returned.
307  * @return   The BcNum corresponding to the result.
308  */
309 static BcNum*
310 bc_program_num(BcProgram* p, BcResult* r)
311 {
312 	BcNum* n;
313 
314 #ifdef _WIN32
315 	// Windows made it an error to not initialize this, so shut it up.
316 	// I don't want to do this on other platforms because this procedure
317 	// is one of the most heavily-used, and eliminating the initialization
318 	// is a performance win.
319 	n = NULL;
320 #endif // _WIN32
321 
322 	switch (r->t)
323 	{
324 		case BC_RESULT_STR:
325 		case BC_RESULT_TEMP:
326 		case BC_RESULT_IBASE:
327 		case BC_RESULT_SCALE:
328 		case BC_RESULT_OBASE:
329 #if BC_ENABLE_EXTRA_MATH
330 		case BC_RESULT_SEED:
331 #endif // BC_ENABLE_EXTRA_MATH
332 		{
333 			n = &r->d.n;
334 			break;
335 		}
336 
337 		case BC_RESULT_VAR:
338 		case BC_RESULT_ARRAY:
339 		case BC_RESULT_ARRAY_ELEM:
340 		{
341 			BcVec* v;
342 			BcType type = (r->t == BC_RESULT_VAR) ? BC_TYPE_VAR : BC_TYPE_ARRAY;
343 
344 			// Get the correct variable or array vector.
345 			v = bc_program_vec(p, r->d.loc.loc, type);
346 
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 
355 				v = bc_vec_top(v);
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.
364 				if (v->size == sizeof(uchar)) v = bc_program_dereference(p, v);
365 #endif // BC_ENABLED
366 
367 				// We want to be sure we got a valid array of numbers.
368 				assert(v->size == sizeof(BcNum));
369 
370 				// The bc spec says that if an element is accessed that does not
371 				// exist, it should be preinitialized to 0. Well, if we access
372 				// an element *way* out there, we have to preinitialize all
373 				// elements between the current last element and the actual
374 				// accessed element.
375 				if (v->len <= idx)
376 				{
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).
385 			// Because bc_vec_top() returns a void*, we don't need to cast.
386 			else n = bc_vec_top(v);
387 
388 			break;
389 		}
390 
391 		case BC_RESULT_ZERO:
392 		{
393 			n = &vm.zero;
394 			break;
395 		}
396 
397 		case BC_RESULT_ONE:
398 		{
399 			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();
410 		}
411 #endif // NDEBUG
412        // Fallthrough
413 		case BC_RESULT_LAST:
414 		{
415 			n = &p->last;
416 			break;
417 		}
418 #endif // BC_ENABLED
419 	}
420 
421 	return n;
422 }
423 
424 /**
425  * Prepares an operand for use.
426  * @param p    The program.
427  * @param r    An out parameter; this is set to the pointer to the result that
428  *             we care about.
429  * @param n    An out parameter; this is set to the pointer to the number that
430  *             we care about.
431  * @param idx  The index of the result from the top of the results stack.
432  */
433 static void
434 bc_program_operand(BcProgram* p, BcResult** r, BcNum** n, size_t idx)
435 {
436 	*r = bc_vec_item_rev(&p->results, idx);
437 
438 #if BC_ENABLED
439 	if (BC_ERR((*r)->t == BC_RESULT_VOID)) bc_err(BC_ERR_EXEC_VOID_VAL);
440 #endif // BC_ENABLED
441 
442 	*n = bc_program_num(p, *r);
443 }
444 
445 /**
446  * Prepares the operands of a binary operator.
447  * @param p    The program.
448  * @param l    An out parameter; this is set to the pointer to the result for
449  *             the left operand.
450  * @param ln   An out parameter; this is set to the pointer to the number for
451  *             the left operand.
452  * @param r    An out parameter; this is set to the pointer to the result for
453  *             the right operand.
454  * @param rn   An out parameter; this is set to the pointer to the number for
455  *             the right operand.
456  * @param idx  The starting index where the operands are in the results stack,
457  *             starting from the top.
458  */
459 static void
460 bc_program_binPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
461                    BcNum** rn, size_t idx)
462 {
463 	BcResultType lt;
464 
465 	assert(p != NULL && l != NULL && ln != NULL && r != NULL && rn != NULL);
466 
467 #ifndef BC_PROG_NO_STACK_CHECK
468 	// Check the stack for dc.
469 	if (BC_IS_DC)
470 	{
471 		if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 2)))
472 		{
473 			bc_err(BC_ERR_EXEC_STACK);
474 		}
475 	}
476 #endif // BC_PROG_NO_STACK_CHECK
477 
478 	assert(BC_PROG_STACK(&p->results, idx + 2));
479 
480 	// Get the operands.
481 	bc_program_operand(p, l, ln, idx + 1);
482 	bc_program_operand(p, r, rn, idx);
483 
484 	lt = (*l)->t;
485 
486 #if BC_ENABLED
487 	// bc_program_operand() checked these for us.
488 	assert(lt != BC_RESULT_VOID && (*r)->t != BC_RESULT_VOID);
489 #endif // BC_ENABLED
490 
491 	// We run this again under these conditions in case any vector has been
492 	// reallocated out from under the BcNums or arrays we had. In other words,
493 	// this is to fix pointer invalidation.
494 	if (lt == (*r)->t && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM))
495 	{
496 		*ln = bc_program_num(p, *l);
497 	}
498 
499 	if (BC_ERR(lt == BC_RESULT_STR)) bc_err(BC_ERR_EXEC_TYPE);
500 }
501 
502 /**
503  * Prepares the operands of a binary operator and type checks them. This is
504  * separate from bc_program_binPrep() because some places want this, others want
505  * bc_program_binPrep().
506  * @param p    The program.
507  * @param l    An out parameter; this is set to the pointer to the result for
508  *             the left operand.
509  * @param ln   An out parameter; this is set to the pointer to the number for
510  *             the left operand.
511  * @param r    An out parameter; this is set to the pointer to the result for
512  *             the right operand.
513  * @param rn   An out parameter; this is set to the pointer to the number for
514  *             the right operand.
515  * @param idx  The starting index where the operands are in the results stack,
516  *             starting from the top.
517  */
518 static void
519 bc_program_binOpPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
520                      BcNum** rn, size_t idx)
521 {
522 	bc_program_binPrep(p, l, ln, r, rn, idx);
523 	bc_program_type_num(*l, *ln);
524 	bc_program_type_num(*r, *rn);
525 }
526 
527 /**
528  * Prepares the operands of an assignment operator.
529  * @param p   The program.
530  * @param l   An out parameter; this is set to the pointer to the result for the
531  *            left operand.
532  * @param ln  An out parameter; this is set to the pointer to the number for the
533  *            left operand.
534  * @param r   An out parameter; this is set to the pointer to the result for the
535  *            right operand.
536  * @param rn  An out parameter; this is set to the pointer to the number for the
537  *            right operand.
538  */
539 static void
540 bc_program_assignPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
541                       BcNum** rn)
542 {
543 	BcResultType lt, min;
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.
558 	bool 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 /**
567  * Prepares a single operand and type checks it. This is separate from
568  * bc_program_operand() because different places want one or the other.
569  * @param p    The program.
570  * @param r    An out parameter; this is set to the pointer to the result that
571  *             we care about.
572  * @param n    An out parameter; this is set to the pointer to the number that
573  *             we care about.
574  * @param idx  The index of the result from the top of the results stack.
575  */
576 static void
577 bc_program_prep(BcProgram* p, BcResult** r, BcNum** n, size_t idx)
578 {
579 	assert(p != NULL && r != NULL && n != NULL);
580 
581 #ifndef BC_PROG_NO_STACK_CHECK
582 	// Check the stack for dc.
583 	if (BC_IS_DC)
584 	{
585 		if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 1)))
586 		{
587 			bc_err(BC_ERR_EXEC_STACK);
588 		}
589 	}
590 #endif // BC_PROG_NO_STACK_CHECK
591 
592 	assert(BC_PROG_STACK(&p->results, idx + 1));
593 
594 	bc_program_operand(p, r, n, idx);
595 
596 	// dc does not allow strings in this case.
597 	bc_program_type_num(*r, *n);
598 }
599 
600 /**
601  * Prepares and returns a clean result for the result of an operation.
602  * @param p  The program.
603  * @return   A clean result.
604  */
605 static BcResult*
606 bc_program_prepResult(BcProgram* p)
607 {
608 	BcResult* res = bc_vec_pushEmpty(&p->results);
609 
610 	bc_result_clear(res);
611 
612 	return res;
613 }
614 
615 /**
616  * Prepares a constant for use. This parses the constant into a number and then
617  * pushes that number onto the results stack.
618  * @param p     The program.
619  * @param code  The bytecode vector that we will pull the index of the constant
620  *              from.
621  * @param bgn   An in/out parameter; marks the start of the index in the
622  *              bytecode vector and will be updated to point to after the index.
623  */
624 static void
625 bc_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);
630 	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 		{
639 			BC_SIG_LOCK;
640 			bc_num_init(&c->num, BC_NUM_RDX(strlen(c->val)));
641 			BC_SIG_UNLOCK;
642 		}
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;
651 
652 	bc_num_createCopy(&r->d.n, &c->num);
653 
654 	BC_SIG_UNLOCK;
655 }
656 
657 /**
658  * Executes a binary operator operation.
659  * @param p     The program.
660  * @param inst  The instruction corresponding to the binary operator to execute.
661  */
662 static void
663 bc_program_op(BcProgram* p, uchar inst)
664 {
665 	BcResult* opd1;
666 	BcResult* opd2;
667 	BcResult* res;
668 	BcNum* n1;
669 	BcNum* n2;
670 	size_t idx = inst - BC_INST_POWER;
671 
672 	res = bc_program_prepResult(p);
673 
674 	bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, 1);
675 
676 	BC_SIG_LOCK;
677 
678 	// Initialize the number with enough space, using the correct
679 	// BcNumBinaryOpReq function. This looks weird because it is executing an
680 	// item of an array. Rest assured that item is a function.
681 	bc_num_init(&res->d.n, bc_program_opReqs[idx](n1, n2, BC_PROG_SCALE(p)));
682 
683 	BC_SIG_UNLOCK;
684 
685 	assert(BC_NUM_RDX_VALID(n1));
686 	assert(BC_NUM_RDX_VALID(n2));
687 
688 	// Run the operation. This also executes an item of an array.
689 	bc_program_ops[idx](n1, n2, &res->d.n, BC_PROG_SCALE(p));
690 
691 	bc_program_retire(p, 1, 2);
692 }
693 
694 /**
695  * Executes a read() or ? command.
696  * @param p  The program.
697  */
698 static void
699 bc_program_read(BcProgram* p)
700 {
701 	BcStatus s;
702 	BcInstPtr ip;
703 	size_t i;
704 	const char* file;
705 	bool is_stdin;
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.
719 	file = vm.file;
720 	is_stdin = vm.is_stdin;
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.
724 	vm.is_stdin = false;
725 
726 	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.
733 		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.
737 		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
741 	else bc_parse_updateFunc(&vm.read_prs, BC_PROG_READ);
742 
743 	BC_SETJMP_LOCKED(exec_err);
744 
745 	BC_SIG_UNLOCK;
746 
747 	// Set up the lexer and the read function.
748 	bc_lex_file(&vm.read_prs.l, bc_program_stdin_name);
749 	bc_vec_popAll(&f->code);
750 
751 	// 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> " : "?> ");
754 
755 	// We should *not* have run into EOF.
756 	if (s == BC_STATUS_EOF) bc_err(BC_ERR_EXEC_READ_EXPR);
757 
758 	// Parse *one* expression, so is_stdin should be false.
759 	bc_parse_text(&vm.read_prs, vm.read_buf.v, false, false);
760 	BC_SIG_LOCK;
761 	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.
766 	if (BC_ERR(vm.read_prs.l.t != BC_LEX_NLINE &&
767 	           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.
786 	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 
801 exec_err:
802 	BC_SIG_MAYLOCK;
803 	vm.is_stdin = is_stdin;
804 	vm.file = file;
805 	BC_LONGJMP_CONT;
806 }
807 
808 #if BC_ENABLE_EXTRA_MATH
809 
810 /**
811  * Execute a rand().
812  * @param p  The program.
813  */
814 static void
815 bc_program_rand(BcProgram* p)
816 {
817 	BcRand rand = bc_rand_int(&p->rng);
818 
819 	bc_program_pushBigdig(p, (BcBigDig) rand, BC_RESULT_TEMP);
820 
821 #ifndef NDEBUG
822 	// This is just to ensure that the generated number is correct. I also use
823 	// braces because I declare every local at the top of the scope.
824 	{
825 		BcResult* r = bc_vec_top(&p->results);
826 		assert(BC_NUM_RDX_VALID_NP(r->d.n));
827 	}
828 #endif // NDEBUG
829 }
830 #endif // BC_ENABLE_EXTRA_MATH
831 
832 /**
833  * Prints a series of characters, without escapes.
834  * @param str  The string (series of characters).
835  */
836 static void
837 bc_program_printChars(const char* str)
838 {
839 	const char* nl;
840 	size_t len = vm.nchars + strlen(str);
841 	sig_atomic_t lock;
842 
843 	BC_SIG_TRYLOCK(lock);
844 
845 	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 
853 	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  */
862 static void
863 bc_program_printString(const char* restrict str)
864 {
865 	size_t i, len = strlen(str);
866 
867 #if DC_ENABLED
868 	// This is to ensure a nul byte is printed for dc's stream operation.
869 	if (!len && BC_IS_DC)
870 	{
871 		bc_vm_putchar('\0', bc_flush_save);
872 		return;
873 	}
874 #endif // DC_ENABLED
875 
876 	// Loop over the characters, processing escapes and printing the rest.
877 	for (i = 0; i < len; ++i)
878 	{
879 		int c = str[i];
880 
881 		// If we have an escape...
882 		if (c == '\\' && i != len - 1)
883 		{
884 			const char* ptr;
885 
886 			// Get the escape character and its companion.
887 			c = str[++i];
888 			ptr = strchr(bc_program_esc_chars, c);
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;
897 					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 			{
906 				// Just print the backslash if there is no companion character.
907 				// The following character will be printed later after the outer
908 				// if statement.
909 				bc_vm_putchar('\\', bc_flush_save);
910 			}
911 		}
912 
913 		bc_vm_putchar(c, bc_flush_save);
914 	}
915 }
916 
917 /**
918  * Executes a print. This function handles all printing except streaming.
919  * @param p     The program.
920  * @param inst  The instruction for the type of print we are doing.
921  * @param idx   The index of the result that we are printing.
922  */
923 static void
924 bc_program_print(BcProgram* p, uchar inst, size_t idx)
925 {
926 	BcResult* r;
927 	char* str;
928 	BcNum* n;
929 	bool pop = (inst != BC_INST_PRINT);
930 
931 	assert(p != NULL);
932 
933 #ifndef BC_PROG_NO_STACK_CHECK
934 	if (BC_IS_DC)
935 	{
936 		if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 1)))
937 		{
938 			bc_err(BC_ERR_EXEC_STACK);
939 		}
940 	}
941 #endif // BC_PROG_NO_STACK_CHECK
942 
943 	assert(BC_PROG_STACK(&p->results, idx + 1));
944 
945 	r = bc_vec_item_rev(&p->results, idx);
946 
947 #if BC_ENABLED
948 	// If we have a void value, that's not necessarily an error. It is if pop is
949 	// true because that means that we are executing a print statement, but
950 	// attempting to do a print on a lone void value is allowed because that's
951 	// exactly how we want void values used.
952 	if (r->t == BC_RESULT_VOID)
953 	{
954 		if (BC_ERR(pop)) bc_err(BC_ERR_EXEC_VOID_VAL);
955 		bc_vec_pop(&p->results);
956 		return;
957 	}
958 #endif // BC_ENABLED
959 
960 	n = bc_program_num(p, r);
961 
962 	// If we have a number...
963 	if (BC_PROG_NUM(r, n))
964 	{
965 #if BC_ENABLED
966 		assert(inst != BC_INST_PRINT_STR);
967 #endif // BC_ENABLED
968 
969 		// Print the number.
970 		bc_num_print(n, BC_PROG_OBASE(p), !pop);
971 
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.
980 		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 
995 	// bc always pops.
996 	if (BC_IS_BC || pop) bc_vec_pop(&p->results);
997 }
998 
999 void
1000 bc_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 }
1005 
1006 void
1007 bc_program_not(BcResult* r, BcNum* n)
1008 {
1009 	if (!bc_num_cmpZero(n)) bc_num_one(&r->d.n);
1010 }
1011 
1012 #if BC_ENABLE_EXTRA_MATH
1013 void
1014 bc_program_trunc(BcResult* r, BcNum* n)
1015 {
1016 	bc_num_copy(&r->d.n, n);
1017 	bc_num_truncate(&r->d.n, n->scale);
1018 }
1019 #endif // BC_ENABLE_EXTRA_MATH
1020 
1021 /**
1022  * Runs a unary operation.
1023  * @param p     The program.
1024  * @param inst  The unary operation.
1025  */
1026 static void
1027 bc_program_unary(BcProgram* p, uchar inst)
1028 {
1029 	BcResult* res;
1030 	BcResult* ptr;
1031 	BcNum* num;
1032 
1033 	res = bc_program_prepResult(p);
1034 
1035 	bc_program_prep(p, &ptr, &num, 1);
1036 
1037 	BC_SIG_LOCK;
1038 
1039 	bc_num_init(&res->d.n, num->len);
1040 
1041 	BC_SIG_UNLOCK;
1042 
1043 	// This calls a function that is in an array.
1044 	bc_program_unarys[inst - BC_INST_NEG](res, num);
1045 	bc_program_retire(p, 1, 1);
1046 }
1047 
1048 /**
1049  * Executes a logical operator.
1050  * @param p     The program.
1051  * @param inst  The operator.
1052  */
1053 static void
1054 bc_program_logical(BcProgram* p, uchar inst)
1055 {
1056 	BcResult* opd1;
1057 	BcResult* opd2;
1058 	BcResult* res;
1059 	BcNum* n1;
1060 	BcNum* n2;
1061 	bool cond = 0;
1062 	ssize_t cmp;
1063 
1064 	res = bc_program_prepResult(p);
1065 
1066 	// All logical operators (except boolean not, which is taken care of by
1067 	// bc_program_unary()), are binary operators.
1068 	bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, 1);
1069 
1070 	// Boolean and and or are not short circuiting. This is why; they can be
1071 	// implemented much easier this way.
1072 	if (inst == BC_INST_BOOL_AND)
1073 	{
1074 		cond = (bc_num_cmpZero(n1) && bc_num_cmpZero(n2));
1075 	}
1076 	else if (inst == BC_INST_BOOL_OR)
1077 	{
1078 		cond = (bc_num_cmpZero(n1) || bc_num_cmpZero(n2));
1079 	}
1080 	else
1081 	{
1082 		// We have a relational operator, so do a comparison.
1083 		cmp = bc_num_cmp(n1, n2);
1084 
1085 		switch (inst)
1086 		{
1087 			case BC_INST_REL_EQ:
1088 			{
1089 				cond = (cmp == 0);
1090 				break;
1091 			}
1092 
1093 			case BC_INST_REL_LE:
1094 			{
1095 				cond = (cmp <= 0);
1096 				break;
1097 			}
1098 
1099 			case BC_INST_REL_GE:
1100 			{
1101 				cond = (cmp >= 0);
1102 				break;
1103 			}
1104 
1105 			case BC_INST_REL_NE:
1106 			{
1107 				cond = (cmp != 0);
1108 				break;
1109 			}
1110 
1111 			case BC_INST_REL_LT:
1112 			{
1113 				cond = (cmp < 0);
1114 				break;
1115 			}
1116 
1117 			case BC_INST_REL_GT:
1118 			{
1119 				cond = (cmp > 0);
1120 				break;
1121 			}
1122 #ifndef NDEBUG
1123 			default:
1124 			{
1125 				// There is a bug if we get here.
1126 				abort();
1127 			}
1128 #endif // NDEBUG
1129 		}
1130 	}
1131 
1132 	BC_SIG_LOCK;
1133 
1134 	bc_num_init(&res->d.n, BC_NUM_DEF_SIZE);
1135 
1136 	BC_SIG_UNLOCK;
1137 
1138 	if (cond) bc_num_one(&res->d.n);
1139 
1140 	bc_program_retire(p, 1, 2);
1141 }
1142 
1143 /**
1144  * Assigns a string to a variable.
1145  * @param p     The program.
1146  * @param num   The location of the string as a BcNum.
1147  * @param v     The stack for the variable.
1148  * @param push  Whether to push the string or not. To push means to move the
1149  *              string from the results stack and push it onto the variable
1150  *              stack.
1151  */
1152 static void
1153 bc_program_assignStr(BcProgram* p, BcNum* num, BcVec* v, bool push)
1154 {
1155 	BcNum* n;
1156 
1157 	assert(BC_PROG_STACK(&p->results, 1 + !push));
1158 	assert(num != NULL && num->num == NULL && num->cap == 0);
1159 
1160 	// If we are not pushing onto the variable stack, we need to replace the
1161 	// top of the variable stack.
1162 	if (!push) bc_vec_pop(v);
1163 
1164 	bc_vec_npop(&p->results, 1 + !push);
1165 
1166 	n = bc_vec_pushEmpty(v);
1167 
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.
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.
1185  */
1186 static void
1187 bc_program_copyToVar(BcProgram* p, size_t idx, BcType t, bool last)
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.
1196 	if (BC_IS_DC)
1197 	{
1198 		if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
1199 	}
1200 #endif
1201 
1202 	assert(BC_PROG_STACK(&p->results, 1));
1203 
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);
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)
1227 	{
1228 		assert(BC_PROG_STR(n));
1229 
1230 		if (BC_ERR(!var)) bc_err(BC_ERR_EXEC_TYPE);
1231 
1232 		bc_program_assignStr(p, n, vec, true);
1233 
1234 		return;
1235 	}
1236 
1237 	BC_SIG_LOCK;
1238 
1239 	// Just create and copy for a normal variable.
1240 	if (var)
1241 	{
1242 		if (BC_PROG_STR(n))
1243 		{
1244 			// NOLINTNEXTLINE
1245 			memcpy(&r.d.n, n, sizeof(BcNum));
1246 		}
1247 		else bc_num_createCopy(&r.d.n, n);
1248 	}
1249 	else
1250 	{
1251 		// If we get here, we are handling an array. This is one place we need
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 		{
1260 			BcVec* parent;
1261 			bool ref, ref_size;
1262 
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 				{
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);
1301 					bc_vec_pushIndex(rv, parent->len - !last - 1);
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);
1310 				bc_vec_pop(&p->results);
1311 
1312 				// We need to return early to avoid executing code that we must
1313 				// not touch.
1314 				BC_SIG_UNLOCK;
1315 				return;
1316 			}
1317 			// If we get here, we have a reference, but we need an array, so
1318 			// dereference the array.
1319 			else if (ref_size && t != BC_TYPE_REF)
1320 			{
1321 				v = bc_program_dereference(p, v);
1322 			}
1323 		}
1324 #endif // BC_ENABLED
1325 
1326 		// If we get here, we need to copy the array because in bc, all
1327 		// arguments are passed by value. Yes, this is expensive.
1328 		bc_array_init(rv, true);
1329 		bc_array_copy(rv, v);
1330 	}
1331 
1332 	// Push the vector onto the array stack and pop the source.
1333 	bc_vec_push(vec, &r.d);
1334 	bc_vec_pop(&p->results);
1335 
1336 	BC_SIG_UNLOCK;
1337 }
1338 
1339 void
1340 bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val)
1341 {
1342 	BcVec* v;
1343 	BcBigDig* ptr;
1344 	BcBigDig* ptr_t;
1345 	BcBigDig max, min;
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;
1354 		max = vm.maxes[BC_PROG_GLOBALS_SCALE];
1355 
1356 		// Get a pointer to the stack and to the current value.
1357 		v = p->globals_v + BC_PROG_GLOBALS_SCALE;
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 		}
1368 		max = vm.maxes[obase + BC_PROG_GLOBALS_IBASE];
1369 
1370 		// Get a pointer to the stack and to the current value.
1371 		v = p->globals_v + BC_PROG_GLOBALS_IBASE + obase;
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 
1388 	// Set the top of the stack and the actual global value.
1389 	ptr = bc_vec_top(v);
1390 	*ptr = val;
1391 	*ptr_t = val;
1392 }
1393 
1394 #if BC_ENABLE_EXTRA_MATH
1395 void
1396 bc_program_assignSeed(BcProgram* p, BcNum* val)
1397 {
1398 	bc_num_rng(val, &p->rng);
1399 }
1400 #endif // BC_ENABLE_EXTRA_MATH
1401 
1402 /**
1403  * Executes an assignment operator.
1404  * @param p     The program.
1405  * @param inst  The assignment operator to execute.
1406  */
1407 static void
1408 bc_program_assign(BcProgram* p, uchar inst)
1409 {
1410 	// The local use_val is true when the assigned value needs to be copied.
1411 	BcResult* left;
1412 	BcResult* right;
1413 	BcResult res;
1414 	BcNum* l;
1415 	BcNum* r;
1416 	bool ob, sc, use_val = BC_INST_USE_VAL(inst);
1417 
1418 	bc_program_assignPrep(p, &left, &l, &right, &r);
1419 
1420 	// Assigning to a string should be impossible simply because of the parse.
1421 	assert(left->t != BC_RESULT_STR);
1422 
1423 	// If we are assigning a string...
1424 	if (right->t == BC_RESULT_STR)
1425 	{
1426 		assert(BC_PROG_STR(r));
1427 
1428 #if BC_ENABLED
1429 		if (inst != BC_INST_ASSIGN && inst != BC_INST_ASSIGN_NO_VAL)
1430 		{
1431 			bc_err(BC_ERR_EXEC_TYPE);
1432 		}
1433 #endif // BC_ENABLED
1434 
1435 		// If we are assigning to an array element...
1436 		if (left->t == BC_RESULT_ARRAY_ELEM)
1437 		{
1438 			BC_SIG_LOCK;
1439 
1440 			// We need to free the number and clear it.
1441 			bc_num_free(l);
1442 
1443 			// NOLINTNEXTLINE
1444 			memcpy(l, r, sizeof(BcNum));
1445 
1446 			// Now we can pop the results.
1447 			bc_vec_npop(&p->results, 2);
1448 
1449 			BC_SIG_UNLOCK;
1450 		}
1451 		else
1452 		{
1453 			// If we get here, we are assigning to a variable, which we can use
1454 			// bc_program_assignStr() for.
1455 			BcVec* v = bc_program_vec(p, left->d.loc.loc, BC_TYPE_VAR);
1456 			bc_program_assignStr(p, r, v, false);
1457 		}
1458 
1459 #if BC_ENABLED
1460 
1461 		// If this is true, the value is going to be used again, so we want to
1462 		// push a temporary with the string.
1463 		if (inst == BC_INST_ASSIGN)
1464 		{
1465 			res.t = BC_RESULT_STR;
1466 			// NOLINTNEXTLINE
1467 			memcpy(&res.d.n, r, sizeof(BcNum));
1468 			bc_vec_push(&p->results, &res);
1469 		}
1470 
1471 #endif // BC_ENABLED
1472 
1473 		// By using bc_program_assignStr(), we short-circuited this, so return.
1474 		return;
1475 	}
1476 
1477 	// If we have a normal assignment operator, not a math one...
1478 	if (BC_INST_IS_ASSIGN(inst))
1479 	{
1480 		// Assigning to a variable that has a string here is fine because there
1481 		// is no math done on it.
1482 
1483 		// BC_RESULT_TEMP, BC_RESULT_IBASE, BC_RESULT_OBASE, BC_RESULT_SCALE,
1484 		// and BC_RESULT_SEED all have temporary copies. Because that's the
1485 		// case, we can free the left and just move the value over. We set the
1486 		// type of right to BC_RESULT_ZERO in order to prevent it from being
1487 		// freed. We also don't have to worry about BC_RESULT_STR because it's
1488 		// take care of above.
1489 		if (right->t == BC_RESULT_TEMP || right->t >= BC_RESULT_IBASE)
1490 		{
1491 			BC_SIG_LOCK;
1492 
1493 			bc_num_free(l);
1494 			// NOLINTNEXTLINE
1495 			memcpy(l, r, sizeof(BcNum));
1496 			right->t = BC_RESULT_ZERO;
1497 
1498 			BC_SIG_UNLOCK;
1499 		}
1500 		// Copy over.
1501 		else bc_num_copy(l, r);
1502 	}
1503 #if BC_ENABLED
1504 	else
1505 	{
1506 		// If we get here, we are doing a math assignment (+=, -=, etc.). So
1507 		// we need to prepare for a binary operator.
1508 		BcBigDig scale = BC_PROG_SCALE(p);
1509 
1510 		// At this point, the left side could still be a string because it could
1511 		// be a variable that has the string. If that's the case, we have a type
1512 		// error.
1513 		if (BC_PROG_STR(l)) bc_err(BC_ERR_EXEC_TYPE);
1514 
1515 		// Get the right type of assignment operator, whether val is used or
1516 		// NO_VAL for performance.
1517 		if (!use_val)
1518 		{
1519 			inst -= (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER);
1520 		}
1521 
1522 		assert(BC_NUM_RDX_VALID(l));
1523 		assert(BC_NUM_RDX_VALID(r));
1524 
1525 		// Run the actual operation. We do not need worry about reallocating l
1526 		// because bc_num_binary() does that behind the scenes for us.
1527 		bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, scale);
1528 	}
1529 #endif // BC_ENABLED
1530 
1531 	ob = (left->t == BC_RESULT_OBASE);
1532 	sc = (left->t == BC_RESULT_SCALE);
1533 
1534 	// The globals need special handling, especially the non-seed ones. The
1535 	// first part of the if statement handles them.
1536 	if (ob || sc || left->t == BC_RESULT_IBASE)
1537 	{
1538 		// Get the actual value.
1539 		BcBigDig val = bc_num_bigdig(l);
1540 
1541 		bc_program_assignBuiltin(p, sc, ob, val);
1542 	}
1543 #if BC_ENABLE_EXTRA_MATH
1544 	// To assign to steed, let bc_num_rng() do its magic.
1545 	else if (left->t == BC_RESULT_SEED) bc_program_assignSeed(p, l);
1546 #endif // BC_ENABLE_EXTRA_MATH
1547 
1548 	BC_SIG_LOCK;
1549 
1550 	// If we needed to use the value, then we need to copy it. Otherwise, we can
1551 	// pop indiscriminately. Oh, and the copy should be a BC_RESULT_TEMP.
1552 	if (use_val)
1553 	{
1554 		bc_num_createCopy(&res.d.n, l);
1555 		res.t = BC_RESULT_TEMP;
1556 		bc_vec_npop(&p->results, 2);
1557 		bc_vec_push(&p->results, &res);
1558 	}
1559 	else bc_vec_npop(&p->results, 2);
1560 
1561 	BC_SIG_UNLOCK;
1562 }
1563 
1564 /**
1565  * Pushes a variable's value onto the results stack.
1566  * @param p     The program.
1567  * @param code  The bytecode vector to pull the variable's index out of.
1568  * @param bgn   An in/out parameter; the start of the index in the bytecode
1569  *              vector, and will be updated to point after the index on return.
1570  * @param pop   True if the variable's value should be popped off its stack.
1571  *              This is only used in dc.
1572  * @param copy  True if the variable's value should be copied to the results
1573  *              stack. This is only used in dc.
1574  */
1575 static void
1576 bc_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);
1581 
1582 	// Set the result appropriately.
1583 	r.t = BC_RESULT_VAR;
1584 	r.d.loc.loc = idx;
1585 
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 	{
1591 		// Get the stack for the variable and the number at the top.
1592 		BcVec* v = bc_program_vec(p, idx, BC_TYPE_VAR);
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 		}
1601 
1602 		assert(BC_PROG_STACK(v, 2 - copy));
1603 
1604 		// If the top of the stack is actually a number...
1605 		if (!BC_PROG_STR(num))
1606 		{
1607 			BC_SIG_LOCK;
1608 
1609 			// Create a copy to go onto the results stack as appropriate.
1610 			r.t = BC_RESULT_TEMP;
1611 			bc_num_createCopy(&r.d.n, num);
1612 
1613 			// If we are not actually copying, we need to do a replace, so pop.
1614 			if (!copy) bc_vec_pop(v);
1615 
1616 			bc_vec_push(&p->results, &r);
1617 
1618 			BC_SIG_UNLOCK;
1619 
1620 			return;
1621 		}
1622 		else
1623 		{
1624 			// Set the string result. We can just memcpy because all of the
1625 			// fields in the num should be cleared.
1626 			// NOLINTNEXTLINE
1627 			memcpy(&r.d.n, num, sizeof(BcNum));
1628 			r.t = BC_RESULT_STR;
1629 		}
1630 
1631 		// If we are not actually copying, we need to do a replace, so pop.
1632 		if (!copy) bc_vec_pop(v);
1633 	}
1634 #endif // DC_ENABLED
1635 
1636 	bc_vec_push(&p->results, &r);
1637 }
1638 
1639 /**
1640  * Pushes an array or an array element onto the results stack.
1641  * @param p     The program.
1642  * @param code  The bytecode vector to pull the variable's index out of.
1643  * @param bgn   An in/out parameter; the start of the index in the bytecode
1644  *              vector, and will be updated to point after the index on return.
1645  * @param inst  The instruction; whether to push an array or an array element.
1646  */
1647 static void
1648 bc_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;
1655 
1656 	// Get the index of the array.
1657 	r.d.loc.loc = bc_program_index(code, bgn);
1658 
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 
1667 	// Grab the top element of the results stack for the array index.
1668 	bc_program_prep(p, &operand, &num, 0);
1669 	temp = bc_num_bigdig(num);
1670 
1671 	// Set the result.
1672 	r.t = BC_RESULT_ARRAY_ELEM;
1673 	r.d.loc.idx = (size_t) temp;
1674 
1675 	BC_SIG_LOCK;
1676 
1677 	// Pop the index and push the element.
1678 	bc_vec_pop(&p->results);
1679 	bc_vec_push(&p->results, &r);
1680 
1681 	BC_SIG_UNLOCK;
1682 }
1683 
1684 #if BC_ENABLED
1685 
1686 /**
1687  * Executes an increment or decrement operator. This only handles postfix
1688  * inc/dec because the parser translates prefix inc/dec into an assignment where
1689  * the value is used.
1690  * @param p     The program.
1691  * @param inst  The instruction; whether to do an increment or decrement.
1692  */
1693 static void
1694 bc_program_incdec(BcProgram* p, uchar inst)
1695 {
1696 	BcResult *ptr, res, copy;
1697 	BcNum* num;
1698 	uchar inst2;
1699 
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 
1708 	BC_SETJMP_LOCKED(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 
1723 	BC_UNSETJMP;
1724 
1725 	BC_SIG_UNLOCK;
1726 
1727 	// No need to free the copy here because we pushed it onto the stack.
1728 	return;
1729 
1730 exit:
1731 	BC_SIG_MAYLOCK;
1732 	bc_num_free(&copy.d.n);
1733 	BC_LONGJMP_CONT;
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
1742  *              vector, and will be updated to point after the indices on
1743  *              return.
1744  */
1745 static void
1746 bc_program_call(BcProgram* p, const char* restrict code, size_t* restrict bgn)
1747 {
1748 	BcInstPtr ip;
1749 	size_t i, nargs;
1750 	BcFunc* f;
1751 	BcVec* v;
1752 	BcAuto* a;
1753 	BcResult* arg;
1754 
1755 	// Pull the number of arguments out of the bytecode vector.
1756 	nargs = bc_program_index(code, bgn);
1757 
1758 	// Set up instruction pointer.
1759 	ip.idx = 0;
1760 	ip.func = bc_program_index(code, bgn);
1761 	f = bc_vec_item(&p->fns, ip.func);
1762 
1763 	// Error checking.
1764 	if (BC_ERR(!f->code.len)) bc_verr(BC_ERR_EXEC_UNDEF_FUNC, f->name);
1765 	if (BC_ERR(nargs != f->nparams))
1766 	{
1767 		bc_verr(BC_ERR_EXEC_PARAMS, f->nparams, nargs);
1768 	}
1769 
1770 	// Set the length of the results stack. We discount the argument, of course.
1771 	ip.len = p->results.len - nargs;
1772 
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 	{
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 
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.
1809 		bc_program_copyToVar(p, a->idx, a->type, last);
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.
1818 		a = bc_vec_item(&f->autos, i);
1819 		v = bc_program_vec(p, a->idx, a->type);
1820 
1821 		// If a variable, just push a 0; otherwise, push an array.
1822 		if (a->type == BC_TYPE_VAR)
1823 		{
1824 			BcNum* n = bc_vec_pushEmpty(v);
1825 			bc_num_init(n, BC_NUM_DEF_SIZE);
1826 		}
1827 		else
1828 		{
1829 			BcVec* v2;
1830 
1831 			assert(a->type == BC_TYPE_ARRAY);
1832 
1833 			v2 = bc_vec_pushEmpty(v);
1834 			bc_array_init(v2, true);
1835 		}
1836 	}
1837 
1838 	// Push the instruction pointer onto the execution stack.
1839 	bc_vec_push(&p->stack, &ip);
1840 
1841 	BC_SIG_UNLOCK;
1842 }
1843 
1844 /**
1845  * Executes a return instruction.
1846  * @param p     The program.
1847  * @param inst  The return instruction. bc can return void, and we need to know
1848  *              if it is.
1849  */
1850 static void
1851 bc_program_return(BcProgram* p, uchar inst)
1852 {
1853 	BcResult* res;
1854 	BcFunc* f;
1855 	BcInstPtr* ip;
1856 	size_t i, nresults;
1857 
1858 	// Get the instruction pointer.
1859 	ip = bc_vec_top(&p->stack);
1860 
1861 	// Get the difference between the actual number of results and the number of
1862 	// results the caller expects.
1863 	nresults = p->results.len - ip->len;
1864 
1865 	// If this isn't true, there was a missing call somewhere.
1866 	assert(BC_PROG_STACK(&p->stack, 2));
1867 
1868 	// If this isn't true, the parser screwed by giving us no value when we
1869 	// expected one, or giving us a value when we expected none.
1870 	assert(BC_PROG_STACK(&p->results, ip->len + (inst == BC_INST_RET)));
1871 
1872 	// Get the function we are returning from.
1873 	f = bc_vec_item(&p->fns, ip->func);
1874 
1875 	res = bc_program_prepResult(p);
1876 
1877 	// If we are returning normally...
1878 	if (inst == BC_INST_RET)
1879 	{
1880 		BcNum* num;
1881 		BcResult* operand;
1882 
1883 		// Prepare and copy the return value.
1884 		bc_program_operand(p, &operand, &num, 1);
1885 
1886 		if (BC_PROG_STR(num))
1887 		{
1888 			// We need to set this because otherwise, it will be a
1889 			// BC_RESULT_TEMP, and BC_RESULT_TEMP needs an actual number to make
1890 			// it easier to do type checking.
1891 			res->t = BC_RESULT_STR;
1892 
1893 			// NOLINTNEXTLINE
1894 			memcpy(&res->d.n, num, sizeof(BcNum));
1895 		}
1896 		else
1897 		{
1898 			BC_SIG_LOCK;
1899 
1900 			bc_num_createCopy(&res->d.n, num);
1901 		}
1902 	}
1903 	// Void is easy; set the result.
1904 	else if (inst == BC_INST_RET_VOID) res->t = BC_RESULT_VOID;
1905 	else
1906 	{
1907 		BC_SIG_LOCK;
1908 
1909 		// If we get here, the instruction is for returning a zero, so do that.
1910 		bc_num_init(&res->d.n, BC_NUM_DEF_SIZE);
1911 	}
1912 
1913 	BC_SIG_MAYUNLOCK;
1914 
1915 	// We need to pop items off of the stacks of arguments and autos as well.
1916 	for (i = 0; i < f->autos.len; ++i)
1917 	{
1918 		BcAuto* a = bc_vec_item(&f->autos, i);
1919 		BcVec* v = bc_program_vec(p, a->idx, a->type);
1920 
1921 		bc_vec_pop(v);
1922 	}
1923 
1924 	BC_SIG_LOCK;
1925 
1926 	// When we retire, pop all of the unused results.
1927 	bc_program_retire(p, 1, nresults);
1928 
1929 	// Pop the globals, if necessary.
1930 	if (BC_G) bc_program_popGlobals(p, false);
1931 
1932 	// Pop the stack. This is what causes the function to actually "return."
1933 	bc_vec_pop(&p->stack);
1934 
1935 	BC_SIG_UNLOCK;
1936 }
1937 #endif // BC_ENABLED
1938 
1939 /**
1940  * Executes a builtin function.
1941  * @param p     The program.
1942  * @param inst  The builtin to execute.
1943  */
1944 static void
1945 bc_program_builtin(BcProgram* p, uchar inst)
1946 {
1947 	BcResult* opd;
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
1956 	assert(inst >= BC_INST_LENGTH && inst <= BC_INST_ABS);
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 	}
1965 #endif // BC_PROG_NO_STACK_CHECK
1966 
1967 	assert(BC_PROG_STACK(&p->results, 1));
1968 
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.
1977 	if (!len && (inst != BC_INST_SCALE_FUNC || BC_IS_BC))
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 #if BC_ENABLE_EXTRA_MATH
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 	}
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 
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 
2033 				assert(v->size == sizeof(BcNum));
2034 
2035 				val = (BcBigDig) v->len;
2036 			}
2037 			else
2038 			{
2039 				// If the item is a string...
2040 				if (!BC_PROG_NUM(opd, num))
2041 				{
2042 					char* str;
2043 
2044 					// Get the string, then get the length.
2045 					str = bc_program_string(p, num);
2046 					val = (BcBigDig) strlen(str);
2047 				}
2048 				else
2049 				{
2050 					// Calculate the length of the number.
2051 					val = (BcBigDig) bc_num_len(num);
2052 				}
2053 			}
2054 		}
2055 		// Like I said; scale() is actually easy. It just also needs the integer
2056 		// conversion that length() does.
2057 		else if (BC_IS_BC || BC_PROG_NUM(opd, num))
2058 		{
2059 			val = (BcBigDig) bc_num_scale(num);
2060 		}
2061 
2062 		BC_SIG_LOCK;
2063 
2064 		// Create the result.
2065 		bc_num_createFromBigdig(&res->d.n, val);
2066 
2067 		BC_SIG_UNLOCK;
2068 	}
2069 
2070 	bc_program_retire(p, 1, 1);
2071 }
2072 
2073 /**
2074  * Executes a divmod.
2075  * @param p  The program.
2076  */
2077 static void
2078 bc_program_divmod(BcProgram* p)
2079 {
2080 	BcResult* opd1;
2081 	BcResult* opd2;
2082 	BcResult* res;
2083 	BcResult* res2;
2084 	BcNum* n1;
2085 	BcNum* n2;
2086 	size_t req;
2087 
2088 	// We grow first to avoid pointer invalidation.
2089 	bc_vec_grow(&p->results, 2);
2090 
2091 	// We don't need to update the pointer because
2092 	// the capacity is enough due to the line above.
2093 	res2 = bc_program_prepResult(p);
2094 	res = bc_program_prepResult(p);
2095 
2096 	// Prepare the operands.
2097 	bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, 2);
2098 
2099 	req = bc_num_mulReq(n1, n2, BC_PROG_SCALE(p));
2100 
2101 	BC_SIG_LOCK;
2102 
2103 	// Initialize the results.
2104 	bc_num_init(&res->d.n, req);
2105 	bc_num_init(&res2->d.n, req);
2106 
2107 	BC_SIG_UNLOCK;
2108 
2109 	// Execute.
2110 	bc_num_divmod(n1, n2, &res2->d.n, &res->d.n, BC_PROG_SCALE(p));
2111 
2112 	bc_program_retire(p, 2, 2);
2113 }
2114 
2115 /**
2116  * Executes modular exponentiation.
2117  * @param p  The program.
2118  */
2119 static void
2120 bc_program_modexp(BcProgram* p)
2121 {
2122 	BcResult* r1;
2123 	BcResult* r2;
2124 	BcResult* r3;
2125 	BcResult* res;
2126 	BcNum* n1;
2127 	BcNum* n2;
2128 	BcNum* n3;
2129 
2130 #if DC_ENABLED
2131 
2132 	// Check the stack.
2133 	if (BC_IS_DC && BC_ERR(!BC_PROG_STACK(&p->results, 3)))
2134 	{
2135 		bc_err(BC_ERR_EXEC_STACK);
2136 	}
2137 
2138 #endif // DC_ENABLED
2139 
2140 	assert(BC_PROG_STACK(&p->results, 3));
2141 
2142 	res = bc_program_prepResult(p);
2143 
2144 	// Get the first operand and typecheck.
2145 	bc_program_operand(p, &r1, &n1, 3);
2146 	bc_program_type_num(r1, n1);
2147 
2148 	// Get the last two operands.
2149 	bc_program_binOpPrep(p, &r2, &n2, &r3, &n3, 1);
2150 
2151 	// Make sure that the values have their pointers updated, if necessary.
2152 	// Only array elements are possible because this is dc.
2153 	if (r1->t == BC_RESULT_ARRAY_ELEM && (r1->t == r2->t || r1->t == r3->t))
2154 	{
2155 		n1 = bc_program_num(p, r1);
2156 	}
2157 
2158 	BC_SIG_LOCK;
2159 
2160 	bc_num_init(&res->d.n, n3->len);
2161 
2162 	BC_SIG_UNLOCK;
2163 
2164 	bc_num_modexp(n1, n2, n3, &res->d.n);
2165 
2166 	bc_program_retire(p, 1, 3);
2167 }
2168 
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  */
2174 static uchar
2175 bc_program_asciifyNum(BcProgram* p, BcNum* n)
2176 {
2177 	BcNum num;
2178 	BcBigDig val;
2179 
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.
2196 	bc_num_truncate(&num, num.scale);
2197 	BC_NUM_NEG_CLR_NP(num);
2198 
2199 	// This is guaranteed to not have a divide by 0
2200 	// because strmb is equal to 256.
2201 	bc_num_mod(&num, &p->strmb, &num, 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.
2206 	val = bc_num_bigdig2(&num);
2207 
2208 num_err:
2209 	BC_SIG_MAYLOCK;
2210 	bc_num_free(&num);
2211 	BC_LONGJMP_CONT;
2212 	return (uchar) val;
2213 }
2214 
2215 /**
2216  * Executes the "asciify" command in dc.
2217  * @param p     The program.
2218  * @param fidx  The index of the current function.
2219  */
2220 static void
2221 bc_program_asciify(BcProgram* p, size_t fidx)
2222 {
2223 	BcResult *r, res;
2224 	BcNum* n;
2225 	char str[2];
2226 	char* str2;
2227 	uchar c;
2228 	size_t idx;
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);
2239 
2240 	// Asciify.
2241 	if (BC_PROG_NUM(r, n)) c = bc_program_asciifyNum(p, n);
2242 	else
2243 	{
2244 		// Get the string itself, then the first character.
2245 		str2 = bc_program_string(p, n);
2246 		c = (uchar) str2[0];
2247 	}
2248 
2249 	// Fill the resulting string.
2250 	str[0] = (char) c;
2251 	str[1] = '\0';
2252 
2253 	// Add the string to the data structures.
2254 	BC_SIG_LOCK;
2255 	idx = bc_program_addString(p, str, fidx);
2256 	BC_SIG_UNLOCK;
2257 
2258 	// Set the result
2259 	res.t = BC_RESULT_STR;
2260 	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);
2267 }
2268 
2269 /**
2270  * Streams a number or a string to stdout.
2271  * @param p  The program.
2272  */
2273 static void
2274 bc_program_printStream(BcProgram* p)
2275 {
2276 	BcResult* r;
2277 	BcNum* n;
2278 
2279 	// Check the stack.
2280 	if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
2281 
2282 	assert(BC_PROG_STACK(&p->results, 1));
2283 
2284 	// Get the top of the results stack.
2285 	bc_program_operand(p, &r, &n, 0);
2286 
2287 	assert(n != NULL);
2288 
2289 	// Stream appropriately.
2290 	if (BC_PROG_NUM(r, n)) bc_num_stream(n);
2291 	else bc_program_printChars(bc_program_string(p, n));
2292 
2293 	// Pop the operand.
2294 	bc_vec_pop(&p->results);
2295 }
2296 
2297 #if DC_ENABLED
2298 
2299 /**
2300  * Gets the length of a register in dc and pushes it onto the results stack.
2301  * @param p     The program.
2302  * @param code  The bytecode vector to pull the register's index out of.
2303  * @param bgn   An in/out parameter; the start of the index in the bytecode
2304  *              vector, and will be updated to point after the index on return.
2305  */
2306 static void
2307 bc_program_regStackLen(BcProgram* p, const char* restrict code,
2308                        size_t* restrict bgn)
2309 {
2310 	size_t idx = bc_program_index(code, bgn);
2311 	BcVec* v = bc_program_vec(p, idx, BC_TYPE_VAR);
2312 
2313 	bc_program_pushBigdig(p, (BcBigDig) v->len, BC_RESULT_TEMP);
2314 }
2315 
2316 /**
2317  * Pushes the length of the results stack onto the results stack.
2318  * @param p  The program.
2319  */
2320 static void
2321 bc_program_stackLen(BcProgram* p)
2322 {
2323 	bc_program_pushBigdig(p, (BcBigDig) p->results.len, BC_RESULT_TEMP);
2324 }
2325 
2326 /**
2327  * Pops a certain number of elements off the execution stack.
2328  * @param p     The program.
2329  * @param inst  The instruction to tell us how many. There is one to pop up to
2330  *              2, and one to pop the amount equal to the number at the top of
2331  *              the results stack.
2332  */
2333 static void
2334 bc_program_nquit(BcProgram* p, uchar inst)
2335 {
2336 	BcResult* opnd;
2337 	BcNum* num;
2338 	BcBigDig val;
2339 	size_t i;
2340 
2341 	// Ensure that the tail calls stack is correct.
2342 	assert(p->stack.len == p->tail_calls.len);
2343 
2344 	// Get the number of executions to pop.
2345 	if (inst == BC_INST_QUIT) val = 2;
2346 	else
2347 	{
2348 		bc_program_prep(p, &opnd, &num, 0);
2349 		val = bc_num_bigdig(num);
2350 
2351 		bc_vec_pop(&p->results);
2352 	}
2353 
2354 	// Loop over the tail call stack and adjust the quit value appropriately.
2355 	for (i = 0; val && i < p->tail_calls.len; ++i)
2356 	{
2357 		// Get the number of tail calls for this one.
2358 		size_t calls = *((size_t*) bc_vec_item_rev(&p->tail_calls, i)) + 1;
2359 
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 	{
2368 		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.
2377 		BC_SIG_LOCK;
2378 		bc_vec_npop(&p->stack, i);
2379 		bc_vec_npop(&p->tail_calls, i);
2380 		BC_SIG_UNLOCK;
2381 	}
2382 }
2383 
2384 /**
2385  * Pushes the depth of the execution stack onto the stack.
2386  * @param p  The program.
2387  */
2388 static void
2389 bc_program_execStackLen(BcProgram* p)
2390 {
2391 	size_t i, amt, len = p->tail_calls.len;
2392 
2393 	amt = len;
2394 
2395 	for (i = 0; i < len; ++i)
2396 	{
2397 		amt += *((size_t*) bc_vec_item(&p->tail_calls, i));
2398 	}
2399 
2400 	bc_program_pushBigdig(p, (BcBigDig) amt, BC_RESULT_TEMP);
2401 }
2402 
2403 /**
2404  *
2405  * @param p     The program.
2406  * @param code  The bytecode vector to pull the register's index out of.
2407  * @param bgn   An in/out parameter; the start of the index in the bytecode
2408  *              vector, and will be updated to point after the index on return.
2409  * @param cond  True if the execution is conditional, false otherwise.
2410  * @param len   The number of bytes in the bytecode vector.
2411  */
2412 static void
2413 bc_program_execStr(BcProgram* p, const char* restrict code,
2414                    size_t* restrict bgn, bool cond, size_t len)
2415 {
2416 	BcResult* r;
2417 	char* str;
2418 	BcFunc* f;
2419 	BcInstPtr ip;
2420 	size_t fidx;
2421 	BcNum* n;
2422 
2423 	assert(p->stack.len == p->tail_calls.len);
2424 
2425 	// Check the stack.
2426 	if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
2427 
2428 	assert(BC_PROG_STACK(&p->results, 1));
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;
2437 		size_t idx, then_idx, else_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;
2449 		BC_SETJMP_LOCKED(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 
2463 		BC_UNSETJMP;
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);
2472 
2473 		if (r->t != BC_RESULT_STR) return;
2474 	}
2475 
2476 	assert(BC_PROG_STR(n));
2477 
2478 	// Get the string.
2479 	str = bc_program_string(p, n);
2480 
2481 	// Get the function index and function.
2482 	BC_SIG_LOCK;
2483 	fidx = bc_program_insertFunc(p, str);
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 
2492 		if (!BC_PARSE_IS_INITED(&vm.read_prs, p))
2493 		{
2494 			bc_parse_init(&vm.read_prs, p, fidx);
2495 
2496 			// Initialize this too because bc_vm_shutdown() expects them to be
2497 			// initialized togther.
2498 			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
2502 		else bc_parse_updateFunc(&vm.read_prs, fidx);
2503 
2504 		bc_lex_file(&vm.read_prs.l, vm.file);
2505 
2506 		BC_SETJMP_LOCKED(err);
2507 
2508 		BC_SIG_UNLOCK;
2509 
2510 		// Parse.
2511 		bc_parse_text(&vm.read_prs, str, false, false);
2512 
2513 		BC_SIG_LOCK;
2514 		vm.expr(&vm.read_prs, BC_PARSE_NOCALL);
2515 
2516 		BC_UNSETJMP;
2517 
2518 		// We can just assert this here because
2519 		// dc should parse everything until EOF.
2520 		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;
2529 
2530 	BC_SIG_LOCK;
2531 
2532 	// Pop the operand.
2533 	bc_vec_pop(&p->results);
2534 
2535 	// Tail call processing. This condition means that there is more on the
2536 	// execution stack, and we are at the end of the bytecode vector, and the
2537 	// last instruction is just a BC_INST_POP_EXEC, which would return.
2538 	if (p->stack.len > 1 && *bgn == len - 1 && code[*bgn] == BC_INST_POP_EXEC)
2539 	{
2540 		size_t* call_ptr = bc_vec_top(&p->tail_calls);
2541 
2542 		// Add one to the tail call.
2543 		*call_ptr += 1;
2544 
2545 		// Pop the execution stack before pushing the new instruction pointer
2546 		// on.
2547 		bc_vec_pop(&p->stack);
2548 	}
2549 	// If not a tail call, just push a new one.
2550 	else bc_vec_push(&p->tail_calls, &ip.idx);
2551 
2552 	// Push the new function onto the execution stack and return.
2553 	bc_vec_push(&p->stack, &ip);
2554 
2555 	BC_SIG_UNLOCK;
2556 
2557 	return;
2558 
2559 err:
2560 	BC_SIG_MAYLOCK;
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 
2567 exit:
2568 	bc_vec_pop(&p->results);
2569 	BC_LONGJMP_CONT;
2570 }
2571 
2572 /**
2573  * Prints every item on the results stack, one per line.
2574  * @param p  The program.
2575  */
2576 static void
2577 bc_program_printStack(BcProgram* p)
2578 {
2579 	size_t idx;
2580 
2581 	for (idx = 0; idx < p->results.len; ++idx)
2582 	{
2583 		bc_program_print(p, BC_INST_PRINT, idx);
2584 	}
2585 }
2586 #endif // DC_ENABLED
2587 
2588 /**
2589  * Pushes the value of a global onto the results stack.
2590  * @param p     The program.
2591  * @param inst  Which global to push, as an instruction.
2592  */
2593 static void
2594 bc_program_pushGlobal(BcProgram* p, uchar inst)
2595 {
2596 	BcResultType t;
2597 
2598 	// Make sure the instruction is valid.
2599 	assert(inst >= BC_INST_IBASE && inst <= BC_INST_SCALE);
2600 
2601 	// Push the global.
2602 	t = inst - BC_INST_IBASE + BC_RESULT_IBASE;
2603 	bc_program_pushBigdig(p, p->globals[inst - BC_INST_IBASE], t);
2604 }
2605 
2606 /**
2607  * Pushes the value of a global setting onto the stack.
2608  * @param p     The program.
2609  * @param inst  Which global setting to push, as an instruction.
2610  */
2611 static void
2612 bc_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 
2619 	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 }
2628 
2629 #if BC_ENABLE_EXTRA_MATH
2630 
2631 /**
2632  * Pushes the value of seed on the stack.
2633  * @param p  The program.
2634  */
2635 static void
2636 bc_program_pushSeed(BcProgram* p)
2637 {
2638 	BcResult* res;
2639 
2640 	res = bc_program_prepResult(p);
2641 	res->t = BC_RESULT_SEED;
2642 
2643 	BC_SIG_LOCK;
2644 
2645 	// We need 2*BC_RAND_NUM_SIZE because of the size of the state.
2646 	bc_num_init(&res->d.n, 2 * BC_RAND_NUM_SIZE);
2647 
2648 	BC_SIG_UNLOCK;
2649 
2650 	bc_num_createFromRNG(&res->d.n, &p->rng);
2651 }
2652 
2653 #endif // BC_ENABLE_EXTRA_MATH
2654 
2655 /**
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  */
2661 static void
2662 bc_program_addFunc(BcProgram* p, BcId* id_ptr)
2663 {
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);
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 
2681 size_t
2682 bc_program_insertFunc(BcProgram* p, const char* name)
2683 {
2684 	BcId* id_ptr;
2685 	bool new;
2686 	size_t idx;
2687 
2688 	BC_SIG_ASSERT_LOCKED;
2689 
2690 	assert(p != NULL && name != NULL);
2691 
2692 	// Insert into the map and get the resulting ID.
2693 	new = bc_map_insert(&p->fn_map, name, p->fns.len, &idx);
2694 	id_ptr = (BcId*) bc_vec_item(&p->fn_map, idx);
2695 	idx = id_ptr->idx;
2696 
2697 	// If the function is new...
2698 	if (new)
2699 	{
2700 		// Add the function to the fns array.
2701 		bc_program_addFunc(p, id_ptr);
2702 	}
2703 #if BC_ENABLED
2704 	// bc has to reset the function because it's about to be redefined.
2705 	else if (BC_IS_BC)
2706 	{
2707 		BcFunc* func = bc_vec_item(&p->fns, idx);
2708 		bc_func_reset(func);
2709 	}
2710 #endif // BC_ENABLED
2711 
2712 	return idx;
2713 }
2714 
2715 #ifndef NDEBUG
2716 void
2717 bc_program_free(BcProgram* p)
2718 {
2719 	size_t i;
2720 
2721 	BC_SIG_ASSERT_LOCKED;
2722 
2723 	assert(p != NULL);
2724 
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 	}
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);
2739 
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 
2748 #if DC_ENABLED
2749 	if (BC_IS_DC) bc_vec_free(&p->tail_calls);
2750 #endif // DC_ENABLED
2751 }
2752 #endif // NDEBUG
2753 
2754 void
2755 bc_program_init(BcProgram* p)
2756 {
2757 	BcInstPtr ip;
2758 	size_t i;
2759 
2760 	BC_SIG_ASSERT_LOCKED;
2761 
2762 	assert(p != NULL);
2763 
2764 	// We want this clear.
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 
2773 		bc_vec_init(p->globals_v + i, sizeof(BcBigDig), BC_DTOR_NONE);
2774 		bc_vec_push(p->globals_v + i, &val);
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 
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
2802 	if (BC_IS_BC) bc_num_init(&p->last, BC_NUM_DEF_SIZE);
2803 #endif // BC_ENABLED
2804 
2805 #ifndef NDEBUG
2806 	bc_vec_init(&p->fns, sizeof(BcFunc), BC_DTOR_FUNC);
2807 #else // NDEBUG
2808 	bc_vec_init(&p->fns, sizeof(BcFunc), BC_DTOR_NONE);
2809 #endif // NDEBUG
2810 	bc_map_init(&p->fn_map);
2811 	bc_program_insertFunc(p, bc_func_main);
2812 	bc_program_insertFunc(p, bc_func_read);
2813 
2814 	bc_vec_init(&p->vars, sizeof(BcVec), BC_DTOR_VEC);
2815 	bc_map_init(&p->var_map);
2816 
2817 	bc_vec_init(&p->arrs, sizeof(BcVec), BC_DTOR_VEC);
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 
2826 	// Make sure the pointers are properly set up.
2827 	bc_program_setVecs(p, (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN));
2828 
2829 	assert(p->consts != NULL && p->strs != NULL);
2830 }
2831 
2832 void
2833 bc_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 
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);
2855 	bc_program_setVecs(p, f);
2856 	// NOLINTNEXTLINE
2857 	memset(ip, 0, sizeof(BcInstPtr));
2858 
2859 	// Write the ready message for a signal, and clear the signal.
2860 	if (vm.sig)
2861 	{
2862 		bc_file_printf(&vm.fout, "%s", bc_program_ready_msg);
2863 		bc_file_flush(&vm.fout, bc_flush_err);
2864 		vm.sig = 0;
2865 	}
2866 }
2867 
2868 void
2869 bc_program_exec(BcProgram* p)
2870 {
2871 	size_t idx;
2872 	BcResult r;
2873 	BcResult* ptr;
2874 	BcInstPtr* ip;
2875 	BcFunc* func;
2876 	char* code;
2877 	bool cond = false;
2878 	uchar inst;
2879 #if BC_ENABLED
2880 	BcNum* num;
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
2889 	BC_PROG_LBLS;
2890 	BC_PROG_LBLS_ASSERT;
2891 
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 
2898 	ip = bc_vec_top(&p->stack);
2899 	func = (BcFunc*) bc_vec_item(&p->fns, ip->func);
2900 	code = func->code.v;
2901 
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
2910 	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 
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
2932 		bc_file_printf(&vm.ferr, "inst: %s\n", bc_inst_names[inst]);
2933 		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,
2942 			// which checks the condition, if necessary.
2943 			// clang-format off
2944 			BC_PROG_LBL(BC_INST_JUMP_ZERO):
2945 			// clang-format on
2946 			{
2947 				bc_program_prep(p, &ptr, &num, 0);
2948 
2949 				cond = !bc_num_cmpZero(num);
2950 				bc_vec_pop(&p->results);
2951 
2952 				BC_PROG_DIRECT_JUMP(BC_INST_JUMP)
2953 			}
2954 			// Fallthrough.
2955 			BC_PROG_FALLTHROUGH
2956 
2957 			// clang-format off
2958 			BC_PROG_LBL(BC_INST_JUMP):
2959 			// clang-format on
2960 			{
2961 				idx = bc_program_index(code, &ip->idx);
2962 
2963 				// If a jump is required...
2964 				if (inst == BC_INST_JUMP || cond)
2965 				{
2966 					// Get the address to jump to.
2967 					size_t* addr = bc_vec_item(&func->labels, idx);
2968 
2969 					// If this fails, then the parser failed to set up the
2970 					// labels correctly.
2971 					assert(*addr != SIZE_MAX);
2972 
2973 					// Set the new address.
2974 					ip->idx = *addr;
2975 				}
2976 
2977 				BC_PROG_JUMP(inst, code, ip);
2978 			}
2979 
2980 			// clang-format off
2981 			BC_PROG_LBL(BC_INST_CALL):
2982 			// clang-format on
2983 			{
2984 				assert(BC_IS_BC);
2985 
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;
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 			{
3013 				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
3022 			BC_PROG_LBL(BC_INST_RET):
3023 			BC_PROG_LBL(BC_INST_RET0):
3024 			BC_PROG_LBL(BC_INST_RET_VOID):
3025 			// clang-format on
3026 			{
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;
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):
3044 			BC_PROG_LBL(BC_INST_BOOL_AND):
3045 			BC_PROG_LBL(BC_INST_REL_EQ):
3046 			BC_PROG_LBL(BC_INST_REL_LE):
3047 			BC_PROG_LBL(BC_INST_REL_GE):
3048 			BC_PROG_LBL(BC_INST_REL_NE):
3049 			BC_PROG_LBL(BC_INST_REL_LT):
3050 			BC_PROG_LBL(BC_INST_REL_GT):
3051 			// clang-format on
3052 			{
3053 				bc_program_logical(p, inst);
3054 				BC_PROG_JUMP(inst, code, ip);
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.
3063 				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;
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):
3082 			// clang-format on
3083 			{
3084 				bc_program_rand(p);
3085 				BC_PROG_JUMP(inst, code, ip);
3086 			}
3087 #endif // BC_ENABLE_EXTRA_MATH
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
3096        // clang-format on
3097 			{
3098 				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):
3107 #endif // BC_ENABLED
3108 			BC_PROG_LBL(BC_INST_LEADING_ZERO):
3109 			// clang-format on
3110 			{
3111 				bc_program_globalSetting(p, inst);
3112 				BC_PROG_JUMP(inst, code, ip);
3113 			}
3114 
3115 			// clang-format off
3116 			BC_PROG_LBL(BC_INST_VAR):
3117 			// clang-format on
3118 			{
3119 				bc_program_pushVar(p, code, &ip->idx, false, false);
3120 				BC_PROG_JUMP(inst, code, ip);
3121 			}
3122 
3123 			// clang-format off
3124 			BC_PROG_LBL(BC_INST_ARRAY_ELEM):
3125 			BC_PROG_LBL(BC_INST_ARRAY):
3126 			// clang-format on
3127 			{
3128 				bc_program_pushArray(p, code, &ip->idx, inst);
3129 				BC_PROG_JUMP(inst, code, ip);
3130 			}
3131 
3132 			// clang-format off
3133 			BC_PROG_LBL(BC_INST_IBASE):
3134 			BC_PROG_LBL(BC_INST_SCALE):
3135 			BC_PROG_LBL(BC_INST_OBASE):
3136 			// clang-format on
3137 			{
3138 				bc_program_pushGlobal(p, inst);
3139 				BC_PROG_JUMP(inst, code, ip);
3140 			}
3141 
3142 #if BC_ENABLE_EXTRA_MATH
3143 			// clang-format off
3144 			BC_PROG_LBL(BC_INST_SEED):
3145 			// clang-format on
3146 			{
3147 				bc_program_pushSeed(p);
3148 				BC_PROG_JUMP(inst, code, ip);
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):
3157 #if BC_ENABLE_EXTRA_MATH
3158 			BC_PROG_LBL(BC_INST_IRAND):
3159 #endif // BC_ENABLE_EXTRA_MATH
3160        // 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 			{
3170 				bc_program_asciify(p, ip->func);
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;
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
3198        // 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
3211        // 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.
3217 				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);
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
3247        // 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
3259        // 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):
3268 			BC_PROG_LBL(BC_INST_ASSIGN_MULTIPLY):
3269 			BC_PROG_LBL(BC_INST_ASSIGN_DIVIDE):
3270 			BC_PROG_LBL(BC_INST_ASSIGN_MODULUS):
3271 			BC_PROG_LBL(BC_INST_ASSIGN_PLUS):
3272 			BC_PROG_LBL(BC_INST_ASSIGN_MINUS):
3273 #if BC_ENABLE_EXTRA_MATH
3274 			BC_PROG_LBL(BC_INST_ASSIGN_PLACES):
3275 			BC_PROG_LBL(BC_INST_ASSIGN_LSHIFT):
3276 			BC_PROG_LBL(BC_INST_ASSIGN_RSHIFT):
3277 #endif // BC_ENABLE_EXTRA_MATH
3278 			BC_PROG_LBL(BC_INST_ASSIGN):
3279 			BC_PROG_LBL(BC_INST_ASSIGN_POWER_NO_VAL):
3280 			BC_PROG_LBL(BC_INST_ASSIGN_MULTIPLY_NO_VAL):
3281 			BC_PROG_LBL(BC_INST_ASSIGN_DIVIDE_NO_VAL):
3282 			BC_PROG_LBL(BC_INST_ASSIGN_MODULUS_NO_VAL):
3283 			BC_PROG_LBL(BC_INST_ASSIGN_PLUS_NO_VAL):
3284 			BC_PROG_LBL(BC_INST_ASSIGN_MINUS_NO_VAL):
3285 #if BC_ENABLE_EXTRA_MATH
3286 			BC_PROG_LBL(BC_INST_ASSIGN_PLACES_NO_VAL):
3287 			BC_PROG_LBL(BC_INST_ASSIGN_LSHIFT_NO_VAL):
3288 			BC_PROG_LBL(BC_INST_ASSIGN_RSHIFT_NO_VAL):
3289 #endif // BC_ENABLE_EXTRA_MATH
3290 #endif // BC_ENABLED
3291 			BC_PROG_LBL(BC_INST_ASSIGN_NO_VAL):
3292 			// clang-format on
3293 			{
3294 				bc_program_assign(p, inst);
3295 				BC_PROG_JUMP(inst, code, ip);
3296 			}
3297 
3298 			// clang-format off
3299 			BC_PROG_LBL(BC_INST_POP):
3300 			// clang-format on
3301 			{
3302 #ifndef BC_PROG_NO_STACK_CHECK
3303 				// dc must do a stack check, but bc does not.
3304 				if (BC_IS_DC)
3305 				{
3306 					if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
3307 					{
3308 						bc_err(BC_ERR_EXEC_STACK);
3309 					}
3310 				}
3311 #endif // BC_PROG_NO_STACK_CHECK
3312 
3313 				assert(BC_PROG_STACK(&p->results, 1));
3314 
3315 				bc_vec_pop(&p->results);
3316 
3317 				BC_PROG_JUMP(inst, code, ip);
3318 			}
3319 
3320 			// clang-format off
3321 			BC_PROG_LBL(BC_INST_SWAP):
3322 			// clang-format on
3323 			{
3324 				BcResult* ptr2;
3325 
3326 				// Check the stack.
3327 				if (BC_ERR(!BC_PROG_STACK(&p->results, 2)))
3328 				{
3329 					bc_err(BC_ERR_EXEC_STACK);
3330 				}
3331 
3332 				assert(BC_PROG_STACK(&p->results, 2));
3333 
3334 				// Get the two items.
3335 				ptr = bc_vec_item_rev(&p->results, 0);
3336 				ptr2 = bc_vec_item_rev(&p->results, 1);
3337 
3338 				// Swap. It's just easiest to do it this way.
3339 				// NOLINTNEXTLINE
3340 				memcpy(&r, ptr, sizeof(BcResult));
3341 				// NOLINTNEXTLINE
3342 				memcpy(ptr, ptr2, sizeof(BcResult));
3343 				// NOLINTNEXTLINE
3344 				memcpy(ptr2, &r, sizeof(BcResult));
3345 
3346 				BC_PROG_JUMP(inst, code, ip);
3347 			}
3348 
3349 			// clang-format off
3350 			BC_PROG_LBL(BC_INST_MODEXP):
3351 			// clang-format on
3352 			{
3353 				bc_program_modexp(p);
3354 				BC_PROG_JUMP(inst, code, ip);
3355 			}
3356 
3357 			// clang-format off
3358 			BC_PROG_LBL(BC_INST_DIVMOD):
3359 			// clang-format on
3360 			{
3361 				bc_program_divmod(p);
3362 				BC_PROG_JUMP(inst, code, ip);
3363 			}
3364 
3365 			// clang-format off
3366 			BC_PROG_LBL(BC_INST_PRINT_STREAM):
3367 			// clang-format on
3368 			{
3369 				bc_program_printStream(p);
3370 				BC_PROG_JUMP(inst, code, ip);
3371 			}
3372 
3373 #if DC_ENABLED
3374 			// clang-format off
3375 			BC_PROG_LBL(BC_INST_POP_EXEC):
3376 			// clang-format on
3377 			{
3378 				// If this fails, the dc parser got something wrong.
3379 				assert(BC_PROG_STACK(&p->stack, 2));
3380 
3381 				// Pop the execution stack and tail call stack.
3382 				bc_vec_pop(&p->stack);
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;
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):
3400 			// clang-format on
3401 			{
3402 				cond = (inst == BC_INST_EXEC_COND);
3403 
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;
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
3421 			{
3422 				bc_program_printStack(p);
3423 				BC_PROG_JUMP(inst, code, ip);
3424 			}
3425 
3426 			// clang-format off
3427 			BC_PROG_LBL(BC_INST_CLEAR_STACK):
3428 			// clang-format on
3429 			{
3430 				bc_vec_popAll(&p->results);
3431 				BC_PROG_JUMP(inst, code, ip);
3432 			}
3433 
3434 			// clang-format off
3435 			BC_PROG_LBL(BC_INST_REG_STACK_LEN):
3436 			// clang-format on
3437 			{
3438 				bc_program_regStackLen(p, code, &ip->idx);
3439 				BC_PROG_JUMP(inst, code, ip);
3440 			}
3441 
3442 			// clang-format off
3443 			BC_PROG_LBL(BC_INST_STACK_LEN):
3444 			// clang-format on
3445 			{
3446 				bc_program_stackLen(p);
3447 				BC_PROG_JUMP(inst, code, ip);
3448 			}
3449 
3450 			// clang-format off
3451 			BC_PROG_LBL(BC_INST_DUPLICATE):
3452 			// clang-format on
3453 			{
3454 				// Check the stack.
3455 				if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
3456 				{
3457 					bc_err(BC_ERR_EXEC_STACK);
3458 				}
3459 
3460 				assert(BC_PROG_STACK(&p->results, 1));
3461 
3462 				// Get the top of the stack.
3463 				ptr = bc_vec_top(&p->results);
3464 
3465 				BC_SIG_LOCK;
3466 
3467 				// Copy and push.
3468 				bc_result_copy(&r, ptr);
3469 				bc_vec_push(&p->results, &r);
3470 
3471 				BC_SIG_UNLOCK;
3472 
3473 				BC_PROG_JUMP(inst, code, ip);
3474 			}
3475 
3476 			// clang-format off
3477 			BC_PROG_LBL(BC_INST_LOAD):
3478 			BC_PROG_LBL(BC_INST_PUSH_VAR):
3479 			// clang-format on
3480 			{
3481 				bool copy = (inst == BC_INST_LOAD);
3482 				bc_program_pushVar(p, code, &ip->idx, true, copy);
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);
3491 				bc_program_copyToVar(p, idx, BC_TYPE_VAR, true);
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;
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 			{
3528 				return;
3529 			}
3530 #else // BC_HAS_COMPUTED_GOTO
3531 			default:
3532 			{
3533 				BC_UNREACHABLE
3534 #ifndef NDEBUG
3535 				abort();
3536 #endif // NDEBUG
3537 			}
3538 #endif // BC_HAS_COMPUTED_GOTO
3539 		}
3540 
3541 #if !BC_HAS_COMPUTED_GOTO
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.
3546 		assert(jmp_bufs_len == vm.jmp_bufs.len);
3547 #endif // NDEBUG
3548 #endif // !BC_HAS_COMPUTED_GOTO
3549 	}
3550 }
3551 
3552 #if BC_DEBUG_CODE
3553 #if BC_ENABLED && DC_ENABLED
3554 void
3555 bc_program_printStackDebug(BcProgram* p)
3556 {
3557 	bc_file_puts(&vm.fout, bc_flush_err, "-------------- Stack ----------\n");
3558 	bc_program_printStack(p);
3559 	bc_file_puts(&vm.fout, bc_flush_err, "-------------- Stack End ------\n");
3560 }
3561 
3562 static void
3563 bc_program_printIndex(const char* restrict code, size_t* restrict bgn)
3564 {
3565 	uchar byte, i, bytes = (uchar) code[(*bgn)++];
3566 	ulong val = 0;
3567 
3568 	for (byte = 1, i = 0; byte && i < bytes; ++i)
3569 	{
3570 		byte = (uchar) code[(*bgn)++];
3571 		if (byte) val |= ((ulong) byte) << (CHAR_BIT * i);
3572 	}
3573 
3574 	bc_vm_printf(" (%lu) ", val);
3575 }
3576 
3577 static void
3578 bc_program_printStr(const BcProgram* p, const char* restrict code,
3579                     size_t* restrict bgn)
3580 {
3581 	size_t idx = bc_program_index(code, bgn);
3582 	char* s;
3583 
3584 	s = *((char**) bc_vec_item(p->strs, idx));
3585 
3586 	bc_vm_printf(" (\"%s\") ", s);
3587 }
3588 
3589 void
3590 bc_program_printInst(const BcProgram* p, const char* restrict code,
3591                      size_t* restrict bgn)
3592 {
3593 	uchar inst = (uchar) code[(*bgn)++];
3594 
3595 	bc_vm_printf("Inst[%zu]: %s [%lu]; ", *bgn - 1, bc_inst_names[inst],
3596 	             (unsigned long) inst);
3597 
3598 	if (inst == BC_INST_VAR || inst == BC_INST_ARRAY_ELEM ||
3599 	    inst == BC_INST_ARRAY)
3600 	{
3601 		bc_program_printIndex(code, bgn);
3602 	}
3603 	else if (inst == BC_INST_STR) bc_program_printStr(p, code, bgn);
3604 	else if (inst == BC_INST_NUM)
3605 	{
3606 		size_t idx = bc_program_index(code, bgn);
3607 		BcConst* c = bc_vec_item(p->consts, idx);
3608 		bc_vm_printf("(%s)", c->val);
3609 	}
3610 	else if (inst == BC_INST_CALL ||
3611 	         (inst > BC_INST_STR && inst <= BC_INST_JUMP_ZERO))
3612 	{
3613 		bc_program_printIndex(code, bgn);
3614 		if (inst == BC_INST_CALL) bc_program_printIndex(code, bgn);
3615 	}
3616 
3617 	bc_vm_putchar('\n', bc_flush_err);
3618 }
3619 
3620 void
3621 bc_program_code(const BcProgram* p)
3622 {
3623 	BcFunc* f;
3624 	char* code;
3625 	BcInstPtr ip;
3626 	size_t i;
3627 
3628 	for (i = 0; i < p->fns.len; ++i)
3629 	{
3630 		ip.idx = ip.len = 0;
3631 		ip.func = i;
3632 
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 		}
3641 		bc_file_puts(&vm.fout, bc_flush_err, "\n\n");
3642 	}
3643 }
3644 #endif // BC_ENABLED && DC_ENABLED
3645 #endif // BC_DEBUG_CODE
3646