1/*
2 * *****************************************************************************
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 *
6 * Copyright (c) 2018-2023 Gavin D. Howard and contributors.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * * Redistributions of source code must retain the above copyright notice, this
12 *   list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright notice,
15 *   this list of conditions and the following disclaimer in the documentation
16 *   and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 * *****************************************************************************
31 *
32 * Definitions for bc programs.
33 *
34 */
35
36#ifndef BC_PROGRAM_H
37#define BC_PROGRAM_H
38
39#include <assert.h>
40#include <stddef.h>
41
42#include <status.h>
43#include <parse.h>
44#include <lang.h>
45#include <num.h>
46#include <rand.h>
47
48/// The index of ibase in the globals array.
49#define BC_PROG_GLOBALS_IBASE (0)
50
51/// The index of obase in the globals array.
52#define BC_PROG_GLOBALS_OBASE (1)
53
54/// The index of scale in the globals array.
55#define BC_PROG_GLOBALS_SCALE (2)
56
57#if BC_ENABLE_EXTRA_MATH
58
59/// The index of the rand max in the maxes array.
60#define BC_PROG_MAX_RAND (3)
61
62#endif // BC_ENABLE_EXTRA_MATH
63
64/// The length of the globals array.
65#define BC_PROG_GLOBALS_LEN (3 + BC_ENABLE_EXTRA_MATH)
66
67typedef struct BcProgram
68{
69	/// The array of globals values.
70	BcBigDig globals[BC_PROG_GLOBALS_LEN];
71
72#if BC_ENABLED
73	/// The array of globals stacks.
74	BcVec globals_v[BC_PROG_GLOBALS_LEN];
75#endif // BC_ENABLED
76
77#if BC_ENABLE_EXTRA_MATH
78
79	/// The pseudo-random number generator.
80	BcRNG rng;
81
82#endif // BC_ENABLE_EXTRA_MATH
83
84	/// The results stack.
85	BcVec results;
86
87	/// The execution stack.
88	BcVec stack;
89
90	/// The constants encountered in the program. They are global to the program
91	/// to prevent bad accesses when functions that used non-auto variables are
92	/// replaced.
93	BcVec consts;
94
95	/// The map of constants to go with consts.
96	BcVec const_map;
97
98	/// The strings encountered in the program. They are global to the program
99	/// to prevent bad accesses when functions that used non-auto variables are
100	/// replaced.
101	BcVec strs;
102
103	/// The map of strings to go with strs.
104	BcVec str_map;
105
106	/// The array of functions.
107	BcVec fns;
108
109	/// The map of functions to go with fns.
110	BcVec fn_map;
111
112	/// The array of variables.
113	BcVec vars;
114
115	/// The map of variables to go with vars.
116	BcVec var_map;
117
118	/// The array of arrays.
119	BcVec arrs;
120
121	/// The map of arrays to go with arrs.
122	BcVec arr_map;
123
124#if DC_ENABLED
125
126	/// A vector of tail calls. These are just integers, which are the number of
127	/// tail calls that have been executed for each function (string) on the
128	/// stack for dc. This is to prevent dc from constantly growing memory use
129	/// because of pushing more and more string executions on the stack.
130	BcVec tail_calls;
131
132#endif // DC_ENABLED
133
134	/// A BcNum that has the proper base for asciify.
135	BcNum strmb;
136
137	// A BcNum to run asciify. This is to prevent GCC longjmp() clobbering
138	// warnings.
139	BcNum asciify;
140
141#if BC_ENABLED
142
143	/// The last printed value for bc.
144	BcNum last;
145
146#endif // BC_ENABLED
147
148	// The BcDig array for strmb. This uses BC_NUM_LONG_LOG10 because it is used
149	// in bc_num_ulong2num(), which attempts to realloc, unless it is big
150	// enough. This is big enough.
151	BcDig strmb_num[BC_NUM_BIGDIG_LOG10];
152
153} BcProgram;
154
155/**
156 * Returns true if the stack @a s has at least @a n items, false otherwise.
157 * @param s  The stack to check.
158 * @param n  The number of items the stack must have.
159 * @return   True if @a s has at least @a n items, false otherwise.
160 */
161#define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) (n)))
162
163/**
164 * Get a pointer to the top value in a global value stack.
165 * @param v  The global value stack.
166 * @return   A pointer to the top value in @a v.
167 */
168#define BC_PROG_GLOBAL_PTR(v) (bc_vec_top(v))
169
170/**
171 * Get the top value in a global value stack.
172 * @param v  The global value stack.
173 * @return   The top value in @a v.
174 */
175#define BC_PROG_GLOBAL(v) (*((BcBigDig*) BC_PROG_GLOBAL_PTR(v)))
176
177/**
178 * Returns the current value of ibase.
179 * @param p  The program.
180 * @return   The current ibase.
181 */
182#define BC_PROG_IBASE(p) ((p)->globals[BC_PROG_GLOBALS_IBASE])
183
184/**
185 * Returns the current value of obase.
186 * @param p  The program.
187 * @return   The current obase.
188 */
189#define BC_PROG_OBASE(p) ((p)->globals[BC_PROG_GLOBALS_OBASE])
190
191/**
192 * Returns the current value of scale.
193 * @param p  The program.
194 * @return   The current scale.
195 */
196#define BC_PROG_SCALE(p) ((p)->globals[BC_PROG_GLOBALS_SCALE])
197
198/// The index for the main function in the functions array.//
199#define BC_PROG_MAIN (0)
200
201/// The index for the read function in the functions array.
202#define BC_PROG_READ (1)
203
204/**
205 * Retires (completes the execution of) an instruction. Some instructions
206 * require special retirement, but most can use this. This basically pops the
207 * operands while preserving the result (which we assumed was pushed before the
208 * actual operation).
209 * @param p     The program.
210 * @param nres  The number of results returned by the instruction.
211 * @param nops  The number of operands used by the instruction.
212 */
213#define bc_program_retire(p, nres, nops) \
214	(bc_vec_npopAt(&(p)->results, (nops), (p)->results.len - (nres + nops)))
215
216#if DC_ENABLED
217
218/// A constant that tells how many functions are required in dc.
219#define BC_PROG_REQ_FUNCS (2)
220
221#if !BC_ENABLED
222
223/// Returns true if the calculator should pop after printing.
224#define BC_PROGRAM_POP(pop) (pop)
225
226#else // !BC_ENABLED
227
228/// Returns true if the calculator should pop after printing.
229#define BC_PROGRAM_POP(pop) (BC_IS_BC || (pop))
230
231#endif // !BC_ENABLED
232
233// This is here to satisfy a clang warning about recursive macros.
234#define bc_program_pushVar(p, code, bgn, pop, copy) \
235	bc_program_pushVar_impl(p, code, bgn, pop, copy)
236
237#else // DC_ENABLED
238
239// This define disappears pop and copy because for bc, 'pop' and 'copy' are
240// always false.
241#define bc_program_pushVar(p, code, bgn, pop, copy) \
242	bc_program_pushVar_impl(p, code, bgn)
243
244/// Returns true if the calculator should pop after printing.
245#define BC_PROGRAM_POP(pop) (BC_IS_BC)
246
247// In debug mode, we want bc to check the stack, but otherwise, we don't because
248// the bc language implicitly mandates that the stack should always have enough
249// items.
250#ifdef BC_DEBUG
251#define BC_PROG_NO_STACK_CHECK
252#endif // BC_DEBUG
253
254#endif // DC_ENABLED
255
256/**
257 * Returns true if the BcNum @a n is acting as a string.
258 * @param n  The BcNum to test.
259 * @return   True if @a n is acting as a string, false otherwise.
260 */
261#define BC_PROG_STR(n) ((n)->num == NULL && !(n)->cap)
262
263#if BC_ENABLED
264
265/**
266 * Returns true if the result @a r and @a n is a number.
267 * @param r  The result.
268 * @param n  The number corresponding to the result.
269 * @return   True if the result holds a number, false otherwise.
270 */
271#define BC_PROG_NUM(r, n) \
272	((r)->t != BC_RESULT_ARRAY && (r)->t != BC_RESULT_STR && !BC_PROG_STR(n))
273
274#else // BC_ENABLED
275
276/**
277 * Returns true if the result @a r and @a n is a number.
278 * @param r  The result.
279 * @param n  The number corresponding to the result.
280 * @return   True if the result holds a number, false otherwise.
281 */
282#define BC_PROG_NUM(r, n) ((r)->t != BC_RESULT_STR && !BC_PROG_STR(n))
283
284#endif // BC_ENABLED
285
286/**
287 * This is a function type for unary operations. Currently, these include
288 * boolean not, negation, and truncation with extra math.
289 * @param r  The BcResult to store the result into.
290 * @param n  The parameter to the unary operation.
291 */
292typedef void (*BcProgramUnary)(BcResult* r, BcNum* n);
293
294/**
295 * Initializes the BcProgram.
296 * @param p  The program to initialize.
297 */
298void
299bc_program_init(BcProgram* p);
300
301#if BC_DEBUG
302
303/**
304 * Frees a BcProgram. This is only used in debug builds because a BcProgram is
305 * only freed on program exit, and we don't care about freeing resources on
306 * exit.
307 * @param p  The program to initialize.
308 */
309void
310bc_program_free(BcProgram* p);
311
312#endif // BC_DEBUG
313
314/**
315 * Prints a stack trace of the bc functions or dc strings currently executing.
316 * @param p  The program.
317 */
318void
319bc_program_printStackTrace(BcProgram* p);
320
321#if BC_DEBUG_CODE
322#if BC_ENABLED && DC_ENABLED
323
324/**
325 * Prints the bytecode in a function. This is a debug-only function.
326 * @param p  The program.
327 */
328void
329bc_program_code(const BcProgram* p);
330
331/**
332 * Prints an instruction. This is a debug-only function.
333 * @param p  The program.
334 * @param code  The bytecode array.
335 * @param bgn   A pointer to the current index. It is also updated to the next
336 *              index.
337 */
338void
339bc_program_printInst(const BcProgram* p, const char* code,
340                     size_t* restrict bgn);
341
342/**
343 * Prints the stack. This is a debug-only function.
344 * @param p  The program.
345 */
346void
347bc_program_printStackDebug(BcProgram* p);
348
349#endif // BC_ENABLED && DC_ENABLED
350#endif // BC_DEBUG_CODE
351
352/**
353 * Returns the index of the variable or array in their respective arrays.
354 * @param p     The program.
355 * @param name  The name of the variable or array.
356 * @param var   True if the search should be for a variable, false for an array.
357 * @return      The index of the variable or array in the correct array.
358 */
359size_t
360bc_program_search(BcProgram* p, const char* name, bool var);
361
362/**
363 * Adds a string to the program and returns the string's index in the program.
364 * @param p    The program.
365 * @param str  The string to add.
366 * @return     The string's index in the program.
367 */
368size_t
369bc_program_addString(BcProgram* p, const char* str);
370
371/**
372 * Inserts a function into the program and returns the index of the function in
373 * the fns array.
374 * @param p     The program.
375 * @param name  The name of the function.
376 * @return      The index of the function after insertion.
377 */
378size_t
379bc_program_insertFunc(BcProgram* p, const char* name);
380
381/**
382 * Resets a program, usually because of resetting after an error.
383 * @param p  The program to reset.
384 */
385void
386bc_program_reset(BcProgram* p);
387
388/**
389 * Executes bc or dc code in the BcProgram.
390 * @param p  The program.
391 */
392void
393bc_program_exec(BcProgram* p);
394
395/**
396 * Negates a copy of a BcNum. This is a BcProgramUnary function.
397 * @param r  The BcResult to store the result into.
398 * @param n  The parameter to the unary operation.
399 */
400void
401bc_program_negate(BcResult* r, BcNum* n);
402
403/**
404 * Returns a boolean not of a BcNum. This is a BcProgramUnary function.
405 * @param r  The BcResult to store the result into.
406 * @param n  The parameter to the unary operation.
407 */
408void
409bc_program_not(BcResult* r, BcNum* n);
410
411#if BC_ENABLE_EXTRA_MATH
412
413/**
414 * Truncates a copy of a BcNum. This is a BcProgramUnary function.
415 * @param r  The BcResult to store the result into.
416 * @param n  The parameter to the unary operation.
417 */
418void
419bc_program_trunc(BcResult* r, BcNum* n);
420
421/**
422 * Assigns a value to the seed builtin variable.
423 * @param p    The program.
424 * @param val  The value to assign to the seed.
425 */
426void
427bc_program_assignSeed(BcProgram* p, BcNum* val);
428
429#endif // BC_ENABLE_EXTRA_MATH
430
431/**
432 * Assigns a value to a builtin value that is not seed.
433 * @param p      The program.
434 * @param scale  True if the builtin is scale.
435 * @param obase  True if the builtin is obase. This cannot be true at the same
436 *               time @a scale is.
437 * @param val    The value to assign to the builtin.
438 */
439void
440bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val);
441
442/// A reference to an array of binary operator functions.
443extern const BcNumBinaryOp bc_program_ops[];
444
445/// A reference to an array of binary operator allocation request functions.
446extern const BcNumBinaryOpReq bc_program_opReqs[];
447
448/// A reference to an array of unary operator functions.
449extern const BcProgramUnary bc_program_unarys[];
450
451/// A reference to a filename for command-line expressions.
452extern const char bc_program_exprs_name[];
453
454/// A reference to a filename for stdin.
455extern const char bc_program_stdin_name[];
456
457/// A reference to the ready message printed on SIGINT.
458extern const char bc_program_ready_msg[];
459
460/// A reference to the length of the ready message.
461extern const size_t bc_program_ready_msg_len;
462
463/// A reference to an array of escape characters for the print statement.
464extern const char bc_program_esc_chars[];
465
466/// A reference to an array of the characters corresponding to the escape
467/// characters in bc_program_esc_chars.
468extern const char bc_program_esc_seqs[];
469
470#if BC_HAS_COMPUTED_GOTO
471
472#if BC_DEBUG_CODE
473
474// clang-format off
475#define BC_PROG_JUMP(inst, code, ip)                                  \
476	do                                                                \
477	{                                                                 \
478		inst = (uchar) (code)[(ip)->idx++];                           \
479		bc_file_printf(&vm->ferr, "inst: %s\n", bc_inst_names[inst]); \
480		bc_file_flush(&vm->ferr, bc_flush_none);                      \
481		goto *bc_program_inst_lbls[inst];                             \
482	}                                                                 \
483	while (0)
484// clang-format on
485
486#else // BC_DEBUG_CODE
487
488// clang-format off
489#define BC_PROG_JUMP(inst, code, ip)        \
490	do                                      \
491	{                                       \
492		inst = (uchar) (code)[(ip)->idx++]; \
493		goto *bc_program_inst_lbls[inst];   \
494	}                                       \
495	while (0)
496// clang-format on
497
498#endif // BC_DEBUG_CODE
499
500#define BC_PROG_DIRECT_JUMP(l) goto lbl_##l;
501#define BC_PROG_LBL(l) lbl_##l
502#define BC_PROG_FALLTHROUGH
503
504#if BC_C11
505
506#define BC_PROG_LBLS_SIZE (sizeof(bc_program_inst_lbls) / sizeof(void*))
507#define BC_PROG_LBLS_ASSERT                                  \
508	_Static_assert(BC_PROG_LBLS_SIZE == BC_INST_INVALID + 1, \
509	               "bc_program_inst_lbls[] mismatches the instructions")
510
511#else // BC_C11
512
513#define BC_PROG_LBLS_ASSERT
514
515#endif // BC_C11
516
517#if BC_ENABLED
518
519#if DC_ENABLED
520
521#if BC_ENABLE_EXTRA_MATH
522
523#define BC_PROG_LBLS                                    \
524	static const void* const bc_program_inst_lbls[] = { \
525		&&lbl_BC_INST_INC,                              \
526		&&lbl_BC_INST_DEC,                              \
527		&&lbl_BC_INST_NEG,                              \
528		&&lbl_BC_INST_BOOL_NOT,                         \
529		&&lbl_BC_INST_TRUNC,                            \
530		&&lbl_BC_INST_POWER,                            \
531		&&lbl_BC_INST_MULTIPLY,                         \
532		&&lbl_BC_INST_DIVIDE,                           \
533		&&lbl_BC_INST_MODULUS,                          \
534		&&lbl_BC_INST_PLUS,                             \
535		&&lbl_BC_INST_MINUS,                            \
536		&&lbl_BC_INST_PLACES,                           \
537		&&lbl_BC_INST_LSHIFT,                           \
538		&&lbl_BC_INST_RSHIFT,                           \
539		&&lbl_BC_INST_REL_EQ,                           \
540		&&lbl_BC_INST_REL_LE,                           \
541		&&lbl_BC_INST_REL_GE,                           \
542		&&lbl_BC_INST_REL_NE,                           \
543		&&lbl_BC_INST_REL_LT,                           \
544		&&lbl_BC_INST_REL_GT,                           \
545		&&lbl_BC_INST_BOOL_OR,                          \
546		&&lbl_BC_INST_BOOL_AND,                         \
547		&&lbl_BC_INST_ASSIGN_POWER,                     \
548		&&lbl_BC_INST_ASSIGN_MULTIPLY,                  \
549		&&lbl_BC_INST_ASSIGN_DIVIDE,                    \
550		&&lbl_BC_INST_ASSIGN_MODULUS,                   \
551		&&lbl_BC_INST_ASSIGN_PLUS,                      \
552		&&lbl_BC_INST_ASSIGN_MINUS,                     \
553		&&lbl_BC_INST_ASSIGN_PLACES,                    \
554		&&lbl_BC_INST_ASSIGN_LSHIFT,                    \
555		&&lbl_BC_INST_ASSIGN_RSHIFT,                    \
556		&&lbl_BC_INST_ASSIGN,                           \
557		&&lbl_BC_INST_ASSIGN_POWER_NO_VAL,              \
558		&&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL,           \
559		&&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL,             \
560		&&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL,            \
561		&&lbl_BC_INST_ASSIGN_PLUS_NO_VAL,               \
562		&&lbl_BC_INST_ASSIGN_MINUS_NO_VAL,              \
563		&&lbl_BC_INST_ASSIGN_PLACES_NO_VAL,             \
564		&&lbl_BC_INST_ASSIGN_LSHIFT_NO_VAL,             \
565		&&lbl_BC_INST_ASSIGN_RSHIFT_NO_VAL,             \
566		&&lbl_BC_INST_ASSIGN_NO_VAL,                    \
567		&&lbl_BC_INST_NUM,                              \
568		&&lbl_BC_INST_VAR,                              \
569		&&lbl_BC_INST_ARRAY_ELEM,                       \
570		&&lbl_BC_INST_ARRAY,                            \
571		&&lbl_BC_INST_ZERO,                             \
572		&&lbl_BC_INST_ONE,                              \
573		&&lbl_BC_INST_LAST,                             \
574		&&lbl_BC_INST_IBASE,                            \
575		&&lbl_BC_INST_OBASE,                            \
576		&&lbl_BC_INST_SCALE,                            \
577		&&lbl_BC_INST_SEED,                             \
578		&&lbl_BC_INST_LENGTH,                           \
579		&&lbl_BC_INST_SCALE_FUNC,                       \
580		&&lbl_BC_INST_SQRT,                             \
581		&&lbl_BC_INST_ABS,                              \
582		&&lbl_BC_INST_IS_NUMBER,                        \
583		&&lbl_BC_INST_IS_STRING,                        \
584		&&lbl_BC_INST_IRAND,                            \
585		&&lbl_BC_INST_ASCIIFY,                          \
586		&&lbl_BC_INST_READ,                             \
587		&&lbl_BC_INST_RAND,                             \
588		&&lbl_BC_INST_MAXIBASE,                         \
589		&&lbl_BC_INST_MAXOBASE,                         \
590		&&lbl_BC_INST_MAXSCALE,                         \
591		&&lbl_BC_INST_MAXRAND,                          \
592		&&lbl_BC_INST_LINE_LENGTH,                      \
593		&&lbl_BC_INST_GLOBAL_STACKS,                    \
594		&&lbl_BC_INST_LEADING_ZERO,                     \
595		&&lbl_BC_INST_PRINT,                            \
596		&&lbl_BC_INST_PRINT_POP,                        \
597		&&lbl_BC_INST_STR,                              \
598		&&lbl_BC_INST_PRINT_STR,                        \
599		&&lbl_BC_INST_JUMP,                             \
600		&&lbl_BC_INST_JUMP_ZERO,                        \
601		&&lbl_BC_INST_CALL,                             \
602		&&lbl_BC_INST_RET,                              \
603		&&lbl_BC_INST_RET0,                             \
604		&&lbl_BC_INST_RET_VOID,                         \
605		&&lbl_BC_INST_HALT,                             \
606		&&lbl_BC_INST_POP,                              \
607		&&lbl_BC_INST_SWAP,                             \
608		&&lbl_BC_INST_MODEXP,                           \
609		&&lbl_BC_INST_DIVMOD,                           \
610		&&lbl_BC_INST_PRINT_STREAM,                     \
611		&&lbl_BC_INST_EXTENDED_REGISTERS,               \
612		&&lbl_BC_INST_POP_EXEC,                         \
613		&&lbl_BC_INST_EXECUTE,                          \
614		&&lbl_BC_INST_EXEC_COND,                        \
615		&&lbl_BC_INST_PRINT_STACK,                      \
616		&&lbl_BC_INST_CLEAR_STACK,                      \
617		&&lbl_BC_INST_REG_STACK_LEN,                    \
618		&&lbl_BC_INST_STACK_LEN,                        \
619		&&lbl_BC_INST_DUPLICATE,                        \
620		&&lbl_BC_INST_LOAD,                             \
621		&&lbl_BC_INST_PUSH_VAR,                         \
622		&&lbl_BC_INST_PUSH_TO_VAR,                      \
623		&&lbl_BC_INST_QUIT,                             \
624		&&lbl_BC_INST_NQUIT,                            \
625		&&lbl_BC_INST_EXEC_STACK_LEN,                   \
626		&&lbl_BC_INST_INVALID,                          \
627	}
628
629#else // BC_ENABLE_EXTRA_MATH
630
631#define BC_PROG_LBLS                                    \
632	static const void* const bc_program_inst_lbls[] = { \
633		&&lbl_BC_INST_INC,                              \
634		&&lbl_BC_INST_DEC,                              \
635		&&lbl_BC_INST_NEG,                              \
636		&&lbl_BC_INST_BOOL_NOT,                         \
637		&&lbl_BC_INST_POWER,                            \
638		&&lbl_BC_INST_MULTIPLY,                         \
639		&&lbl_BC_INST_DIVIDE,                           \
640		&&lbl_BC_INST_MODULUS,                          \
641		&&lbl_BC_INST_PLUS,                             \
642		&&lbl_BC_INST_MINUS,                            \
643		&&lbl_BC_INST_REL_EQ,                           \
644		&&lbl_BC_INST_REL_LE,                           \
645		&&lbl_BC_INST_REL_GE,                           \
646		&&lbl_BC_INST_REL_NE,                           \
647		&&lbl_BC_INST_REL_LT,                           \
648		&&lbl_BC_INST_REL_GT,                           \
649		&&lbl_BC_INST_BOOL_OR,                          \
650		&&lbl_BC_INST_BOOL_AND,                         \
651		&&lbl_BC_INST_ASSIGN_POWER,                     \
652		&&lbl_BC_INST_ASSIGN_MULTIPLY,                  \
653		&&lbl_BC_INST_ASSIGN_DIVIDE,                    \
654		&&lbl_BC_INST_ASSIGN_MODULUS,                   \
655		&&lbl_BC_INST_ASSIGN_PLUS,                      \
656		&&lbl_BC_INST_ASSIGN_MINUS,                     \
657		&&lbl_BC_INST_ASSIGN,                           \
658		&&lbl_BC_INST_ASSIGN_POWER_NO_VAL,              \
659		&&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL,           \
660		&&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL,             \
661		&&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL,            \
662		&&lbl_BC_INST_ASSIGN_PLUS_NO_VAL,               \
663		&&lbl_BC_INST_ASSIGN_MINUS_NO_VAL,              \
664		&&lbl_BC_INST_ASSIGN_NO_VAL,                    \
665		&&lbl_BC_INST_NUM,                              \
666		&&lbl_BC_INST_VAR,                              \
667		&&lbl_BC_INST_ARRAY_ELEM,                       \
668		&&lbl_BC_INST_ARRAY,                            \
669		&&lbl_BC_INST_ZERO,                             \
670		&&lbl_BC_INST_ONE,                              \
671		&&lbl_BC_INST_LAST,                             \
672		&&lbl_BC_INST_IBASE,                            \
673		&&lbl_BC_INST_OBASE,                            \
674		&&lbl_BC_INST_SCALE,                            \
675		&&lbl_BC_INST_LENGTH,                           \
676		&&lbl_BC_INST_SCALE_FUNC,                       \
677		&&lbl_BC_INST_SQRT,                             \
678		&&lbl_BC_INST_ABS,                              \
679		&&lbl_BC_INST_IS_NUMBER,                        \
680		&&lbl_BC_INST_IS_STRING,                        \
681		&&lbl_BC_INST_ASCIIFY,                          \
682		&&lbl_BC_INST_READ,                             \
683		&&lbl_BC_INST_MAXIBASE,                         \
684		&&lbl_BC_INST_MAXOBASE,                         \
685		&&lbl_BC_INST_MAXSCALE,                         \
686		&&lbl_BC_INST_LINE_LENGTH,                      \
687		&&lbl_BC_INST_GLOBAL_STACKS,                    \
688		&&lbl_BC_INST_LEADING_ZERO,                     \
689		&&lbl_BC_INST_PRINT,                            \
690		&&lbl_BC_INST_PRINT_POP,                        \
691		&&lbl_BC_INST_STR,                              \
692		&&lbl_BC_INST_PRINT_STR,                        \
693		&&lbl_BC_INST_JUMP,                             \
694		&&lbl_BC_INST_JUMP_ZERO,                        \
695		&&lbl_BC_INST_CALL,                             \
696		&&lbl_BC_INST_RET,                              \
697		&&lbl_BC_INST_RET0,                             \
698		&&lbl_BC_INST_RET_VOID,                         \
699		&&lbl_BC_INST_HALT,                             \
700		&&lbl_BC_INST_POP,                              \
701		&&lbl_BC_INST_SWAP,                             \
702		&&lbl_BC_INST_MODEXP,                           \
703		&&lbl_BC_INST_DIVMOD,                           \
704		&&lbl_BC_INST_PRINT_STREAM,                     \
705		&&lbl_BC_INST_EXTENDED_REGISTERS,               \
706		&&lbl_BC_INST_POP_EXEC,                         \
707		&&lbl_BC_INST_EXECUTE,                          \
708		&&lbl_BC_INST_EXEC_COND,                        \
709		&&lbl_BC_INST_PRINT_STACK,                      \
710		&&lbl_BC_INST_CLEAR_STACK,                      \
711		&&lbl_BC_INST_REG_STACK_LEN,                    \
712		&&lbl_BC_INST_STACK_LEN,                        \
713		&&lbl_BC_INST_DUPLICATE,                        \
714		&&lbl_BC_INST_LOAD,                             \
715		&&lbl_BC_INST_PUSH_VAR,                         \
716		&&lbl_BC_INST_PUSH_TO_VAR,                      \
717		&&lbl_BC_INST_QUIT,                             \
718		&&lbl_BC_INST_NQUIT,                            \
719		&&lbl_BC_INST_EXEC_STACK_LEN,                   \
720		&&lbl_BC_INST_INVALID,                          \
721	}
722
723#endif // BC_ENABLE_EXTRA_MATH
724
725#else // DC_ENABLED
726
727#if BC_ENABLE_EXTRA_MATH
728
729#define BC_PROG_LBLS                                    \
730	static const void* const bc_program_inst_lbls[] = { \
731		&&lbl_BC_INST_INC,                              \
732		&&lbl_BC_INST_DEC,                              \
733		&&lbl_BC_INST_NEG,                              \
734		&&lbl_BC_INST_BOOL_NOT,                         \
735		&&lbl_BC_INST_TRUNC,                            \
736		&&lbl_BC_INST_POWER,                            \
737		&&lbl_BC_INST_MULTIPLY,                         \
738		&&lbl_BC_INST_DIVIDE,                           \
739		&&lbl_BC_INST_MODULUS,                          \
740		&&lbl_BC_INST_PLUS,                             \
741		&&lbl_BC_INST_MINUS,                            \
742		&&lbl_BC_INST_PLACES,                           \
743		&&lbl_BC_INST_LSHIFT,                           \
744		&&lbl_BC_INST_RSHIFT,                           \
745		&&lbl_BC_INST_REL_EQ,                           \
746		&&lbl_BC_INST_REL_LE,                           \
747		&&lbl_BC_INST_REL_GE,                           \
748		&&lbl_BC_INST_REL_NE,                           \
749		&&lbl_BC_INST_REL_LT,                           \
750		&&lbl_BC_INST_REL_GT,                           \
751		&&lbl_BC_INST_BOOL_OR,                          \
752		&&lbl_BC_INST_BOOL_AND,                         \
753		&&lbl_BC_INST_ASSIGN_POWER,                     \
754		&&lbl_BC_INST_ASSIGN_MULTIPLY,                  \
755		&&lbl_BC_INST_ASSIGN_DIVIDE,                    \
756		&&lbl_BC_INST_ASSIGN_MODULUS,                   \
757		&&lbl_BC_INST_ASSIGN_PLUS,                      \
758		&&lbl_BC_INST_ASSIGN_MINUS,                     \
759		&&lbl_BC_INST_ASSIGN_PLACES,                    \
760		&&lbl_BC_INST_ASSIGN_LSHIFT,                    \
761		&&lbl_BC_INST_ASSIGN_RSHIFT,                    \
762		&&lbl_BC_INST_ASSIGN,                           \
763		&&lbl_BC_INST_ASSIGN_POWER_NO_VAL,              \
764		&&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL,           \
765		&&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL,             \
766		&&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL,            \
767		&&lbl_BC_INST_ASSIGN_PLUS_NO_VAL,               \
768		&&lbl_BC_INST_ASSIGN_MINUS_NO_VAL,              \
769		&&lbl_BC_INST_ASSIGN_PLACES_NO_VAL,             \
770		&&lbl_BC_INST_ASSIGN_LSHIFT_NO_VAL,             \
771		&&lbl_BC_INST_ASSIGN_RSHIFT_NO_VAL,             \
772		&&lbl_BC_INST_ASSIGN_NO_VAL,                    \
773		&&lbl_BC_INST_NUM,                              \
774		&&lbl_BC_INST_VAR,                              \
775		&&lbl_BC_INST_ARRAY_ELEM,                       \
776		&&lbl_BC_INST_ARRAY,                            \
777		&&lbl_BC_INST_ZERO,                             \
778		&&lbl_BC_INST_ONE,                              \
779		&&lbl_BC_INST_LAST,                             \
780		&&lbl_BC_INST_IBASE,                            \
781		&&lbl_BC_INST_OBASE,                            \
782		&&lbl_BC_INST_SCALE,                            \
783		&&lbl_BC_INST_SEED,                             \
784		&&lbl_BC_INST_LENGTH,                           \
785		&&lbl_BC_INST_SCALE_FUNC,                       \
786		&&lbl_BC_INST_SQRT,                             \
787		&&lbl_BC_INST_ABS,                              \
788		&&lbl_BC_INST_IS_NUMBER,                        \
789		&&lbl_BC_INST_IS_STRING,                        \
790		&&lbl_BC_INST_IRAND,                            \
791		&&lbl_BC_INST_ASCIIFY,                          \
792		&&lbl_BC_INST_READ,                             \
793		&&lbl_BC_INST_RAND,                             \
794		&&lbl_BC_INST_MAXIBASE,                         \
795		&&lbl_BC_INST_MAXOBASE,                         \
796		&&lbl_BC_INST_MAXSCALE,                         \
797		&&lbl_BC_INST_MAXRAND,                          \
798		&&lbl_BC_INST_LINE_LENGTH,                      \
799		&&lbl_BC_INST_GLOBAL_STACKS,                    \
800		&&lbl_BC_INST_LEADING_ZERO,                     \
801		&&lbl_BC_INST_PRINT,                            \
802		&&lbl_BC_INST_PRINT_POP,                        \
803		&&lbl_BC_INST_STR,                              \
804		&&lbl_BC_INST_PRINT_STR,                        \
805		&&lbl_BC_INST_JUMP,                             \
806		&&lbl_BC_INST_JUMP_ZERO,                        \
807		&&lbl_BC_INST_CALL,                             \
808		&&lbl_BC_INST_RET,                              \
809		&&lbl_BC_INST_RET0,                             \
810		&&lbl_BC_INST_RET_VOID,                         \
811		&&lbl_BC_INST_HALT,                             \
812		&&lbl_BC_INST_POP,                              \
813		&&lbl_BC_INST_SWAP,                             \
814		&&lbl_BC_INST_MODEXP,                           \
815		&&lbl_BC_INST_DIVMOD,                           \
816		&&lbl_BC_INST_PRINT_STREAM,                     \
817		&&lbl_BC_INST_INVALID,                          \
818	}
819
820#else // BC_ENABLE_EXTRA_MATH
821
822#define BC_PROG_LBLS                                    \
823	static const void* const bc_program_inst_lbls[] = { \
824		&&lbl_BC_INST_INC,                              \
825		&&lbl_BC_INST_DEC,                              \
826		&&lbl_BC_INST_NEG,                              \
827		&&lbl_BC_INST_BOOL_NOT,                         \
828		&&lbl_BC_INST_POWER,                            \
829		&&lbl_BC_INST_MULTIPLY,                         \
830		&&lbl_BC_INST_DIVIDE,                           \
831		&&lbl_BC_INST_MODULUS,                          \
832		&&lbl_BC_INST_PLUS,                             \
833		&&lbl_BC_INST_MINUS,                            \
834		&&lbl_BC_INST_REL_EQ,                           \
835		&&lbl_BC_INST_REL_LE,                           \
836		&&lbl_BC_INST_REL_GE,                           \
837		&&lbl_BC_INST_REL_NE,                           \
838		&&lbl_BC_INST_REL_LT,                           \
839		&&lbl_BC_INST_REL_GT,                           \
840		&&lbl_BC_INST_BOOL_OR,                          \
841		&&lbl_BC_INST_BOOL_AND,                         \
842		&&lbl_BC_INST_ASSIGN_POWER,                     \
843		&&lbl_BC_INST_ASSIGN_MULTIPLY,                  \
844		&&lbl_BC_INST_ASSIGN_DIVIDE,                    \
845		&&lbl_BC_INST_ASSIGN_MODULUS,                   \
846		&&lbl_BC_INST_ASSIGN_PLUS,                      \
847		&&lbl_BC_INST_ASSIGN_MINUS,                     \
848		&&lbl_BC_INST_ASSIGN,                           \
849		&&lbl_BC_INST_ASSIGN_POWER_NO_VAL,              \
850		&&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL,           \
851		&&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL,             \
852		&&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL,            \
853		&&lbl_BC_INST_ASSIGN_PLUS_NO_VAL,               \
854		&&lbl_BC_INST_ASSIGN_MINUS_NO_VAL,              \
855		&&lbl_BC_INST_ASSIGN_NO_VAL,                    \
856		&&lbl_BC_INST_NUM,                              \
857		&&lbl_BC_INST_VAR,                              \
858		&&lbl_BC_INST_ARRAY_ELEM,                       \
859		&&lbl_BC_INST_ARRAY,                            \
860		&&lbl_BC_INST_ZERO,                             \
861		&&lbl_BC_INST_ONE,                              \
862		&&lbl_BC_INST_LAST,                             \
863		&&lbl_BC_INST_IBASE,                            \
864		&&lbl_BC_INST_OBASE,                            \
865		&&lbl_BC_INST_SCALE,                            \
866		&&lbl_BC_INST_LENGTH,                           \
867		&&lbl_BC_INST_SCALE_FUNC,                       \
868		&&lbl_BC_INST_SQRT,                             \
869		&&lbl_BC_INST_ABS,                              \
870		&&lbl_BC_INST_IS_NUMBER,                        \
871		&&lbl_BC_INST_IS_STRING,                        \
872		&&lbl_BC_INST_ASCIIFY,                          \
873		&&lbl_BC_INST_READ,                             \
874		&&lbl_BC_INST_MAXIBASE,                         \
875		&&lbl_BC_INST_MAXOBASE,                         \
876		&&lbl_BC_INST_MAXSCALE,                         \
877		&&lbl_BC_INST_LINE_LENGTH,                      \
878		&&lbl_BC_INST_GLOBAL_STACKS,                    \
879		&&lbl_BC_INST_LEADING_ZERO,                     \
880		&&lbl_BC_INST_PRINT,                            \
881		&&lbl_BC_INST_PRINT_POP,                        \
882		&&lbl_BC_INST_STR,                              \
883		&&lbl_BC_INST_PRINT_STR,                        \
884		&&lbl_BC_INST_JUMP,                             \
885		&&lbl_BC_INST_JUMP_ZERO,                        \
886		&&lbl_BC_INST_CALL,                             \
887		&&lbl_BC_INST_RET,                              \
888		&&lbl_BC_INST_RET0,                             \
889		&&lbl_BC_INST_RET_VOID,                         \
890		&&lbl_BC_INST_HALT,                             \
891		&&lbl_BC_INST_POP,                              \
892		&&lbl_BC_INST_SWAP,                             \
893		&&lbl_BC_INST_MODEXP,                           \
894		&&lbl_BC_INST_DIVMOD,                           \
895		&&lbl_BC_INST_PRINT_STREAM,                     \
896		&&lbl_BC_INST_INVALID,                          \
897	}
898
899#endif // BC_ENABLE_EXTRA_MATH
900
901#endif // DC_ENABLED
902
903#else // BC_ENABLED
904
905#if BC_ENABLE_EXTRA_MATH
906
907#define BC_PROG_LBLS                                                   \
908	static const void* const bc_program_inst_lbls[] = {                \
909		&&lbl_BC_INST_NEG,           &&lbl_BC_INST_BOOL_NOT,           \
910		&&lbl_BC_INST_TRUNC,         &&lbl_BC_INST_POWER,              \
911		&&lbl_BC_INST_MULTIPLY,      &&lbl_BC_INST_DIVIDE,             \
912		&&lbl_BC_INST_MODULUS,       &&lbl_BC_INST_PLUS,               \
913		&&lbl_BC_INST_MINUS,         &&lbl_BC_INST_PLACES,             \
914		&&lbl_BC_INST_LSHIFT,        &&lbl_BC_INST_RSHIFT,             \
915		&&lbl_BC_INST_REL_EQ,        &&lbl_BC_INST_REL_LE,             \
916		&&lbl_BC_INST_REL_GE,        &&lbl_BC_INST_REL_NE,             \
917		&&lbl_BC_INST_REL_LT,        &&lbl_BC_INST_REL_GT,             \
918		&&lbl_BC_INST_BOOL_OR,       &&lbl_BC_INST_BOOL_AND,           \
919		&&lbl_BC_INST_ASSIGN_NO_VAL, &&lbl_BC_INST_NUM,                \
920		&&lbl_BC_INST_VAR,           &&lbl_BC_INST_ARRAY_ELEM,         \
921		&&lbl_BC_INST_ARRAY,         &&lbl_BC_INST_ZERO,               \
922		&&lbl_BC_INST_ONE,           &&lbl_BC_INST_IBASE,              \
923		&&lbl_BC_INST_OBASE,         &&lbl_BC_INST_SCALE,              \
924		&&lbl_BC_INST_SEED,          &&lbl_BC_INST_LENGTH,             \
925		&&lbl_BC_INST_SCALE_FUNC,    &&lbl_BC_INST_SQRT,               \
926		&&lbl_BC_INST_ABS,           &&lbl_BC_INST_IS_NUMBER,          \
927		&&lbl_BC_INST_IS_STRING,     &&lbl_BC_INST_IRAND,              \
928		&&lbl_BC_INST_ASCIIFY,       &&lbl_BC_INST_READ,               \
929		&&lbl_BC_INST_RAND,          &&lbl_BC_INST_MAXIBASE,           \
930		&&lbl_BC_INST_MAXOBASE,      &&lbl_BC_INST_MAXSCALE,           \
931		&&lbl_BC_INST_MAXRAND,       &&lbl_BC_INST_LINE_LENGTH,        \
932		&&lbl_BC_INST_LEADING_ZERO,  &&lbl_BC_INST_PRINT,              \
933		&&lbl_BC_INST_PRINT_POP,     &&lbl_BC_INST_STR,                \
934		&&lbl_BC_INST_POP,           &&lbl_BC_INST_SWAP,               \
935		&&lbl_BC_INST_MODEXP,        &&lbl_BC_INST_DIVMOD,             \
936		&&lbl_BC_INST_PRINT_STREAM,  &&lbl_BC_INST_EXTENDED_REGISTERS, \
937		&&lbl_BC_INST_POP_EXEC,      &&lbl_BC_INST_EXECUTE,            \
938		&&lbl_BC_INST_EXEC_COND,     &&lbl_BC_INST_PRINT_STACK,        \
939		&&lbl_BC_INST_CLEAR_STACK,   &&lbl_BC_INST_REG_STACK_LEN,      \
940		&&lbl_BC_INST_STACK_LEN,     &&lbl_BC_INST_DUPLICATE,          \
941		&&lbl_BC_INST_LOAD,          &&lbl_BC_INST_PUSH_VAR,           \
942		&&lbl_BC_INST_PUSH_TO_VAR,   &&lbl_BC_INST_QUIT,               \
943		&&lbl_BC_INST_NQUIT,         &&lbl_BC_INST_EXEC_STACK_LEN,     \
944		&&lbl_BC_INST_INVALID,                                         \
945	}
946
947#else // BC_ENABLE_EXTRA_MATH
948
949#define BC_PROG_LBLS                                                   \
950	static const void* const bc_program_inst_lbls[] = {                \
951		&&lbl_BC_INST_NEG,           &&lbl_BC_INST_BOOL_NOT,           \
952		&&lbl_BC_INST_POWER,         &&lbl_BC_INST_MULTIPLY,           \
953		&&lbl_BC_INST_DIVIDE,        &&lbl_BC_INST_MODULUS,            \
954		&&lbl_BC_INST_PLUS,          &&lbl_BC_INST_MINUS,              \
955		&&lbl_BC_INST_REL_EQ,        &&lbl_BC_INST_REL_LE,             \
956		&&lbl_BC_INST_REL_GE,        &&lbl_BC_INST_REL_NE,             \
957		&&lbl_BC_INST_REL_LT,        &&lbl_BC_INST_REL_GT,             \
958		&&lbl_BC_INST_BOOL_OR,       &&lbl_BC_INST_BOOL_AND,           \
959		&&lbl_BC_INST_ASSIGN_NO_VAL, &&lbl_BC_INST_NUM,                \
960		&&lbl_BC_INST_VAR,           &&lbl_BC_INST_ARRAY_ELEM,         \
961		&&lbl_BC_INST_ARRAY,         &&lbl_BC_INST_ZERO,               \
962		&&lbl_BC_INST_ONE,           &&lbl_BC_INST_IBASE,              \
963		&&lbl_BC_INST_OBASE,         &&lbl_BC_INST_SCALE,              \
964		&&lbl_BC_INST_LENGTH,        &&lbl_BC_INST_SCALE_FUNC,         \
965		&&lbl_BC_INST_SQRT,          &&lbl_BC_INST_ABS,                \
966		&&lbl_BC_INST_IS_NUMBER,     &&lbl_BC_INST_IS_STRING,          \
967		&&lbl_BC_INST_ASCIIFY,       &&lbl_BC_INST_READ,               \
968		&&lbl_BC_INST_MAXIBASE,      &&lbl_BC_INST_MAXOBASE,           \
969		&&lbl_BC_INST_MAXSCALE,      &&lbl_BC_INST_LINE_LENGTH,        \
970		&&lbl_BC_INST_LEADING_ZERO,  &&lbl_BC_INST_PRINT,              \
971		&&lbl_BC_INST_PRINT_POP,     &&lbl_BC_INST_STR,                \
972		&&lbl_BC_INST_POP,           &&lbl_BC_INST_SWAP,               \
973		&&lbl_BC_INST_MODEXP,        &&lbl_BC_INST_DIVMOD,             \
974		&&lbl_BC_INST_PRINT_STREAM,  &&lbl_BC_INST_EXTENDED_REGISTERS, \
975		&&lbl_BC_INST_POP_EXEC,      &&lbl_BC_INST_EXECUTE,            \
976		&&lbl_BC_INST_EXEC_COND,     &&lbl_BC_INST_PRINT_STACK,        \
977		&&lbl_BC_INST_CLEAR_STACK,   &&lbl_BC_INST_REG_STACK_LEN,      \
978		&&lbl_BC_INST_STACK_LEN,     &&lbl_BC_INST_DUPLICATE,          \
979		&&lbl_BC_INST_LOAD,          &&lbl_BC_INST_PUSH_VAR,           \
980		&&lbl_BC_INST_PUSH_TO_VAR,   &&lbl_BC_INST_QUIT,               \
981		&&lbl_BC_INST_NQUIT,         &&lbl_BC_INST_EXEC_STACK_LEN,     \
982		&&lbl_BC_INST_INVALID,                                         \
983	}
984
985#endif // BC_ENABLE_EXTRA_MATH
986
987#endif // BC_ENABLED
988
989#else // BC_HAS_COMPUTED_GOTO
990
991#define BC_PROG_JUMP(inst, code, ip) break
992#define BC_PROG_DIRECT_JUMP(l)
993#define BC_PROG_LBL(l) case l
994#define BC_PROG_FALLTHROUGH BC_FALLTHROUGH
995
996#define BC_PROG_LBLS
997
998#endif // BC_HAS_COMPUTED_GOTO
999
1000#endif // BC_PROGRAM_H
1001