]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bc/src/program.c
vendor/bc: upgrade to version 6.7.2
[FreeBSD/FreeBSD.git] / contrib / bc / src / program.c
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2023 Gavin D. Howard and contributors.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * * Redistributions of source code must retain the above copyright notice, this
12  *   list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright notice,
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  * Does a type check for something that expects a number.
53  * @param r  The result that will be checked.
54  * @param n  The result's number.
55  */
56 static inline void
57 bc_program_type_num(BcResult* r, BcNum* n)
58 {
59 #if BC_ENABLED
60
61         // This should have already been taken care of.
62         assert(r->t != BC_RESULT_VOID);
63
64 #endif // BC_ENABLED
65
66         if (BC_ERR(!BC_PROG_NUM(r, n))) bc_err(BC_ERR_EXEC_TYPE);
67 }
68
69 #if BC_ENABLED
70
71 /**
72  * Does a type check.
73  * @param r  The result to check.
74  * @param t  The type that the result should be.
75  */
76 static void
77 bc_program_type_match(BcResult* r, BcType t)
78 {
79         if (BC_ERR((r->t != BC_RESULT_ARRAY) != (!t))) bc_err(BC_ERR_EXEC_TYPE);
80 }
81 #endif // BC_ENABLED
82
83 /**
84  * Pulls an index out of a bytecode vector and updates the index into the vector
85  * to point to the spot after the index. For more details on bytecode indices,
86  * see the development manual (manuals/development.md#bytecode-indices).
87  * @param code  The bytecode vector.
88  * @param bgn   An in/out parameter; the index into the vector that will be
89  *              updated.
90  * @return      The index at @a bgn in the bytecode vector.
91  */
92 static size_t
93 bc_program_index(const char* restrict code, size_t* restrict bgn)
94 {
95         uchar amt = (uchar) code[(*bgn)++], i = 0;
96         size_t res = 0;
97
98         for (; i < amt; ++i, ++(*bgn))
99         {
100                 size_t temp = ((size_t) ((int) (uchar) code[*bgn]) & UCHAR_MAX);
101                 res |= (temp << (i * CHAR_BIT));
102         }
103
104         return res;
105 }
106
107 /**
108  * Returns a string from a result and its number.
109  * @param p  The program.
110  * @param n  The number tied to the result.
111  * @return   The string corresponding to the result and number.
112  */
113 static inline char*
114 bc_program_string(BcProgram* p, const BcNum* n)
115 {
116         return *((char**) bc_vec_item(&p->strs, n->scale));
117 }
118
119 #if BC_ENABLED
120
121 /**
122  * Prepares the globals for a function call. This is only called when global
123  * stacks are on because it pushes a copy of the current globals onto each of
124  * their respective stacks.
125  * @param p  The program.
126  */
127 static void
128 bc_program_prepGlobals(BcProgram* p)
129 {
130         size_t i;
131
132         for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
133         {
134                 bc_vec_push(p->globals_v + i, p->globals + i);
135         }
136
137 #if BC_ENABLE_EXTRA_MATH
138         bc_rand_push(&p->rng);
139 #endif // BC_ENABLE_EXTRA_MATH
140 }
141
142 /**
143  * Pops globals stacks on returning from a function, or in the case of reset,
144  * pops all but one item on each global stack.
145  * @param p      The program.
146  * @param reset  True if all but one item on each stack should be popped, false
147  *               otherwise.
148  */
149 static void
150 bc_program_popGlobals(BcProgram* p, bool reset)
151 {
152         size_t i;
153
154         BC_SIG_ASSERT_LOCKED;
155
156         for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
157         {
158                 BcVec* v = p->globals_v + i;
159                 bc_vec_npop(v, reset ? v->len - 1 : 1);
160                 p->globals[i] = BC_PROG_GLOBAL(v);
161         }
162
163 #if BC_ENABLE_EXTRA_MATH
164         bc_rand_pop(&p->rng, reset);
165 #endif // BC_ENABLE_EXTRA_MATH
166 }
167
168 /**
169  * Derefeneces an array reference and returns a pointer to the real array.
170  * @param p    The program.
171  * @param vec  The reference vector.
172  * @return     A pointer to the desired array.
173  */
174 static BcVec*
175 bc_program_dereference(const BcProgram* p, BcVec* vec)
176 {
177         BcVec* v;
178         size_t vidx, nidx, i = 0;
179
180         // We want to be sure we have a reference vector.
181         assert(vec->size == sizeof(uchar));
182
183         // Get the index of the vector in arrs, then the index of the original
184         // referenced vector.
185         vidx = bc_program_index(vec->v, &i);
186         nidx = bc_program_index(vec->v, &i);
187
188         v = bc_vec_item(bc_vec_item(&p->arrs, vidx), nidx);
189
190         // We want to be sure we do *not* have a reference vector.
191         assert(v->size != sizeof(uchar));
192
193         return v;
194 }
195
196 #endif // BC_ENABLED
197
198 /**
199  * Creates a BcNum from a BcBigDig and pushes onto the results stack. This is a
200  * convenience function.
201  * @param p     The program.
202  * @param dig   The BcBigDig to push onto the results stack.
203  * @param type  The type that the pushed result should be.
204  */
205 static void
206 bc_program_pushBigdig(BcProgram* p, BcBigDig dig, BcResultType type)
207 {
208         BcResult res;
209
210         res.t = type;
211
212         BC_SIG_LOCK;
213
214         bc_num_createFromBigdig(&res.d.n, dig);
215         bc_vec_push(&p->results, &res);
216
217         BC_SIG_UNLOCK;
218 }
219
220 size_t
221 bc_program_addString(BcProgram* p, const char* str)
222 {
223         size_t idx;
224
225         BC_SIG_ASSERT_LOCKED;
226
227         if (bc_map_insert(&p->str_map, str, p->strs.len, &idx))
228         {
229                 char** str_ptr;
230                 BcId* id = bc_vec_item(&p->str_map, idx);
231
232                 // Get the index.
233                 idx = id->idx;
234
235                 // Push an empty string on the proper vector.
236                 str_ptr = bc_vec_pushEmpty(&p->strs);
237
238                 // We reuse the string in the ID (allocated by bc_map_insert()), because
239                 // why not?
240                 *str_ptr = id->name;
241         }
242         else
243         {
244                 BcId* id = bc_vec_item(&p->str_map, idx);
245                 idx = id->idx;
246         }
247
248         return idx;
249 }
250
251 size_t
252 bc_program_search(BcProgram* p, const char* name, bool var)
253 {
254         BcVec* v;
255         BcVec* map;
256         size_t i;
257
258         BC_SIG_ASSERT_LOCKED;
259
260         // Grab the right vector and map.
261         v = var ? &p->vars : &p->arrs;
262         map = var ? &p->var_map : &p->arr_map;
263
264         // We do an insert because the variable might not exist yet. This is because
265         // the parser calls this function. If the insert succeeds, we create a stack
266         // for the variable/array. But regardless, bc_map_insert() gives us the
267         // index of the item in i.
268         if (bc_map_insert(map, name, v->len, &i))
269         {
270                 BcVec* temp = bc_vec_pushEmpty(v);
271                 bc_array_init(temp, var);
272         }
273
274         return ((BcId*) bc_vec_item(map, i))->idx;
275 }
276
277 /**
278  * Returns the correct variable or array stack for the type.
279  * @param p     The program.
280  * @param idx   The index of the variable or array in the variable or array
281  *              vector.
282  * @param type  The type of vector to return.
283  * @return      A pointer to the variable or array stack.
284  */
285 static inline BcVec*
286 bc_program_vec(const BcProgram* p, size_t idx, BcType type)
287 {
288         const BcVec* v = (type == BC_TYPE_VAR) ? &p->vars : &p->arrs;
289         return bc_vec_item(v, idx);
290 }
291
292 /**
293  * Returns a pointer to the BcNum corresponding to the result. There is one
294  * case, however, where this returns a pointer to a BcVec: if the type of the
295  * result is array. In that case, the pointer is casted to a pointer to BcNum,
296  * but is never used. The function that calls this expecting an array casts the
297  * pointer back. This function is called a lot and needs to be as fast as
298  * possible.
299  * @param p  The program.
300  * @param r  The result whose number will be returned.
301  * @return   The BcNum corresponding to the result.
302  */
303 static BcNum*
304 bc_program_num(BcProgram* p, BcResult* r)
305 {
306         BcNum* n;
307
308 #ifdef _WIN32
309         // Windows made it an error to not initialize this, so shut it up.
310         // I don't want to do this on other platforms because this procedure
311         // is one of the most heavily-used, and eliminating the initialization
312         // is a performance win.
313         n = NULL;
314 #endif // _WIN32
315
316         switch (r->t)
317         {
318                 case BC_RESULT_STR:
319                 case BC_RESULT_TEMP:
320                 case BC_RESULT_IBASE:
321                 case BC_RESULT_SCALE:
322                 case BC_RESULT_OBASE:
323 #if BC_ENABLE_EXTRA_MATH
324                 case BC_RESULT_SEED:
325 #endif // BC_ENABLE_EXTRA_MATH
326                 {
327                         n = &r->d.n;
328                         break;
329                 }
330
331                 case BC_RESULT_VAR:
332                 case BC_RESULT_ARRAY:
333                 case BC_RESULT_ARRAY_ELEM:
334                 {
335                         BcVec* v;
336                         BcType type = (r->t == BC_RESULT_VAR) ? BC_TYPE_VAR : BC_TYPE_ARRAY;
337
338                         // Get the correct variable or array vector.
339                         v = bc_program_vec(p, r->d.loc.loc, type);
340
341                         // Surprisingly enough, the hard case is *not* returning an array;
342                         // it's returning an array element. This is because we have to dig
343                         // deeper to get *to* the element. That's what the code inside this
344                         // if statement does.
345                         if (r->t == BC_RESULT_ARRAY_ELEM)
346                         {
347                                 size_t idx = r->d.loc.idx;
348
349                                 v = bc_vec_item(v, r->d.loc.stack_idx);
350
351 #if BC_ENABLED
352                                 // If this is true, we have a reference vector, so dereference
353                                 // it. The reason we don't need to worry about it for returning
354                                 // a straight array is because we only care about references
355                                 // when we access elements of an array that is a reference. That
356                                 // is this code, so in essence, this line takes care of arrays
357                                 // as well.
358                                 if (v->size == sizeof(uchar)) v = bc_program_dereference(p, v);
359 #endif // BC_ENABLED
360
361                                 // We want to be sure we got a valid array of numbers.
362                                 assert(v->size == sizeof(BcNum));
363
364                                 // The bc spec says that if an element is accessed that does not
365                                 // exist, it should be preinitialized to 0. Well, if we access
366                                 // an element *way* out there, we have to preinitialize all
367                                 // elements between the current last element and the actual
368                                 // accessed element.
369                                 if (v->len <= idx)
370                                 {
371                                         BC_SIG_LOCK;
372                                         bc_array_expand(v, bc_vm_growSize(idx, 1));
373                                         BC_SIG_UNLOCK;
374                                 }
375
376                                 n = bc_vec_item(v, idx);
377                         }
378                         // This is either a number (for a var) or an array (for an array).
379                         // Because bc_vec_top() and bc_vec_item() return a void*, we don't
380                         // need to cast.
381                         else
382                         {
383 #if BC_ENABLED
384                                 if (BC_IS_BC)
385                                 {
386                                         n = bc_vec_item(v, r->d.loc.stack_idx);
387                                 }
388                                 else
389 #endif // BC_ENABLED
390                                 {
391                                         n = bc_vec_top(v);
392                                 }
393                         }
394
395                         break;
396                 }
397
398                 case BC_RESULT_ZERO:
399                 {
400                         n = &vm->zero;
401                         break;
402                 }
403
404                 case BC_RESULT_ONE:
405                 {
406                         n = &vm->one;
407                         break;
408                 }
409
410 #if BC_ENABLED
411                 // We should never get here; this is taken care of earlier because a
412                 // result is expected.
413                 case BC_RESULT_VOID:
414 #if BC_DEBUG
415                 {
416                         abort();
417                         // Fallthrough
418                 }
419 #endif // BC_DEBUG
420                 case BC_RESULT_LAST:
421                 {
422                         n = &p->last;
423                         break;
424                 }
425 #endif // BC_ENABLED
426
427 #if BC_GCC
428                 // This is here in GCC to quiet the "maybe-uninitialized" warning.
429                 default:
430                 {
431                         abort();
432                 }
433 #endif // BC_GCC
434         }
435
436         return n;
437 }
438
439 /**
440  * Prepares an operand for use.
441  * @param p    The program.
442  * @param r    An out parameter; this is set to the pointer to the result that
443  *             we care about.
444  * @param n    An out parameter; this is set to the pointer to the number that
445  *             we care about.
446  * @param idx  The index of the result from the top of the results stack.
447  */
448 static void
449 bc_program_operand(BcProgram* p, BcResult** r, BcNum** n, size_t idx)
450 {
451         *r = bc_vec_item_rev(&p->results, idx);
452
453 #if BC_ENABLED
454         if (BC_ERR((*r)->t == BC_RESULT_VOID)) bc_err(BC_ERR_EXEC_VOID_VAL);
455 #endif // BC_ENABLED
456
457         *n = bc_program_num(p, *r);
458 }
459
460 /**
461  * Prepares the operands of a binary operator.
462  * @param p    The program.
463  * @param l    An out parameter; this is set to the pointer to the result for
464  *             the left operand.
465  * @param ln   An out parameter; this is set to the pointer to the number for
466  *             the left operand.
467  * @param r    An out parameter; this is set to the pointer to the result for
468  *             the right operand.
469  * @param rn   An out parameter; this is set to the pointer to the number for
470  *             the right operand.
471  * @param idx  The starting index where the operands are in the results stack,
472  *             starting from the top.
473  */
474 static void
475 bc_program_binPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
476                    BcNum** rn, size_t idx)
477 {
478         BcResultType lt;
479
480         assert(p != NULL && l != NULL && ln != NULL && r != NULL && rn != NULL);
481
482 #ifndef BC_PROG_NO_STACK_CHECK
483         // Check the stack for dc.
484         if (BC_IS_DC)
485         {
486                 if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 2)))
487                 {
488                         bc_err(BC_ERR_EXEC_STACK);
489                 }
490         }
491 #endif // BC_PROG_NO_STACK_CHECK
492
493         assert(BC_PROG_STACK(&p->results, idx + 2));
494
495         // Get the operands.
496         bc_program_operand(p, l, ln, idx + 1);
497         bc_program_operand(p, r, rn, idx);
498
499         lt = (*l)->t;
500
501 #if BC_ENABLED
502         // bc_program_operand() checked these for us.
503         assert(lt != BC_RESULT_VOID && (*r)->t != BC_RESULT_VOID);
504 #endif // BC_ENABLED
505
506         // We run this again under these conditions in case any vector has been
507         // reallocated out from under the BcNums or arrays we had. In other words,
508         // this is to fix pointer invalidation.
509         if (lt == (*r)->t && (lt == BC_RESULT_VAR || lt == BC_RESULT_ARRAY_ELEM))
510         {
511                 *ln = bc_program_num(p, *l);
512         }
513
514         if (BC_ERR(lt == BC_RESULT_STR)) bc_err(BC_ERR_EXEC_TYPE);
515 }
516
517 /**
518  * Prepares the operands of a binary operator and type checks them. This is
519  * separate from bc_program_binPrep() because some places want this, others want
520  * bc_program_binPrep().
521  * @param p    The program.
522  * @param l    An out parameter; this is set to the pointer to the result for
523  *             the left operand.
524  * @param ln   An out parameter; this is set to the pointer to the number for
525  *             the left operand.
526  * @param r    An out parameter; this is set to the pointer to the result for
527  *             the right operand.
528  * @param rn   An out parameter; this is set to the pointer to the number for
529  *             the right operand.
530  * @param idx  The starting index where the operands are in the results stack,
531  *             starting from the top.
532  */
533 static void
534 bc_program_binOpPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
535                      BcNum** rn, size_t idx)
536 {
537         bc_program_binPrep(p, l, ln, r, rn, idx);
538         bc_program_type_num(*l, *ln);
539         bc_program_type_num(*r, *rn);
540 }
541
542 /**
543  * Prepares the operands of an assignment operator.
544  * @param p   The program.
545  * @param l   An out parameter; this is set to the pointer to the result for the
546  *            left operand.
547  * @param ln  An out parameter; this is set to the pointer to the number for the
548  *            left operand.
549  * @param r   An out parameter; this is set to the pointer to the result for the
550  *            right operand.
551  * @param rn  An out parameter; this is set to the pointer to the number for the
552  *            right operand.
553  */
554 static void
555 bc_program_assignPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r,
556                       BcNum** rn)
557 {
558         BcResultType lt, min;
559         bool good;
560
561         // This is the min non-allowable result type. dc allows strings.
562         min = BC_RESULT_TEMP - ((unsigned int) (BC_IS_BC));
563
564         // Prepare the operands.
565         bc_program_binPrep(p, l, ln, r, rn, 0);
566
567         lt = (*l)->t;
568
569         // Typecheck the left.
570         if (BC_ERR(lt >= min && lt <= BC_RESULT_ONE)) bc_err(BC_ERR_EXEC_TYPE);
571
572         // Strings can be assigned to variables. We are already good if we are
573         // assigning a string.
574         good = ((*r)->t == BC_RESULT_STR && lt <= BC_RESULT_ARRAY_ELEM);
575
576         assert(BC_PROG_STR(*rn) || (*r)->t != BC_RESULT_STR);
577
578         // If not, type check for a number.
579         if (!good) bc_program_type_num(*r, *rn);
580 }
581
582 /**
583  * Prepares a single operand and type checks it. This is separate from
584  * bc_program_operand() because different places want one or the other.
585  * @param p    The program.
586  * @param r    An out parameter; this is set to the pointer to the result that
587  *             we care about.
588  * @param n    An out parameter; this is set to the pointer to the number that
589  *             we care about.
590  * @param idx  The index of the result from the top of the results stack.
591  */
592 static void
593 bc_program_prep(BcProgram* p, BcResult** r, BcNum** n, size_t idx)
594 {
595         assert(p != NULL && r != NULL && n != NULL);
596
597 #ifndef BC_PROG_NO_STACK_CHECK
598         // Check the stack for dc.
599         if (BC_IS_DC)
600         {
601                 if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 1)))
602                 {
603                         bc_err(BC_ERR_EXEC_STACK);
604                 }
605         }
606 #endif // BC_PROG_NO_STACK_CHECK
607
608         assert(BC_PROG_STACK(&p->results, idx + 1));
609
610         bc_program_operand(p, r, n, idx);
611
612         // dc does not allow strings in this case.
613         bc_program_type_num(*r, *n);
614 }
615
616 /**
617  * Prepares and returns a clean result for the result of an operation.
618  * @param p  The program.
619  * @return   A clean result.
620  */
621 static BcResult*
622 bc_program_prepResult(BcProgram* p)
623 {
624         BcResult* res = bc_vec_pushEmpty(&p->results);
625
626         bc_result_clear(res);
627
628         return res;
629 }
630
631 /**
632  * Prepares a constant for use. This parses the constant into a number and then
633  * pushes that number onto the results stack.
634  * @param p     The program.
635  * @param code  The bytecode vector that we will pull the index of the constant
636  *              from.
637  * @param bgn   An in/out parameter; marks the start of the index in the
638  *              bytecode vector and will be updated to point to after the index.
639  */
640 static void
641 bc_program_const(BcProgram* p, const char* code, size_t* bgn)
642 {
643         // I lied. I actually push the result first. I can do this because the
644         // result will be popped on error. I also get the constant itself.
645         BcResult* r = bc_program_prepResult(p);
646         BcConst* c = bc_vec_item(&p->consts, bc_program_index(code, bgn));
647         BcBigDig base = BC_PROG_IBASE(p);
648
649         // Only reparse if the base changed.
650         if (c->base != base)
651         {
652                 // Allocate if we haven't yet.
653                 if (c->num.num == NULL)
654                 {
655                         // The plus 1 is in case of overflow with lack of clamping.
656                         size_t len = strlen(c->val) + (BC_DIGIT_CLAMP == 0);
657
658                         BC_SIG_LOCK;
659                         bc_num_init(&c->num, BC_NUM_RDX(len));
660                         BC_SIG_UNLOCK;
661                 }
662                 // We need to zero an already existing number.
663                 else bc_num_zero(&c->num);
664
665                 // bc_num_parse() should only do operations that cannot fail.
666                 bc_num_parse(&c->num, c->val, base);
667
668                 c->base = base;
669         }
670
671         BC_SIG_LOCK;
672
673         bc_num_createCopy(&r->d.n, &c->num);
674
675         BC_SIG_UNLOCK;
676 }
677
678 /**
679  * Executes a binary operator operation.
680  * @param p     The program.
681  * @param inst  The instruction corresponding to the binary operator to execute.
682  */
683 static void
684 bc_program_op(BcProgram* p, uchar inst)
685 {
686         BcResult* opd1;
687         BcResult* opd2;
688         BcResult* res;
689         BcNum* n1;
690         BcNum* n2;
691         size_t idx = inst - BC_INST_POWER;
692
693         res = bc_program_prepResult(p);
694
695         bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, 1);
696
697         BC_SIG_LOCK;
698
699         // Initialize the number with enough space, using the correct
700         // BcNumBinaryOpReq function. This looks weird because it is executing an
701         // item of an array. Rest assured that item is a function.
702         bc_num_init(&res->d.n, bc_program_opReqs[idx](n1, n2, BC_PROG_SCALE(p)));
703
704         BC_SIG_UNLOCK;
705
706         assert(BC_NUM_RDX_VALID(n1));
707         assert(BC_NUM_RDX_VALID(n2));
708
709         // Run the operation. This also executes an item of an array.
710         bc_program_ops[idx](n1, n2, &res->d.n, BC_PROG_SCALE(p));
711
712         bc_program_retire(p, 1, 2);
713 }
714
715 /**
716  * Executes a read() or ? command.
717  * @param p  The program.
718  */
719 static void
720 bc_program_read(BcProgram* p)
721 {
722         BcStatus s;
723         BcInstPtr ip;
724         size_t i;
725         const char* file;
726         BcMode mode;
727         BcFunc* f = bc_vec_item(&p->fns, BC_PROG_READ);
728
729         // If we are already executing a read, that is an error. So look for a read
730         // and barf.
731         for (i = 0; i < p->stack.len; ++i)
732         {
733                 BcInstPtr* ip_ptr = bc_vec_item(&p->stack, i);
734                 if (ip_ptr->func == BC_PROG_READ) bc_err(BC_ERR_EXEC_REC_READ);
735         }
736
737         BC_SIG_LOCK;
738
739         // Save the filename because we are going to overwrite it.
740         file = vm->file;
741         mode = vm->mode;
742
743         // It is a parse error if there needs to be more than one line, so we unset
744         // this to tell the lexer to not request more. We set it back later.
745         vm->mode = BC_MODE_FILE;
746
747         if (!BC_PARSE_IS_INITED(&vm->read_prs, p))
748         {
749                 // We need to parse, but we don't want to use the existing parser
750                 // because it has state it needs to keep. (It could have a partial parse
751                 // state.) So we create a new parser. This parser is in the BcVm struct
752                 // so that it is not local, which means that a longjmp() could change
753                 // it.
754                 bc_parse_init(&vm->read_prs, p, BC_PROG_READ);
755
756                 // We need a separate input buffer; that's why it is also in the BcVm
757                 // struct.
758                 bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE);
759         }
760         else
761         {
762                 // This needs to be updated because the parser could have been used
763                 // somewhere else.
764                 bc_parse_updateFunc(&vm->read_prs, BC_PROG_READ);
765
766                 // The read buffer also needs to be emptied or else it will still
767                 // contain previous read expressions.
768                 bc_vec_empty(&vm->read_buf);
769         }
770
771         BC_SETJMP_LOCKED(vm, exec_err);
772
773         BC_SIG_UNLOCK;
774
775         // Set up the lexer and the read function.
776         bc_lex_file(&vm->read_prs.l, bc_program_stdin_name);
777         bc_vec_popAll(&f->code);
778
779         // Read a line.
780         if (!BC_R) s = bc_read_line(&vm->read_buf, "");
781         else s = bc_read_line(&vm->read_buf, BC_VM_READ_PROMPT);
782
783         // We should *not* have run into EOF.
784         if (s == BC_STATUS_EOF) bc_err(BC_ERR_EXEC_READ_EXPR);
785
786         // Parse *one* expression, so mode should not be stdin.
787         bc_parse_text(&vm->read_prs, vm->read_buf.v, BC_MODE_FILE);
788         BC_SIG_LOCK;
789         vm->expr(&vm->read_prs, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL);
790         BC_SIG_UNLOCK;
791
792         // We *must* have a valid expression. A semicolon cannot end an expression,
793         // although EOF can.
794         if (BC_ERR(vm->read_prs.l.t != BC_LEX_NLINE &&
795                    vm->read_prs.l.t != BC_LEX_EOF))
796         {
797                 bc_err(BC_ERR_EXEC_READ_EXPR);
798         }
799
800 #if BC_ENABLED
801         // Push on the globals stack if necessary.
802         if (BC_G) bc_program_prepGlobals(p);
803 #endif // BC_ENABLED
804
805         // Set up a new BcInstPtr.
806         ip.func = BC_PROG_READ;
807         ip.idx = 0;
808         ip.len = p->results.len;
809
810         // Update this pointer, just in case.
811         f = bc_vec_item(&p->fns, BC_PROG_READ);
812
813         // We want a return instruction to simplify things.
814         bc_vec_pushByte(&f->code, vm->read_ret);
815
816         // This lock is here to make sure dc's tail calls are the same length.
817         BC_SIG_LOCK;
818         bc_vec_push(&p->stack, &ip);
819
820 #if DC_ENABLED
821         // We need a new tail call entry for dc.
822         if (BC_IS_DC)
823         {
824                 size_t temp = 0;
825                 bc_vec_push(&p->tail_calls, &temp);
826         }
827 #endif // DC_ENABLED
828
829 exec_err:
830         BC_SIG_MAYLOCK;
831         vm->mode = (uchar) mode;
832         vm->file = file;
833         BC_LONGJMP_CONT(vm);
834 }
835
836 #if BC_ENABLE_EXTRA_MATH
837
838 /**
839  * Execute a rand().
840  * @param p  The program.
841  */
842 static void
843 bc_program_rand(BcProgram* p)
844 {
845         BcRand rand = bc_rand_int(&p->rng);
846
847         bc_program_pushBigdig(p, (BcBigDig) rand, BC_RESULT_TEMP);
848
849 #if BC_DEBUG
850         // This is just to ensure that the generated number is correct. I also use
851         // braces because I declare every local at the top of the scope.
852         {
853                 BcResult* r = bc_vec_top(&p->results);
854                 assert(BC_NUM_RDX_VALID_NP(r->d.n));
855         }
856 #endif // BC_DEBUG
857 }
858 #endif // BC_ENABLE_EXTRA_MATH
859
860 /**
861  * Prints a series of characters, without escapes.
862  * @param str  The string (series of characters).
863  */
864 static void
865 bc_program_printChars(const char* str)
866 {
867         const char* nl;
868         size_t len = vm->nchars + strlen(str);
869         sig_atomic_t lock;
870
871         BC_SIG_TRYLOCK(lock);
872
873         bc_file_puts(&vm->fout, bc_flush_save, str);
874
875         // We need to update the number of characters, so we find the last newline
876         // and set the characters accordingly.
877         nl = strrchr(str, '\n');
878
879         if (nl != NULL) len = strlen(nl + 1);
880
881         vm->nchars = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len;
882
883         BC_SIG_TRYUNLOCK(lock);
884 }
885
886 /**
887  * Prints a string with escapes.
888  * @param str  The string.
889  */
890 static void
891 bc_program_printString(const char* restrict str)
892 {
893         size_t i, len = strlen(str);
894
895 #if DC_ENABLED
896         // This is to ensure a nul byte is printed for dc's stream operation.
897         if (!len && BC_IS_DC)
898         {
899                 bc_vm_putchar('\0', bc_flush_save);
900                 return;
901         }
902 #endif // DC_ENABLED
903
904         // Loop over the characters, processing escapes and printing the rest.
905         for (i = 0; i < len; ++i)
906         {
907                 int c = str[i];
908
909                 // If we have an escape...
910                 if (c == '\\' && i != len - 1)
911                 {
912                         const char* ptr;
913
914                         // Get the escape character and its companion.
915                         c = str[++i];
916                         ptr = strchr(bc_program_esc_chars, c);
917
918                         // If we have a companion character...
919                         if (ptr != NULL)
920                         {
921                                 // We need to specially handle a newline.
922                                 if (c == 'n')
923                                 {
924                                         BC_SIG_LOCK;
925                                         vm->nchars = UINT16_MAX;
926                                         BC_SIG_UNLOCK;
927                                 }
928
929                                 // Grab the actual character.
930                                 c = bc_program_esc_seqs[(size_t) (ptr - bc_program_esc_chars)];
931                         }
932                         else
933                         {
934                                 // Just print the backslash if there is no companion character.
935                                 // The following character will be printed later after the outer
936                                 // if statement.
937                                 bc_vm_putchar('\\', bc_flush_save);
938                         }
939                 }
940
941                 bc_vm_putchar(c, bc_flush_save);
942         }
943 }
944
945 /**
946  * Executes a print. This function handles all printing except streaming.
947  * @param p     The program.
948  * @param inst  The instruction for the type of print we are doing.
949  * @param idx   The index of the result that we are printing.
950  */
951 static void
952 bc_program_print(BcProgram* p, uchar inst, size_t idx)
953 {
954         BcResult* r;
955         char* str;
956         BcNum* n;
957         bool pop = (inst != BC_INST_PRINT);
958
959         assert(p != NULL);
960
961 #ifndef BC_PROG_NO_STACK_CHECK
962         if (BC_IS_DC)
963         {
964                 if (BC_ERR(!BC_PROG_STACK(&p->results, idx + 1)))
965                 {
966                         bc_err(BC_ERR_EXEC_STACK);
967                 }
968         }
969 #endif // BC_PROG_NO_STACK_CHECK
970
971         assert(BC_PROG_STACK(&p->results, idx + 1));
972
973         r = bc_vec_item_rev(&p->results, idx);
974
975 #if BC_ENABLED
976         // If we have a void value, that's not necessarily an error. It is if pop is
977         // true because that means that we are executing a print statement, but
978         // attempting to do a print on a lone void value is allowed because that's
979         // exactly how we want void values used.
980         if (r->t == BC_RESULT_VOID)
981         {
982                 if (BC_ERR(pop)) bc_err(BC_ERR_EXEC_VOID_VAL);
983                 bc_vec_pop(&p->results);
984                 return;
985         }
986 #endif // BC_ENABLED
987
988         n = bc_program_num(p, r);
989
990         // If we have a number...
991         if (BC_PROG_NUM(r, n))
992         {
993 #if BC_ENABLED
994                 assert(inst != BC_INST_PRINT_STR);
995 #endif // BC_ENABLED
996
997                 // Print the number.
998                 bc_num_print(n, BC_PROG_OBASE(p), !pop);
999
1000 #if BC_ENABLED
1001                 // Need to store the number in last.
1002                 if (BC_IS_BC) bc_num_copy(&p->last, n);
1003 #endif // BC_ENABLED
1004         }
1005         else
1006         {
1007                 // We want to flush any stuff in the stdout buffer first.
1008                 bc_file_flush(&vm->fout, bc_flush_save);
1009                 str = bc_program_string(p, n);
1010
1011 #if BC_ENABLED
1012                 if (inst == BC_INST_PRINT_STR) bc_program_printChars(str);
1013                 else
1014 #endif // BC_ENABLED
1015                 {
1016                         bc_program_printString(str);
1017
1018                         // Need to print a newline only in this case.
1019                         if (inst == BC_INST_PRINT) bc_vm_putchar('\n', bc_flush_err);
1020                 }
1021         }
1022
1023         // bc always pops. This macro makes sure that happens.
1024         if (BC_PROGRAM_POP(pop)) bc_vec_pop(&p->results);
1025 }
1026
1027 void
1028 bc_program_negate(BcResult* r, BcNum* n)
1029 {
1030         bc_num_copy(&r->d.n, n);
1031         if (BC_NUM_NONZERO(&r->d.n)) BC_NUM_NEG_TGL_NP(r->d.n);
1032 }
1033
1034 void
1035 bc_program_not(BcResult* r, BcNum* n)
1036 {
1037         if (!bc_num_cmpZero(n)) bc_num_one(&r->d.n);
1038 }
1039
1040 #if BC_ENABLE_EXTRA_MATH
1041 void
1042 bc_program_trunc(BcResult* r, BcNum* n)
1043 {
1044         bc_num_copy(&r->d.n, n);
1045         bc_num_truncate(&r->d.n, n->scale);
1046 }
1047 #endif // BC_ENABLE_EXTRA_MATH
1048
1049 /**
1050  * Runs a unary operation.
1051  * @param p     The program.
1052  * @param inst  The unary operation.
1053  */
1054 static void
1055 bc_program_unary(BcProgram* p, uchar inst)
1056 {
1057         BcResult* res;
1058         BcResult* ptr;
1059         BcNum* num;
1060
1061         res = bc_program_prepResult(p);
1062
1063         bc_program_prep(p, &ptr, &num, 1);
1064
1065         BC_SIG_LOCK;
1066
1067         bc_num_init(&res->d.n, num->len);
1068
1069         BC_SIG_UNLOCK;
1070
1071         // This calls a function that is in an array.
1072         bc_program_unarys[inst - BC_INST_NEG](res, num);
1073         bc_program_retire(p, 1, 1);
1074 }
1075
1076 /**
1077  * Executes a logical operator.
1078  * @param p     The program.
1079  * @param inst  The operator.
1080  */
1081 static void
1082 bc_program_logical(BcProgram* p, uchar inst)
1083 {
1084         BcResult* opd1;
1085         BcResult* opd2;
1086         BcResult* res;
1087         BcNum* n1;
1088         BcNum* n2;
1089         bool cond = 0;
1090         ssize_t cmp;
1091
1092         res = bc_program_prepResult(p);
1093
1094         // All logical operators (except boolean not, which is taken care of by
1095         // bc_program_unary()), are binary operators.
1096         bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, 1);
1097
1098         // Boolean and and or are not short circuiting. This is why; they can be
1099         // implemented much easier this way.
1100         if (inst == BC_INST_BOOL_AND)
1101         {
1102                 cond = (bc_num_cmpZero(n1) && bc_num_cmpZero(n2));
1103         }
1104         else if (inst == BC_INST_BOOL_OR)
1105         {
1106                 cond = (bc_num_cmpZero(n1) || bc_num_cmpZero(n2));
1107         }
1108         else
1109         {
1110                 // We have a relational operator, so do a comparison.
1111                 cmp = bc_num_cmp(n1, n2);
1112
1113                 switch (inst)
1114                 {
1115                         case BC_INST_REL_EQ:
1116                         {
1117                                 cond = (cmp == 0);
1118                                 break;
1119                         }
1120
1121                         case BC_INST_REL_LE:
1122                         {
1123                                 cond = (cmp <= 0);
1124                                 break;
1125                         }
1126
1127                         case BC_INST_REL_GE:
1128                         {
1129                                 cond = (cmp >= 0);
1130                                 break;
1131                         }
1132
1133                         case BC_INST_REL_NE:
1134                         {
1135                                 cond = (cmp != 0);
1136                                 break;
1137                         }
1138
1139                         case BC_INST_REL_LT:
1140                         {
1141                                 cond = (cmp < 0);
1142                                 break;
1143                         }
1144
1145                         case BC_INST_REL_GT:
1146                         {
1147                                 cond = (cmp > 0);
1148                                 break;
1149                         }
1150 #if BC_DEBUG
1151                         default:
1152                         {
1153                                 // There is a bug if we get here.
1154                                 abort();
1155                         }
1156 #endif // BC_DEBUG
1157                 }
1158         }
1159
1160         BC_SIG_LOCK;
1161
1162         bc_num_init(&res->d.n, BC_NUM_DEF_SIZE);
1163
1164         BC_SIG_UNLOCK;
1165
1166         if (cond) bc_num_one(&res->d.n);
1167
1168         bc_program_retire(p, 1, 2);
1169 }
1170
1171 /**
1172  * Assigns a string to a variable.
1173  * @param p     The program.
1174  * @param num   The location of the string as a BcNum.
1175  * @param v     The stack for the variable.
1176  * @param push  Whether to push the string or not. To push means to move the
1177  *              string from the results stack and push it onto the variable
1178  *              stack.
1179  */
1180 static void
1181 bc_program_assignStr(BcProgram* p, BcNum* num, BcVec* v, bool push)
1182 {
1183         BcNum* n;
1184
1185         assert(BC_PROG_STACK(&p->results, 1 + !push));
1186         assert(num != NULL && num->num == NULL && num->cap == 0);
1187
1188         // If we are not pushing onto the variable stack, we need to replace the
1189         // top of the variable stack.
1190         if (!push) bc_vec_pop(v);
1191
1192         bc_vec_npop(&p->results, 1 + !push);
1193
1194         n = bc_vec_pushEmpty(v);
1195
1196         // We can just copy because the num should not have allocated anything.
1197         // NOLINTNEXTLINE
1198         memcpy(n, num, sizeof(BcNum));
1199 }
1200
1201 /**
1202  * Copies a value to a variable. This is used for storing in dc as well as to
1203  * set function parameters to arguments in bc.
1204  * @param p    The program.
1205  * @param idx  The index of the variable or array to copy to.
1206  * @param t    The type to copy to. This could be a variable or an array.
1207  */
1208 static void
1209 bc_program_copyToVar(BcProgram* p, size_t idx, BcType t)
1210 {
1211         BcResult *ptr = NULL, r;
1212         BcVec* vec;
1213         BcNum* n = NULL;
1214         bool var = (t == BC_TYPE_VAR);
1215
1216 #if DC_ENABLED
1217         // Check the stack for dc.
1218         if (BC_IS_DC)
1219         {
1220                 if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
1221         }
1222 #endif
1223
1224         assert(BC_PROG_STACK(&p->results, 1));
1225
1226         bc_program_operand(p, &ptr, &n, 0);
1227
1228 #if BC_ENABLED
1229         // Get the variable for a bc function call.
1230         if (BC_IS_BC)
1231         {
1232                 // Type match the result.
1233                 bc_program_type_match(ptr, t);
1234         }
1235 #endif // BC_ENABLED
1236
1237         vec = bc_program_vec(p, idx, t);
1238
1239         // We can shortcut in dc if it's assigning a string by using
1240         // bc_program_assignStr().
1241         if (ptr->t == BC_RESULT_STR)
1242         {
1243                 assert(BC_PROG_STR(n));
1244
1245                 if (BC_ERR(!var)) bc_err(BC_ERR_EXEC_TYPE);
1246
1247                 bc_program_assignStr(p, n, vec, true);
1248
1249                 return;
1250         }
1251
1252         BC_SIG_LOCK;
1253
1254         // Just create and copy for a normal variable.
1255         if (var)
1256         {
1257                 if (BC_PROG_STR(n))
1258                 {
1259                         // NOLINTNEXTLINE
1260                         memcpy(&r.d.n, n, sizeof(BcNum));
1261                 }
1262                 else bc_num_createCopy(&r.d.n, n);
1263         }
1264         else
1265         {
1266                 // If we get here, we are handling an array. This is one place we need
1267                 // to cast the number from bc_program_num() to a vector.
1268                 BcVec* v = (BcVec*) n;
1269                 BcVec* rv = &r.d.v;
1270
1271 #if BC_ENABLED
1272
1273                 if (BC_IS_BC)
1274                 {
1275                         bool ref, ref_size;
1276
1277                         // True if we are using a reference.
1278                         ref = (v->size == sizeof(BcNum) && t == BC_TYPE_REF);
1279
1280                         // True if we already have a reference vector. This is slightly
1281                         // (okay, a lot; it just doesn't look that way) different from
1282                         // above. The above means that we need to construct a reference
1283                         // vector, whereas this means that we have one and we might have to
1284                         // *dereference* it.
1285                         ref_size = (v->size == sizeof(uchar));
1286
1287                         // If we *should* have a reference.
1288                         if (ref || (ref_size && t == BC_TYPE_REF))
1289                         {
1290                                 // Create a new reference vector.
1291                                 bc_vec_init(rv, sizeof(uchar), BC_DTOR_NONE);
1292
1293                                 // If this is true, then we need to construct a reference.
1294                                 if (ref)
1295                                 {
1296                                         // Make sure the pointer was not invalidated.
1297                                         vec = bc_program_vec(p, idx, t);
1298
1299                                         // Push the indices onto the reference vector. This takes
1300                                         // care of last; it ensures the reference goes to the right
1301                                         // place.
1302                                         bc_vec_pushIndex(rv, ptr->d.loc.loc);
1303                                         bc_vec_pushIndex(rv, ptr->d.loc.stack_idx);
1304                                 }
1305                                 // If we get here, we are copying a ref to a ref. Just push a
1306                                 // copy of all of the bytes.
1307                                 else bc_vec_npush(rv, v->len * sizeof(uchar), v->v);
1308
1309                                 // Push the reference vector onto the array stack and pop the
1310                                 // source.
1311                                 bc_vec_push(vec, &r.d);
1312                                 bc_vec_pop(&p->results);
1313
1314                                 // We need to return early to avoid executing code that we must
1315                                 // not touch.
1316                                 BC_SIG_UNLOCK;
1317                                 return;
1318                         }
1319                         // If we get here, we have a reference, but we need an array, so
1320                         // dereference the array.
1321                         else if (ref_size && t != BC_TYPE_REF)
1322                         {
1323                                 v = bc_program_dereference(p, v);
1324                         }
1325                 }
1326 #endif // BC_ENABLED
1327
1328                 // If we get here, we need to copy the array because in bc, all
1329                 // arguments are passed by value. Yes, this is expensive.
1330                 bc_array_init(rv, true);
1331                 bc_array_copy(rv, v);
1332         }
1333
1334         // Push the vector onto the array stack and pop the source.
1335         bc_vec_push(vec, &r.d);
1336         bc_vec_pop(&p->results);
1337
1338         BC_SIG_UNLOCK;
1339 }
1340
1341 void
1342 bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val)
1343 {
1344         BcBigDig* ptr_t;
1345         BcBigDig max, min;
1346 #if BC_ENABLED
1347         BcVec* v;
1348         BcBigDig* ptr;
1349 #endif // BC_ENABLED
1350
1351         assert(!scale || !obase);
1352
1353         // Scale needs handling separate from ibase and obase.
1354         if (scale)
1355         {
1356                 // Set the min and max.
1357                 min = 0;
1358                 max = vm->maxes[BC_PROG_GLOBALS_SCALE];
1359
1360 #if BC_ENABLED
1361                 // Get a pointer to the stack.
1362                 v = p->globals_v + BC_PROG_GLOBALS_SCALE;
1363 #endif // BC_ENABLED
1364
1365                 // Get a pointer to the current value.
1366                 ptr_t = p->globals + BC_PROG_GLOBALS_SCALE;
1367         }
1368         else
1369         {
1370                 // Set the min and max.
1371                 min = BC_NUM_MIN_BASE;
1372                 if (BC_ENABLE_EXTRA_MATH && obase && (BC_IS_DC || !BC_IS_POSIX))
1373                 {
1374                         min = 0;
1375                 }
1376                 max = vm->maxes[obase + BC_PROG_GLOBALS_IBASE];
1377
1378 #if BC_ENABLED
1379                 // Get a pointer to the stack.
1380                 v = p->globals_v + BC_PROG_GLOBALS_IBASE + obase;
1381 #endif // BC_ENABLED
1382
1383                 // Get a pointer to the current value.
1384                 ptr_t = p->globals + BC_PROG_GLOBALS_IBASE + obase;
1385         }
1386
1387         // Check for error.
1388         if (BC_ERR(val > max || val < min))
1389         {
1390                 BcErr e;
1391
1392                 // This grabs the right error.
1393                 if (scale) e = BC_ERR_EXEC_SCALE;
1394                 else if (obase) e = BC_ERR_EXEC_OBASE;
1395                 else e = BC_ERR_EXEC_IBASE;
1396
1397                 bc_verr(e, min, max);
1398         }
1399
1400 #if BC_ENABLED
1401         // Set the top of the stack.
1402         ptr = bc_vec_top(v);
1403         *ptr = val;
1404 #endif // BC_ENABLED
1405
1406         // Set the actual global variable.
1407         *ptr_t = val;
1408 }
1409
1410 #if BC_ENABLE_EXTRA_MATH
1411 void
1412 bc_program_assignSeed(BcProgram* p, BcNum* val)
1413 {
1414         bc_num_rng(val, &p->rng);
1415 }
1416 #endif // BC_ENABLE_EXTRA_MATH
1417
1418 /**
1419  * Executes an assignment operator.
1420  * @param p     The program.
1421  * @param inst  The assignment operator to execute.
1422  */
1423 static void
1424 bc_program_assign(BcProgram* p, uchar inst)
1425 {
1426         // The local use_val is true when the assigned value needs to be copied.
1427         BcResult* left;
1428         BcResult* right;
1429         BcResult res;
1430         BcNum* l;
1431         BcNum* r;
1432         bool ob, sc, use_val = BC_INST_USE_VAL(inst);
1433
1434         bc_program_assignPrep(p, &left, &l, &right, &r);
1435
1436         // Assigning to a string should be impossible simply because of the parse.
1437         assert(left->t != BC_RESULT_STR);
1438
1439         // If we are assigning a string...
1440         if (right->t == BC_RESULT_STR)
1441         {
1442                 assert(BC_PROG_STR(r));
1443
1444 #if BC_ENABLED
1445                 if (inst != BC_INST_ASSIGN && inst != BC_INST_ASSIGN_NO_VAL)
1446                 {
1447                         bc_err(BC_ERR_EXEC_TYPE);
1448                 }
1449 #endif // BC_ENABLED
1450
1451                 // If we are assigning to an array element...
1452                 if (left->t == BC_RESULT_ARRAY_ELEM)
1453                 {
1454                         BC_SIG_LOCK;
1455
1456                         // We need to free the number and clear it.
1457                         bc_num_free(l);
1458
1459                         // NOLINTNEXTLINE
1460                         memcpy(l, r, sizeof(BcNum));
1461
1462                         // Now we can pop the results.
1463                         bc_vec_npop(&p->results, 2);
1464
1465                         BC_SIG_UNLOCK;
1466                 }
1467                 else
1468                 {
1469                         // If we get here, we are assigning to a variable, which we can use
1470                         // bc_program_assignStr() for.
1471                         BcVec* v = bc_program_vec(p, left->d.loc.loc, BC_TYPE_VAR);
1472                         bc_program_assignStr(p, r, v, false);
1473                 }
1474
1475 #if BC_ENABLED
1476
1477                 // If this is true, the value is going to be used again, so we want to
1478                 // push a temporary with the string.
1479                 if (inst == BC_INST_ASSIGN)
1480                 {
1481                         res.t = BC_RESULT_STR;
1482                         // NOLINTNEXTLINE
1483                         memcpy(&res.d.n, r, sizeof(BcNum));
1484                         bc_vec_push(&p->results, &res);
1485                 }
1486
1487 #endif // BC_ENABLED
1488
1489                 // By using bc_program_assignStr(), we short-circuited this, so return.
1490                 return;
1491         }
1492
1493         // If we have a normal assignment operator, not a math one...
1494         if (BC_INST_IS_ASSIGN(inst))
1495         {
1496                 // Assigning to a variable that has a string here is fine because there
1497                 // is no math done on it.
1498
1499                 // BC_RESULT_TEMP, BC_RESULT_IBASE, BC_RESULT_OBASE, BC_RESULT_SCALE,
1500                 // and BC_RESULT_SEED all have temporary copies. Because that's the
1501                 // case, we can free the left and just move the value over. We set the
1502                 // type of right to BC_RESULT_ZERO in order to prevent it from being
1503                 // freed. We also don't have to worry about BC_RESULT_STR because it's
1504                 // take care of above.
1505                 if (right->t == BC_RESULT_TEMP || right->t >= BC_RESULT_IBASE)
1506                 {
1507                         BC_SIG_LOCK;
1508
1509                         bc_num_free(l);
1510                         // NOLINTNEXTLINE
1511                         memcpy(l, r, sizeof(BcNum));
1512                         right->t = BC_RESULT_ZERO;
1513
1514                         BC_SIG_UNLOCK;
1515                 }
1516                 // Copy over.
1517                 else bc_num_copy(l, r);
1518         }
1519 #if BC_ENABLED
1520         else
1521         {
1522                 // If we get here, we are doing a math assignment (+=, -=, etc.). So
1523                 // we need to prepare for a binary operator.
1524                 BcBigDig scale = BC_PROG_SCALE(p);
1525
1526                 // At this point, the left side could still be a string because it could
1527                 // be a variable that has the string. If that's the case, we have a type
1528                 // error.
1529                 if (BC_PROG_STR(l)) bc_err(BC_ERR_EXEC_TYPE);
1530
1531                 // Get the right type of assignment operator, whether val is used or
1532                 // NO_VAL for performance.
1533                 if (!use_val)
1534                 {
1535                         inst -= (BC_INST_ASSIGN_POWER_NO_VAL - BC_INST_ASSIGN_POWER);
1536                 }
1537
1538                 assert(BC_NUM_RDX_VALID(l));
1539                 assert(BC_NUM_RDX_VALID(r));
1540
1541                 // Run the actual operation. We do not need worry about reallocating l
1542                 // because bc_num_binary() does that behind the scenes for us.
1543                 bc_program_ops[inst - BC_INST_ASSIGN_POWER](l, r, l, scale);
1544         }
1545 #endif // BC_ENABLED
1546
1547         ob = (left->t == BC_RESULT_OBASE);
1548         sc = (left->t == BC_RESULT_SCALE);
1549
1550         // The globals need special handling, especially the non-seed ones. The
1551         // first part of the if statement handles them.
1552         if (ob || sc || left->t == BC_RESULT_IBASE)
1553         {
1554                 // Get the actual value.
1555                 BcBigDig val = bc_num_bigdig(l);
1556
1557                 bc_program_assignBuiltin(p, sc, ob, val);
1558         }
1559 #if BC_ENABLE_EXTRA_MATH
1560         // To assign to steed, let bc_num_rng() do its magic.
1561         else if (left->t == BC_RESULT_SEED) bc_program_assignSeed(p, l);
1562 #endif // BC_ENABLE_EXTRA_MATH
1563
1564         BC_SIG_LOCK;
1565
1566         // If we needed to use the value, then we need to copy it. Otherwise, we can
1567         // pop indiscriminately. Oh, and the copy should be a BC_RESULT_TEMP.
1568         if (use_val)
1569         {
1570                 bc_num_createCopy(&res.d.n, l);
1571                 res.t = BC_RESULT_TEMP;
1572                 bc_vec_npop(&p->results, 2);
1573                 bc_vec_push(&p->results, &res);
1574         }
1575         else bc_vec_npop(&p->results, 2);
1576
1577         BC_SIG_UNLOCK;
1578 }
1579
1580 /**
1581  * Pushes a variable's value onto the results stack.
1582  * @param p     The program.
1583  * @param code  The bytecode vector to pull the variable's index out of.
1584  * @param bgn   An in/out parameter; the start of the index in the bytecode
1585  *              vector, and will be updated to point after the index on return.
1586  * @param pop   True if the variable's value should be popped off its stack.
1587  *              This is only used in dc.
1588  * @param copy  True if the variable's value should be copied to the results
1589  *              stack. This is only used in dc.
1590  */
1591 static void
1592 bc_program_pushVar(BcProgram* p, const char* restrict code,
1593                    size_t* restrict bgn, bool pop, bool copy)
1594 {
1595         BcResult r;
1596         size_t idx = bc_program_index(code, bgn);
1597         BcVec* v;
1598
1599         // Set the result appropriately.
1600         r.t = BC_RESULT_VAR;
1601         r.d.loc.loc = idx;
1602
1603         // Get the stack for the variable. This is used in both bc and dc.
1604         v = bc_program_vec(p, idx, BC_TYPE_VAR);
1605         r.d.loc.stack_idx = v->len - 1;
1606
1607 #if DC_ENABLED
1608         // If this condition is true, then we have the hard case, where we have to
1609         // adjust dc registers.
1610         if (BC_IS_DC && (pop || copy))
1611         {
1612                 // Get the number at the top at the top of the stack.
1613                 BcNum* num = bc_vec_top(v);
1614
1615                 // Ensure there are enough elements on the stack.
1616                 if (BC_ERR(!BC_PROG_STACK(v, 2 - copy)))
1617                 {
1618                         const char* name = bc_map_name(&p->var_map, idx);
1619                         bc_verr(BC_ERR_EXEC_STACK_REGISTER, name);
1620                 }
1621
1622                 assert(BC_PROG_STACK(v, 2 - copy));
1623
1624                 // If the top of the stack is actually a number...
1625                 if (!BC_PROG_STR(num))
1626                 {
1627                         BC_SIG_LOCK;
1628
1629                         // Create a copy to go onto the results stack as appropriate.
1630                         r.t = BC_RESULT_TEMP;
1631                         bc_num_createCopy(&r.d.n, num);
1632
1633                         // If we are not actually copying, we need to do a replace, so pop.
1634                         if (!copy) bc_vec_pop(v);
1635
1636                         bc_vec_push(&p->results, &r);
1637
1638                         BC_SIG_UNLOCK;
1639
1640                         return;
1641                 }
1642                 else
1643                 {
1644                         // Set the string result. We can just memcpy because all of the
1645                         // fields in the num should be cleared.
1646                         // NOLINTNEXTLINE
1647                         memcpy(&r.d.n, num, sizeof(BcNum));
1648                         r.t = BC_RESULT_STR;
1649                 }
1650
1651                 // If we are not actually copying, we need to do a replace, so pop.
1652                 if (!copy) bc_vec_pop(v);
1653         }
1654 #endif // DC_ENABLED
1655
1656         bc_vec_push(&p->results, &r);
1657 }
1658
1659 /**
1660  * Pushes an array or an array element onto the results stack.
1661  * @param p     The program.
1662  * @param code  The bytecode vector to pull the variable's index out of.
1663  * @param bgn   An in/out parameter; the start of the index in the bytecode
1664  *              vector, and will be updated to point after the index on return.
1665  * @param inst  The instruction; whether to push an array or an array element.
1666  */
1667 static void
1668 bc_program_pushArray(BcProgram* p, const char* restrict code,
1669                      size_t* restrict bgn, uchar inst)
1670 {
1671         BcResult r;
1672         BcResult* operand;
1673         BcNum* num;
1674         BcBigDig temp;
1675         BcVec* v;
1676
1677         // Get the index of the array.
1678         r.d.loc.loc = bc_program_index(code, bgn);
1679
1680         // We need the array to get its length.
1681         v = bc_program_vec(p, r.d.loc.loc, BC_TYPE_ARRAY);
1682         assert(v != NULL);
1683
1684         r.d.loc.stack_idx = v->len - 1;
1685
1686         // Doing an array is easy; just set the result type and finish.
1687         if (inst == BC_INST_ARRAY)
1688         {
1689                 r.t = BC_RESULT_ARRAY;
1690                 bc_vec_push(&p->results, &r);
1691                 return;
1692         }
1693
1694         // Grab the top element of the results stack for the array index.
1695         bc_program_prep(p, &operand, &num, 0);
1696         temp = bc_num_bigdig(num);
1697
1698         // Set the result.
1699         r.t = BC_RESULT_ARRAY_ELEM;
1700         r.d.loc.idx = (size_t) temp;
1701
1702         BC_SIG_LOCK;
1703
1704         // Pop the index and push the element.
1705         bc_vec_pop(&p->results);
1706         bc_vec_push(&p->results, &r);
1707
1708         BC_SIG_UNLOCK;
1709 }
1710
1711 #if BC_ENABLED
1712
1713 /**
1714  * Executes an increment or decrement operator. This only handles postfix
1715  * inc/dec because the parser translates prefix inc/dec into an assignment where
1716  * the value is used.
1717  * @param p     The program.
1718  * @param inst  The instruction; whether to do an increment or decrement.
1719  */
1720 static void
1721 bc_program_incdec(BcProgram* p, uchar inst)
1722 {
1723         BcResult *ptr, res, copy;
1724         BcNum* num;
1725         uchar inst2;
1726
1727         bc_program_prep(p, &ptr, &num, 0);
1728
1729         BC_SIG_LOCK;
1730
1731         // We need a copy from *before* the operation.
1732         copy.t = BC_RESULT_TEMP;
1733         bc_num_createCopy(&copy.d.n, num);
1734
1735         BC_SETJMP_LOCKED(vm, exit);
1736
1737         BC_SIG_UNLOCK;
1738
1739         // Create the proper assignment.
1740         res.t = BC_RESULT_ONE;
1741         inst2 = BC_INST_ASSIGN_PLUS_NO_VAL + (inst & 0x01);
1742
1743         bc_vec_push(&p->results, &res);
1744         bc_program_assign(p, inst2);
1745
1746         BC_SIG_LOCK;
1747
1748         bc_vec_push(&p->results, &copy);
1749
1750         BC_UNSETJMP(vm);
1751
1752         BC_SIG_UNLOCK;
1753
1754         // No need to free the copy here because we pushed it onto the stack.
1755         return;
1756
1757 exit:
1758         BC_SIG_MAYLOCK;
1759         bc_num_free(&copy.d.n);
1760         BC_LONGJMP_CONT(vm);
1761 }
1762
1763 /**
1764  * Executes a function call for bc.
1765  * @param p     The program.
1766  * @param code  The bytecode vector to pull the number of arguments and the
1767  *              function index out of.
1768  * @param bgn   An in/out parameter; the start of the indices in the bytecode
1769  *              vector, and will be updated to point after the indices on
1770  *              return.
1771  */
1772 static void
1773 bc_program_call(BcProgram* p, const char* restrict code, size_t* restrict bgn)
1774 {
1775         BcInstPtr ip;
1776         size_t i, nargs;
1777         BcFunc* f;
1778         BcVec* v;
1779         BcAuto* a;
1780         BcResult* arg;
1781
1782         // Pull the number of arguments out of the bytecode vector.
1783         nargs = bc_program_index(code, bgn);
1784
1785         // Set up instruction pointer.
1786         ip.idx = 0;
1787         ip.func = bc_program_index(code, bgn);
1788         f = bc_vec_item(&p->fns, ip.func);
1789
1790         // Error checking.
1791         if (BC_ERR(!f->code.len)) bc_verr(BC_ERR_EXEC_UNDEF_FUNC, f->name);
1792         if (BC_ERR(nargs != f->nparams))
1793         {
1794                 bc_verr(BC_ERR_EXEC_PARAMS, f->nparams, nargs);
1795         }
1796
1797         // Set the length of the results stack. We discount the argument, of course.
1798         ip.len = p->results.len - nargs;
1799
1800         assert(BC_PROG_STACK(&p->results, nargs));
1801
1802         // Prepare the globals' stacks.
1803         if (BC_G) bc_program_prepGlobals(p);
1804
1805         // Push the arguments onto the stacks of their respective parameters.
1806         for (i = 0; i < nargs; ++i)
1807         {
1808                 arg = bc_vec_top(&p->results);
1809                 if (BC_ERR(arg->t == BC_RESULT_VOID)) bc_err(BC_ERR_EXEC_VOID_VAL);
1810
1811                 // Get the corresponding parameter.
1812                 a = bc_vec_item(&f->autos, nargs - 1 - i);
1813
1814                 // Actually push the value onto the parameter's stack.
1815                 bc_program_copyToVar(p, a->idx, a->type);
1816         }
1817
1818         BC_SIG_LOCK;
1819
1820         // Push zeroes onto the stacks of the auto variables.
1821         for (; i < f->autos.len; ++i)
1822         {
1823                 // Get the auto and its stack.
1824                 a = bc_vec_item(&f->autos, i);
1825                 v = bc_program_vec(p, a->idx, a->type);
1826
1827                 // If a variable, just push a 0; otherwise, push an array.
1828                 if (a->type == BC_TYPE_VAR)
1829                 {
1830                         BcNum* n = bc_vec_pushEmpty(v);
1831                         bc_num_init(n, BC_NUM_DEF_SIZE);
1832                 }
1833                 else
1834                 {
1835                         BcVec* v2;
1836
1837                         assert(a->type == BC_TYPE_ARRAY);
1838
1839                         v2 = bc_vec_pushEmpty(v);
1840                         bc_array_init(v2, true);
1841                 }
1842         }
1843
1844         // Push the instruction pointer onto the execution stack.
1845         bc_vec_push(&p->stack, &ip);
1846
1847         BC_SIG_UNLOCK;
1848 }
1849
1850 /**
1851  * Executes a return instruction.
1852  * @param p     The program.
1853  * @param inst  The return instruction. bc can return void, and we need to know
1854  *              if it is.
1855  */
1856 static void
1857 bc_program_return(BcProgram* p, uchar inst)
1858 {
1859         BcResult* res;
1860         BcFunc* f;
1861         BcInstPtr* ip;
1862         size_t i, nresults;
1863
1864         // Get the instruction pointer.
1865         ip = bc_vec_top(&p->stack);
1866
1867         // Get the difference between the actual number of results and the number of
1868         // results the caller expects.
1869         nresults = p->results.len - ip->len;
1870
1871         // If this isn't true, there was a missing call somewhere.
1872         assert(BC_PROG_STACK(&p->stack, 2));
1873
1874         // If this isn't true, the parser screwed by giving us no value when we
1875         // expected one, or giving us a value when we expected none.
1876         assert(BC_PROG_STACK(&p->results, ip->len + (inst == BC_INST_RET)));
1877
1878         // Get the function we are returning from.
1879         f = bc_vec_item(&p->fns, ip->func);
1880
1881         res = bc_program_prepResult(p);
1882
1883         // If we are returning normally...
1884         if (inst == BC_INST_RET)
1885         {
1886                 BcNum* num;
1887                 BcResult* operand;
1888
1889                 // Prepare and copy the return value.
1890                 bc_program_operand(p, &operand, &num, 1);
1891
1892                 if (BC_PROG_STR(num))
1893                 {
1894                         // We need to set this because otherwise, it will be a
1895                         // BC_RESULT_TEMP, and BC_RESULT_TEMP needs an actual number to make
1896                         // it easier to do type checking.
1897                         res->t = BC_RESULT_STR;
1898
1899                         // NOLINTNEXTLINE
1900                         memcpy(&res->d.n, num, sizeof(BcNum));
1901                 }
1902                 else
1903                 {
1904                         BC_SIG_LOCK;
1905
1906                         bc_num_createCopy(&res->d.n, num);
1907                 }
1908         }
1909         // Void is easy; set the result.
1910         else if (inst == BC_INST_RET_VOID) res->t = BC_RESULT_VOID;
1911         else
1912         {
1913                 BC_SIG_LOCK;
1914
1915                 // If we get here, the instruction is for returning a zero, so do that.
1916                 bc_num_init(&res->d.n, BC_NUM_DEF_SIZE);
1917         }
1918
1919         BC_SIG_MAYUNLOCK;
1920
1921         // We need to pop items off of the stacks of arguments and autos as well.
1922         for (i = 0; i < f->autos.len; ++i)
1923         {
1924                 BcAuto* a = bc_vec_item(&f->autos, i);
1925                 BcVec* v = bc_program_vec(p, a->idx, a->type);
1926
1927                 bc_vec_pop(v);
1928         }
1929
1930         BC_SIG_LOCK;
1931
1932         // When we retire, pop all of the unused results.
1933         bc_program_retire(p, 1, nresults);
1934
1935         // Pop the globals, if necessary.
1936         if (BC_G) bc_program_popGlobals(p, false);
1937
1938         // Pop the stack. This is what causes the function to actually "return."
1939         bc_vec_pop(&p->stack);
1940
1941         BC_SIG_UNLOCK;
1942 }
1943 #endif // BC_ENABLED
1944
1945 /**
1946  * Executes a builtin function.
1947  * @param p     The program.
1948  * @param inst  The builtin to execute.
1949  */
1950 static void
1951 bc_program_builtin(BcProgram* p, uchar inst)
1952 {
1953         BcResult* opd;
1954         BcResult* res;
1955         BcNum* num;
1956         bool len = (inst == BC_INST_LENGTH);
1957
1958         // Ensure we have a valid builtin.
1959 #if BC_ENABLE_EXTRA_MATH
1960         assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IRAND);
1961 #else // BC_ENABLE_EXTRA_MATH
1962         assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IS_STRING);
1963 #endif // BC_ENABLE_EXTRA_MATH
1964
1965 #ifndef BC_PROG_NO_STACK_CHECK
1966         // Check stack for dc.
1967         if (BC_IS_DC && BC_ERR(!BC_PROG_STACK(&p->results, 1)))
1968         {
1969                 bc_err(BC_ERR_EXEC_STACK);
1970         }
1971 #endif // BC_PROG_NO_STACK_CHECK
1972
1973         assert(BC_PROG_STACK(&p->results, 1));
1974
1975         res = bc_program_prepResult(p);
1976
1977         bc_program_operand(p, &opd, &num, 1);
1978
1979         assert(num != NULL);
1980
1981         // We need to ensure that strings and arrays aren't passed to most builtins.
1982         // The scale function can take strings in dc.
1983         if (!len && (inst != BC_INST_SCALE_FUNC || BC_IS_BC) &&
1984             inst != BC_INST_IS_NUMBER && inst != BC_INST_IS_STRING)
1985         {
1986                 bc_program_type_num(opd, num);
1987         }
1988
1989         // Square root is easy.
1990         if (inst == BC_INST_SQRT) bc_num_sqrt(num, &res->d.n, BC_PROG_SCALE(p));
1991
1992         // Absolute value is easy.
1993         else if (inst == BC_INST_ABS)
1994         {
1995                 BC_SIG_LOCK;
1996
1997                 bc_num_createCopy(&res->d.n, num);
1998
1999                 BC_SIG_UNLOCK;
2000
2001                 BC_NUM_NEG_CLR_NP(res->d.n);
2002         }
2003
2004         // Testing for number or string is easy.
2005         else if (inst == BC_INST_IS_NUMBER || inst == BC_INST_IS_STRING)
2006         {
2007                 bool cond;
2008                 bool is_str;
2009
2010                 BC_SIG_LOCK;
2011
2012                 bc_num_init(&res->d.n, BC_NUM_DEF_SIZE);
2013
2014                 BC_SIG_UNLOCK;
2015
2016                 // Test if the number is a string.
2017                 is_str = BC_PROG_STR(num);
2018
2019                 // This confusing condition simply means that the instruction must be
2020                 // true if is_str is, or it must be false if is_str is. Otherwise, the
2021                 // returned value is false (0).
2022                 cond = ((inst == BC_INST_IS_STRING) == is_str);
2023                 if (cond) bc_num_one(&res->d.n);
2024         }
2025
2026 #if BC_ENABLE_EXTRA_MATH
2027
2028         // irand() is easy.
2029         else if (inst == BC_INST_IRAND)
2030         {
2031                 BC_SIG_LOCK;
2032
2033                 bc_num_init(&res->d.n, num->len - BC_NUM_RDX_VAL(num));
2034
2035                 BC_SIG_UNLOCK;
2036
2037                 bc_num_irand(num, &res->d.n, &p->rng);
2038         }
2039
2040 #endif // BC_ENABLE_EXTRA_MATH
2041
2042         // Everything else is...not easy.
2043         else
2044         {
2045                 BcBigDig val = 0;
2046
2047                 // Well, scale() is easy, but length() is not.
2048                 if (len)
2049                 {
2050                         // If we are bc and we have an array...
2051                         if (opd->t == BC_RESULT_ARRAY)
2052                         {
2053                                 // Yes, this is one place where we need to cast the number from
2054                                 // bc_program_num() to a vector.
2055                                 BcVec* v = (BcVec*) num;
2056
2057                                 // XXX: If this is changed, you should also change the similar
2058                                 // code in bc_program_asciify().
2059
2060 #if BC_ENABLED
2061                                 // Dereference the array, if necessary.
2062                                 if (BC_IS_BC && v->size == sizeof(uchar))
2063                                 {
2064                                         v = bc_program_dereference(p, v);
2065                                 }
2066 #endif // BC_ENABLED
2067
2068                                 assert(v->size == sizeof(BcNum));
2069
2070                                 val = (BcBigDig) v->len;
2071                         }
2072                         else
2073                         {
2074                                 // If the item is a string...
2075                                 if (!BC_PROG_NUM(opd, num))
2076                                 {
2077                                         char* str;
2078
2079                                         // Get the string, then get the length.
2080                                         str = bc_program_string(p, num);
2081                                         val = (BcBigDig) strlen(str);
2082                                 }
2083                                 else
2084                                 {
2085                                         // Calculate the length of the number.
2086                                         val = (BcBigDig) bc_num_len(num);
2087                                 }
2088                         }
2089                 }
2090                 // Like I said; scale() is actually easy. It just also needs the integer
2091                 // conversion that length() does.
2092                 else if (BC_IS_BC || BC_PROG_NUM(opd, num))
2093                 {
2094                         val = (BcBigDig) bc_num_scale(num);
2095                 }
2096
2097                 BC_SIG_LOCK;
2098
2099                 // Create the result.
2100                 bc_num_createFromBigdig(&res->d.n, val);
2101
2102                 BC_SIG_UNLOCK;
2103         }
2104
2105         bc_program_retire(p, 1, 1);
2106 }
2107
2108 /**
2109  * Executes a divmod.
2110  * @param p  The program.
2111  */
2112 static void
2113 bc_program_divmod(BcProgram* p)
2114 {
2115         BcResult* opd1;
2116         BcResult* opd2;
2117         BcResult* res;
2118         BcResult* res2;
2119         BcNum* n1;
2120         BcNum* n2;
2121         size_t req;
2122
2123         // We grow first to avoid pointer invalidation.
2124         bc_vec_grow(&p->results, 2);
2125
2126         // We don't need to update the pointer because
2127         // the capacity is enough due to the line above.
2128         res2 = bc_program_prepResult(p);
2129         res = bc_program_prepResult(p);
2130
2131         // Prepare the operands.
2132         bc_program_binOpPrep(p, &opd1, &n1, &opd2, &n2, 2);
2133
2134         req = bc_num_mulReq(n1, n2, BC_PROG_SCALE(p));
2135
2136         BC_SIG_LOCK;
2137
2138         // Initialize the results.
2139         bc_num_init(&res->d.n, req);
2140         bc_num_init(&res2->d.n, req);
2141
2142         BC_SIG_UNLOCK;
2143
2144         // Execute.
2145         bc_num_divmod(n1, n2, &res2->d.n, &res->d.n, BC_PROG_SCALE(p));
2146
2147         bc_program_retire(p, 2, 2);
2148 }
2149
2150 /**
2151  * Executes modular exponentiation.
2152  * @param p  The program.
2153  */
2154 static void
2155 bc_program_modexp(BcProgram* p)
2156 {
2157         BcResult* r1;
2158         BcResult* r2;
2159         BcResult* r3;
2160         BcResult* res;
2161         BcNum* n1;
2162         BcNum* n2;
2163         BcNum* n3;
2164
2165 #if DC_ENABLED
2166
2167         // Check the stack.
2168         if (BC_IS_DC && BC_ERR(!BC_PROG_STACK(&p->results, 3)))
2169         {
2170                 bc_err(BC_ERR_EXEC_STACK);
2171         }
2172
2173 #endif // DC_ENABLED
2174
2175         assert(BC_PROG_STACK(&p->results, 3));
2176
2177         res = bc_program_prepResult(p);
2178
2179         // Get the first operand and typecheck.
2180         bc_program_operand(p, &r1, &n1, 3);
2181         bc_program_type_num(r1, n1);
2182
2183         // Get the last two operands.
2184         bc_program_binOpPrep(p, &r2, &n2, &r3, &n3, 1);
2185
2186         // Make sure that the values have their pointers updated, if necessary.
2187         // Only array elements are possible because this is dc.
2188         if (r1->t == BC_RESULT_ARRAY_ELEM && (r1->t == r2->t || r1->t == r3->t))
2189         {
2190                 n1 = bc_program_num(p, r1);
2191         }
2192
2193         BC_SIG_LOCK;
2194
2195         bc_num_init(&res->d.n, n3->len);
2196
2197         BC_SIG_UNLOCK;
2198
2199         bc_num_modexp(n1, n2, n3, &res->d.n);
2200
2201         bc_program_retire(p, 1, 3);
2202 }
2203
2204 /**
2205  * Asciifies a number for dc. This is a helper for bc_program_asciify().
2206  * @param p  The program.
2207  * @param n  The number to asciify.
2208  */
2209 static uchar
2210 bc_program_asciifyNum(BcProgram* p, BcNum* n)
2211 {
2212         bc_num_copy(&p->asciify, n);
2213
2214         // We want to clear the scale and sign for easy mod later.
2215         bc_num_truncate(&p->asciify, p->asciify.scale);
2216         BC_NUM_NEG_CLR(&p->asciify);
2217
2218         // This is guaranteed to not have a divide by 0
2219         // because strmb is equal to 256.
2220         bc_num_mod(&p->asciify, &p->strmb, &p->asciify, 0);
2221
2222         // This is also guaranteed to not error because num is in the range
2223         // [0, UCHAR_MAX], which is definitely in range for a BcBigDig. And
2224         // it is not negative.
2225         return (uchar) bc_num_bigdig2(&p->asciify);
2226 }
2227
2228 /**
2229  * Executes the "asciify" command in bc and dc.
2230  * @param p  The program.
2231  */
2232 static void
2233 bc_program_asciify(BcProgram* p)
2234 {
2235         BcResult *r, res;
2236         BcNum* n;
2237         uchar c;
2238         size_t idx;
2239 #if BC_ENABLED
2240         // This is in the outer scope because it has to be freed after a jump.
2241         char* temp_str;
2242 #endif // BC_ENABLED
2243
2244         // Check the stack.
2245         if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
2246
2247         assert(BC_PROG_STACK(&p->results, 1));
2248
2249         // Get the top of the results stack.
2250         bc_program_operand(p, &r, &n, 0);
2251
2252         assert(n != NULL);
2253         assert(BC_IS_BC || r->t != BC_RESULT_ARRAY);
2254
2255 #if BC_ENABLED
2256         // Handle arrays in bc specially.
2257         if (r->t == BC_RESULT_ARRAY)
2258         {
2259                 // Yes, this is one place where we need to cast the number from
2260                 // bc_program_num() to a vector.
2261                 BcVec* v = (BcVec*) n;
2262                 size_t i;
2263
2264                 // XXX: If this is changed, you should also change the similar code in
2265                 // bc_program_builtin().
2266
2267                 // Dereference the array, if necessary.
2268                 if (v->size == sizeof(uchar))
2269                 {
2270                         v = bc_program_dereference(p, v);
2271                 }
2272
2273                 assert(v->size == sizeof(BcNum));
2274
2275                 // Allocate the string and set the jump for it.
2276                 BC_SIG_LOCK;
2277                 temp_str = bc_vm_malloc(v->len + 1);
2278                 BC_SETJMP_LOCKED(vm, exit);
2279                 BC_SIG_UNLOCK;
2280
2281                 // Convert the array.
2282                 for (i = 0; i < v->len; ++i)
2283                 {
2284                         BcNum* num = (BcNum*) bc_vec_item(v, i);
2285
2286                         if (BC_PROG_STR(num))
2287                         {
2288                                 temp_str[i] = (bc_program_string(p, num))[0];
2289                         }
2290                         else
2291                         {
2292                                 temp_str[i] = (char) bc_program_asciifyNum(p, num);
2293                         }
2294                 }
2295
2296                 temp_str[v->len] = '\0';
2297
2298                 // Store the string in the slab and map, and free the temp string.
2299                 BC_SIG_LOCK;
2300                 idx = bc_program_addString(p, temp_str);
2301                 free(temp_str);
2302                 BC_UNSETJMP(vm);
2303                 BC_SIG_UNLOCK;
2304         }
2305         else
2306 #endif // BC_ENABLED
2307         {
2308                 char str[2];
2309                 char* str2;
2310
2311                 // Asciify.
2312                 if (BC_PROG_NUM(r, n)) c = bc_program_asciifyNum(p, n);
2313                 else
2314                 {
2315                         // Get the string itself, then the first character.
2316                         str2 = bc_program_string(p, n);
2317                         c = (uchar) str2[0];
2318                 }
2319
2320                 // Fill the resulting string.
2321                 str[0] = (char) c;
2322                 str[1] = '\0';
2323
2324                 // Add the string to the data structures.
2325                 BC_SIG_LOCK;
2326                 idx = bc_program_addString(p, str);
2327                 BC_SIG_UNLOCK;
2328         }
2329
2330         // Set the result
2331         res.t = BC_RESULT_STR;
2332         bc_num_clear(&res.d.n);
2333         res.d.n.scale = idx;
2334
2335         // Pop and push.
2336         bc_vec_pop(&p->results);
2337         bc_vec_push(&p->results, &res);
2338
2339         return;
2340
2341 #if BC_ENABLED
2342 exit:
2343         free(temp_str);
2344 #endif // BC_ENABLED
2345 }
2346
2347 /**
2348  * Streams a number or a string to stdout.
2349  * @param p  The program.
2350  */
2351 static void
2352 bc_program_printStream(BcProgram* p)
2353 {
2354         BcResult* r;
2355         BcNum* n;
2356
2357         // Check the stack.
2358         if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
2359
2360         assert(BC_PROG_STACK(&p->results, 1));
2361
2362         // Get the top of the results stack.
2363         bc_program_operand(p, &r, &n, 0);
2364
2365         assert(n != NULL);
2366
2367         // Stream appropriately.
2368         if (BC_PROG_NUM(r, n)) bc_num_stream(n);
2369         else bc_program_printChars(bc_program_string(p, n));
2370
2371         // Pop the operand.
2372         bc_vec_pop(&p->results);
2373 }
2374
2375 #if DC_ENABLED
2376
2377 /**
2378  * Gets the length of a register in dc and pushes it onto the results stack.
2379  * @param p     The program.
2380  * @param code  The bytecode vector to pull the register's index out of.
2381  * @param bgn   An in/out parameter; the start of the index in the bytecode
2382  *              vector, and will be updated to point after the index on return.
2383  */
2384 static void
2385 bc_program_regStackLen(BcProgram* p, const char* restrict code,
2386                        size_t* restrict bgn)
2387 {
2388         size_t idx = bc_program_index(code, bgn);
2389         BcVec* v = bc_program_vec(p, idx, BC_TYPE_VAR);
2390
2391         bc_program_pushBigdig(p, (BcBigDig) v->len, BC_RESULT_TEMP);
2392 }
2393
2394 /**
2395  * Pushes the length of the results stack onto the results stack.
2396  * @param p  The program.
2397  */
2398 static void
2399 bc_program_stackLen(BcProgram* p)
2400 {
2401         bc_program_pushBigdig(p, (BcBigDig) p->results.len, BC_RESULT_TEMP);
2402 }
2403
2404 /**
2405  * Pops a certain number of elements off the execution stack.
2406  * @param p     The program.
2407  * @param inst  The instruction to tell us how many. There is one to pop up to
2408  *              2, and one to pop the amount equal to the number at the top of
2409  *              the results stack.
2410  */
2411 static void
2412 bc_program_nquit(BcProgram* p, uchar inst)
2413 {
2414         BcResult* opnd;
2415         BcNum* num;
2416         BcBigDig val;
2417         size_t i;
2418
2419         // Ensure that the tail calls stack is correct.
2420         assert(p->stack.len == p->tail_calls.len);
2421
2422         // Get the number of executions to pop.
2423         if (inst == BC_INST_QUIT) val = 2;
2424         else
2425         {
2426                 bc_program_prep(p, &opnd, &num, 0);
2427                 val = bc_num_bigdig(num);
2428
2429                 bc_vec_pop(&p->results);
2430         }
2431
2432         // Loop over the tail call stack and adjust the quit value appropriately.
2433         for (i = 0; val && i < p->tail_calls.len; ++i)
2434         {
2435                 // Get the number of tail calls for this one.
2436                 size_t calls = *((size_t*) bc_vec_item_rev(&p->tail_calls, i)) + 1;
2437
2438                 // Adjust the value.
2439                 if (calls >= val) val = 0;
2440                 else val -= (BcBigDig) calls;
2441         }
2442
2443         // If we don't have enough executions, just quit.
2444         if (i == p->stack.len)
2445         {
2446                 vm->status = BC_STATUS_QUIT;
2447                 BC_JMP;
2448         }
2449         else
2450         {
2451                 // We can always pop the last item we reached on the tail call stack
2452                 // because these are for tail calls. That means that any executions that
2453                 // we would not have quit in that position on the stack would have quit
2454                 // anyway.
2455                 BC_SIG_LOCK;
2456                 bc_vec_npop(&p->stack, i);
2457                 bc_vec_npop(&p->tail_calls, i);
2458                 BC_SIG_UNLOCK;
2459         }
2460 }
2461
2462 /**
2463  * Pushes the depth of the execution stack onto the stack.
2464  * @param p  The program.
2465  */
2466 static void
2467 bc_program_execStackLen(BcProgram* p)
2468 {
2469         size_t i, amt, len = p->tail_calls.len;
2470
2471         amt = len;
2472
2473         for (i = 0; i < len; ++i)
2474         {
2475                 amt += *((size_t*) bc_vec_item(&p->tail_calls, i));
2476         }
2477
2478         bc_program_pushBigdig(p, (BcBigDig) amt, BC_RESULT_TEMP);
2479 }
2480
2481 /**
2482  *
2483  * @param p     The program.
2484  * @param code  The bytecode vector to pull the register's index out of.
2485  * @param bgn   An in/out parameter; the start of the index in the bytecode
2486  *              vector, and will be updated to point after the index on return.
2487  * @param cond  True if the execution is conditional, false otherwise.
2488  * @param len   The number of bytes in the bytecode vector.
2489  */
2490 static void
2491 bc_program_execStr(BcProgram* p, const char* restrict code,
2492                    size_t* restrict bgn, bool cond, size_t len)
2493 {
2494         BcResult* r;
2495         char* str;
2496         BcFunc* f;
2497         BcInstPtr ip;
2498         size_t fidx;
2499         BcNum* n;
2500
2501         assert(p->stack.len == p->tail_calls.len);
2502
2503         // Check the stack.
2504         if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK);
2505
2506         assert(BC_PROG_STACK(&p->results, 1));
2507
2508         // Get the operand.
2509         bc_program_operand(p, &r, &n, 0);
2510
2511         // If execution is conditional...
2512         if (cond)
2513         {
2514                 bool exec;
2515                 size_t then_idx;
2516                 // These are volatile to quiet warnings on GCC about clobbering with
2517                 // longjmp().
2518                 volatile size_t else_idx;
2519                 volatile size_t idx;
2520
2521                 // Get the index of the "then" var and "else" var.
2522                 then_idx = bc_program_index(code, bgn);
2523                 else_idx = bc_program_index(code, bgn);
2524
2525                 // Figure out if we should execute.
2526                 exec = (r->d.n.len != 0);
2527
2528                 idx = exec ? then_idx : else_idx;
2529
2530                 BC_SIG_LOCK;
2531                 BC_SETJMP_LOCKED(vm, exit);
2532
2533                 // If we are supposed to execute, execute. If else_idx == SIZE_MAX, that
2534                 // means there was no else clause, so if execute is false and else does
2535                 // not exist, we don't execute. The goto skips all of the setup for the
2536                 // execution.
2537                 if (exec || (else_idx != SIZE_MAX))
2538                 {
2539                         n = bc_vec_top(bc_program_vec(p, idx, BC_TYPE_VAR));
2540                 }
2541                 else goto exit;
2542
2543                 if (BC_ERR(!BC_PROG_STR(n))) bc_err(BC_ERR_EXEC_TYPE);
2544
2545                 BC_UNSETJMP(vm);
2546                 BC_SIG_UNLOCK;
2547         }
2548         else
2549         {
2550                 // In non-conditional situations, only the top of stack can be executed,
2551                 // and in those cases, variables are not allowed to be "on the stack";
2552                 // they are only put on the stack to be assigned to.
2553                 assert(r->t != BC_RESULT_VAR);
2554
2555                 if (r->t != BC_RESULT_STR) return;
2556         }
2557
2558         assert(BC_PROG_STR(n));
2559
2560         // Get the string.
2561         str = bc_program_string(p, n);
2562
2563         // Get the function index and function.
2564         BC_SIG_LOCK;
2565         fidx = bc_program_insertFunc(p, str);
2566         BC_SIG_UNLOCK;
2567         f = bc_vec_item(&p->fns, fidx);
2568
2569         // If the function has not been parsed yet...
2570         if (!f->code.len)
2571         {
2572                 BC_SIG_LOCK;
2573
2574                 if (!BC_PARSE_IS_INITED(&vm->read_prs, p))
2575                 {
2576                         bc_parse_init(&vm->read_prs, p, fidx);
2577
2578                         // Initialize this too because bc_vm_shutdown() expects them to be
2579                         // initialized togther.
2580                         bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE);
2581                 }
2582                 // This needs to be updated because the parser could have been used
2583                 // somewhere else
2584                 else bc_parse_updateFunc(&vm->read_prs, fidx);
2585
2586                 bc_lex_file(&vm->read_prs.l, vm->file);
2587
2588                 BC_SETJMP_LOCKED(vm, err);
2589
2590                 BC_SIG_UNLOCK;
2591
2592                 // Parse. Only one expression is needed, so stdin isn't used.
2593                 bc_parse_text(&vm->read_prs, str, BC_MODE_FILE);
2594
2595                 BC_SIG_LOCK;
2596                 vm->expr(&vm->read_prs, BC_PARSE_NOCALL);
2597
2598                 BC_UNSETJMP(vm);
2599
2600                 // We can just assert this here because
2601                 // dc should parse everything until EOF.
2602                 assert(vm->read_prs.l.t == BC_LEX_EOF);
2603
2604                 BC_SIG_UNLOCK;
2605         }
2606
2607         // Set the instruction pointer.
2608         ip.idx = 0;
2609         ip.len = p->results.len;
2610         ip.func = fidx;
2611
2612         BC_SIG_LOCK;
2613
2614         // Pop the operand.
2615         bc_vec_pop(&p->results);
2616
2617         // Tail call processing. This condition means that there is more on the
2618         // execution stack, and we are at the end of the bytecode vector, and the
2619         // last instruction is just a BC_INST_POP_EXEC, which would return.
2620         if (p->stack.len > 1 && *bgn == len - 1 && code[*bgn] == BC_INST_POP_EXEC)
2621         {
2622                 size_t* call_ptr = bc_vec_top(&p->tail_calls);
2623
2624                 // Add one to the tail call.
2625                 *call_ptr += 1;
2626
2627                 // Pop the execution stack before pushing the new instruction pointer
2628                 // on.
2629                 bc_vec_pop(&p->stack);
2630         }
2631         // If not a tail call, just push a new one.
2632         else bc_vec_push(&p->tail_calls, &ip.idx);
2633
2634         // Push the new function onto the execution stack and return.
2635         bc_vec_push(&p->stack, &ip);
2636
2637         BC_SIG_UNLOCK;
2638
2639         return;
2640
2641 err:
2642         BC_SIG_MAYLOCK;
2643
2644         f = bc_vec_item(&p->fns, fidx);
2645
2646         // Make sure to erase the bytecode vector so dc knows it is not parsed.
2647         bc_vec_popAll(&f->code);
2648
2649 exit:
2650         bc_vec_pop(&p->results);
2651         BC_LONGJMP_CONT(vm);
2652 }
2653
2654 /**
2655  * Prints every item on the results stack, one per line.
2656  * @param p  The program.
2657  */
2658 static void
2659 bc_program_printStack(BcProgram* p)
2660 {
2661         size_t idx;
2662
2663         for (idx = 0; idx < p->results.len; ++idx)
2664         {
2665                 bc_program_print(p, BC_INST_PRINT, idx);
2666         }
2667 }
2668 #endif // DC_ENABLED
2669
2670 /**
2671  * Pushes the value of a global onto the results stack.
2672  * @param p     The program.
2673  * @param inst  Which global to push, as an instruction.
2674  */
2675 static void
2676 bc_program_pushGlobal(BcProgram* p, uchar inst)
2677 {
2678         BcResultType t;
2679
2680         // Make sure the instruction is valid.
2681         assert(inst >= BC_INST_IBASE && inst <= BC_INST_SCALE);
2682
2683         // Push the global.
2684         t = inst - BC_INST_IBASE + BC_RESULT_IBASE;
2685         bc_program_pushBigdig(p, p->globals[inst - BC_INST_IBASE], t);
2686 }
2687
2688 /**
2689  * Pushes the value of a global setting onto the stack.
2690  * @param p     The program.
2691  * @param inst  Which global setting to push, as an instruction.
2692  */
2693 static void
2694 bc_program_globalSetting(BcProgram* p, uchar inst)
2695 {
2696         BcBigDig val;
2697
2698         // Make sure the instruction is valid.
2699 #if DC_ENABLED
2700         assert((inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO) ||
2701                (BC_IS_DC && inst == BC_INST_EXTENDED_REGISTERS));
2702 #else // DC_ENABLED
2703         assert(inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO);
2704 #endif // DC_ENABLED
2705
2706         if (inst == BC_INST_LINE_LENGTH)
2707         {
2708                 val = (BcBigDig) vm->line_len;
2709         }
2710 #if BC_ENABLED
2711         else if (inst == BC_INST_GLOBAL_STACKS)
2712         {
2713                 val = (BC_G != 0);
2714         }
2715 #endif // BC_ENABLED
2716 #if DC_ENABLED
2717         else if (inst == BC_INST_EXTENDED_REGISTERS)
2718         {
2719                 val = (DC_X != 0);
2720         }
2721 #endif // DC_ENABLED
2722         else val = (BC_Z != 0);
2723
2724         // Push the global.
2725         bc_program_pushBigdig(p, val, BC_RESULT_TEMP);
2726 }
2727
2728 #if BC_ENABLE_EXTRA_MATH
2729
2730 /**
2731  * Pushes the value of seed on the stack.
2732  * @param p  The program.
2733  */
2734 static void
2735 bc_program_pushSeed(BcProgram* p)
2736 {
2737         BcResult* res;
2738
2739         res = bc_program_prepResult(p);
2740         res->t = BC_RESULT_SEED;
2741
2742         BC_SIG_LOCK;
2743
2744         // We need 2*BC_RAND_NUM_SIZE because of the size of the state.
2745         bc_num_init(&res->d.n, 2 * BC_RAND_NUM_SIZE);
2746
2747         BC_SIG_UNLOCK;
2748
2749         bc_num_createFromRNG(&res->d.n, &p->rng);
2750 }
2751
2752 #endif // BC_ENABLE_EXTRA_MATH
2753
2754 /**
2755  * Adds a function to the fns array. The function's ID must have already been
2756  * inserted into the map.
2757  * @param p       The program.
2758  * @param id_ptr  The ID of the function as inserted into the map.
2759  */
2760 static void
2761 bc_program_addFunc(BcProgram* p, BcId* id_ptr)
2762 {
2763         BcFunc* f;
2764
2765         BC_SIG_ASSERT_LOCKED;
2766
2767         // Push and init.
2768         f = bc_vec_pushEmpty(&p->fns);
2769         bc_func_init(f, id_ptr->name);
2770 }
2771
2772 size_t
2773 bc_program_insertFunc(BcProgram* p, const char* name)
2774 {
2775         BcId* id_ptr;
2776         bool new;
2777         size_t idx;
2778
2779         BC_SIG_ASSERT_LOCKED;
2780
2781         assert(p != NULL && name != NULL);
2782
2783         // Insert into the map and get the resulting ID.
2784         new = bc_map_insert(&p->fn_map, name, p->fns.len, &idx);
2785         id_ptr = (BcId*) bc_vec_item(&p->fn_map, idx);
2786         idx = id_ptr->idx;
2787
2788         // If the function is new...
2789         if (new)
2790         {
2791                 // Add the function to the fns array.
2792                 bc_program_addFunc(p, id_ptr);
2793         }
2794 #if BC_ENABLED
2795         // bc has to reset the function because it's about to be redefined.
2796         else if (BC_IS_BC)
2797         {
2798                 BcFunc* func = bc_vec_item(&p->fns, idx);
2799                 bc_func_reset(func);
2800         }
2801 #endif // BC_ENABLED
2802
2803         return idx;
2804 }
2805
2806 #if BC_DEBUG
2807 void
2808 bc_program_free(BcProgram* p)
2809 {
2810 #if BC_ENABLED
2811         size_t i;
2812 #endif // BC_ENABLED
2813
2814         BC_SIG_ASSERT_LOCKED;
2815
2816         assert(p != NULL);
2817
2818 #if BC_ENABLED
2819         // Free the globals stacks.
2820         for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
2821         {
2822                 bc_vec_free(p->globals_v + i);
2823         }
2824 #endif // BC_ENABLED
2825
2826         bc_vec_free(&p->fns);
2827         bc_vec_free(&p->fn_map);
2828         bc_vec_free(&p->vars);
2829         bc_vec_free(&p->var_map);
2830         bc_vec_free(&p->arrs);
2831         bc_vec_free(&p->arr_map);
2832         bc_vec_free(&p->results);
2833         bc_vec_free(&p->stack);
2834         bc_vec_free(&p->consts);
2835         bc_vec_free(&p->const_map);
2836         bc_vec_free(&p->strs);
2837         bc_vec_free(&p->str_map);
2838
2839         bc_num_free(&p->asciify);
2840
2841 #if BC_ENABLED
2842         if (BC_IS_BC) bc_num_free(&p->last);
2843 #endif // BC_ENABLED
2844
2845 #if BC_ENABLE_EXTRA_MATH
2846         bc_rand_free(&p->rng);
2847 #endif // BC_ENABLE_EXTRA_MATH
2848
2849 #if DC_ENABLED
2850         if (BC_IS_DC) bc_vec_free(&p->tail_calls);
2851 #endif // DC_ENABLED
2852 }
2853 #endif // BC_DEBUG
2854
2855 void
2856 bc_program_init(BcProgram* p)
2857 {
2858         BcInstPtr ip;
2859         size_t i;
2860
2861         BC_SIG_ASSERT_LOCKED;
2862
2863         assert(p != NULL);
2864
2865         // We want this clear.
2866         // NOLINTNEXTLINE
2867         memset(&ip, 0, sizeof(BcInstPtr));
2868
2869         // Setup the globals stacks and the current values.
2870         for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i)
2871         {
2872                 BcBigDig val = i == BC_PROG_GLOBALS_SCALE ? 0 : BC_BASE;
2873
2874 #if BC_ENABLED
2875                 bc_vec_init(p->globals_v + i, sizeof(BcBigDig), BC_DTOR_NONE);
2876                 bc_vec_push(p->globals_v + i, &val);
2877 #endif // BC_ENABLED
2878
2879                 p->globals[i] = val;
2880         }
2881
2882 #if DC_ENABLED
2883         // dc-only setup.
2884         if (BC_IS_DC)
2885         {
2886                 bc_vec_init(&p->tail_calls, sizeof(size_t), BC_DTOR_NONE);
2887
2888                 // We want an item for the main function on the tail call stack.
2889                 i = 0;
2890                 bc_vec_push(&p->tail_calls, &i);
2891         }
2892 #endif // DC_ENABLED
2893
2894         bc_num_setup(&p->strmb, p->strmb_num, BC_NUM_BIGDIG_LOG10);
2895         bc_num_bigdig2num(&p->strmb, BC_NUM_STREAM_BASE);
2896
2897         bc_num_init(&p->asciify, BC_NUM_DEF_SIZE);
2898
2899 #if BC_ENABLE_EXTRA_MATH
2900         // We need to initialize srand() just in case /dev/urandom and /dev/random
2901         // are not available.
2902         srand((unsigned int) time(NULL));
2903         bc_rand_init(&p->rng);
2904 #endif // BC_ENABLE_EXTRA_MATH
2905
2906 #if BC_ENABLED
2907         if (BC_IS_BC) bc_num_init(&p->last, BC_NUM_DEF_SIZE);
2908 #endif // BC_ENABLED
2909
2910 #if BC_DEBUG
2911         bc_vec_init(&p->fns, sizeof(BcFunc), BC_DTOR_FUNC);
2912 #else // BC_DEBUG
2913         bc_vec_init(&p->fns, sizeof(BcFunc), BC_DTOR_NONE);
2914 #endif // BC_DEBUG
2915         bc_map_init(&p->fn_map);
2916         bc_program_insertFunc(p, bc_func_main);
2917         bc_program_insertFunc(p, bc_func_read);
2918
2919         bc_vec_init(&p->vars, sizeof(BcVec), BC_DTOR_VEC);
2920         bc_map_init(&p->var_map);
2921
2922         bc_vec_init(&p->arrs, sizeof(BcVec), BC_DTOR_VEC);
2923         bc_map_init(&p->arr_map);
2924
2925         bc_vec_init(&p->results, sizeof(BcResult), BC_DTOR_RESULT);
2926
2927         // Push the first instruction pointer onto the execution stack.
2928         bc_vec_init(&p->stack, sizeof(BcInstPtr), BC_DTOR_NONE);
2929         bc_vec_push(&p->stack, &ip);
2930
2931         bc_vec_init(&p->consts, sizeof(BcConst), BC_DTOR_CONST);
2932         bc_map_init(&p->const_map);
2933         bc_vec_init(&p->strs, sizeof(char*), BC_DTOR_NONE);
2934         bc_map_init(&p->str_map);
2935 }
2936
2937 void
2938 bc_program_printStackTrace(BcProgram* p)
2939 {
2940         size_t i, max_digits;
2941
2942         max_digits = bc_vm_numDigits(p->stack.len - 1);
2943
2944         for (i = 0; i < p->stack.len; ++i)
2945         {
2946                 BcInstPtr* ip = bc_vec_item_rev(&p->stack, i);
2947                 BcFunc* f = bc_vec_item(&p->fns, ip->func);
2948                 size_t j, digits;
2949
2950                 digits = bc_vm_numDigits(i);
2951
2952                 bc_file_puts(&vm->ferr, bc_flush_none, "    ");
2953
2954                 for (j = 0; j < max_digits - digits; ++j)
2955                 {
2956                         bc_file_putchar(&vm->ferr, bc_flush_none, ' ');
2957                 }
2958
2959                 bc_file_printf(&vm->ferr, "%zu: %s", i, f->name);
2960
2961 #if BC_ENABLED
2962                 if (BC_IS_BC && ip->func != BC_PROG_MAIN && ip->func != BC_PROG_READ)
2963                 {
2964                         bc_file_puts(&vm->ferr, bc_flush_none, "()");
2965                 }
2966 #endif // BC_ENABLED
2967
2968                 bc_file_putchar(&vm->ferr, bc_flush_none, '\n');
2969         }
2970 }
2971
2972 void
2973 bc_program_reset(BcProgram* p)
2974 {
2975         BcFunc* f;
2976         BcInstPtr* ip;
2977
2978         BC_SIG_ASSERT_LOCKED;
2979
2980         // Pop all but the last execution and all results.
2981         bc_vec_npop(&p->stack, p->stack.len - 1);
2982         bc_vec_popAll(&p->results);
2983
2984 #if DC_ENABLED
2985         // We need to pop tail calls too.
2986         if (BC_IS_DC) bc_vec_npop(&p->tail_calls, p->tail_calls.len - 1);
2987 #endif // DC_ENABLED
2988
2989 #if BC_ENABLED
2990         // Clear the globals' stacks.
2991         if (BC_G) bc_program_popGlobals(p, true);
2992 #endif // BC_ENABLED
2993
2994         // Clear the bytecode vector of the main function.
2995         f = bc_vec_item(&p->fns, BC_PROG_MAIN);
2996         bc_vec_npop(&f->code, f->code.len);
2997
2998         // Reset the instruction pointer.
2999         ip = bc_vec_top(&p->stack);
3000         // NOLINTNEXTLINE
3001         memset(ip, 0, sizeof(BcInstPtr));
3002
3003         if (BC_SIG_INTERRUPT(vm))
3004         {
3005                 // Write the ready message for a signal.
3006                 bc_file_printf(&vm->fout, "%s", bc_program_ready_msg);
3007                 bc_file_flush(&vm->fout, bc_flush_err);
3008         }
3009
3010         // Clear the signal.
3011         vm->sig = 0;
3012 }
3013
3014 void
3015 bc_program_exec(BcProgram* p)
3016 {
3017         size_t idx;
3018         BcResult r;
3019         BcResult* ptr;
3020         BcInstPtr* ip;
3021         BcFunc* func;
3022         char* code;
3023         bool cond = false;
3024         uchar inst;
3025 #if BC_ENABLED
3026         BcNum* num;
3027 #endif // BC_ENABLED
3028 #if !BC_HAS_COMPUTED_GOTO
3029 #if BC_DEBUG
3030         size_t jmp_bufs_len;
3031 #endif // BC_DEBUG
3032 #endif // !BC_HAS_COMPUTED_GOTO
3033
3034 #if BC_HAS_COMPUTED_GOTO
3035
3036 #if BC_GCC
3037 #pragma GCC diagnostic ignored "-Wpedantic"
3038 #endif // BC_GCC
3039
3040 #if BC_CLANG
3041 #pragma clang diagnostic ignored "-Wgnu-label-as-value"
3042 #endif // BC_CLANG
3043
3044         BC_PROG_LBLS;
3045         BC_PROG_LBLS_ASSERT;
3046
3047 #if BC_CLANG
3048 #pragma clang diagnostic warning "-Wgnu-label-as-value"
3049 #endif // BC_CLANG
3050
3051 #if BC_GCC
3052 #pragma GCC diagnostic warning "-Wpedantic"
3053 #endif // BC_GCC
3054
3055         // BC_INST_INVALID is a marker for the end so that we don't have to have an
3056         // execution loop.
3057         func = (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN);
3058         bc_vec_pushByte(&func->code, BC_INST_INVALID);
3059 #endif // BC_HAS_COMPUTED_GOTO
3060
3061         BC_SETJMP(vm, end);
3062
3063         ip = bc_vec_top(&p->stack);
3064         func = (BcFunc*) bc_vec_item(&p->fns, ip->func);
3065         code = func->code.v;
3066
3067 #if !BC_HAS_COMPUTED_GOTO
3068
3069 #if BC_DEBUG
3070         jmp_bufs_len = vm->jmp_bufs.len;
3071 #endif // BC_DEBUG
3072
3073         // This loop is the heart of the execution engine. It *is* the engine. For
3074         // computed goto, it is ignored.
3075         while (ip->idx < func->code.len)
3076 #endif // !BC_HAS_COMPUTED_GOTO
3077         {
3078                 BC_SIG_ASSERT_NOT_LOCKED;
3079
3080 #if BC_HAS_COMPUTED_GOTO
3081
3082 #if BC_GCC
3083 #pragma GCC diagnostic ignored "-Wpedantic"
3084 #endif // BC_GCC
3085
3086 #if BC_CLANG
3087 #pragma clang diagnostic ignored "-Wgnu-label-as-value"
3088 #endif // BC_CLANG
3089
3090                 BC_PROG_JUMP(inst, code, ip);
3091
3092 #else // BC_HAS_COMPUTED_GOTO
3093
3094                 // Get the next instruction and increment the index.
3095                 inst = (uchar) code[(ip->idx)++];
3096
3097 #endif // BC_HAS_COMPUTED_GOTO
3098
3099 #if BC_DEBUG_CODE
3100                 bc_file_printf(&vm->ferr, "inst: %s\n", bc_inst_names[inst]);
3101                 bc_file_flush(&vm->ferr, bc_flush_none);
3102 #endif // BC_DEBUG_CODE
3103
3104 #if !BC_HAS_COMPUTED_GOTO
3105                 switch (inst)
3106 #endif // !BC_HAS_COMPUTED_GOTO
3107                 {
3108 #if BC_ENABLED
3109                         // This just sets up the condition for the unconditional jump below,
3110                         // which checks the condition, if necessary.
3111                         // clang-format off
3112                         BC_PROG_LBL(BC_INST_JUMP_ZERO):
3113                         // clang-format on
3114                         {
3115                                 bc_program_prep(p, &ptr, &num, 0);
3116
3117                                 cond = !bc_num_cmpZero(num);
3118                                 bc_vec_pop(&p->results);
3119
3120                                 BC_PROG_DIRECT_JUMP(BC_INST_JUMP)
3121                         }
3122                         // Fallthrough.
3123                         BC_PROG_FALLTHROUGH
3124
3125                         // clang-format off
3126                         BC_PROG_LBL(BC_INST_JUMP):
3127                         // clang-format on
3128                         {
3129                                 idx = bc_program_index(code, &ip->idx);
3130
3131                                 // If a jump is required...
3132                                 if (inst == BC_INST_JUMP || cond)
3133                                 {
3134                                         // Get the address to jump to.
3135                                         size_t* addr = bc_vec_item(&func->labels, idx);
3136
3137                                         // If this fails, then the parser failed to set up the
3138                                         // labels correctly.
3139                                         assert(*addr != SIZE_MAX);
3140
3141                                         // Set the new address.
3142                                         ip->idx = *addr;
3143                                 }
3144
3145                                 BC_PROG_JUMP(inst, code, ip);
3146                         }
3147
3148                         // clang-format off
3149                         BC_PROG_LBL(BC_INST_CALL):
3150                         // clang-format on
3151                         {
3152                                 assert(BC_IS_BC);
3153
3154                                 bc_program_call(p, code, &ip->idx);
3155
3156                                 // Because we changed the execution stack and where we are
3157                                 // executing, we have to update all of this.
3158                                 BC_SIG_LOCK;
3159                                 ip = bc_vec_top(&p->stack);
3160                                 func = bc_vec_item(&p->fns, ip->func);
3161                                 code = func->code.v;
3162                                 BC_SIG_UNLOCK;
3163
3164                                 BC_PROG_JUMP(inst, code, ip);
3165                         }
3166
3167                         // clang-format off
3168                         BC_PROG_LBL(BC_INST_INC):
3169                         BC_PROG_LBL(BC_INST_DEC):
3170                         // clang-format on
3171                         {
3172                                 bc_program_incdec(p, inst);
3173                                 BC_PROG_JUMP(inst, code, ip);
3174                         }
3175
3176                         // clang-format off
3177                         BC_PROG_LBL(BC_INST_HALT):
3178                         // clang-format on
3179                         {
3180                                 vm->status = BC_STATUS_QUIT;
3181
3182                                 // Just jump out. The jump series will take care of everything.
3183                                 BC_JMP;
3184
3185                                 BC_PROG_JUMP(inst, code, ip);
3186                         }
3187
3188                         // clang-format off
3189                         BC_PROG_LBL(BC_INST_RET):
3190                         BC_PROG_LBL(BC_INST_RET0):
3191                         BC_PROG_LBL(BC_INST_RET_VOID):
3192                         // clang-format on
3193                         {
3194                                 bc_program_return(p, inst);
3195
3196                                 // Because we changed the execution stack and where we are
3197                                 // executing, we have to update all of this.
3198                                 BC_SIG_LOCK;
3199                                 ip = bc_vec_top(&p->stack);
3200                                 func = bc_vec_item(&p->fns, ip->func);
3201                                 code = func->code.v;
3202                                 BC_SIG_UNLOCK;
3203
3204                                 BC_PROG_JUMP(inst, code, ip);
3205                         }
3206 #endif // BC_ENABLED
3207
3208                         // clang-format off
3209                         BC_PROG_LBL(BC_INST_BOOL_OR):
3210                         BC_PROG_LBL(BC_INST_BOOL_AND):
3211                         BC_PROG_LBL(BC_INST_REL_EQ):
3212                         BC_PROG_LBL(BC_INST_REL_LE):
3213                         BC_PROG_LBL(BC_INST_REL_GE):
3214                         BC_PROG_LBL(BC_INST_REL_NE):
3215                         BC_PROG_LBL(BC_INST_REL_LT):
3216                         BC_PROG_LBL(BC_INST_REL_GT):
3217                         // clang-format on
3218                         {
3219                                 bc_program_logical(p, inst);
3220                                 BC_PROG_JUMP(inst, code, ip);
3221                         }
3222
3223                         // clang-format off
3224                         BC_PROG_LBL(BC_INST_READ):
3225                         // clang-format on
3226                         {
3227                                 // We want to flush output before
3228                                 // this in case there is a prompt.
3229                                 bc_file_flush(&vm->fout, bc_flush_save);
3230
3231                                 bc_program_read(p);
3232
3233                                 // Because we changed the execution stack and where we are
3234                                 // executing, we have to update all of this.
3235                                 BC_SIG_LOCK;
3236                                 ip = bc_vec_top(&p->stack);
3237                                 func = bc_vec_item(&p->fns, ip->func);
3238                                 code = func->code.v;
3239                                 BC_SIG_UNLOCK;
3240
3241                                 BC_PROG_JUMP(inst, code, ip);
3242                         }
3243
3244 #if BC_ENABLE_EXTRA_MATH
3245                         // clang-format off
3246                         BC_PROG_LBL(BC_INST_RAND):
3247                         // clang-format on
3248                         {
3249                                 bc_program_rand(p);
3250                                 BC_PROG_JUMP(inst, code, ip);
3251                         }
3252 #endif // BC_ENABLE_EXTRA_MATH
3253
3254                         // clang-format off
3255                         BC_PROG_LBL(BC_INST_MAXIBASE):
3256                         BC_PROG_LBL(BC_INST_MAXOBASE):
3257                         BC_PROG_LBL(BC_INST_MAXSCALE):
3258 #if BC_ENABLE_EXTRA_MATH
3259                         BC_PROG_LBL(BC_INST_MAXRAND):
3260 #endif // BC_ENABLE_EXTRA_MATH
3261                         // clang-format on
3262                         {
3263                                 BcBigDig dig = vm->maxes[inst - BC_INST_MAXIBASE];
3264                                 bc_program_pushBigdig(p, dig, BC_RESULT_TEMP);
3265                                 BC_PROG_JUMP(inst, code, ip);
3266                         }
3267
3268                         // clang-format off
3269                         BC_PROG_LBL(BC_INST_LINE_LENGTH):
3270 #if BC_ENABLED
3271                         BC_PROG_LBL(BC_INST_GLOBAL_STACKS):
3272 #endif // BC_ENABLED
3273 #if DC_ENABLED
3274                         BC_PROG_LBL(BC_INST_EXTENDED_REGISTERS):
3275 #endif // DC_ENABLE
3276                         BC_PROG_LBL(BC_INST_LEADING_ZERO):
3277                         // clang-format on
3278                         {
3279                                 bc_program_globalSetting(p, inst);
3280                                 BC_PROG_JUMP(inst, code, ip);
3281                         }
3282
3283                         // clang-format off
3284                         BC_PROG_LBL(BC_INST_VAR):
3285                         // clang-format on
3286                         {
3287                                 bc_program_pushVar(p, code, &ip->idx, false, false);
3288                                 BC_PROG_JUMP(inst, code, ip);
3289                         }
3290
3291                         // clang-format off
3292                         BC_PROG_LBL(BC_INST_ARRAY_ELEM):
3293                         BC_PROG_LBL(BC_INST_ARRAY):
3294                         // clang-format on
3295                         {
3296                                 bc_program_pushArray(p, code, &ip->idx, inst);
3297                                 BC_PROG_JUMP(inst, code, ip);
3298                         }
3299
3300                         // clang-format off
3301                         BC_PROG_LBL(BC_INST_IBASE):
3302                         BC_PROG_LBL(BC_INST_SCALE):
3303                         BC_PROG_LBL(BC_INST_OBASE):
3304                         // clang-format on
3305                         {
3306                                 bc_program_pushGlobal(p, inst);
3307                                 BC_PROG_JUMP(inst, code, ip);
3308                         }
3309
3310 #if BC_ENABLE_EXTRA_MATH
3311                         // clang-format off
3312                         BC_PROG_LBL(BC_INST_SEED):
3313                         // clang-format on
3314                         {
3315                                 bc_program_pushSeed(p);
3316                                 BC_PROG_JUMP(inst, code, ip);
3317                         }
3318 #endif // BC_ENABLE_EXTRA_MATH
3319
3320                         // clang-format off
3321                         BC_PROG_LBL(BC_INST_LENGTH):
3322                         BC_PROG_LBL(BC_INST_SCALE_FUNC):
3323                         BC_PROG_LBL(BC_INST_SQRT):
3324                         BC_PROG_LBL(BC_INST_ABS):
3325                         BC_PROG_LBL(BC_INST_IS_NUMBER):
3326                         BC_PROG_LBL(BC_INST_IS_STRING):
3327 #if BC_ENABLE_EXTRA_MATH
3328                         BC_PROG_LBL(BC_INST_IRAND):
3329 #endif // BC_ENABLE_EXTRA_MATH
3330                         // clang-format on
3331                         {
3332                                 bc_program_builtin(p, inst);
3333                                 BC_PROG_JUMP(inst, code, ip);
3334                         }
3335
3336                         // clang-format off
3337                         BC_PROG_LBL(BC_INST_ASCIIFY):
3338                         // clang-format on
3339                         {
3340                                 bc_program_asciify(p);
3341
3342                                 // Because we changed the execution stack and where we are
3343                                 // executing, we have to update all of this.
3344                                 BC_SIG_LOCK;
3345                                 ip = bc_vec_top(&p->stack);
3346                                 func = bc_vec_item(&p->fns, ip->func);
3347                                 code = func->code.v;
3348                                 BC_SIG_UNLOCK;
3349
3350                                 BC_PROG_JUMP(inst, code, ip);
3351                         }
3352
3353                         // clang-format off
3354                         BC_PROG_LBL(BC_INST_NUM):
3355                         // clang-format on
3356                         {
3357                                 bc_program_const(p, code, &ip->idx);
3358                                 BC_PROG_JUMP(inst, code, ip);
3359                         }
3360
3361                         // clang-format off
3362                         BC_PROG_LBL(BC_INST_ZERO):
3363                         BC_PROG_LBL(BC_INST_ONE):
3364 #if BC_ENABLED
3365                         BC_PROG_LBL(BC_INST_LAST):
3366 #endif // BC_ENABLED
3367                         // clang-format on
3368                         {
3369                                 r.t = BC_RESULT_ZERO + (inst - BC_INST_ZERO);
3370                                 bc_vec_push(&p->results, &r);
3371                                 BC_PROG_JUMP(inst, code, ip);
3372                         }
3373
3374                         // clang-format off
3375                         BC_PROG_LBL(BC_INST_PRINT):
3376                         BC_PROG_LBL(BC_INST_PRINT_POP):
3377 #if BC_ENABLED
3378                         BC_PROG_LBL(BC_INST_PRINT_STR):
3379 #endif // BC_ENABLED
3380                         // clang-format on
3381                         {
3382                                 bc_program_print(p, inst, 0);
3383
3384                                 // We want to flush right away to save the output for history,
3385                                 // if history must preserve it when taking input.
3386                                 bc_file_flush(&vm->fout, bc_flush_save);
3387
3388                                 BC_PROG_JUMP(inst, code, ip);
3389                         }
3390
3391                         // clang-format off
3392                         BC_PROG_LBL(BC_INST_STR):
3393                         // clang-format on
3394                         {
3395                                 // Set up the result and push.
3396                                 r.t = BC_RESULT_STR;
3397                                 bc_num_clear(&r.d.n);
3398                                 r.d.n.scale = bc_program_index(code, &ip->idx);
3399                                 bc_vec_push(&p->results, &r);
3400                                 BC_PROG_JUMP(inst, code, ip);
3401                         }
3402
3403                         // clang-format off
3404                         BC_PROG_LBL(BC_INST_POWER):
3405                         BC_PROG_LBL(BC_INST_MULTIPLY):
3406                         BC_PROG_LBL(BC_INST_DIVIDE):
3407                         BC_PROG_LBL(BC_INST_MODULUS):
3408                         BC_PROG_LBL(BC_INST_PLUS):
3409                         BC_PROG_LBL(BC_INST_MINUS):
3410 #if BC_ENABLE_EXTRA_MATH
3411                         BC_PROG_LBL(BC_INST_PLACES):
3412                         BC_PROG_LBL(BC_INST_LSHIFT):
3413                         BC_PROG_LBL(BC_INST_RSHIFT):
3414 #endif // BC_ENABLE_EXTRA_MATH
3415                         // clang-format on
3416                         {
3417                                 bc_program_op(p, inst);
3418                                 BC_PROG_JUMP(inst, code, ip);
3419                         }
3420
3421                         // clang-format off
3422                         BC_PROG_LBL(BC_INST_NEG):
3423                         BC_PROG_LBL(BC_INST_BOOL_NOT):
3424 #if BC_ENABLE_EXTRA_MATH
3425                         BC_PROG_LBL(BC_INST_TRUNC):
3426 #endif // BC_ENABLE_EXTRA_MATH
3427                         // clang-format on
3428                         {
3429                                 bc_program_unary(p, inst);
3430                                 BC_PROG_JUMP(inst, code, ip);
3431                         }
3432
3433                         // clang-format off
3434 #if BC_ENABLED
3435                         BC_PROG_LBL(BC_INST_ASSIGN_POWER):
3436                         BC_PROG_LBL(BC_INST_ASSIGN_MULTIPLY):
3437                         BC_PROG_LBL(BC_INST_ASSIGN_DIVIDE):
3438                         BC_PROG_LBL(BC_INST_ASSIGN_MODULUS):
3439                         BC_PROG_LBL(BC_INST_ASSIGN_PLUS):
3440                         BC_PROG_LBL(BC_INST_ASSIGN_MINUS):
3441 #if BC_ENABLE_EXTRA_MATH
3442                         BC_PROG_LBL(BC_INST_ASSIGN_PLACES):
3443                         BC_PROG_LBL(BC_INST_ASSIGN_LSHIFT):
3444                         BC_PROG_LBL(BC_INST_ASSIGN_RSHIFT):
3445 #endif // BC_ENABLE_EXTRA_MATH
3446                         BC_PROG_LBL(BC_INST_ASSIGN):
3447                         BC_PROG_LBL(BC_INST_ASSIGN_POWER_NO_VAL):
3448                         BC_PROG_LBL(BC_INST_ASSIGN_MULTIPLY_NO_VAL):
3449                         BC_PROG_LBL(BC_INST_ASSIGN_DIVIDE_NO_VAL):
3450                         BC_PROG_LBL(BC_INST_ASSIGN_MODULUS_NO_VAL):
3451                         BC_PROG_LBL(BC_INST_ASSIGN_PLUS_NO_VAL):
3452                         BC_PROG_LBL(BC_INST_ASSIGN_MINUS_NO_VAL):
3453 #if BC_ENABLE_EXTRA_MATH
3454                         BC_PROG_LBL(BC_INST_ASSIGN_PLACES_NO_VAL):
3455                         BC_PROG_LBL(BC_INST_ASSIGN_LSHIFT_NO_VAL):
3456                         BC_PROG_LBL(BC_INST_ASSIGN_RSHIFT_NO_VAL):
3457 #endif // BC_ENABLE_EXTRA_MATH
3458 #endif // BC_ENABLED
3459                         BC_PROG_LBL(BC_INST_ASSIGN_NO_VAL):
3460                         // clang-format on
3461                         {
3462                                 bc_program_assign(p, inst);
3463                                 BC_PROG_JUMP(inst, code, ip);
3464                         }
3465
3466                         // clang-format off
3467                         BC_PROG_LBL(BC_INST_POP):
3468                         // clang-format on
3469                         {
3470 #ifndef BC_PROG_NO_STACK_CHECK
3471                                 // dc must do a stack check, but bc does not.
3472                                 if (BC_IS_DC)
3473                                 {
3474                                         if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
3475                                         {
3476                                                 bc_err(BC_ERR_EXEC_STACK);
3477                                         }
3478                                 }
3479 #endif // BC_PROG_NO_STACK_CHECK
3480
3481                                 assert(BC_PROG_STACK(&p->results, 1));
3482
3483                                 bc_vec_pop(&p->results);
3484
3485                                 BC_PROG_JUMP(inst, code, ip);
3486                         }
3487
3488                         // clang-format off
3489                         BC_PROG_LBL(BC_INST_SWAP):
3490                         // clang-format on
3491                         {
3492                                 BcResult* ptr2;
3493
3494                                 // Check the stack.
3495                                 if (BC_ERR(!BC_PROG_STACK(&p->results, 2)))
3496                                 {
3497                                         bc_err(BC_ERR_EXEC_STACK);
3498                                 }
3499
3500                                 assert(BC_PROG_STACK(&p->results, 2));
3501
3502                                 // Get the two items.
3503                                 ptr = bc_vec_item_rev(&p->results, 0);
3504                                 ptr2 = bc_vec_item_rev(&p->results, 1);
3505
3506                                 // Swap. It's just easiest to do it this way.
3507                                 // NOLINTNEXTLINE
3508                                 memcpy(&r, ptr, sizeof(BcResult));
3509                                 // NOLINTNEXTLINE
3510                                 memcpy(ptr, ptr2, sizeof(BcResult));
3511                                 // NOLINTNEXTLINE
3512                                 memcpy(ptr2, &r, sizeof(BcResult));
3513
3514                                 BC_PROG_JUMP(inst, code, ip);
3515                         }
3516
3517                         // clang-format off
3518                         BC_PROG_LBL(BC_INST_MODEXP):
3519                         // clang-format on
3520                         {
3521                                 bc_program_modexp(p);
3522                                 BC_PROG_JUMP(inst, code, ip);
3523                         }
3524
3525                         // clang-format off
3526                         BC_PROG_LBL(BC_INST_DIVMOD):
3527                         // clang-format on
3528                         {
3529                                 bc_program_divmod(p);
3530                                 BC_PROG_JUMP(inst, code, ip);
3531                         }
3532
3533                         // clang-format off
3534                         BC_PROG_LBL(BC_INST_PRINT_STREAM):
3535                         // clang-format on
3536                         {
3537                                 bc_program_printStream(p);
3538                                 BC_PROG_JUMP(inst, code, ip);
3539                         }
3540
3541 #if DC_ENABLED
3542                         // clang-format off
3543                         BC_PROG_LBL(BC_INST_POP_EXEC):
3544                         // clang-format on
3545                         {
3546                                 // If this fails, the dc parser got something wrong.
3547                                 assert(BC_PROG_STACK(&p->stack, 2));
3548
3549                                 // Pop the execution stack and tail call stack.
3550                                 bc_vec_pop(&p->stack);
3551                                 bc_vec_pop(&p->tail_calls);
3552
3553                                 // Because we changed the execution stack and where we are
3554                                 // executing, we have to update all of this.
3555                                 BC_SIG_LOCK;
3556                                 ip = bc_vec_top(&p->stack);
3557                                 func = bc_vec_item(&p->fns, ip->func);
3558                                 code = func->code.v;
3559                                 BC_SIG_UNLOCK;
3560
3561                                 BC_PROG_JUMP(inst, code, ip);
3562                         }
3563
3564                         // clang-format off
3565                         BC_PROG_LBL(BC_INST_EXECUTE):
3566                         BC_PROG_LBL(BC_INST_EXEC_COND):
3567                         // clang-format on
3568                         {
3569                                 cond = (inst == BC_INST_EXEC_COND);
3570
3571                                 bc_program_execStr(p, code, &ip->idx, cond, func->code.len);
3572
3573                                 // Because we changed the execution stack and where we are
3574                                 // executing, we have to update all of this.
3575                                 BC_SIG_LOCK;
3576                                 ip = bc_vec_top(&p->stack);
3577                                 func = bc_vec_item(&p->fns, ip->func);
3578                                 code = func->code.v;
3579                                 BC_SIG_UNLOCK;
3580
3581                                 BC_PROG_JUMP(inst, code, ip);
3582                         }
3583
3584                         // clang-format off
3585                         BC_PROG_LBL(BC_INST_PRINT_STACK):
3586                         // clang-format on
3587                         {
3588                                 bc_program_printStack(p);
3589                                 BC_PROG_JUMP(inst, code, ip);
3590                         }
3591
3592                         // clang-format off
3593                         BC_PROG_LBL(BC_INST_CLEAR_STACK):
3594                         // clang-format on
3595                         {
3596                                 bc_vec_popAll(&p->results);
3597                                 BC_PROG_JUMP(inst, code, ip);
3598                         }
3599
3600                         // clang-format off
3601                         BC_PROG_LBL(BC_INST_REG_STACK_LEN):
3602                         // clang-format on
3603                         {
3604                                 bc_program_regStackLen(p, code, &ip->idx);
3605                                 BC_PROG_JUMP(inst, code, ip);
3606                         }
3607
3608                         // clang-format off
3609                         BC_PROG_LBL(BC_INST_STACK_LEN):
3610                         // clang-format on
3611                         {
3612                                 bc_program_stackLen(p);
3613                                 BC_PROG_JUMP(inst, code, ip);
3614                         }
3615
3616                         // clang-format off
3617                         BC_PROG_LBL(BC_INST_DUPLICATE):
3618                         // clang-format on
3619                         {
3620                                 // Check the stack.
3621                                 if (BC_ERR(!BC_PROG_STACK(&p->results, 1)))
3622                                 {
3623                                         bc_err(BC_ERR_EXEC_STACK);
3624                                 }
3625
3626                                 assert(BC_PROG_STACK(&p->results, 1));
3627
3628                                 // Get the top of the stack.
3629                                 ptr = bc_vec_top(&p->results);
3630
3631                                 BC_SIG_LOCK;
3632
3633                                 // Copy and push.
3634                                 bc_result_copy(&r, ptr);
3635                                 bc_vec_push(&p->results, &r);
3636
3637                                 BC_SIG_UNLOCK;
3638
3639                                 BC_PROG_JUMP(inst, code, ip);
3640                         }
3641
3642                         // clang-format off
3643                         BC_PROG_LBL(BC_INST_LOAD):
3644                         BC_PROG_LBL(BC_INST_PUSH_VAR):
3645                         // clang-format on
3646                         {
3647                                 bool copy = (inst == BC_INST_LOAD);
3648                                 bc_program_pushVar(p, code, &ip->idx, true, copy);
3649                                 BC_PROG_JUMP(inst, code, ip);
3650                         }
3651
3652                         // clang-format off
3653                         BC_PROG_LBL(BC_INST_PUSH_TO_VAR):
3654                         // clang-format on
3655                         {
3656                                 idx = bc_program_index(code, &ip->idx);
3657                                 bc_program_copyToVar(p, idx, BC_TYPE_VAR);
3658                                 BC_PROG_JUMP(inst, code, ip);
3659                         }
3660
3661                         // clang-format off
3662                         BC_PROG_LBL(BC_INST_QUIT):
3663                         BC_PROG_LBL(BC_INST_NQUIT):
3664                         // clang-format on
3665                         {
3666                                 bc_program_nquit(p, inst);
3667
3668                                 // Because we changed the execution stack and where we are
3669                                 // executing, we have to update all of this.
3670                                 BC_SIG_LOCK;
3671                                 ip = bc_vec_top(&p->stack);
3672                                 func = bc_vec_item(&p->fns, ip->func);
3673                                 code = func->code.v;
3674                                 BC_SIG_UNLOCK;
3675
3676                                 BC_PROG_JUMP(inst, code, ip);
3677                         }
3678
3679                         // clang-format off
3680                         BC_PROG_LBL(BC_INST_EXEC_STACK_LEN):
3681                         // clang-format on
3682                         {
3683                                 bc_program_execStackLen(p);
3684                                 BC_PROG_JUMP(inst, code, ip);
3685                         }
3686 #endif // DC_ENABLED
3687
3688 #if BC_HAS_COMPUTED_GOTO
3689                         // clang-format off
3690                         BC_PROG_LBL(BC_INST_INVALID):
3691                         // clang-format on
3692                         {
3693                                 goto end;
3694                         }
3695 #else // BC_HAS_COMPUTED_GOTO
3696                         default:
3697                         {
3698                                 BC_UNREACHABLE
3699 #if BC_DEBUG && !BC_CLANG
3700                                 abort();
3701 #endif // BC_DEBUG && !BC_CLANG
3702                         }
3703 #endif // BC_HAS_COMPUTED_GOTO
3704                 }
3705
3706 #if BC_HAS_COMPUTED_GOTO
3707
3708 #if BC_CLANG
3709 #pragma clang diagnostic warning "-Wgnu-label-as-value"
3710 #endif // BC_CLANG
3711
3712 #if BC_GCC
3713 #pragma GCC diagnostic warning "-Wpedantic"
3714 #endif // BC_GCC
3715
3716 #else // BC_HAS_COMPUTED_GOTO
3717
3718 #if BC_DEBUG
3719                 // This is to allow me to use a debugger to see the last instruction,
3720                 // which will point to which function was the problem. But it's also a
3721                 // good smoke test for error handling changes.
3722                 assert(jmp_bufs_len == vm->jmp_bufs.len);
3723 #endif // BC_DEBUG
3724
3725 #endif // BC_HAS_COMPUTED_GOTO
3726         }
3727
3728 end:
3729         BC_SIG_MAYLOCK;
3730
3731         // This is here just to print a stack trace on interrupts. This is for
3732         // finding infinite loops.
3733         if (BC_SIG_INTERRUPT(vm))
3734         {
3735                 BcStatus s;
3736
3737                 bc_file_putchar(&vm->ferr, bc_flush_none, '\n');
3738
3739                 bc_program_printStackTrace(p);
3740
3741                 s = bc_file_flushErr(&vm->ferr, bc_flush_err);
3742                 if (BC_ERR(s != BC_STATUS_SUCCESS && vm->status == BC_STATUS_SUCCESS))
3743                 {
3744                         vm->status = (sig_atomic_t) s;
3745                 }
3746         }
3747
3748         BC_LONGJMP_CONT(vm);
3749 }
3750
3751 #if BC_DEBUG_CODE
3752 #if BC_ENABLED && DC_ENABLED
3753 void
3754 bc_program_printStackDebug(BcProgram* p)
3755 {
3756         bc_file_puts(&vm->fout, bc_flush_err, "-------------- Stack ----------\n");
3757         bc_program_printStack(p);
3758         bc_file_puts(&vm->fout, bc_flush_err, "-------------- Stack End ------\n");
3759 }
3760
3761 static void
3762 bc_program_printIndex(const char* restrict code, size_t* restrict bgn)
3763 {
3764         uchar byte, i, bytes = (uchar) code[(*bgn)++];
3765         ulong val = 0;
3766
3767         for (byte = 1, i = 0; byte && i < bytes; ++i)
3768         {
3769                 byte = (uchar) code[(*bgn)++];
3770                 if (byte) val |= ((ulong) byte) << (CHAR_BIT * i);
3771         }
3772
3773         bc_vm_printf(" (%lu) ", val);
3774 }
3775
3776 static void
3777 bc_program_printStr(const BcProgram* p, const char* restrict code,
3778                     size_t* restrict bgn)
3779 {
3780         size_t idx = bc_program_index(code, bgn);
3781         char* s;
3782
3783         s = *((char**) bc_vec_item(p->strs, idx));
3784
3785         bc_vm_printf(" (\"%s\") ", s);
3786 }
3787
3788 void
3789 bc_program_printInst(const BcProgram* p, const char* restrict code,
3790                      size_t* restrict bgn)
3791 {
3792         uchar inst = (uchar) code[(*bgn)++];
3793
3794         bc_vm_printf("Inst[%zu]: %s [%lu]; ", *bgn - 1, bc_inst_names[inst],
3795                      (unsigned long) inst);
3796
3797         if (inst == BC_INST_VAR || inst == BC_INST_ARRAY_ELEM ||
3798             inst == BC_INST_ARRAY)
3799         {
3800                 bc_program_printIndex(code, bgn);
3801         }
3802         else if (inst == BC_INST_STR) bc_program_printStr(p, code, bgn);
3803         else if (inst == BC_INST_NUM)
3804         {
3805                 size_t idx = bc_program_index(code, bgn);
3806                 BcConst* c = bc_vec_item(p->consts, idx);
3807                 bc_vm_printf("(%s)", c->val);
3808         }
3809         else if (inst == BC_INST_CALL ||
3810                  (inst > BC_INST_STR && inst <= BC_INST_JUMP_ZERO))
3811         {
3812                 bc_program_printIndex(code, bgn);
3813                 if (inst == BC_INST_CALL) bc_program_printIndex(code, bgn);
3814         }
3815
3816         bc_vm_putchar('\n', bc_flush_err);
3817 }
3818
3819 void
3820 bc_program_code(const BcProgram* p)
3821 {
3822         BcFunc* f;
3823         char* code;
3824         BcInstPtr ip;
3825         size_t i;
3826
3827         for (i = 0; i < p->fns.len; ++i)
3828         {
3829                 ip.idx = ip.len = 0;
3830                 ip.func = i;
3831
3832                 f = bc_vec_item(&p->fns, ip.func);
3833                 code = f->code.v;
3834
3835                 bc_vm_printf("func[%zu]:\n", ip.func);
3836                 while (ip.idx < f->code.len)
3837                 {
3838                         bc_program_printInst(p, code, &ip.idx);
3839                 }
3840                 bc_file_puts(&vm->fout, bc_flush_err, "\n\n");
3841         }
3842 }
3843 #endif // BC_ENABLED && DC_ENABLED
3844 #endif // BC_DEBUG_CODE