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