/* * ***************************************************************************** * * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2018-2024 Gavin D. Howard and contributors. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * ***************************************************************************** * * Definitions for bc programs. * */ #ifndef BC_PROGRAM_H #define BC_PROGRAM_H #include #include #include #include #include #include #include /// The index of ibase in the globals array. #define BC_PROG_GLOBALS_IBASE (0) /// The index of obase in the globals array. #define BC_PROG_GLOBALS_OBASE (1) /// The index of scale in the globals array. #define BC_PROG_GLOBALS_SCALE (2) #if BC_ENABLE_EXTRA_MATH /// The index of the rand max in the maxes array. #define BC_PROG_MAX_RAND (3) #endif // BC_ENABLE_EXTRA_MATH /// The length of the globals array. #define BC_PROG_GLOBALS_LEN (3 + BC_ENABLE_EXTRA_MATH) typedef struct BcProgram { /// The array of globals values. BcBigDig globals[BC_PROG_GLOBALS_LEN]; #if BC_ENABLED /// The array of globals stacks. BcVec globals_v[BC_PROG_GLOBALS_LEN]; #endif // BC_ENABLED #if BC_ENABLE_EXTRA_MATH /// The pseudo-random number generator. BcRNG rng; #endif // BC_ENABLE_EXTRA_MATH /// The results stack. BcVec results; /// The execution stack. BcVec stack; /// The constants encountered in the program. They are global to the program /// to prevent bad accesses when functions that used non-auto variables are /// replaced. BcVec consts; /// The map of constants to go with consts. BcVec const_map; /// The strings encountered in the program. They are global to the program /// to prevent bad accesses when functions that used non-auto variables are /// replaced. BcVec strs; /// The map of strings to go with strs. BcVec str_map; /// The array of functions. BcVec fns; /// The map of functions to go with fns. BcVec fn_map; /// The array of variables. BcVec vars; /// The map of variables to go with vars. BcVec var_map; /// The array of arrays. BcVec arrs; /// The map of arrays to go with arrs. BcVec arr_map; #if DC_ENABLED /// A vector of tail calls. These are just integers, which are the number of /// tail calls that have been executed for each function (string) on the /// stack for dc. This is to prevent dc from constantly growing memory use /// because of pushing more and more string executions on the stack. BcVec tail_calls; #endif // DC_ENABLED /// A BcNum that has the proper base for asciify. BcNum strmb; // A BcNum to run asciify. This is to prevent GCC longjmp() clobbering // warnings. BcNum asciify; #if BC_ENABLED /// The last printed value for bc. BcNum last; #endif // BC_ENABLED // The BcDig array for strmb. This uses BC_NUM_LONG_LOG10 because it is used // in bc_num_ulong2num(), which attempts to realloc, unless it is big // enough. This is big enough. BcDig strmb_num[BC_NUM_BIGDIG_LOG10]; } BcProgram; /** * Returns true if the stack @a s has at least @a n items, false otherwise. * @param s The stack to check. * @param n The number of items the stack must have. * @return True if @a s has at least @a n items, false otherwise. */ #define BC_PROG_STACK(s, n) ((s)->len >= ((size_t) (n))) /** * Get a pointer to the top value in a global value stack. * @param v The global value stack. * @return A pointer to the top value in @a v. */ #define BC_PROG_GLOBAL_PTR(v) (bc_vec_top(v)) /** * Get the top value in a global value stack. * @param v The global value stack. * @return The top value in @a v. */ #define BC_PROG_GLOBAL(v) (*((BcBigDig*) BC_PROG_GLOBAL_PTR(v))) /** * Returns the current value of ibase. * @param p The program. * @return The current ibase. */ #define BC_PROG_IBASE(p) ((p)->globals[BC_PROG_GLOBALS_IBASE]) /** * Returns the current value of obase. * @param p The program. * @return The current obase. */ #define BC_PROG_OBASE(p) ((p)->globals[BC_PROG_GLOBALS_OBASE]) /** * Returns the current value of scale. * @param p The program. * @return The current scale. */ #define BC_PROG_SCALE(p) ((p)->globals[BC_PROG_GLOBALS_SCALE]) /// The index for the main function in the functions array.// #define BC_PROG_MAIN (0) /// The index for the read function in the functions array. #define BC_PROG_READ (1) /** * Retires (completes the execution of) an instruction. Some instructions * require special retirement, but most can use this. This basically pops the * operands while preserving the result (which we assumed was pushed before the * actual operation). * @param p The program. * @param nres The number of results returned by the instruction. * @param nops The number of operands used by the instruction. */ #define bc_program_retire(p, nres, nops) \ (bc_vec_npopAt(&(p)->results, (nops), (p)->results.len - (nres + nops))) #if DC_ENABLED /// A constant that tells how many functions are required in dc. #define BC_PROG_REQ_FUNCS (2) #if !BC_ENABLED /// Returns true if the calculator should pop after printing. #define BC_PROGRAM_POP(pop) (pop) #else // !BC_ENABLED /// Returns true if the calculator should pop after printing. #define BC_PROGRAM_POP(pop) (BC_IS_BC || (pop)) #endif // !BC_ENABLED // This is here to satisfy a clang warning about recursive macros. #define bc_program_pushVar(p, code, bgn, pop, copy) \ bc_program_pushVar_impl(p, code, bgn, pop, copy) #else // DC_ENABLED // This define disappears pop and copy because for bc, 'pop' and 'copy' are // always false. #define bc_program_pushVar(p, code, bgn, pop, copy) \ bc_program_pushVar_impl(p, code, bgn) /// Returns true if the calculator should pop after printing. #define BC_PROGRAM_POP(pop) (BC_IS_BC) // In debug mode, we want bc to check the stack, but otherwise, we don't because // the bc language implicitly mandates that the stack should always have enough // items. #ifdef BC_DEBUG #define BC_PROG_NO_STACK_CHECK #endif // BC_DEBUG #endif // DC_ENABLED /** * Returns true if the BcNum @a n is acting as a string. * @param n The BcNum to test. * @return True if @a n is acting as a string, false otherwise. */ #define BC_PROG_STR(n) ((n)->num == NULL && !(n)->cap) #if BC_ENABLED /** * Returns true if the result @a r and @a n is a number. * @param r The result. * @param n The number corresponding to the result. * @return True if the result holds a number, false otherwise. */ #define BC_PROG_NUM(r, n) \ ((r)->t != BC_RESULT_ARRAY && (r)->t != BC_RESULT_STR && !BC_PROG_STR(n)) #else // BC_ENABLED /** * Returns true if the result @a r and @a n is a number. * @param r The result. * @param n The number corresponding to the result. * @return True if the result holds a number, false otherwise. */ #define BC_PROG_NUM(r, n) ((r)->t != BC_RESULT_STR && !BC_PROG_STR(n)) #endif // BC_ENABLED /** * This is a function type for unary operations. Currently, these include * boolean not, negation, and truncation with extra math. * @param r The BcResult to store the result into. * @param n The parameter to the unary operation. */ typedef void (*BcProgramUnary)(BcResult* r, BcNum* n); /** * Initializes the BcProgram. * @param p The program to initialize. */ void bc_program_init(BcProgram* p); #if BC_DEBUG /** * Frees a BcProgram. This is only used in debug builds because a BcProgram is * only freed on program exit, and we don't care about freeing resources on * exit. * @param p The program to initialize. */ void bc_program_free(BcProgram* p); #endif // BC_DEBUG /** * Prints a stack trace of the bc functions or dc strings currently executing. * @param p The program. */ void bc_program_printStackTrace(BcProgram* p); #if BC_DEBUG_CODE #if BC_ENABLED && DC_ENABLED /** * Prints the bytecode in a function. This is a debug-only function. * @param p The program. */ void bc_program_code(const BcProgram* p); /** * Prints an instruction. This is a debug-only function. * @param p The program. * @param code The bytecode array. * @param bgn A pointer to the current index. It is also updated to the next * index. */ void bc_program_printInst(const BcProgram* p, const char* code, size_t* restrict bgn); /** * Prints the stack. This is a debug-only function. * @param p The program. */ void bc_program_printStackDebug(BcProgram* p); #endif // BC_ENABLED && DC_ENABLED #endif // BC_DEBUG_CODE /** * Returns the index of the variable or array in their respective arrays. * @param p The program. * @param name The name of the variable or array. * @param var True if the search should be for a variable, false for an array. * @return The index of the variable or array in the correct array. */ size_t bc_program_search(BcProgram* p, const char* name, bool var); /** * Adds a string to the program and returns the string's index in the program. * @param p The program. * @param str The string to add. * @return The string's index in the program. */ size_t bc_program_addString(BcProgram* p, const char* str); /** * Inserts a function into the program and returns the index of the function in * the fns array. * @param p The program. * @param name The name of the function. * @return The index of the function after insertion. */ size_t bc_program_insertFunc(BcProgram* p, const char* name); /** * Resets a program, usually because of resetting after an error. * @param p The program to reset. */ void bc_program_reset(BcProgram* p); /** * Executes bc or dc code in the BcProgram. * @param p The program. */ void bc_program_exec(BcProgram* p); /** * Negates a copy of a BcNum. This is a BcProgramUnary function. * @param r The BcResult to store the result into. * @param n The parameter to the unary operation. */ void bc_program_negate(BcResult* r, BcNum* n); /** * Returns a boolean not of a BcNum. This is a BcProgramUnary function. * @param r The BcResult to store the result into. * @param n The parameter to the unary operation. */ void bc_program_not(BcResult* r, BcNum* n); #if BC_ENABLE_EXTRA_MATH /** * Truncates a copy of a BcNum. This is a BcProgramUnary function. * @param r The BcResult to store the result into. * @param n The parameter to the unary operation. */ void bc_program_trunc(BcResult* r, BcNum* n); /** * Assigns a value to the seed builtin variable. * @param p The program. * @param val The value to assign to the seed. */ void bc_program_assignSeed(BcProgram* p, BcNum* val); #endif // BC_ENABLE_EXTRA_MATH /** * Assigns a value to a builtin value that is not seed. * @param p The program. * @param scale True if the builtin is scale. * @param obase True if the builtin is obase. This cannot be true at the same * time @a scale is. * @param val The value to assign to the builtin. */ void bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val); /// A reference to an array of binary operator functions. extern const BcNumBinaryOp bc_program_ops[]; /// A reference to an array of binary operator allocation request functions. extern const BcNumBinaryOpReq bc_program_opReqs[]; /// A reference to an array of unary operator functions. extern const BcProgramUnary bc_program_unarys[]; /// A reference to a filename for command-line expressions. extern const char bc_program_exprs_name[]; /// A reference to a filename for stdin. extern const char bc_program_stdin_name[]; /// A reference to the ready message printed on SIGINT. extern const char bc_program_ready_msg[]; /// A reference to the length of the ready message. extern const size_t bc_program_ready_msg_len; /// A reference to an array of escape characters for the print statement. extern const char bc_program_esc_chars[]; /// A reference to an array of the characters corresponding to the escape /// characters in bc_program_esc_chars. extern const char bc_program_esc_seqs[]; #if BC_HAS_COMPUTED_GOTO #if BC_DEBUG_CODE // clang-format off #define BC_PROG_JUMP(inst, code, ip) \ do \ { \ inst = (uchar) (code)[(ip)->idx++]; \ bc_file_printf(&vm->ferr, "inst: %s\n", bc_inst_names[inst]); \ bc_file_flush(&vm->ferr, bc_flush_none); \ goto *bc_program_inst_lbls[inst]; \ } \ while (0) // clang-format on #else // BC_DEBUG_CODE // clang-format off #define BC_PROG_JUMP(inst, code, ip) \ do \ { \ inst = (uchar) (code)[(ip)->idx++]; \ goto *bc_program_inst_lbls[inst]; \ } \ while (0) // clang-format on #endif // BC_DEBUG_CODE #define BC_PROG_DIRECT_JUMP(l) goto lbl_##l; #define BC_PROG_LBL(l) lbl_##l #define BC_PROG_FALLTHROUGH #if BC_C11 #define BC_PROG_LBLS_SIZE (sizeof(bc_program_inst_lbls) / sizeof(void*)) #define BC_PROG_LBLS_ASSERT \ _Static_assert(BC_PROG_LBLS_SIZE == BC_INST_INVALID + 1, \ "bc_program_inst_lbls[] mismatches the instructions") #else // BC_C11 #define BC_PROG_LBLS_ASSERT #endif // BC_C11 #if BC_ENABLED #if DC_ENABLED #if BC_ENABLE_EXTRA_MATH #define BC_PROG_LBLS \ static const void* const bc_program_inst_lbls[] = { \ &&lbl_BC_INST_INC, \ &&lbl_BC_INST_DEC, \ &&lbl_BC_INST_NEG, \ &&lbl_BC_INST_BOOL_NOT, \ &&lbl_BC_INST_TRUNC, \ &&lbl_BC_INST_POWER, \ &&lbl_BC_INST_MULTIPLY, \ &&lbl_BC_INST_DIVIDE, \ &&lbl_BC_INST_MODULUS, \ &&lbl_BC_INST_PLUS, \ &&lbl_BC_INST_MINUS, \ &&lbl_BC_INST_PLACES, \ &&lbl_BC_INST_LSHIFT, \ &&lbl_BC_INST_RSHIFT, \ &&lbl_BC_INST_REL_EQ, \ &&lbl_BC_INST_REL_LE, \ &&lbl_BC_INST_REL_GE, \ &&lbl_BC_INST_REL_NE, \ &&lbl_BC_INST_REL_LT, \ &&lbl_BC_INST_REL_GT, \ &&lbl_BC_INST_BOOL_OR, \ &&lbl_BC_INST_BOOL_AND, \ &&lbl_BC_INST_ASSIGN_POWER, \ &&lbl_BC_INST_ASSIGN_MULTIPLY, \ &&lbl_BC_INST_ASSIGN_DIVIDE, \ &&lbl_BC_INST_ASSIGN_MODULUS, \ &&lbl_BC_INST_ASSIGN_PLUS, \ &&lbl_BC_INST_ASSIGN_MINUS, \ &&lbl_BC_INST_ASSIGN_PLACES, \ &&lbl_BC_INST_ASSIGN_LSHIFT, \ &&lbl_BC_INST_ASSIGN_RSHIFT, \ &&lbl_BC_INST_ASSIGN, \ &&lbl_BC_INST_ASSIGN_POWER_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL, \ &&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_PLUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MINUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_PLACES_NO_VAL, \ &&lbl_BC_INST_ASSIGN_LSHIFT_NO_VAL, \ &&lbl_BC_INST_ASSIGN_RSHIFT_NO_VAL, \ &&lbl_BC_INST_ASSIGN_NO_VAL, \ &&lbl_BC_INST_NUM, \ &&lbl_BC_INST_VAR, \ &&lbl_BC_INST_ARRAY_ELEM, \ &&lbl_BC_INST_ARRAY, \ &&lbl_BC_INST_ZERO, \ &&lbl_BC_INST_ONE, \ &&lbl_BC_INST_LAST, \ &&lbl_BC_INST_IBASE, \ &&lbl_BC_INST_OBASE, \ &&lbl_BC_INST_SCALE, \ &&lbl_BC_INST_SEED, \ &&lbl_BC_INST_LENGTH, \ &&lbl_BC_INST_SCALE_FUNC, \ &&lbl_BC_INST_SQRT, \ &&lbl_BC_INST_ABS, \ &&lbl_BC_INST_IS_NUMBER, \ &&lbl_BC_INST_IS_STRING, \ &&lbl_BC_INST_IRAND, \ &&lbl_BC_INST_ASCIIFY, \ &&lbl_BC_INST_READ, \ &&lbl_BC_INST_RAND, \ &&lbl_BC_INST_MAXIBASE, \ &&lbl_BC_INST_MAXOBASE, \ &&lbl_BC_INST_MAXSCALE, \ &&lbl_BC_INST_MAXRAND, \ &&lbl_BC_INST_LINE_LENGTH, \ &&lbl_BC_INST_GLOBAL_STACKS, \ &&lbl_BC_INST_LEADING_ZERO, \ &&lbl_BC_INST_PRINT, \ &&lbl_BC_INST_PRINT_POP, \ &&lbl_BC_INST_STR, \ &&lbl_BC_INST_PRINT_STR, \ &&lbl_BC_INST_JUMP, \ &&lbl_BC_INST_JUMP_ZERO, \ &&lbl_BC_INST_CALL, \ &&lbl_BC_INST_RET, \ &&lbl_BC_INST_RET0, \ &&lbl_BC_INST_RET_VOID, \ &&lbl_BC_INST_HALT, \ &&lbl_BC_INST_POP, \ &&lbl_BC_INST_SWAP, \ &&lbl_BC_INST_MODEXP, \ &&lbl_BC_INST_DIVMOD, \ &&lbl_BC_INST_PRINT_STREAM, \ &&lbl_BC_INST_EXTENDED_REGISTERS, \ &&lbl_BC_INST_POP_EXEC, \ &&lbl_BC_INST_EXECUTE, \ &&lbl_BC_INST_EXEC_COND, \ &&lbl_BC_INST_PRINT_STACK, \ &&lbl_BC_INST_CLEAR_STACK, \ &&lbl_BC_INST_REG_STACK_LEN, \ &&lbl_BC_INST_STACK_LEN, \ &&lbl_BC_INST_DUPLICATE, \ &&lbl_BC_INST_LOAD, \ &&lbl_BC_INST_PUSH_VAR, \ &&lbl_BC_INST_PUSH_TO_VAR, \ &&lbl_BC_INST_QUIT, \ &&lbl_BC_INST_NQUIT, \ &&lbl_BC_INST_EXEC_STACK_LEN, \ &&lbl_BC_INST_INVALID, \ } #else // BC_ENABLE_EXTRA_MATH #define BC_PROG_LBLS \ static const void* const bc_program_inst_lbls[] = { \ &&lbl_BC_INST_INC, \ &&lbl_BC_INST_DEC, \ &&lbl_BC_INST_NEG, \ &&lbl_BC_INST_BOOL_NOT, \ &&lbl_BC_INST_POWER, \ &&lbl_BC_INST_MULTIPLY, \ &&lbl_BC_INST_DIVIDE, \ &&lbl_BC_INST_MODULUS, \ &&lbl_BC_INST_PLUS, \ &&lbl_BC_INST_MINUS, \ &&lbl_BC_INST_REL_EQ, \ &&lbl_BC_INST_REL_LE, \ &&lbl_BC_INST_REL_GE, \ &&lbl_BC_INST_REL_NE, \ &&lbl_BC_INST_REL_LT, \ &&lbl_BC_INST_REL_GT, \ &&lbl_BC_INST_BOOL_OR, \ &&lbl_BC_INST_BOOL_AND, \ &&lbl_BC_INST_ASSIGN_POWER, \ &&lbl_BC_INST_ASSIGN_MULTIPLY, \ &&lbl_BC_INST_ASSIGN_DIVIDE, \ &&lbl_BC_INST_ASSIGN_MODULUS, \ &&lbl_BC_INST_ASSIGN_PLUS, \ &&lbl_BC_INST_ASSIGN_MINUS, \ &&lbl_BC_INST_ASSIGN, \ &&lbl_BC_INST_ASSIGN_POWER_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL, \ &&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_PLUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MINUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_NO_VAL, \ &&lbl_BC_INST_NUM, \ &&lbl_BC_INST_VAR, \ &&lbl_BC_INST_ARRAY_ELEM, \ &&lbl_BC_INST_ARRAY, \ &&lbl_BC_INST_ZERO, \ &&lbl_BC_INST_ONE, \ &&lbl_BC_INST_LAST, \ &&lbl_BC_INST_IBASE, \ &&lbl_BC_INST_OBASE, \ &&lbl_BC_INST_SCALE, \ &&lbl_BC_INST_LENGTH, \ &&lbl_BC_INST_SCALE_FUNC, \ &&lbl_BC_INST_SQRT, \ &&lbl_BC_INST_ABS, \ &&lbl_BC_INST_IS_NUMBER, \ &&lbl_BC_INST_IS_STRING, \ &&lbl_BC_INST_ASCIIFY, \ &&lbl_BC_INST_READ, \ &&lbl_BC_INST_MAXIBASE, \ &&lbl_BC_INST_MAXOBASE, \ &&lbl_BC_INST_MAXSCALE, \ &&lbl_BC_INST_LINE_LENGTH, \ &&lbl_BC_INST_GLOBAL_STACKS, \ &&lbl_BC_INST_LEADING_ZERO, \ &&lbl_BC_INST_PRINT, \ &&lbl_BC_INST_PRINT_POP, \ &&lbl_BC_INST_STR, \ &&lbl_BC_INST_PRINT_STR, \ &&lbl_BC_INST_JUMP, \ &&lbl_BC_INST_JUMP_ZERO, \ &&lbl_BC_INST_CALL, \ &&lbl_BC_INST_RET, \ &&lbl_BC_INST_RET0, \ &&lbl_BC_INST_RET_VOID, \ &&lbl_BC_INST_HALT, \ &&lbl_BC_INST_POP, \ &&lbl_BC_INST_SWAP, \ &&lbl_BC_INST_MODEXP, \ &&lbl_BC_INST_DIVMOD, \ &&lbl_BC_INST_PRINT_STREAM, \ &&lbl_BC_INST_EXTENDED_REGISTERS, \ &&lbl_BC_INST_POP_EXEC, \ &&lbl_BC_INST_EXECUTE, \ &&lbl_BC_INST_EXEC_COND, \ &&lbl_BC_INST_PRINT_STACK, \ &&lbl_BC_INST_CLEAR_STACK, \ &&lbl_BC_INST_REG_STACK_LEN, \ &&lbl_BC_INST_STACK_LEN, \ &&lbl_BC_INST_DUPLICATE, \ &&lbl_BC_INST_LOAD, \ &&lbl_BC_INST_PUSH_VAR, \ &&lbl_BC_INST_PUSH_TO_VAR, \ &&lbl_BC_INST_QUIT, \ &&lbl_BC_INST_NQUIT, \ &&lbl_BC_INST_EXEC_STACK_LEN, \ &&lbl_BC_INST_INVALID, \ } #endif // BC_ENABLE_EXTRA_MATH #else // DC_ENABLED #if BC_ENABLE_EXTRA_MATH #define BC_PROG_LBLS \ static const void* const bc_program_inst_lbls[] = { \ &&lbl_BC_INST_INC, \ &&lbl_BC_INST_DEC, \ &&lbl_BC_INST_NEG, \ &&lbl_BC_INST_BOOL_NOT, \ &&lbl_BC_INST_TRUNC, \ &&lbl_BC_INST_POWER, \ &&lbl_BC_INST_MULTIPLY, \ &&lbl_BC_INST_DIVIDE, \ &&lbl_BC_INST_MODULUS, \ &&lbl_BC_INST_PLUS, \ &&lbl_BC_INST_MINUS, \ &&lbl_BC_INST_PLACES, \ &&lbl_BC_INST_LSHIFT, \ &&lbl_BC_INST_RSHIFT, \ &&lbl_BC_INST_REL_EQ, \ &&lbl_BC_INST_REL_LE, \ &&lbl_BC_INST_REL_GE, \ &&lbl_BC_INST_REL_NE, \ &&lbl_BC_INST_REL_LT, \ &&lbl_BC_INST_REL_GT, \ &&lbl_BC_INST_BOOL_OR, \ &&lbl_BC_INST_BOOL_AND, \ &&lbl_BC_INST_ASSIGN_POWER, \ &&lbl_BC_INST_ASSIGN_MULTIPLY, \ &&lbl_BC_INST_ASSIGN_DIVIDE, \ &&lbl_BC_INST_ASSIGN_MODULUS, \ &&lbl_BC_INST_ASSIGN_PLUS, \ &&lbl_BC_INST_ASSIGN_MINUS, \ &&lbl_BC_INST_ASSIGN_PLACES, \ &&lbl_BC_INST_ASSIGN_LSHIFT, \ &&lbl_BC_INST_ASSIGN_RSHIFT, \ &&lbl_BC_INST_ASSIGN, \ &&lbl_BC_INST_ASSIGN_POWER_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL, \ &&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_PLUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MINUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_PLACES_NO_VAL, \ &&lbl_BC_INST_ASSIGN_LSHIFT_NO_VAL, \ &&lbl_BC_INST_ASSIGN_RSHIFT_NO_VAL, \ &&lbl_BC_INST_ASSIGN_NO_VAL, \ &&lbl_BC_INST_NUM, \ &&lbl_BC_INST_VAR, \ &&lbl_BC_INST_ARRAY_ELEM, \ &&lbl_BC_INST_ARRAY, \ &&lbl_BC_INST_ZERO, \ &&lbl_BC_INST_ONE, \ &&lbl_BC_INST_LAST, \ &&lbl_BC_INST_IBASE, \ &&lbl_BC_INST_OBASE, \ &&lbl_BC_INST_SCALE, \ &&lbl_BC_INST_SEED, \ &&lbl_BC_INST_LENGTH, \ &&lbl_BC_INST_SCALE_FUNC, \ &&lbl_BC_INST_SQRT, \ &&lbl_BC_INST_ABS, \ &&lbl_BC_INST_IS_NUMBER, \ &&lbl_BC_INST_IS_STRING, \ &&lbl_BC_INST_IRAND, \ &&lbl_BC_INST_ASCIIFY, \ &&lbl_BC_INST_READ, \ &&lbl_BC_INST_RAND, \ &&lbl_BC_INST_MAXIBASE, \ &&lbl_BC_INST_MAXOBASE, \ &&lbl_BC_INST_MAXSCALE, \ &&lbl_BC_INST_MAXRAND, \ &&lbl_BC_INST_LINE_LENGTH, \ &&lbl_BC_INST_GLOBAL_STACKS, \ &&lbl_BC_INST_LEADING_ZERO, \ &&lbl_BC_INST_PRINT, \ &&lbl_BC_INST_PRINT_POP, \ &&lbl_BC_INST_STR, \ &&lbl_BC_INST_PRINT_STR, \ &&lbl_BC_INST_JUMP, \ &&lbl_BC_INST_JUMP_ZERO, \ &&lbl_BC_INST_CALL, \ &&lbl_BC_INST_RET, \ &&lbl_BC_INST_RET0, \ &&lbl_BC_INST_RET_VOID, \ &&lbl_BC_INST_HALT, \ &&lbl_BC_INST_POP, \ &&lbl_BC_INST_SWAP, \ &&lbl_BC_INST_MODEXP, \ &&lbl_BC_INST_DIVMOD, \ &&lbl_BC_INST_PRINT_STREAM, \ &&lbl_BC_INST_INVALID, \ } #else // BC_ENABLE_EXTRA_MATH #define BC_PROG_LBLS \ static const void* const bc_program_inst_lbls[] = { \ &&lbl_BC_INST_INC, \ &&lbl_BC_INST_DEC, \ &&lbl_BC_INST_NEG, \ &&lbl_BC_INST_BOOL_NOT, \ &&lbl_BC_INST_POWER, \ &&lbl_BC_INST_MULTIPLY, \ &&lbl_BC_INST_DIVIDE, \ &&lbl_BC_INST_MODULUS, \ &&lbl_BC_INST_PLUS, \ &&lbl_BC_INST_MINUS, \ &&lbl_BC_INST_REL_EQ, \ &&lbl_BC_INST_REL_LE, \ &&lbl_BC_INST_REL_GE, \ &&lbl_BC_INST_REL_NE, \ &&lbl_BC_INST_REL_LT, \ &&lbl_BC_INST_REL_GT, \ &&lbl_BC_INST_BOOL_OR, \ &&lbl_BC_INST_BOOL_AND, \ &&lbl_BC_INST_ASSIGN_POWER, \ &&lbl_BC_INST_ASSIGN_MULTIPLY, \ &&lbl_BC_INST_ASSIGN_DIVIDE, \ &&lbl_BC_INST_ASSIGN_MODULUS, \ &&lbl_BC_INST_ASSIGN_PLUS, \ &&lbl_BC_INST_ASSIGN_MINUS, \ &&lbl_BC_INST_ASSIGN, \ &&lbl_BC_INST_ASSIGN_POWER_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL, \ &&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_PLUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_MINUS_NO_VAL, \ &&lbl_BC_INST_ASSIGN_NO_VAL, \ &&lbl_BC_INST_NUM, \ &&lbl_BC_INST_VAR, \ &&lbl_BC_INST_ARRAY_ELEM, \ &&lbl_BC_INST_ARRAY, \ &&lbl_BC_INST_ZERO, \ &&lbl_BC_INST_ONE, \ &&lbl_BC_INST_LAST, \ &&lbl_BC_INST_IBASE, \ &&lbl_BC_INST_OBASE, \ &&lbl_BC_INST_SCALE, \ &&lbl_BC_INST_LENGTH, \ &&lbl_BC_INST_SCALE_FUNC, \ &&lbl_BC_INST_SQRT, \ &&lbl_BC_INST_ABS, \ &&lbl_BC_INST_IS_NUMBER, \ &&lbl_BC_INST_IS_STRING, \ &&lbl_BC_INST_ASCIIFY, \ &&lbl_BC_INST_READ, \ &&lbl_BC_INST_MAXIBASE, \ &&lbl_BC_INST_MAXOBASE, \ &&lbl_BC_INST_MAXSCALE, \ &&lbl_BC_INST_LINE_LENGTH, \ &&lbl_BC_INST_GLOBAL_STACKS, \ &&lbl_BC_INST_LEADING_ZERO, \ &&lbl_BC_INST_PRINT, \ &&lbl_BC_INST_PRINT_POP, \ &&lbl_BC_INST_STR, \ &&lbl_BC_INST_PRINT_STR, \ &&lbl_BC_INST_JUMP, \ &&lbl_BC_INST_JUMP_ZERO, \ &&lbl_BC_INST_CALL, \ &&lbl_BC_INST_RET, \ &&lbl_BC_INST_RET0, \ &&lbl_BC_INST_RET_VOID, \ &&lbl_BC_INST_HALT, \ &&lbl_BC_INST_POP, \ &&lbl_BC_INST_SWAP, \ &&lbl_BC_INST_MODEXP, \ &&lbl_BC_INST_DIVMOD, \ &&lbl_BC_INST_PRINT_STREAM, \ &&lbl_BC_INST_INVALID, \ } #endif // BC_ENABLE_EXTRA_MATH #endif // DC_ENABLED #else // BC_ENABLED #if BC_ENABLE_EXTRA_MATH #define BC_PROG_LBLS \ static const void* const bc_program_inst_lbls[] = { \ &&lbl_BC_INST_NEG, &&lbl_BC_INST_BOOL_NOT, \ &&lbl_BC_INST_TRUNC, &&lbl_BC_INST_POWER, \ &&lbl_BC_INST_MULTIPLY, &&lbl_BC_INST_DIVIDE, \ &&lbl_BC_INST_MODULUS, &&lbl_BC_INST_PLUS, \ &&lbl_BC_INST_MINUS, &&lbl_BC_INST_PLACES, \ &&lbl_BC_INST_LSHIFT, &&lbl_BC_INST_RSHIFT, \ &&lbl_BC_INST_REL_EQ, &&lbl_BC_INST_REL_LE, \ &&lbl_BC_INST_REL_GE, &&lbl_BC_INST_REL_NE, \ &&lbl_BC_INST_REL_LT, &&lbl_BC_INST_REL_GT, \ &&lbl_BC_INST_BOOL_OR, &&lbl_BC_INST_BOOL_AND, \ &&lbl_BC_INST_ASSIGN_NO_VAL, &&lbl_BC_INST_NUM, \ &&lbl_BC_INST_VAR, &&lbl_BC_INST_ARRAY_ELEM, \ &&lbl_BC_INST_ARRAY, &&lbl_BC_INST_ZERO, \ &&lbl_BC_INST_ONE, &&lbl_BC_INST_IBASE, \ &&lbl_BC_INST_OBASE, &&lbl_BC_INST_SCALE, \ &&lbl_BC_INST_SEED, &&lbl_BC_INST_LENGTH, \ &&lbl_BC_INST_SCALE_FUNC, &&lbl_BC_INST_SQRT, \ &&lbl_BC_INST_ABS, &&lbl_BC_INST_IS_NUMBER, \ &&lbl_BC_INST_IS_STRING, &&lbl_BC_INST_IRAND, \ &&lbl_BC_INST_ASCIIFY, &&lbl_BC_INST_READ, \ &&lbl_BC_INST_RAND, &&lbl_BC_INST_MAXIBASE, \ &&lbl_BC_INST_MAXOBASE, &&lbl_BC_INST_MAXSCALE, \ &&lbl_BC_INST_MAXRAND, &&lbl_BC_INST_LINE_LENGTH, \ &&lbl_BC_INST_LEADING_ZERO, &&lbl_BC_INST_PRINT, \ &&lbl_BC_INST_PRINT_POP, &&lbl_BC_INST_STR, \ &&lbl_BC_INST_POP, &&lbl_BC_INST_SWAP, \ &&lbl_BC_INST_MODEXP, &&lbl_BC_INST_DIVMOD, \ &&lbl_BC_INST_PRINT_STREAM, &&lbl_BC_INST_EXTENDED_REGISTERS, \ &&lbl_BC_INST_POP_EXEC, &&lbl_BC_INST_EXECUTE, \ &&lbl_BC_INST_EXEC_COND, &&lbl_BC_INST_PRINT_STACK, \ &&lbl_BC_INST_CLEAR_STACK, &&lbl_BC_INST_REG_STACK_LEN, \ &&lbl_BC_INST_STACK_LEN, &&lbl_BC_INST_DUPLICATE, \ &&lbl_BC_INST_LOAD, &&lbl_BC_INST_PUSH_VAR, \ &&lbl_BC_INST_PUSH_TO_VAR, &&lbl_BC_INST_QUIT, \ &&lbl_BC_INST_NQUIT, &&lbl_BC_INST_EXEC_STACK_LEN, \ &&lbl_BC_INST_INVALID, \ } #else // BC_ENABLE_EXTRA_MATH #define BC_PROG_LBLS \ static const void* const bc_program_inst_lbls[] = { \ &&lbl_BC_INST_NEG, &&lbl_BC_INST_BOOL_NOT, \ &&lbl_BC_INST_POWER, &&lbl_BC_INST_MULTIPLY, \ &&lbl_BC_INST_DIVIDE, &&lbl_BC_INST_MODULUS, \ &&lbl_BC_INST_PLUS, &&lbl_BC_INST_MINUS, \ &&lbl_BC_INST_REL_EQ, &&lbl_BC_INST_REL_LE, \ &&lbl_BC_INST_REL_GE, &&lbl_BC_INST_REL_NE, \ &&lbl_BC_INST_REL_LT, &&lbl_BC_INST_REL_GT, \ &&lbl_BC_INST_BOOL_OR, &&lbl_BC_INST_BOOL_AND, \ &&lbl_BC_INST_ASSIGN_NO_VAL, &&lbl_BC_INST_NUM, \ &&lbl_BC_INST_VAR, &&lbl_BC_INST_ARRAY_ELEM, \ &&lbl_BC_INST_ARRAY, &&lbl_BC_INST_ZERO, \ &&lbl_BC_INST_ONE, &&lbl_BC_INST_IBASE, \ &&lbl_BC_INST_OBASE, &&lbl_BC_INST_SCALE, \ &&lbl_BC_INST_LENGTH, &&lbl_BC_INST_SCALE_FUNC, \ &&lbl_BC_INST_SQRT, &&lbl_BC_INST_ABS, \ &&lbl_BC_INST_IS_NUMBER, &&lbl_BC_INST_IS_STRING, \ &&lbl_BC_INST_ASCIIFY, &&lbl_BC_INST_READ, \ &&lbl_BC_INST_MAXIBASE, &&lbl_BC_INST_MAXOBASE, \ &&lbl_BC_INST_MAXSCALE, &&lbl_BC_INST_LINE_LENGTH, \ &&lbl_BC_INST_LEADING_ZERO, &&lbl_BC_INST_PRINT, \ &&lbl_BC_INST_PRINT_POP, &&lbl_BC_INST_STR, \ &&lbl_BC_INST_POP, &&lbl_BC_INST_SWAP, \ &&lbl_BC_INST_MODEXP, &&lbl_BC_INST_DIVMOD, \ &&lbl_BC_INST_PRINT_STREAM, &&lbl_BC_INST_EXTENDED_REGISTERS, \ &&lbl_BC_INST_POP_EXEC, &&lbl_BC_INST_EXECUTE, \ &&lbl_BC_INST_EXEC_COND, &&lbl_BC_INST_PRINT_STACK, \ &&lbl_BC_INST_CLEAR_STACK, &&lbl_BC_INST_REG_STACK_LEN, \ &&lbl_BC_INST_STACK_LEN, &&lbl_BC_INST_DUPLICATE, \ &&lbl_BC_INST_LOAD, &&lbl_BC_INST_PUSH_VAR, \ &&lbl_BC_INST_PUSH_TO_VAR, &&lbl_BC_INST_QUIT, \ &&lbl_BC_INST_NQUIT, &&lbl_BC_INST_EXEC_STACK_LEN, \ &&lbl_BC_INST_INVALID, \ } #endif // BC_ENABLE_EXTRA_MATH #endif // BC_ENABLED #else // BC_HAS_COMPUTED_GOTO #define BC_PROG_JUMP(inst, code, ip) break #define BC_PROG_DIRECT_JUMP(l) #define BC_PROG_LBL(l) case l #define BC_PROG_FALLTHROUGH BC_FALLTHROUGH #define BC_PROG_LBLS #endif // BC_HAS_COMPUTED_GOTO #endif // BC_PROGRAM_H