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