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 67 typedef 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 NDEBUG 251 #define BC_PROG_NO_STACK_CHECK 252 #endif // NDEBUG 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 */ 292 typedef void (*BcProgramUnary)(BcResult* r, BcNum* n); 293 294 /** 295 * Initializes the BcProgram. 296 * @param p The program to initialize. 297 */ 298 void 299 bc_program_init(BcProgram* p); 300 301 #ifndef NDEBUG 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 */ 309 void 310 bc_program_free(BcProgram* p); 311 312 #endif // NDEBUG 313 314 /** 315 * Prints a stack trace of the bc functions or dc strings currently executing. 316 * @param p The program. 317 */ 318 void 319 bc_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 */ 328 void 329 bc_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 */ 338 void 339 bc_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 */ 346 void 347 bc_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 */ 359 size_t 360 bc_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 */ 368 size_t 369 bc_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 */ 378 size_t 379 bc_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 */ 385 void 386 bc_program_reset(BcProgram* p); 387 388 /** 389 * Executes bc or dc code in the BcProgram. 390 * @param p The program. 391 */ 392 void 393 bc_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 */ 400 void 401 bc_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 */ 408 void 409 bc_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 */ 418 void 419 bc_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 */ 426 void 427 bc_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 */ 439 void 440 bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val); 441 442 /// A reference to an array of binary operator functions. 443 extern const BcNumBinaryOp bc_program_ops[]; 444 445 /// A reference to an array of binary operator allocation request functions. 446 extern const BcNumBinaryOpReq bc_program_opReqs[]; 447 448 /// A reference to an array of unary operator functions. 449 extern const BcProgramUnary bc_program_unarys[]; 450 451 /// A reference to a filename for command-line expressions. 452 extern const char bc_program_exprs_name[]; 453 454 /// A reference to a filename for stdin. 455 extern const char bc_program_stdin_name[]; 456 457 /// A reference to the ready message printed on SIGINT. 458 extern const char bc_program_ready_msg[]; 459 460 /// A reference to the length of the ready message. 461 extern const size_t bc_program_ready_msg_len; 462 463 /// A reference to an array of escape characters for the print statement. 464 extern 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. 468 extern 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_POP_EXEC, \ 612 &&lbl_BC_INST_EXECUTE, \ 613 &&lbl_BC_INST_EXEC_COND, \ 614 &&lbl_BC_INST_PRINT_STACK, \ 615 &&lbl_BC_INST_CLEAR_STACK, \ 616 &&lbl_BC_INST_REG_STACK_LEN, \ 617 &&lbl_BC_INST_STACK_LEN, \ 618 &&lbl_BC_INST_DUPLICATE, \ 619 &&lbl_BC_INST_LOAD, \ 620 &&lbl_BC_INST_PUSH_VAR, \ 621 &&lbl_BC_INST_PUSH_TO_VAR, \ 622 &&lbl_BC_INST_QUIT, \ 623 &&lbl_BC_INST_NQUIT, \ 624 &&lbl_BC_INST_EXEC_STACK_LEN, \ 625 &&lbl_BC_INST_INVALID, \ 626 } 627 628 #else // BC_ENABLE_EXTRA_MATH 629 630 #define BC_PROG_LBLS \ 631 static const void* const bc_program_inst_lbls[] = { \ 632 &&lbl_BC_INST_INC, \ 633 &&lbl_BC_INST_DEC, \ 634 &&lbl_BC_INST_NEG, \ 635 &&lbl_BC_INST_BOOL_NOT, \ 636 &&lbl_BC_INST_POWER, \ 637 &&lbl_BC_INST_MULTIPLY, \ 638 &&lbl_BC_INST_DIVIDE, \ 639 &&lbl_BC_INST_MODULUS, \ 640 &&lbl_BC_INST_PLUS, \ 641 &&lbl_BC_INST_MINUS, \ 642 &&lbl_BC_INST_REL_EQ, \ 643 &&lbl_BC_INST_REL_LE, \ 644 &&lbl_BC_INST_REL_GE, \ 645 &&lbl_BC_INST_REL_NE, \ 646 &&lbl_BC_INST_REL_LT, \ 647 &&lbl_BC_INST_REL_GT, \ 648 &&lbl_BC_INST_BOOL_OR, \ 649 &&lbl_BC_INST_BOOL_AND, \ 650 &&lbl_BC_INST_ASSIGN_POWER, \ 651 &&lbl_BC_INST_ASSIGN_MULTIPLY, \ 652 &&lbl_BC_INST_ASSIGN_DIVIDE, \ 653 &&lbl_BC_INST_ASSIGN_MODULUS, \ 654 &&lbl_BC_INST_ASSIGN_PLUS, \ 655 &&lbl_BC_INST_ASSIGN_MINUS, \ 656 &&lbl_BC_INST_ASSIGN, \ 657 &&lbl_BC_INST_ASSIGN_POWER_NO_VAL, \ 658 &&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL, \ 659 &&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL, \ 660 &&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL, \ 661 &&lbl_BC_INST_ASSIGN_PLUS_NO_VAL, \ 662 &&lbl_BC_INST_ASSIGN_MINUS_NO_VAL, \ 663 &&lbl_BC_INST_ASSIGN_NO_VAL, \ 664 &&lbl_BC_INST_NUM, \ 665 &&lbl_BC_INST_VAR, \ 666 &&lbl_BC_INST_ARRAY_ELEM, \ 667 &&lbl_BC_INST_ARRAY, \ 668 &&lbl_BC_INST_ZERO, \ 669 &&lbl_BC_INST_ONE, \ 670 &&lbl_BC_INST_LAST, \ 671 &&lbl_BC_INST_IBASE, \ 672 &&lbl_BC_INST_OBASE, \ 673 &&lbl_BC_INST_SCALE, \ 674 &&lbl_BC_INST_LENGTH, \ 675 &&lbl_BC_INST_SCALE_FUNC, \ 676 &&lbl_BC_INST_SQRT, \ 677 &&lbl_BC_INST_ABS, \ 678 &&lbl_BC_INST_IS_NUMBER, \ 679 &&lbl_BC_INST_IS_STRING, \ 680 &&lbl_BC_INST_ASCIIFY, \ 681 &&lbl_BC_INST_READ, \ 682 &&lbl_BC_INST_MAXIBASE, \ 683 &&lbl_BC_INST_MAXOBASE, \ 684 &&lbl_BC_INST_MAXSCALE, \ 685 &&lbl_BC_INST_LINE_LENGTH, \ 686 &&lbl_BC_INST_GLOBAL_STACKS, \ 687 &&lbl_BC_INST_LEADING_ZERO, \ 688 &&lbl_BC_INST_PRINT, \ 689 &&lbl_BC_INST_PRINT_POP, \ 690 &&lbl_BC_INST_STR, \ 691 &&lbl_BC_INST_PRINT_STR, \ 692 &&lbl_BC_INST_JUMP, \ 693 &&lbl_BC_INST_JUMP_ZERO, \ 694 &&lbl_BC_INST_CALL, \ 695 &&lbl_BC_INST_RET, \ 696 &&lbl_BC_INST_RET0, \ 697 &&lbl_BC_INST_RET_VOID, \ 698 &&lbl_BC_INST_HALT, \ 699 &&lbl_BC_INST_POP, \ 700 &&lbl_BC_INST_SWAP, \ 701 &&lbl_BC_INST_MODEXP, \ 702 &&lbl_BC_INST_DIVMOD, \ 703 &&lbl_BC_INST_PRINT_STREAM, \ 704 &&lbl_BC_INST_POP_EXEC, \ 705 &&lbl_BC_INST_EXECUTE, \ 706 &&lbl_BC_INST_EXEC_COND, \ 707 &&lbl_BC_INST_PRINT_STACK, \ 708 &&lbl_BC_INST_CLEAR_STACK, \ 709 &&lbl_BC_INST_REG_STACK_LEN, \ 710 &&lbl_BC_INST_STACK_LEN, \ 711 &&lbl_BC_INST_DUPLICATE, \ 712 &&lbl_BC_INST_LOAD, \ 713 &&lbl_BC_INST_PUSH_VAR, \ 714 &&lbl_BC_INST_PUSH_TO_VAR, \ 715 &&lbl_BC_INST_QUIT, \ 716 &&lbl_BC_INST_NQUIT, \ 717 &&lbl_BC_INST_EXEC_STACK_LEN, \ 718 &&lbl_BC_INST_INVALID, \ 719 } 720 721 #endif // BC_ENABLE_EXTRA_MATH 722 723 #else // DC_ENABLED 724 725 #if BC_ENABLE_EXTRA_MATH 726 727 #define BC_PROG_LBLS \ 728 static const void* const bc_program_inst_lbls[] = { \ 729 &&lbl_BC_INST_INC, \ 730 &&lbl_BC_INST_DEC, \ 731 &&lbl_BC_INST_NEG, \ 732 &&lbl_BC_INST_BOOL_NOT, \ 733 &&lbl_BC_INST_TRUNC, \ 734 &&lbl_BC_INST_POWER, \ 735 &&lbl_BC_INST_MULTIPLY, \ 736 &&lbl_BC_INST_DIVIDE, \ 737 &&lbl_BC_INST_MODULUS, \ 738 &&lbl_BC_INST_PLUS, \ 739 &&lbl_BC_INST_MINUS, \ 740 &&lbl_BC_INST_PLACES, \ 741 &&lbl_BC_INST_LSHIFT, \ 742 &&lbl_BC_INST_RSHIFT, \ 743 &&lbl_BC_INST_REL_EQ, \ 744 &&lbl_BC_INST_REL_LE, \ 745 &&lbl_BC_INST_REL_GE, \ 746 &&lbl_BC_INST_REL_NE, \ 747 &&lbl_BC_INST_REL_LT, \ 748 &&lbl_BC_INST_REL_GT, \ 749 &&lbl_BC_INST_BOOL_OR, \ 750 &&lbl_BC_INST_BOOL_AND, \ 751 &&lbl_BC_INST_ASSIGN_POWER, \ 752 &&lbl_BC_INST_ASSIGN_MULTIPLY, \ 753 &&lbl_BC_INST_ASSIGN_DIVIDE, \ 754 &&lbl_BC_INST_ASSIGN_MODULUS, \ 755 &&lbl_BC_INST_ASSIGN_PLUS, \ 756 &&lbl_BC_INST_ASSIGN_MINUS, \ 757 &&lbl_BC_INST_ASSIGN_PLACES, \ 758 &&lbl_BC_INST_ASSIGN_LSHIFT, \ 759 &&lbl_BC_INST_ASSIGN_RSHIFT, \ 760 &&lbl_BC_INST_ASSIGN, \ 761 &&lbl_BC_INST_ASSIGN_POWER_NO_VAL, \ 762 &&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL, \ 763 &&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL, \ 764 &&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL, \ 765 &&lbl_BC_INST_ASSIGN_PLUS_NO_VAL, \ 766 &&lbl_BC_INST_ASSIGN_MINUS_NO_VAL, \ 767 &&lbl_BC_INST_ASSIGN_PLACES_NO_VAL, \ 768 &&lbl_BC_INST_ASSIGN_LSHIFT_NO_VAL, \ 769 &&lbl_BC_INST_ASSIGN_RSHIFT_NO_VAL, \ 770 &&lbl_BC_INST_ASSIGN_NO_VAL, \ 771 &&lbl_BC_INST_NUM, \ 772 &&lbl_BC_INST_VAR, \ 773 &&lbl_BC_INST_ARRAY_ELEM, \ 774 &&lbl_BC_INST_ARRAY, \ 775 &&lbl_BC_INST_ZERO, \ 776 &&lbl_BC_INST_ONE, \ 777 &&lbl_BC_INST_LAST, \ 778 &&lbl_BC_INST_IBASE, \ 779 &&lbl_BC_INST_OBASE, \ 780 &&lbl_BC_INST_SCALE, \ 781 &&lbl_BC_INST_SEED, \ 782 &&lbl_BC_INST_LENGTH, \ 783 &&lbl_BC_INST_SCALE_FUNC, \ 784 &&lbl_BC_INST_SQRT, \ 785 &&lbl_BC_INST_ABS, \ 786 &&lbl_BC_INST_IS_NUMBER, \ 787 &&lbl_BC_INST_IS_STRING, \ 788 &&lbl_BC_INST_IRAND, \ 789 &&lbl_BC_INST_ASCIIFY, \ 790 &&lbl_BC_INST_READ, \ 791 &&lbl_BC_INST_RAND, \ 792 &&lbl_BC_INST_MAXIBASE, \ 793 &&lbl_BC_INST_MAXOBASE, \ 794 &&lbl_BC_INST_MAXSCALE, \ 795 &&lbl_BC_INST_MAXRAND, \ 796 &&lbl_BC_INST_LINE_LENGTH, \ 797 &&lbl_BC_INST_GLOBAL_STACKS, \ 798 &&lbl_BC_INST_LEADING_ZERO, \ 799 &&lbl_BC_INST_PRINT, \ 800 &&lbl_BC_INST_PRINT_POP, \ 801 &&lbl_BC_INST_STR, \ 802 &&lbl_BC_INST_PRINT_STR, \ 803 &&lbl_BC_INST_JUMP, \ 804 &&lbl_BC_INST_JUMP_ZERO, \ 805 &&lbl_BC_INST_CALL, \ 806 &&lbl_BC_INST_RET, \ 807 &&lbl_BC_INST_RET0, \ 808 &&lbl_BC_INST_RET_VOID, \ 809 &&lbl_BC_INST_HALT, \ 810 &&lbl_BC_INST_POP, \ 811 &&lbl_BC_INST_SWAP, \ 812 &&lbl_BC_INST_MODEXP, \ 813 &&lbl_BC_INST_DIVMOD, \ 814 &&lbl_BC_INST_PRINT_STREAM, \ 815 &&lbl_BC_INST_INVALID, \ 816 } 817 818 #else // BC_ENABLE_EXTRA_MATH 819 820 #define BC_PROG_LBLS \ 821 static const void* const bc_program_inst_lbls[] = { \ 822 &&lbl_BC_INST_INC, \ 823 &&lbl_BC_INST_DEC, \ 824 &&lbl_BC_INST_NEG, \ 825 &&lbl_BC_INST_BOOL_NOT, \ 826 &&lbl_BC_INST_POWER, \ 827 &&lbl_BC_INST_MULTIPLY, \ 828 &&lbl_BC_INST_DIVIDE, \ 829 &&lbl_BC_INST_MODULUS, \ 830 &&lbl_BC_INST_PLUS, \ 831 &&lbl_BC_INST_MINUS, \ 832 &&lbl_BC_INST_REL_EQ, \ 833 &&lbl_BC_INST_REL_LE, \ 834 &&lbl_BC_INST_REL_GE, \ 835 &&lbl_BC_INST_REL_NE, \ 836 &&lbl_BC_INST_REL_LT, \ 837 &&lbl_BC_INST_REL_GT, \ 838 &&lbl_BC_INST_BOOL_OR, \ 839 &&lbl_BC_INST_BOOL_AND, \ 840 &&lbl_BC_INST_ASSIGN_POWER, \ 841 &&lbl_BC_INST_ASSIGN_MULTIPLY, \ 842 &&lbl_BC_INST_ASSIGN_DIVIDE, \ 843 &&lbl_BC_INST_ASSIGN_MODULUS, \ 844 &&lbl_BC_INST_ASSIGN_PLUS, \ 845 &&lbl_BC_INST_ASSIGN_MINUS, \ 846 &&lbl_BC_INST_ASSIGN, \ 847 &&lbl_BC_INST_ASSIGN_POWER_NO_VAL, \ 848 &&lbl_BC_INST_ASSIGN_MULTIPLY_NO_VAL, \ 849 &&lbl_BC_INST_ASSIGN_DIVIDE_NO_VAL, \ 850 &&lbl_BC_INST_ASSIGN_MODULUS_NO_VAL, \ 851 &&lbl_BC_INST_ASSIGN_PLUS_NO_VAL, \ 852 &&lbl_BC_INST_ASSIGN_MINUS_NO_VAL, \ 853 &&lbl_BC_INST_ASSIGN_NO_VAL, \ 854 &&lbl_BC_INST_NUM, \ 855 &&lbl_BC_INST_VAR, \ 856 &&lbl_BC_INST_ARRAY_ELEM, \ 857 &&lbl_BC_INST_ARRAY, \ 858 &&lbl_BC_INST_ZERO, \ 859 &&lbl_BC_INST_ONE, \ 860 &&lbl_BC_INST_LAST, \ 861 &&lbl_BC_INST_IBASE, \ 862 &&lbl_BC_INST_OBASE, \ 863 &&lbl_BC_INST_SCALE, \ 864 &&lbl_BC_INST_LENGTH, \ 865 &&lbl_BC_INST_SCALE_FUNC, \ 866 &&lbl_BC_INST_SQRT, \ 867 &&lbl_BC_INST_ABS, \ 868 &&lbl_BC_INST_IS_NUMBER, \ 869 &&lbl_BC_INST_IS_STRING, \ 870 &&lbl_BC_INST_ASCIIFY, \ 871 &&lbl_BC_INST_READ, \ 872 &&lbl_BC_INST_MAXIBASE, \ 873 &&lbl_BC_INST_MAXOBASE, \ 874 &&lbl_BC_INST_MAXSCALE, \ 875 &&lbl_BC_INST_LINE_LENGTH, \ 876 &&lbl_BC_INST_GLOBAL_STACKS, \ 877 &&lbl_BC_INST_LEADING_ZERO, \ 878 &&lbl_BC_INST_PRINT, \ 879 &&lbl_BC_INST_PRINT_POP, \ 880 &&lbl_BC_INST_STR, \ 881 &&lbl_BC_INST_PRINT_STR, \ 882 &&lbl_BC_INST_JUMP, \ 883 &&lbl_BC_INST_JUMP_ZERO, \ 884 &&lbl_BC_INST_CALL, \ 885 &&lbl_BC_INST_RET, \ 886 &&lbl_BC_INST_RET0, \ 887 &&lbl_BC_INST_RET_VOID, \ 888 &&lbl_BC_INST_HALT, \ 889 &&lbl_BC_INST_POP, \ 890 &&lbl_BC_INST_SWAP, \ 891 &&lbl_BC_INST_MODEXP, \ 892 &&lbl_BC_INST_DIVMOD, \ 893 &&lbl_BC_INST_PRINT_STREAM, \ 894 &&lbl_BC_INST_INVALID, \ 895 } 896 897 #endif // BC_ENABLE_EXTRA_MATH 898 899 #endif // DC_ENABLED 900 901 #else // BC_ENABLED 902 903 #if BC_ENABLE_EXTRA_MATH 904 905 #define BC_PROG_LBLS \ 906 static const void* const bc_program_inst_lbls[] = { \ 907 &&lbl_BC_INST_NEG, \ 908 &&lbl_BC_INST_BOOL_NOT, \ 909 &&lbl_BC_INST_TRUNC, \ 910 &&lbl_BC_INST_POWER, \ 911 &&lbl_BC_INST_MULTIPLY, \ 912 &&lbl_BC_INST_DIVIDE, \ 913 &&lbl_BC_INST_MODULUS, \ 914 &&lbl_BC_INST_PLUS, \ 915 &&lbl_BC_INST_MINUS, \ 916 &&lbl_BC_INST_PLACES, \ 917 &&lbl_BC_INST_LSHIFT, \ 918 &&lbl_BC_INST_RSHIFT, \ 919 &&lbl_BC_INST_REL_EQ, \ 920 &&lbl_BC_INST_REL_LE, \ 921 &&lbl_BC_INST_REL_GE, \ 922 &&lbl_BC_INST_REL_NE, \ 923 &&lbl_BC_INST_REL_LT, \ 924 &&lbl_BC_INST_REL_GT, \ 925 &&lbl_BC_INST_BOOL_OR, \ 926 &&lbl_BC_INST_BOOL_AND, \ 927 &&lbl_BC_INST_ASSIGN_NO_VAL, \ 928 &&lbl_BC_INST_NUM, \ 929 &&lbl_BC_INST_VAR, \ 930 &&lbl_BC_INST_ARRAY_ELEM, \ 931 &&lbl_BC_INST_ARRAY, \ 932 &&lbl_BC_INST_ZERO, \ 933 &&lbl_BC_INST_ONE, \ 934 &&lbl_BC_INST_IBASE, \ 935 &&lbl_BC_INST_OBASE, \ 936 &&lbl_BC_INST_SCALE, \ 937 &&lbl_BC_INST_SEED, \ 938 &&lbl_BC_INST_LENGTH, \ 939 &&lbl_BC_INST_SCALE_FUNC, \ 940 &&lbl_BC_INST_SQRT, \ 941 &&lbl_BC_INST_ABS, \ 942 &&lbl_BC_INST_IS_NUMBER, \ 943 &&lbl_BC_INST_IS_STRING, \ 944 &&lbl_BC_INST_IRAND, \ 945 &&lbl_BC_INST_ASCIIFY, \ 946 &&lbl_BC_INST_READ, \ 947 &&lbl_BC_INST_RAND, \ 948 &&lbl_BC_INST_MAXIBASE, \ 949 &&lbl_BC_INST_MAXOBASE, \ 950 &&lbl_BC_INST_MAXSCALE, \ 951 &&lbl_BC_INST_MAXRAND, \ 952 &&lbl_BC_INST_LINE_LENGTH, \ 953 &&lbl_BC_INST_LEADING_ZERO, \ 954 &&lbl_BC_INST_PRINT, \ 955 &&lbl_BC_INST_PRINT_POP, \ 956 &&lbl_BC_INST_STR, \ 957 &&lbl_BC_INST_POP, \ 958 &&lbl_BC_INST_SWAP, \ 959 &&lbl_BC_INST_MODEXP, \ 960 &&lbl_BC_INST_DIVMOD, \ 961 &&lbl_BC_INST_PRINT_STREAM, \ 962 &&lbl_BC_INST_POP_EXEC, \ 963 &&lbl_BC_INST_EXECUTE, \ 964 &&lbl_BC_INST_EXEC_COND, \ 965 &&lbl_BC_INST_PRINT_STACK, \ 966 &&lbl_BC_INST_CLEAR_STACK, \ 967 &&lbl_BC_INST_REG_STACK_LEN, \ 968 &&lbl_BC_INST_STACK_LEN, \ 969 &&lbl_BC_INST_DUPLICATE, \ 970 &&lbl_BC_INST_LOAD, \ 971 &&lbl_BC_INST_PUSH_VAR, \ 972 &&lbl_BC_INST_PUSH_TO_VAR, \ 973 &&lbl_BC_INST_QUIT, \ 974 &&lbl_BC_INST_NQUIT, \ 975 &&lbl_BC_INST_EXEC_STACK_LEN, \ 976 &&lbl_BC_INST_INVALID, \ 977 } 978 979 #else // BC_ENABLE_EXTRA_MATH 980 981 #define BC_PROG_LBLS \ 982 static const void* const bc_program_inst_lbls[] = { \ 983 &&lbl_BC_INST_NEG, \ 984 &&lbl_BC_INST_BOOL_NOT, \ 985 &&lbl_BC_INST_POWER, \ 986 &&lbl_BC_INST_MULTIPLY, \ 987 &&lbl_BC_INST_DIVIDE, \ 988 &&lbl_BC_INST_MODULUS, \ 989 &&lbl_BC_INST_PLUS, \ 990 &&lbl_BC_INST_MINUS, \ 991 &&lbl_BC_INST_REL_EQ, \ 992 &&lbl_BC_INST_REL_LE, \ 993 &&lbl_BC_INST_REL_GE, \ 994 &&lbl_BC_INST_REL_NE, \ 995 &&lbl_BC_INST_REL_LT, \ 996 &&lbl_BC_INST_REL_GT, \ 997 &&lbl_BC_INST_BOOL_OR, \ 998 &&lbl_BC_INST_BOOL_AND, \ 999 &&lbl_BC_INST_ASSIGN_NO_VAL, \ 1000 &&lbl_BC_INST_NUM, \ 1001 &&lbl_BC_INST_VAR, \ 1002 &&lbl_BC_INST_ARRAY_ELEM, \ 1003 &&lbl_BC_INST_ARRAY, \ 1004 &&lbl_BC_INST_ZERO, \ 1005 &&lbl_BC_INST_ONE, \ 1006 &&lbl_BC_INST_IBASE, \ 1007 &&lbl_BC_INST_OBASE, \ 1008 &&lbl_BC_INST_SCALE, \ 1009 &&lbl_BC_INST_LENGTH, \ 1010 &&lbl_BC_INST_SCALE_FUNC, \ 1011 &&lbl_BC_INST_SQRT, \ 1012 &&lbl_BC_INST_ABS, \ 1013 &&lbl_BC_INST_IS_NUMBER, \ 1014 &&lbl_BC_INST_IS_STRING, \ 1015 &&lbl_BC_INST_ASCIIFY, \ 1016 &&lbl_BC_INST_READ, \ 1017 &&lbl_BC_INST_MAXIBASE, \ 1018 &&lbl_BC_INST_MAXOBASE, \ 1019 &&lbl_BC_INST_MAXSCALE, \ 1020 &&lbl_BC_INST_LINE_LENGTH, \ 1021 &&lbl_BC_INST_LEADING_ZERO, \ 1022 &&lbl_BC_INST_PRINT, \ 1023 &&lbl_BC_INST_PRINT_POP, \ 1024 &&lbl_BC_INST_STR, \ 1025 &&lbl_BC_INST_POP, \ 1026 &&lbl_BC_INST_SWAP, \ 1027 &&lbl_BC_INST_MODEXP, \ 1028 &&lbl_BC_INST_DIVMOD, \ 1029 &&lbl_BC_INST_PRINT_STREAM, \ 1030 &&lbl_BC_INST_POP_EXEC, \ 1031 &&lbl_BC_INST_EXECUTE, \ 1032 &&lbl_BC_INST_EXEC_COND, \ 1033 &&lbl_BC_INST_PRINT_STACK, \ 1034 &&lbl_BC_INST_CLEAR_STACK, \ 1035 &&lbl_BC_INST_REG_STACK_LEN, \ 1036 &&lbl_BC_INST_STACK_LEN, \ 1037 &&lbl_BC_INST_DUPLICATE, \ 1038 &&lbl_BC_INST_LOAD, \ 1039 &&lbl_BC_INST_PUSH_VAR, \ 1040 &&lbl_BC_INST_PUSH_TO_VAR, \ 1041 &&lbl_BC_INST_QUIT, \ 1042 &&lbl_BC_INST_NQUIT, \ 1043 &&lbl_BC_INST_EXEC_STACK_LEN, \ 1044 &&lbl_BC_INST_INVALID, \ 1045 } 1046 1047 #endif // BC_ENABLE_EXTRA_MATH 1048 1049 #endif // BC_ENABLED 1050 1051 #else // BC_HAS_COMPUTED_GOTO 1052 1053 #define BC_PROG_JUMP(inst, code, ip) break 1054 #define BC_PROG_DIRECT_JUMP(l) 1055 #define BC_PROG_LBL(l) case l 1056 #define BC_PROG_FALLTHROUGH BC_FALLTHROUGH 1057 1058 #define BC_PROG_LBLS 1059 1060 #endif // BC_HAS_COMPUTED_GOTO 1061 1062 #endif // BC_PROGRAM_H 1063