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