program.c (78bc019d220e05abb5b12f678f9b4a847019bbcc) | program.c (d101cdd6edd782f6ec56eef63ed91abd77a8b317) |
---|---|
1/* 2 * ***************************************************************************** 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * | 1/* 2 * ***************************************************************************** 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * |
6 * Copyright (c) 2018-2021 Gavin D. Howard and contributors. | 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, --- 29 unchanged lines hidden (view full) --- 44#include <time.h> 45 46#include <read.h> 47#include <parse.h> 48#include <program.h> 49#include <vm.h> 50 51/** | 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, --- 29 unchanged lines hidden (view full) --- 44#include <time.h> 45 46#include <read.h> 47#include <parse.h> 48#include <program.h> 49#include <vm.h> 50 51/** |
52 * Quickly sets the const and strs vector pointers in the program. This is a 53 * convenience function. 54 * @param p The program. 55 * @param f The new function. 56 */ 57static inline void 58bc_program_setVecs(BcProgram* p, BcFunc* f) 59{ 60 BC_SIG_ASSERT_LOCKED; 61 p->consts = &f->consts; 62 p->strs = &f->strs; 63} 64 65/** | |
66 * Does a type check for something that expects a number. 67 * @param r The result that will be checked. 68 * @param n The result's number. 69 */ 70static inline void 71bc_program_type_num(BcResult* r, BcNum* n) 72{ 73#if BC_ENABLED --- 45 unchanged lines hidden (view full) --- 119} 120 121/** 122 * Returns a string from a result and its number. 123 * @param p The program. 124 * @param n The number tied to the result. 125 * @return The string corresponding to the result and number. 126 */ | 52 * Does a type check for something that expects a number. 53 * @param r The result that will be checked. 54 * @param n The result's number. 55 */ 56static inline void 57bc_program_type_num(BcResult* r, BcNum* n) 58{ 59#if BC_ENABLED --- 45 unchanged lines hidden (view full) --- 105} 106 107/** 108 * Returns a string from a result and its number. 109 * @param p The program. 110 * @param n The number tied to the result. 111 * @return The string corresponding to the result and number. 112 */ |
127static char* | 113static inline char* |
128bc_program_string(BcProgram* p, const BcNum* n) 129{ | 114bc_program_string(BcProgram* p, const BcNum* n) 115{ |
130 BcFunc* f = bc_vec_item(&p->fns, n->rdx); 131 return *((char**) bc_vec_item(&f->strs, n->scale)); | 116 return *((char**) bc_vec_item(&p->strs, n->scale)); |
132} 133 134#if BC_ENABLED 135 136/** 137 * Prepares the globals for a function call. This is only called when global 138 * stacks are on because it pushes a copy of the current globals onto each of 139 * their respective stacks. --- 62 unchanged lines hidden (view full) --- 202 203 v = bc_vec_item(bc_vec_item(&p->arrs, vidx), nidx); 204 205 // We want to be sure we do *not* have a reference vector. 206 assert(v->size != sizeof(uchar)); 207 208 return v; 209} | 117} 118 119#if BC_ENABLED 120 121/** 122 * Prepares the globals for a function call. This is only called when global 123 * stacks are on because it pushes a copy of the current globals onto each of 124 * their respective stacks. --- 62 unchanged lines hidden (view full) --- 187 188 v = bc_vec_item(bc_vec_item(&p->arrs, vidx), nidx); 189 190 // We want to be sure we do *not* have a reference vector. 191 assert(v->size != sizeof(uchar)); 192 193 return v; 194} |
195 |
|
210#endif // BC_ENABLED 211 212/** 213 * Creates a BcNum from a BcBigDig and pushes onto the results stack. This is a 214 * convenience function. 215 * @param p The program. 216 * @param dig The BcBigDig to push onto the results stack. 217 * @param type The type that the pushed result should be. --- 9 unchanged lines hidden (view full) --- 227 228 bc_num_createFromBigdig(&res.d.n, dig); 229 bc_vec_push(&p->results, &res); 230 231 BC_SIG_UNLOCK; 232} 233 234size_t | 196#endif // BC_ENABLED 197 198/** 199 * Creates a BcNum from a BcBigDig and pushes onto the results stack. This is a 200 * convenience function. 201 * @param p The program. 202 * @param dig The BcBigDig to push onto the results stack. 203 * @param type The type that the pushed result should be. --- 9 unchanged lines hidden (view full) --- 213 214 bc_num_createFromBigdig(&res.d.n, dig); 215 bc_vec_push(&p->results, &res); 216 217 BC_SIG_UNLOCK; 218} 219 220size_t |
235bc_program_addString(BcProgram* p, const char* str, size_t fidx) | 221bc_program_addString(BcProgram* p, const char* str) |
236{ | 222{ |
237 BcFunc* f; 238 char** str_ptr; 239 BcVec* slabs; | 223 size_t idx; |
240 241 BC_SIG_ASSERT_LOCKED; 242 | 224 225 BC_SIG_ASSERT_LOCKED; 226 |
243 // Push an empty string on the proper vector. 244 f = bc_vec_item(&p->fns, fidx); 245 str_ptr = bc_vec_pushEmpty(&f->strs); | 227 if (bc_map_insert(&p->str_map, str, p->strs.len, &idx)) 228 { 229 char** str_ptr; 230 BcId* id = bc_vec_item(&p->str_map, idx); |
246 | 231 |
247 // Figure out which slab vector to use. 248 slabs = fidx == BC_PROG_MAIN || fidx == BC_PROG_READ ? 249 &vm.main_slabs : 250 &vm.other_slabs; | 232 // Get the index. 233 idx = id->idx; |
251 | 234 |
252 *str_ptr = bc_slabvec_strdup(slabs, str); | 235 // Push an empty string on the proper vector. 236 str_ptr = bc_vec_pushEmpty(&p->strs); |
253 | 237 |
254 return f->strs.len - 1; | 238 // We reuse the string in the ID (allocated by bc_map_insert()), because 239 // why not? 240 *str_ptr = id->name; 241 } 242 else 243 { 244 BcId* id = bc_vec_item(&p->str_map, idx); 245 idx = id->idx; 246 } 247 248 return idx; |
255} 256 257size_t | 249} 250 251size_t |
258bc_program_search(BcProgram* p, const char* id, bool var) | 252bc_program_search(BcProgram* p, const char* name, bool var) |
259{ 260 BcVec* v; 261 BcVec* map; 262 size_t i; 263 264 BC_SIG_ASSERT_LOCKED; 265 266 // Grab the right vector and map. 267 v = var ? &p->vars : &p->arrs; 268 map = var ? &p->var_map : &p->arr_map; 269 270 // We do an insert because the variable might not exist yet. This is because 271 // the parser calls this function. If the insert succeeds, we create a stack 272 // for the variable/array. But regardless, bc_map_insert() gives us the 273 // index of the item in i. | 253{ 254 BcVec* v; 255 BcVec* map; 256 size_t i; 257 258 BC_SIG_ASSERT_LOCKED; 259 260 // Grab the right vector and map. 261 v = var ? &p->vars : &p->arrs; 262 map = var ? &p->var_map : &p->arr_map; 263 264 // We do an insert because the variable might not exist yet. This is because 265 // the parser calls this function. If the insert succeeds, we create a stack 266 // for the variable/array. But regardless, bc_map_insert() gives us the 267 // index of the item in i. |
274 if (bc_map_insert(map, id, v->len, &i)) | 268 if (bc_map_insert(map, name, v->len, &i)) |
275 { 276 BcVec* temp = bc_vec_pushEmpty(v); 277 bc_array_init(temp, var); 278 } 279 280 return ((BcId*) bc_vec_item(map, i))->idx; 281} 282 --- 64 unchanged lines hidden (view full) --- 347 // Surprisingly enough, the hard case is *not* returning an array; 348 // it's returning an array element. This is because we have to dig 349 // deeper to get *to* the element. That's what the code inside this 350 // if statement does. 351 if (r->t == BC_RESULT_ARRAY_ELEM) 352 { 353 size_t idx = r->d.loc.idx; 354 | 269 { 270 BcVec* temp = bc_vec_pushEmpty(v); 271 bc_array_init(temp, var); 272 } 273 274 return ((BcId*) bc_vec_item(map, i))->idx; 275} 276 --- 64 unchanged lines hidden (view full) --- 341 // Surprisingly enough, the hard case is *not* returning an array; 342 // it's returning an array element. This is because we have to dig 343 // deeper to get *to* the element. That's what the code inside this 344 // if statement does. 345 if (r->t == BC_RESULT_ARRAY_ELEM) 346 { 347 size_t idx = r->d.loc.idx; 348 |
355 v = bc_vec_top(v); | 349 v = bc_vec_item(v, r->d.loc.stack_idx); |
356 357#if BC_ENABLED 358 // If this is true, we have a reference vector, so dereference 359 // it. The reason we don't need to worry about it for returning 360 // a straight array is because we only care about references 361 // when we access elements of an array that is a reference. That 362 // is this code, so in essence, this line takes care of arrays 363 // as well. --- 13 unchanged lines hidden (view full) --- 377 BC_SIG_LOCK; 378 bc_array_expand(v, bc_vm_growSize(idx, 1)); 379 BC_SIG_UNLOCK; 380 } 381 382 n = bc_vec_item(v, idx); 383 } 384 // This is either a number (for a var) or an array (for an array). | 350 351#if BC_ENABLED 352 // If this is true, we have a reference vector, so dereference 353 // it. The reason we don't need to worry about it for returning 354 // a straight array is because we only care about references 355 // when we access elements of an array that is a reference. That 356 // is this code, so in essence, this line takes care of arrays 357 // as well. --- 13 unchanged lines hidden (view full) --- 371 BC_SIG_LOCK; 372 bc_array_expand(v, bc_vm_growSize(idx, 1)); 373 BC_SIG_UNLOCK; 374 } 375 376 n = bc_vec_item(v, idx); 377 } 378 // This is either a number (for a var) or an array (for an array). |
385 // Because bc_vec_top() returns a void*, we don't need to cast. 386 else n = bc_vec_top(v); | 379 // Because bc_vec_top() and bc_vec_item() return a void*, we don't 380 // need to cast. 381 else 382 { 383#if BC_ENABLED 384 if (BC_IS_BC) 385 { 386 n = bc_vec_item(v, r->d.loc.stack_idx); 387 } 388 else 389#endif // BC_ENABLED 390 { 391 n = bc_vec_top(v); 392 } 393 } |
387 388 break; 389 } 390 391 case BC_RESULT_ZERO: 392 { | 394 395 break; 396 } 397 398 case BC_RESULT_ZERO: 399 { |
393 n = &vm.zero; | 400 n = &vm->zero; |
394 break; 395 } 396 397 case BC_RESULT_ONE: 398 { | 401 break; 402 } 403 404 case BC_RESULT_ONE: 405 { |
399 n = &vm.one; | 406 n = &vm->one; |
400 break; 401 } 402 403#if BC_ENABLED 404 // We should never get here; this is taken care of earlier because a 405 // result is expected. 406 case BC_RESULT_VOID: 407#ifndef NDEBUG 408 { 409 abort(); | 407 break; 408 } 409 410#if BC_ENABLED 411 // We should never get here; this is taken care of earlier because a 412 // result is expected. 413 case BC_RESULT_VOID: 414#ifndef NDEBUG 415 { 416 abort(); |
417 // Fallthrough |
|
410 } 411#endif // NDEBUG | 418 } 419#endif // NDEBUG |
412 // Fallthrough | |
413 case BC_RESULT_LAST: 414 { 415 n = &p->last; 416 break; 417 } 418#endif // BC_ENABLED | 420 case BC_RESULT_LAST: 421 { 422 n = &p->last; 423 break; 424 } 425#endif // BC_ENABLED |
426 427#if BC_GCC 428 // This is here in GCC to quiet the "maybe-uninitialized" warning. 429 default: 430 { 431 abort(); 432 } 433#endif // BC_GCC |
|
419 } 420 421 return n; 422} 423 424/** 425 * Prepares an operand for use. 426 * @param p The program. --- 109 unchanged lines hidden (view full) --- 536 * @param rn An out parameter; this is set to the pointer to the number for the 537 * right operand. 538 */ 539static void 540bc_program_assignPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r, 541 BcNum** rn) 542{ 543 BcResultType lt, min; | 434 } 435 436 return n; 437} 438 439/** 440 * Prepares an operand for use. 441 * @param p The program. --- 109 unchanged lines hidden (view full) --- 551 * @param rn An out parameter; this is set to the pointer to the number for the 552 * right operand. 553 */ 554static void 555bc_program_assignPrep(BcProgram* p, BcResult** l, BcNum** ln, BcResult** r, 556 BcNum** rn) 557{ 558 BcResultType lt, min; |
559 bool good; |
|
544 545 // This is the min non-allowable result type. dc allows strings. 546 min = BC_RESULT_TEMP - ((unsigned int) (BC_IS_BC)); 547 548 // Prepare the operands. 549 bc_program_binPrep(p, l, ln, r, rn, 0); 550 551 lt = (*l)->t; 552 553 // Typecheck the left. 554 if (BC_ERR(lt >= min && lt <= BC_RESULT_ONE)) bc_err(BC_ERR_EXEC_TYPE); 555 556 // Strings can be assigned to variables. We are already good if we are 557 // assigning a string. | 560 561 // This is the min non-allowable result type. dc allows strings. 562 min = BC_RESULT_TEMP - ((unsigned int) (BC_IS_BC)); 563 564 // Prepare the operands. 565 bc_program_binPrep(p, l, ln, r, rn, 0); 566 567 lt = (*l)->t; 568 569 // Typecheck the left. 570 if (BC_ERR(lt >= min && lt <= BC_RESULT_ONE)) bc_err(BC_ERR_EXEC_TYPE); 571 572 // Strings can be assigned to variables. We are already good if we are 573 // assigning a string. |
558 bool good = ((*r)->t == BC_RESULT_STR && lt <= BC_RESULT_ARRAY_ELEM); | 574 good = ((*r)->t == BC_RESULT_STR && lt <= BC_RESULT_ARRAY_ELEM); |
559 560 assert(BC_PROG_STR(*rn) || (*r)->t != BC_RESULT_STR); 561 562 // If not, type check for a number. 563 if (!good) bc_program_type_num(*r, *rn); 564} 565 566/** --- 55 unchanged lines hidden (view full) --- 622 * bytecode vector and will be updated to point to after the index. 623 */ 624static void 625bc_program_const(BcProgram* p, const char* code, size_t* bgn) 626{ 627 // I lied. I actually push the result first. I can do this because the 628 // result will be popped on error. I also get the constant itself. 629 BcResult* r = bc_program_prepResult(p); | 575 576 assert(BC_PROG_STR(*rn) || (*r)->t != BC_RESULT_STR); 577 578 // If not, type check for a number. 579 if (!good) bc_program_type_num(*r, *rn); 580} 581 582/** --- 55 unchanged lines hidden (view full) --- 638 * bytecode vector and will be updated to point to after the index. 639 */ 640static void 641bc_program_const(BcProgram* p, const char* code, size_t* bgn) 642{ 643 // I lied. I actually push the result first. I can do this because the 644 // result will be popped on error. I also get the constant itself. 645 BcResult* r = bc_program_prepResult(p); |
630 BcConst* c = bc_vec_item(p->consts, bc_program_index(code, bgn)); | 646 BcConst* c = bc_vec_item(&p->consts, bc_program_index(code, bgn)); |
631 BcBigDig base = BC_PROG_IBASE(p); 632 633 // Only reparse if the base changed. 634 if (c->base != base) 635 { 636 // Allocate if we haven't yet. 637 if (c->num.num == NULL) 638 { | 647 BcBigDig base = BC_PROG_IBASE(p); 648 649 // Only reparse if the base changed. 650 if (c->base != base) 651 { 652 // Allocate if we haven't yet. 653 if (c->num.num == NULL) 654 { |
655 // The plus 1 is in case of overflow with lack of clamping. 656 size_t len = strlen(c->val) + (BC_DIGIT_CLAMP == 0); 657 |
|
639 BC_SIG_LOCK; | 658 BC_SIG_LOCK; |
640 bc_num_init(&c->num, BC_NUM_RDX(strlen(c->val))); | 659 bc_num_init(&c->num, BC_NUM_RDX(len)); |
641 BC_SIG_UNLOCK; 642 } | 660 BC_SIG_UNLOCK; 661 } |
662 // We need to zero an already existing number. 663 else bc_num_zero(&c->num); |
|
643 644 // bc_num_parse() should only do operations that cannot fail. 645 bc_num_parse(&c->num, c->val, base); 646 647 c->base = base; 648 } 649 650 BC_SIG_LOCK; --- 46 unchanged lines hidden (view full) --- 697 */ 698static void 699bc_program_read(BcProgram* p) 700{ 701 BcStatus s; 702 BcInstPtr ip; 703 size_t i; 704 const char* file; | 664 665 // bc_num_parse() should only do operations that cannot fail. 666 bc_num_parse(&c->num, c->val, base); 667 668 c->base = base; 669 } 670 671 BC_SIG_LOCK; --- 46 unchanged lines hidden (view full) --- 718 */ 719static void 720bc_program_read(BcProgram* p) 721{ 722 BcStatus s; 723 BcInstPtr ip; 724 size_t i; 725 const char* file; |
705 bool is_stdin; | 726 BcMode mode; |
706 BcFunc* f = bc_vec_item(&p->fns, BC_PROG_READ); 707 708 // If we are already executing a read, that is an error. So look for a read 709 // and barf. 710 for (i = 0; i < p->stack.len; ++i) 711 { 712 BcInstPtr* ip_ptr = bc_vec_item(&p->stack, i); 713 if (ip_ptr->func == BC_PROG_READ) bc_err(BC_ERR_EXEC_REC_READ); 714 } 715 716 BC_SIG_LOCK; 717 718 // Save the filename because we are going to overwrite it. | 727 BcFunc* f = bc_vec_item(&p->fns, BC_PROG_READ); 728 729 // If we are already executing a read, that is an error. So look for a read 730 // and barf. 731 for (i = 0; i < p->stack.len; ++i) 732 { 733 BcInstPtr* ip_ptr = bc_vec_item(&p->stack, i); 734 if (ip_ptr->func == BC_PROG_READ) bc_err(BC_ERR_EXEC_REC_READ); 735 } 736 737 BC_SIG_LOCK; 738 739 // Save the filename because we are going to overwrite it. |
719 file = vm.file; 720 is_stdin = vm.is_stdin; | 740 file = vm->file; 741 mode = vm->mode; |
721 722 // It is a parse error if there needs to be more than one line, so we unset 723 // this to tell the lexer to not request more. We set it back later. | 742 743 // It is a parse error if there needs to be more than one line, so we unset 744 // this to tell the lexer to not request more. We set it back later. |
724 vm.is_stdin = false; | 745 vm->mode = BC_MODE_FILE; |
725 | 746 |
726 if (!BC_PARSE_IS_INITED(&vm.read_prs, p)) | 747 if (!BC_PARSE_IS_INITED(&vm->read_prs, p)) |
727 { 728 // We need to parse, but we don't want to use the existing parser 729 // because it has state it needs to keep. (It could have a partial parse 730 // state.) So we create a new parser. This parser is in the BcVm struct 731 // so that it is not local, which means that a longjmp() could change 732 // it. | 748 { 749 // We need to parse, but we don't want to use the existing parser 750 // because it has state it needs to keep. (It could have a partial parse 751 // state.) So we create a new parser. This parser is in the BcVm struct 752 // so that it is not local, which means that a longjmp() could change 753 // it. |
733 bc_parse_init(&vm.read_prs, p, BC_PROG_READ); | 754 bc_parse_init(&vm->read_prs, p, BC_PROG_READ); |
734 735 // We need a separate input buffer; that's why it is also in the BcVm 736 // struct. | 755 756 // We need a separate input buffer; that's why it is also in the BcVm 757 // struct. |
737 bc_vec_init(&vm.read_buf, sizeof(char), BC_DTOR_NONE); | 758 bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE); |
738 } 739 // This needs to be updated because the parser could have been used 740 // somewhere else | 759 } 760 // This needs to be updated because the parser could have been used 761 // somewhere else |
741 else bc_parse_updateFunc(&vm.read_prs, BC_PROG_READ); | 762 else bc_parse_updateFunc(&vm->read_prs, BC_PROG_READ); |
742 | 763 |
743 BC_SETJMP_LOCKED(exec_err); | 764 BC_SETJMP_LOCKED(vm, exec_err); |
744 745 BC_SIG_UNLOCK; 746 747 // Set up the lexer and the read function. | 765 766 BC_SIG_UNLOCK; 767 768 // Set up the lexer and the read function. |
748 bc_lex_file(&vm.read_prs.l, bc_program_stdin_name); | 769 bc_lex_file(&vm->read_prs.l, bc_program_stdin_name); |
749 bc_vec_popAll(&f->code); 750 751 // Read a line. | 770 bc_vec_popAll(&f->code); 771 772 // Read a line. |
752 if (!BC_R) s = bc_read_line(&vm.read_buf, ""); 753 else s = bc_read_line(&vm.read_buf, BC_IS_BC ? "read> " : "?> "); | 773 if (!BC_R) s = bc_read_line(&vm->read_buf, ""); 774 else s = bc_read_line(&vm->read_buf, BC_VM_READ_PROMPT); |
754 755 // We should *not* have run into EOF. 756 if (s == BC_STATUS_EOF) bc_err(BC_ERR_EXEC_READ_EXPR); 757 | 775 776 // We should *not* have run into EOF. 777 if (s == BC_STATUS_EOF) bc_err(BC_ERR_EXEC_READ_EXPR); 778 |
758 // Parse *one* expression, so is_stdin should be false. 759 bc_parse_text(&vm.read_prs, vm.read_buf.v, false, false); | 779 // Parse *one* expression, so mode should not be stdin. 780 bc_parse_text(&vm->read_prs, vm->read_buf.v, BC_MODE_FILE); |
760 BC_SIG_LOCK; | 781 BC_SIG_LOCK; |
761 vm.expr(&vm.read_prs, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL); | 782 vm->expr(&vm->read_prs, BC_PARSE_NOREAD | BC_PARSE_NEEDVAL); |
762 BC_SIG_UNLOCK; 763 764 // We *must* have a valid expression. A semicolon cannot end an expression, 765 // although EOF can. | 783 BC_SIG_UNLOCK; 784 785 // We *must* have a valid expression. A semicolon cannot end an expression, 786 // although EOF can. |
766 if (BC_ERR(vm.read_prs.l.t != BC_LEX_NLINE && 767 vm.read_prs.l.t != BC_LEX_EOF)) | 787 if (BC_ERR(vm->read_prs.l.t != BC_LEX_NLINE && 788 vm->read_prs.l.t != BC_LEX_EOF)) |
768 { 769 bc_err(BC_ERR_EXEC_READ_EXPR); 770 } 771 772#if BC_ENABLED 773 // Push on the globals stack if necessary. 774 if (BC_G) bc_program_prepGlobals(p); 775#endif // BC_ENABLED 776 777 // Set up a new BcInstPtr. 778 ip.func = BC_PROG_READ; 779 ip.idx = 0; 780 ip.len = p->results.len; 781 782 // Update this pointer, just in case. 783 f = bc_vec_item(&p->fns, BC_PROG_READ); 784 785 // We want a return instruction to simplify things. | 789 { 790 bc_err(BC_ERR_EXEC_READ_EXPR); 791 } 792 793#if BC_ENABLED 794 // Push on the globals stack if necessary. 795 if (BC_G) bc_program_prepGlobals(p); 796#endif // BC_ENABLED 797 798 // Set up a new BcInstPtr. 799 ip.func = BC_PROG_READ; 800 ip.idx = 0; 801 ip.len = p->results.len; 802 803 // Update this pointer, just in case. 804 f = bc_vec_item(&p->fns, BC_PROG_READ); 805 806 // We want a return instruction to simplify things. |
786 bc_vec_pushByte(&f->code, vm.read_ret); | 807 bc_vec_pushByte(&f->code, vm->read_ret); |
787 788 // This lock is here to make sure dc's tail calls are the same length. 789 BC_SIG_LOCK; 790 bc_vec_push(&p->stack, &ip); 791 792#if DC_ENABLED 793 // We need a new tail call entry for dc. 794 if (BC_IS_DC) 795 { 796 size_t temp = 0; 797 bc_vec_push(&p->tail_calls, &temp); 798 } 799#endif // DC_ENABLED 800 801exec_err: 802 BC_SIG_MAYLOCK; | 808 809 // This lock is here to make sure dc's tail calls are the same length. 810 BC_SIG_LOCK; 811 bc_vec_push(&p->stack, &ip); 812 813#if DC_ENABLED 814 // We need a new tail call entry for dc. 815 if (BC_IS_DC) 816 { 817 size_t temp = 0; 818 bc_vec_push(&p->tail_calls, &temp); 819 } 820#endif // DC_ENABLED 821 822exec_err: 823 BC_SIG_MAYLOCK; |
803 vm.is_stdin = is_stdin; 804 vm.file = file; 805 BC_LONGJMP_CONT; | 824 vm->mode = (uchar) mode; 825 vm->file = file; 826 BC_LONGJMP_CONT(vm); |
806} 807 808#if BC_ENABLE_EXTRA_MATH 809 810/** 811 * Execute a rand(). 812 * @param p The program. 813 */ --- 18 unchanged lines hidden (view full) --- 832/** 833 * Prints a series of characters, without escapes. 834 * @param str The string (series of characters). 835 */ 836static void 837bc_program_printChars(const char* str) 838{ 839 const char* nl; | 827} 828 829#if BC_ENABLE_EXTRA_MATH 830 831/** 832 * Execute a rand(). 833 * @param p The program. 834 */ --- 18 unchanged lines hidden (view full) --- 853/** 854 * Prints a series of characters, without escapes. 855 * @param str The string (series of characters). 856 */ 857static void 858bc_program_printChars(const char* str) 859{ 860 const char* nl; |
840 size_t len = vm.nchars + strlen(str); | 861 size_t len = vm->nchars + strlen(str); |
841 sig_atomic_t lock; 842 843 BC_SIG_TRYLOCK(lock); 844 | 862 sig_atomic_t lock; 863 864 BC_SIG_TRYLOCK(lock); 865 |
845 bc_file_puts(&vm.fout, bc_flush_save, str); | 866 bc_file_puts(&vm->fout, bc_flush_save, str); |
846 847 // We need to update the number of characters, so we find the last newline 848 // and set the characters accordingly. 849 nl = strrchr(str, '\n'); 850 851 if (nl != NULL) len = strlen(nl + 1); 852 | 867 868 // We need to update the number of characters, so we find the last newline 869 // and set the characters accordingly. 870 nl = strrchr(str, '\n'); 871 872 if (nl != NULL) len = strlen(nl + 1); 873 |
853 vm.nchars = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len; | 874 vm->nchars = len > UINT16_MAX ? UINT16_MAX : (uint16_t) len; |
854 855 BC_SIG_TRYUNLOCK(lock); 856} 857 858/** 859 * Prints a string with escapes. 860 * @param str The string. 861 */ --- 27 unchanged lines hidden (view full) --- 889 890 // If we have a companion character... 891 if (ptr != NULL) 892 { 893 // We need to specially handle a newline. 894 if (c == 'n') 895 { 896 BC_SIG_LOCK; | 875 876 BC_SIG_TRYUNLOCK(lock); 877} 878 879/** 880 * Prints a string with escapes. 881 * @param str The string. 882 */ --- 27 unchanged lines hidden (view full) --- 910 911 // If we have a companion character... 912 if (ptr != NULL) 913 { 914 // We need to specially handle a newline. 915 if (c == 'n') 916 { 917 BC_SIG_LOCK; |
897 vm.nchars = UINT16_MAX; | 918 vm->nchars = UINT16_MAX; |
898 BC_SIG_UNLOCK; 899 } 900 901 // Grab the actual character. 902 c = bc_program_esc_seqs[(size_t) (ptr - bc_program_esc_chars)]; 903 } 904 else 905 { --- 66 unchanged lines hidden (view full) --- 972#if BC_ENABLED 973 // Need to store the number in last. 974 if (BC_IS_BC) bc_num_copy(&p->last, n); 975#endif // BC_ENABLED 976 } 977 else 978 { 979 // We want to flush any stuff in the stdout buffer first. | 919 BC_SIG_UNLOCK; 920 } 921 922 // Grab the actual character. 923 c = bc_program_esc_seqs[(size_t) (ptr - bc_program_esc_chars)]; 924 } 925 else 926 { --- 66 unchanged lines hidden (view full) --- 993#if BC_ENABLED 994 // Need to store the number in last. 995 if (BC_IS_BC) bc_num_copy(&p->last, n); 996#endif // BC_ENABLED 997 } 998 else 999 { 1000 // We want to flush any stuff in the stdout buffer first. |
980 bc_file_flush(&vm.fout, bc_flush_save); | 1001 bc_file_flush(&vm->fout, bc_flush_save); |
981 str = bc_program_string(p, n); 982 983#if BC_ENABLED 984 if (inst == BC_INST_PRINT_STR) bc_program_printChars(str); 985 else 986#endif // BC_ENABLED 987 { 988 bc_program_printString(str); 989 990 // Need to print a newline only in this case. 991 if (inst == BC_INST_PRINT) bc_vm_putchar('\n', bc_flush_err); 992 } 993 } 994 | 1002 str = bc_program_string(p, n); 1003 1004#if BC_ENABLED 1005 if (inst == BC_INST_PRINT_STR) bc_program_printChars(str); 1006 else 1007#endif // BC_ENABLED 1008 { 1009 bc_program_printString(str); 1010 1011 // Need to print a newline only in this case. 1012 if (inst == BC_INST_PRINT) bc_vm_putchar('\n', bc_flush_err); 1013 } 1014 } 1015 |
995 // bc always pops. 996 if (BC_IS_BC || pop) bc_vec_pop(&p->results); | 1016 // bc always pops. This macro makes sure that happens. 1017 if (BC_PROGRAM_POP(pop)) bc_vec_pop(&p->results); |
997} 998 999void 1000bc_program_negate(BcResult* r, BcNum* n) 1001{ 1002 bc_num_copy(&r->d.n, n); 1003 if (BC_NUM_NONZERO(&r->d.n)) BC_NUM_NEG_TGL_NP(r->d.n); 1004} --- 163 unchanged lines hidden (view full) --- 1168 // We can just copy because the num should not have allocated anything. 1169 // NOLINTNEXTLINE 1170 memcpy(n, num, sizeof(BcNum)); 1171} 1172 1173/** 1174 * Copies a value to a variable. This is used for storing in dc as well as to 1175 * set function parameters to arguments in bc. | 1018} 1019 1020void 1021bc_program_negate(BcResult* r, BcNum* n) 1022{ 1023 bc_num_copy(&r->d.n, n); 1024 if (BC_NUM_NONZERO(&r->d.n)) BC_NUM_NEG_TGL_NP(r->d.n); 1025} --- 163 unchanged lines hidden (view full) --- 1189 // We can just copy because the num should not have allocated anything. 1190 // NOLINTNEXTLINE 1191 memcpy(n, num, sizeof(BcNum)); 1192} 1193 1194/** 1195 * Copies a value to a variable. This is used for storing in dc as well as to 1196 * set function parameters to arguments in bc. |
1176 * @param p The program. 1177 * @param idx The index of the variable or array to copy to. 1178 * @param t The type to copy to. This could be a variable or an array. 1179 * @param last Whether to grab the last item on the variable stack or not (for 1180 * bc function parameters). This is important because if a new 1181 * value has been pushed to the variable already, we need to grab 1182 * the value pushed before. This happens when you have a parameter 1183 * named something like "x", and a variable "x" is passed to 1184 * another parameter. | 1197 * @param p The program. 1198 * @param idx The index of the variable or array to copy to. 1199 * @param t The type to copy to. This could be a variable or an array. |
1185 */ 1186static void | 1200 */ 1201static void |
1187bc_program_copyToVar(BcProgram* p, size_t idx, BcType t, bool last) | 1202bc_program_copyToVar(BcProgram* p, size_t idx, BcType t) |
1188{ 1189 BcResult *ptr = NULL, r; 1190 BcVec* vec; 1191 BcNum* n = NULL; 1192 bool var = (t == BC_TYPE_VAR); 1193 1194#if DC_ENABLED 1195 // Check the stack for dc. --- 8 unchanged lines hidden (view full) --- 1204 bc_program_operand(p, &ptr, &n, 0); 1205 1206#if BC_ENABLED 1207 // Get the variable for a bc function call. 1208 if (BC_IS_BC) 1209 { 1210 // Type match the result. 1211 bc_program_type_match(ptr, t); | 1203{ 1204 BcResult *ptr = NULL, r; 1205 BcVec* vec; 1206 BcNum* n = NULL; 1207 bool var = (t == BC_TYPE_VAR); 1208 1209#if DC_ENABLED 1210 // Check the stack for dc. --- 8 unchanged lines hidden (view full) --- 1219 bc_program_operand(p, &ptr, &n, 0); 1220 1221#if BC_ENABLED 1222 // Get the variable for a bc function call. 1223 if (BC_IS_BC) 1224 { 1225 // Type match the result. 1226 bc_program_type_match(ptr, t); |
1212 1213 // Get the variable or array, taking care to get the real item. We take 1214 // care of last with arrays later. 1215 if (!last && var) 1216 { 1217 n = bc_vec_item_rev(bc_program_vec(p, ptr->d.loc.loc, t), 1); 1218 } | |
1219 } 1220#endif // BC_ENABLED 1221 1222 vec = bc_program_vec(p, idx, t); 1223 1224 // We can shortcut in dc if it's assigning a string by using 1225 // bc_program_assignStr(). 1226 if (ptr->t == BC_RESULT_STR) --- 25 unchanged lines hidden (view full) --- 1252 // to cast the number from bc_program_num() to a vector. 1253 BcVec* v = (BcVec*) n; 1254 BcVec* rv = &r.d.v; 1255 1256#if BC_ENABLED 1257 1258 if (BC_IS_BC) 1259 { | 1227 } 1228#endif // BC_ENABLED 1229 1230 vec = bc_program_vec(p, idx, t); 1231 1232 // We can shortcut in dc if it's assigning a string by using 1233 // bc_program_assignStr(). 1234 if (ptr->t == BC_RESULT_STR) --- 25 unchanged lines hidden (view full) --- 1260 // to cast the number from bc_program_num() to a vector. 1261 BcVec* v = (BcVec*) n; 1262 BcVec* rv = &r.d.v; 1263 1264#if BC_ENABLED 1265 1266 if (BC_IS_BC) 1267 { |
1260 BcVec* parent; | |
1261 bool ref, ref_size; 1262 | 1268 bool ref, ref_size; 1269 |
1263 // We need to figure out if the parameter is a reference or not and 1264 // construct the reference vector, if necessary. So this gets the 1265 // parent stack for the array. 1266 parent = bc_program_vec(p, ptr->d.loc.loc, t); 1267 assert(parent != NULL); 1268 1269 // This takes care of last for arrays. Mostly. 1270 if (!last) v = bc_vec_item_rev(parent, !last); 1271 assert(v != NULL); 1272 | |
1273 // True if we are using a reference. 1274 ref = (v->size == sizeof(BcNum) && t == BC_TYPE_REF); 1275 1276 // True if we already have a reference vector. This is slightly 1277 // (okay, a lot; it just doesn't look that way) different from 1278 // above. The above means that we need to construct a reference 1279 // vector, whereas this means that we have one and we might have to 1280 // *dereference* it. 1281 ref_size = (v->size == sizeof(uchar)); 1282 1283 // If we *should* have a reference. 1284 if (ref || (ref_size && t == BC_TYPE_REF)) 1285 { 1286 // Create a new reference vector. 1287 bc_vec_init(rv, sizeof(uchar), BC_DTOR_NONE); 1288 1289 // If this is true, then we need to construct a reference. 1290 if (ref) 1291 { | 1270 // True if we are using a reference. 1271 ref = (v->size == sizeof(BcNum) && t == BC_TYPE_REF); 1272 1273 // True if we already have a reference vector. This is slightly 1274 // (okay, a lot; it just doesn't look that way) different from 1275 // above. The above means that we need to construct a reference 1276 // vector, whereas this means that we have one and we might have to 1277 // *dereference* it. 1278 ref_size = (v->size == sizeof(uchar)); 1279 1280 // If we *should* have a reference. 1281 if (ref || (ref_size && t == BC_TYPE_REF)) 1282 { 1283 // Create a new reference vector. 1284 bc_vec_init(rv, sizeof(uchar), BC_DTOR_NONE); 1285 1286 // If this is true, then we need to construct a reference. 1287 if (ref) 1288 { |
1292 assert(parent->len >= (size_t) (!last + 1)); 1293 | |
1294 // Make sure the pointer was not invalidated. 1295 vec = bc_program_vec(p, idx, t); 1296 1297 // Push the indices onto the reference vector. This takes 1298 // care of last; it ensures the reference goes to the right 1299 // place. 1300 bc_vec_pushIndex(rv, ptr->d.loc.loc); | 1289 // Make sure the pointer was not invalidated. 1290 vec = bc_program_vec(p, idx, t); 1291 1292 // Push the indices onto the reference vector. This takes 1293 // care of last; it ensures the reference goes to the right 1294 // place. 1295 bc_vec_pushIndex(rv, ptr->d.loc.loc); |
1301 bc_vec_pushIndex(rv, parent->len - !last - 1); | 1296 bc_vec_pushIndex(rv, ptr->d.loc.stack_idx); |
1302 } 1303 // If we get here, we are copying a ref to a ref. Just push a 1304 // copy of all of the bytes. 1305 else bc_vec_npush(rv, v->len * sizeof(uchar), v->v); 1306 1307 // Push the reference vector onto the array stack and pop the 1308 // source. 1309 bc_vec_push(vec, &r.d); --- 24 unchanged lines hidden (view full) --- 1334 bc_vec_pop(&p->results); 1335 1336 BC_SIG_UNLOCK; 1337} 1338 1339void 1340bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val) 1341{ | 1297 } 1298 // If we get here, we are copying a ref to a ref. Just push a 1299 // copy of all of the bytes. 1300 else bc_vec_npush(rv, v->len * sizeof(uchar), v->v); 1301 1302 // Push the reference vector onto the array stack and pop the 1303 // source. 1304 bc_vec_push(vec, &r.d); --- 24 unchanged lines hidden (view full) --- 1329 bc_vec_pop(&p->results); 1330 1331 BC_SIG_UNLOCK; 1332} 1333 1334void 1335bc_program_assignBuiltin(BcProgram* p, bool scale, bool obase, BcBigDig val) 1336{ |
1342 BcVec* v; 1343 BcBigDig* ptr; | |
1344 BcBigDig* ptr_t; 1345 BcBigDig max, min; | 1337 BcBigDig* ptr_t; 1338 BcBigDig max, min; |
1339#if BC_ENABLED 1340 BcVec* v; 1341 BcBigDig* ptr; 1342#endif // BC_ENABLED |
|
1346 1347 assert(!scale || !obase); 1348 1349 // Scale needs handling separate from ibase and obase. 1350 if (scale) 1351 { 1352 // Set the min and max. 1353 min = 0; | 1343 1344 assert(!scale || !obase); 1345 1346 // Scale needs handling separate from ibase and obase. 1347 if (scale) 1348 { 1349 // Set the min and max. 1350 min = 0; |
1354 max = vm.maxes[BC_PROG_GLOBALS_SCALE]; | 1351 max = vm->maxes[BC_PROG_GLOBALS_SCALE]; |
1355 | 1352 |
1356 // Get a pointer to the stack and to the current value. | 1353#if BC_ENABLED 1354 // Get a pointer to the stack. |
1357 v = p->globals_v + BC_PROG_GLOBALS_SCALE; | 1355 v = p->globals_v + BC_PROG_GLOBALS_SCALE; |
1356#endif // BC_ENABLED 1357 1358 // Get a pointer to the current value. |
|
1358 ptr_t = p->globals + BC_PROG_GLOBALS_SCALE; 1359 } 1360 else 1361 { 1362 // Set the min and max. 1363 min = BC_NUM_MIN_BASE; 1364 if (BC_ENABLE_EXTRA_MATH && obase && (BC_IS_DC || !BC_IS_POSIX)) 1365 { 1366 min = 0; 1367 } | 1359 ptr_t = p->globals + BC_PROG_GLOBALS_SCALE; 1360 } 1361 else 1362 { 1363 // Set the min and max. 1364 min = BC_NUM_MIN_BASE; 1365 if (BC_ENABLE_EXTRA_MATH && obase && (BC_IS_DC || !BC_IS_POSIX)) 1366 { 1367 min = 0; 1368 } |
1368 max = vm.maxes[obase + BC_PROG_GLOBALS_IBASE]; | 1369 max = vm->maxes[obase + BC_PROG_GLOBALS_IBASE]; |
1369 | 1370 |
1370 // Get a pointer to the stack and to the current value. | 1371#if BC_ENABLED 1372 // Get a pointer to the stack. |
1371 v = p->globals_v + BC_PROG_GLOBALS_IBASE + obase; | 1373 v = p->globals_v + BC_PROG_GLOBALS_IBASE + obase; |
1374#endif // BC_ENABLED 1375 1376 // Get a pointer to the current value. |
|
1372 ptr_t = p->globals + BC_PROG_GLOBALS_IBASE + obase; 1373 } 1374 1375 // Check for error. 1376 if (BC_ERR(val > max || val < min)) 1377 { 1378 BcErr e; 1379 1380 // This grabs the right error. 1381 if (scale) e = BC_ERR_EXEC_SCALE; 1382 else if (obase) e = BC_ERR_EXEC_OBASE; 1383 else e = BC_ERR_EXEC_IBASE; 1384 1385 bc_verr(e, min, max); 1386 } 1387 | 1377 ptr_t = p->globals + BC_PROG_GLOBALS_IBASE + obase; 1378 } 1379 1380 // Check for error. 1381 if (BC_ERR(val > max || val < min)) 1382 { 1383 BcErr e; 1384 1385 // This grabs the right error. 1386 if (scale) e = BC_ERR_EXEC_SCALE; 1387 else if (obase) e = BC_ERR_EXEC_OBASE; 1388 else e = BC_ERR_EXEC_IBASE; 1389 1390 bc_verr(e, min, max); 1391 } 1392 |
1388 // Set the top of the stack and the actual global value. | 1393#if BC_ENABLED 1394 // Set the top of the stack. |
1389 ptr = bc_vec_top(v); 1390 *ptr = val; | 1395 ptr = bc_vec_top(v); 1396 *ptr = val; |
1397#endif // BC_ENABLED 1398 1399 // Set the actual global variable. |
|
1391 *ptr_t = val; 1392} 1393 1394#if BC_ENABLE_EXTRA_MATH 1395void 1396bc_program_assignSeed(BcProgram* p, BcNum* val) 1397{ 1398 bc_num_rng(val, &p->rng); --- 174 unchanged lines hidden (view full) --- 1573 * stack. This is only used in dc. 1574 */ 1575static void 1576bc_program_pushVar(BcProgram* p, const char* restrict code, 1577 size_t* restrict bgn, bool pop, bool copy) 1578{ 1579 BcResult r; 1580 size_t idx = bc_program_index(code, bgn); | 1400 *ptr_t = val; 1401} 1402 1403#if BC_ENABLE_EXTRA_MATH 1404void 1405bc_program_assignSeed(BcProgram* p, BcNum* val) 1406{ 1407 bc_num_rng(val, &p->rng); --- 174 unchanged lines hidden (view full) --- 1582 * stack. This is only used in dc. 1583 */ 1584static void 1585bc_program_pushVar(BcProgram* p, const char* restrict code, 1586 size_t* restrict bgn, bool pop, bool copy) 1587{ 1588 BcResult r; 1589 size_t idx = bc_program_index(code, bgn); |
1590 BcVec* v; |
|
1581 1582 // Set the result appropriately. 1583 r.t = BC_RESULT_VAR; 1584 r.d.loc.loc = idx; 1585 | 1591 1592 // Set the result appropriately. 1593 r.t = BC_RESULT_VAR; 1594 r.d.loc.loc = idx; 1595 |
1596 // Get the stack for the variable. This is used in both bc and dc. 1597 v = bc_program_vec(p, idx, BC_TYPE_VAR); 1598 r.d.loc.stack_idx = v->len - 1; 1599 |
|
1586#if DC_ENABLED 1587 // If this condition is true, then we have the hard case, where we have to 1588 // adjust dc registers. 1589 if (BC_IS_DC && (pop || copy)) 1590 { | 1600#if DC_ENABLED 1601 // If this condition is true, then we have the hard case, where we have to 1602 // adjust dc registers. 1603 if (BC_IS_DC && (pop || copy)) 1604 { |
1591 // Get the stack for the variable and the number at the top. 1592 BcVec* v = bc_program_vec(p, idx, BC_TYPE_VAR); | 1605 // Get the number at the top at the top of the stack. |
1593 BcNum* num = bc_vec_top(v); 1594 1595 // Ensure there are enough elements on the stack. 1596 if (BC_ERR(!BC_PROG_STACK(v, 2 - copy))) 1597 { 1598 const char* name = bc_map_name(&p->var_map, idx); 1599 bc_verr(BC_ERR_EXEC_STACK_REGISTER, name); 1600 } --- 46 unchanged lines hidden (view full) --- 1647static void 1648bc_program_pushArray(BcProgram* p, const char* restrict code, 1649 size_t* restrict bgn, uchar inst) 1650{ 1651 BcResult r; 1652 BcResult* operand; 1653 BcNum* num; 1654 BcBigDig temp; | 1606 BcNum* num = bc_vec_top(v); 1607 1608 // Ensure there are enough elements on the stack. 1609 if (BC_ERR(!BC_PROG_STACK(v, 2 - copy))) 1610 { 1611 const char* name = bc_map_name(&p->var_map, idx); 1612 bc_verr(BC_ERR_EXEC_STACK_REGISTER, name); 1613 } --- 46 unchanged lines hidden (view full) --- 1660static void 1661bc_program_pushArray(BcProgram* p, const char* restrict code, 1662 size_t* restrict bgn, uchar inst) 1663{ 1664 BcResult r; 1665 BcResult* operand; 1666 BcNum* num; 1667 BcBigDig temp; |
1668 BcVec* v; |
|
1655 1656 // Get the index of the array. 1657 r.d.loc.loc = bc_program_index(code, bgn); 1658 | 1669 1670 // Get the index of the array. 1671 r.d.loc.loc = bc_program_index(code, bgn); 1672 |
1673 // We need the array to get its length. 1674 v = bc_program_vec(p, r.d.loc.loc, BC_TYPE_ARRAY); 1675 assert(v != NULL); 1676 1677 r.d.loc.stack_idx = v->len - 1; 1678 |
|
1659 // Doing an array is easy; just set the result type and finish. 1660 if (inst == BC_INST_ARRAY) 1661 { 1662 r.t = BC_RESULT_ARRAY; 1663 bc_vec_push(&p->results, &r); 1664 return; 1665 } 1666 --- 33 unchanged lines hidden (view full) --- 1700 bc_program_prep(p, &ptr, &num, 0); 1701 1702 BC_SIG_LOCK; 1703 1704 // We need a copy from *before* the operation. 1705 copy.t = BC_RESULT_TEMP; 1706 bc_num_createCopy(©.d.n, num); 1707 | 1679 // Doing an array is easy; just set the result type and finish. 1680 if (inst == BC_INST_ARRAY) 1681 { 1682 r.t = BC_RESULT_ARRAY; 1683 bc_vec_push(&p->results, &r); 1684 return; 1685 } 1686 --- 33 unchanged lines hidden (view full) --- 1720 bc_program_prep(p, &ptr, &num, 0); 1721 1722 BC_SIG_LOCK; 1723 1724 // We need a copy from *before* the operation. 1725 copy.t = BC_RESULT_TEMP; 1726 bc_num_createCopy(©.d.n, num); 1727 |
1708 BC_SETJMP_LOCKED(exit); | 1728 BC_SETJMP_LOCKED(vm, exit); |
1709 1710 BC_SIG_UNLOCK; 1711 1712 // Create the proper assignment. 1713 res.t = BC_RESULT_ONE; 1714 inst2 = BC_INST_ASSIGN_PLUS_NO_VAL + (inst & 0x01); 1715 1716 bc_vec_push(&p->results, &res); 1717 bc_program_assign(p, inst2); 1718 1719 BC_SIG_LOCK; 1720 1721 bc_vec_push(&p->results, ©); 1722 | 1729 1730 BC_SIG_UNLOCK; 1731 1732 // Create the proper assignment. 1733 res.t = BC_RESULT_ONE; 1734 inst2 = BC_INST_ASSIGN_PLUS_NO_VAL + (inst & 0x01); 1735 1736 bc_vec_push(&p->results, &res); 1737 bc_program_assign(p, inst2); 1738 1739 BC_SIG_LOCK; 1740 1741 bc_vec_push(&p->results, ©); 1742 |
1723 BC_UNSETJMP; | 1743 BC_UNSETJMP(vm); |
1724 1725 BC_SIG_UNLOCK; 1726 1727 // No need to free the copy here because we pushed it onto the stack. 1728 return; 1729 1730exit: 1731 BC_SIG_MAYLOCK; 1732 bc_num_free(©.d.n); | 1744 1745 BC_SIG_UNLOCK; 1746 1747 // No need to free the copy here because we pushed it onto the stack. 1748 return; 1749 1750exit: 1751 BC_SIG_MAYLOCK; 1752 bc_num_free(©.d.n); |
1733 BC_LONGJMP_CONT; | 1753 BC_LONGJMP_CONT(vm); |
1734} 1735 1736/** 1737 * Executes a function call for bc. 1738 * @param p The program. 1739 * @param code The bytecode vector to pull the number of arguments and the 1740 * function index out of. 1741 * @param bgn An in/out parameter; the start of the indices in the bytecode --- 31 unchanged lines hidden (view full) --- 1773 assert(BC_PROG_STACK(&p->results, nargs)); 1774 1775 // Prepare the globals' stacks. 1776 if (BC_G) bc_program_prepGlobals(p); 1777 1778 // Push the arguments onto the stacks of their respective parameters. 1779 for (i = 0; i < nargs; ++i) 1780 { | 1754} 1755 1756/** 1757 * Executes a function call for bc. 1758 * @param p The program. 1759 * @param code The bytecode vector to pull the number of arguments and the 1760 * function index out of. 1761 * @param bgn An in/out parameter; the start of the indices in the bytecode --- 31 unchanged lines hidden (view full) --- 1793 assert(BC_PROG_STACK(&p->results, nargs)); 1794 1795 // Prepare the globals' stacks. 1796 if (BC_G) bc_program_prepGlobals(p); 1797 1798 // Push the arguments onto the stacks of their respective parameters. 1799 for (i = 0; i < nargs; ++i) 1800 { |
1781 size_t j; 1782 bool last = true; 1783 | |
1784 arg = bc_vec_top(&p->results); 1785 if (BC_ERR(arg->t == BC_RESULT_VOID)) bc_err(BC_ERR_EXEC_VOID_VAL); 1786 1787 // Get the corresponding parameter. 1788 a = bc_vec_item(&f->autos, nargs - 1 - i); 1789 | 1801 arg = bc_vec_top(&p->results); 1802 if (BC_ERR(arg->t == BC_RESULT_VOID)) bc_err(BC_ERR_EXEC_VOID_VAL); 1803 1804 // Get the corresponding parameter. 1805 a = bc_vec_item(&f->autos, nargs - 1 - i); 1806 |
1790 // If I have already pushed to a var, I need to make sure I 1791 // get the previous version, not the already pushed one. This condition 1792 // must be true for that to even be possible. 1793 if (arg->t == BC_RESULT_VAR || arg->t == BC_RESULT_ARRAY) 1794 { 1795 // Loop through all of the previous parameters. 1796 for (j = 0; j < i && last; ++j) 1797 { 1798 BcAuto* aptr = bc_vec_item(&f->autos, nargs - 1 - j); 1799 1800 // This condition is true if there is a previous parameter with 1801 // the same name *and* type because variables and arrays do not 1802 // interfere with each other. 1803 last = (arg->d.loc.loc != aptr->idx || 1804 (!aptr->type) != (arg->t == BC_RESULT_VAR)); 1805 } 1806 } 1807 | |
1808 // Actually push the value onto the parameter's stack. | 1807 // Actually push the value onto the parameter's stack. |
1809 bc_program_copyToVar(p, a->idx, a->type, last); | 1808 bc_program_copyToVar(p, a->idx, a->type); |
1810 } 1811 1812 BC_SIG_LOCK; 1813 1814 // Push zeroes onto the stacks of the auto variables. 1815 for (; i < f->autos.len; ++i) 1816 { 1817 // Get the auto and its stack. --- 130 unchanged lines hidden (view full) --- 1948 BcResult* res; 1949 BcNum* num; 1950 bool len = (inst == BC_INST_LENGTH); 1951 1952 // Ensure we have a valid builtin. 1953#if BC_ENABLE_EXTRA_MATH 1954 assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IRAND); 1955#else // BC_ENABLE_EXTRA_MATH | 1809 } 1810 1811 BC_SIG_LOCK; 1812 1813 // Push zeroes onto the stacks of the auto variables. 1814 for (; i < f->autos.len; ++i) 1815 { 1816 // Get the auto and its stack. --- 130 unchanged lines hidden (view full) --- 1947 BcResult* res; 1948 BcNum* num; 1949 bool len = (inst == BC_INST_LENGTH); 1950 1951 // Ensure we have a valid builtin. 1952#if BC_ENABLE_EXTRA_MATH 1953 assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IRAND); 1954#else // BC_ENABLE_EXTRA_MATH |
1956 assert(inst >= BC_INST_LENGTH && inst <= BC_INST_ABS); | 1955 assert(inst >= BC_INST_LENGTH && inst <= BC_INST_IS_STRING); |
1957#endif // BC_ENABLE_EXTRA_MATH 1958 1959#ifndef BC_PROG_NO_STACK_CHECK 1960 // Check stack for dc. 1961 if (BC_IS_DC && BC_ERR(!BC_PROG_STACK(&p->results, 1))) 1962 { 1963 bc_err(BC_ERR_EXEC_STACK); 1964 } --- 4 unchanged lines hidden (view full) --- 1969 res = bc_program_prepResult(p); 1970 1971 bc_program_operand(p, &opd, &num, 1); 1972 1973 assert(num != NULL); 1974 1975 // We need to ensure that strings and arrays aren't passed to most builtins. 1976 // The scale function can take strings in dc. | 1956#endif // BC_ENABLE_EXTRA_MATH 1957 1958#ifndef BC_PROG_NO_STACK_CHECK 1959 // Check stack for dc. 1960 if (BC_IS_DC && BC_ERR(!BC_PROG_STACK(&p->results, 1))) 1961 { 1962 bc_err(BC_ERR_EXEC_STACK); 1963 } --- 4 unchanged lines hidden (view full) --- 1968 res = bc_program_prepResult(p); 1969 1970 bc_program_operand(p, &opd, &num, 1); 1971 1972 assert(num != NULL); 1973 1974 // We need to ensure that strings and arrays aren't passed to most builtins. 1975 // The scale function can take strings in dc. |
1977 if (!len && (inst != BC_INST_SCALE_FUNC || BC_IS_BC)) | 1976 if (!len && (inst != BC_INST_SCALE_FUNC || BC_IS_BC) && 1977 inst != BC_INST_IS_NUMBER && inst != BC_INST_IS_STRING) |
1978 { 1979 bc_program_type_num(opd, num); 1980 } 1981 1982 // Square root is easy. 1983 if (inst == BC_INST_SQRT) bc_num_sqrt(num, &res->d.n, BC_PROG_SCALE(p)); 1984 1985 // Absolute value is easy. 1986 else if (inst == BC_INST_ABS) 1987 { 1988 BC_SIG_LOCK; 1989 1990 bc_num_createCopy(&res->d.n, num); 1991 1992 BC_SIG_UNLOCK; 1993 1994 BC_NUM_NEG_CLR_NP(res->d.n); 1995 } | 1978 { 1979 bc_program_type_num(opd, num); 1980 } 1981 1982 // Square root is easy. 1983 if (inst == BC_INST_SQRT) bc_num_sqrt(num, &res->d.n, BC_PROG_SCALE(p)); 1984 1985 // Absolute value is easy. 1986 else if (inst == BC_INST_ABS) 1987 { 1988 BC_SIG_LOCK; 1989 1990 bc_num_createCopy(&res->d.n, num); 1991 1992 BC_SIG_UNLOCK; 1993 1994 BC_NUM_NEG_CLR_NP(res->d.n); 1995 } |
1996 1997 // Testing for number or string is easy. 1998 else if (inst == BC_INST_IS_NUMBER || inst == BC_INST_IS_STRING) 1999 { 2000 bool cond; 2001 bool is_str; 2002 2003 BC_SIG_LOCK; 2004 2005 bc_num_init(&res->d.n, BC_NUM_DEF_SIZE); 2006 2007 BC_SIG_UNLOCK; 2008 2009 // Test if the number is a string. 2010 is_str = BC_PROG_STR(num); 2011 2012 // This confusing condition simply means that the instruction must be 2013 // true if is_str is, or it must be false if is_str is. Otherwise, the 2014 // returned value is false (0). 2015 cond = ((inst == BC_INST_IS_STRING) == is_str); 2016 if (cond) bc_num_one(&res->d.n); 2017 } 2018 |
|
1996#if BC_ENABLE_EXTRA_MATH | 2019#if BC_ENABLE_EXTRA_MATH |
2020 |
|
1997 // irand() is easy. 1998 else if (inst == BC_INST_IRAND) 1999 { 2000 BC_SIG_LOCK; 2001 2002 bc_num_init(&res->d.n, num->len - BC_NUM_RDX_VAL(num)); 2003 2004 BC_SIG_UNLOCK; 2005 2006 bc_num_irand(num, &res->d.n, &p->rng); 2007 } | 2021 // irand() is easy. 2022 else if (inst == BC_INST_IRAND) 2023 { 2024 BC_SIG_LOCK; 2025 2026 bc_num_init(&res->d.n, num->len - BC_NUM_RDX_VAL(num)); 2027 2028 BC_SIG_UNLOCK; 2029 2030 bc_num_irand(num, &res->d.n, &p->rng); 2031 } |
2032 |
|
2008#endif // BC_ENABLE_EXTRA_MATH 2009 2010 // Everything else is...not easy. 2011 else 2012 { 2013 BcBigDig val = 0; 2014 2015 // Well, scale() is easy, but length() is not. 2016 if (len) 2017 { 2018 // If we are bc and we have an array... 2019 if (opd->t == BC_RESULT_ARRAY) 2020 { 2021 // Yes, this is one place where we need to cast the number from 2022 // bc_program_num() to a vector. 2023 BcVec* v = (BcVec*) num; 2024 | 2033#endif // BC_ENABLE_EXTRA_MATH 2034 2035 // Everything else is...not easy. 2036 else 2037 { 2038 BcBigDig val = 0; 2039 2040 // Well, scale() is easy, but length() is not. 2041 if (len) 2042 { 2043 // If we are bc and we have an array... 2044 if (opd->t == BC_RESULT_ARRAY) 2045 { 2046 // Yes, this is one place where we need to cast the number from 2047 // bc_program_num() to a vector. 2048 BcVec* v = (BcVec*) num; 2049 |
2050 // XXX: If this is changed, you should also change the similar 2051 // code in bc_program_asciify(). 2052 |
|
2025#if BC_ENABLED 2026 // Dereference the array, if necessary. 2027 if (BC_IS_BC && v->size == sizeof(uchar)) 2028 { 2029 v = bc_program_dereference(p, v); 2030 } 2031#endif // BC_ENABLED 2032 --- 136 unchanged lines hidden (view full) --- 2169/** 2170 * Asciifies a number for dc. This is a helper for bc_program_asciify(). 2171 * @param p The program. 2172 * @param n The number to asciify. 2173 */ 2174static uchar 2175bc_program_asciifyNum(BcProgram* p, BcNum* n) 2176{ | 2053#if BC_ENABLED 2054 // Dereference the array, if necessary. 2055 if (BC_IS_BC && v->size == sizeof(uchar)) 2056 { 2057 v = bc_program_dereference(p, v); 2058 } 2059#endif // BC_ENABLED 2060 --- 136 unchanged lines hidden (view full) --- 2197/** 2198 * Asciifies a number for dc. This is a helper for bc_program_asciify(). 2199 * @param p The program. 2200 * @param n The number to asciify. 2201 */ 2202static uchar 2203bc_program_asciifyNum(BcProgram* p, BcNum* n) 2204{ |
2177 BcNum num; 2178 BcBigDig val; | 2205 bc_num_copy(&p->asciify, n); |
2179 | 2206 |
2180#ifndef NDEBUG 2181 // This is entirely to satisfy a useless scan-build error. 2182 val = 0; 2183#endif // NDEBUG 2184 2185 bc_num_clear(&num); 2186 2187 BC_SETJMP(num_err); 2188 2189 BC_SIG_LOCK; 2190 2191 bc_num_createCopy(&num, n); 2192 2193 BC_SIG_UNLOCK; 2194 | |
2195 // We want to clear the scale and sign for easy mod later. | 2207 // We want to clear the scale and sign for easy mod later. |
2196 bc_num_truncate(&num, num.scale); 2197 BC_NUM_NEG_CLR_NP(num); | 2208 bc_num_truncate(&p->asciify, p->asciify.scale); 2209 BC_NUM_NEG_CLR(&p->asciify); |
2198 2199 // This is guaranteed to not have a divide by 0 2200 // because strmb is equal to 256. | 2210 2211 // This is guaranteed to not have a divide by 0 2212 // because strmb is equal to 256. |
2201 bc_num_mod(&num, &p->strmb, &num, 0); | 2213 bc_num_mod(&p->asciify, &p->strmb, &p->asciify, 0); |
2202 2203 // This is also guaranteed to not error because num is in the range 2204 // [0, UCHAR_MAX], which is definitely in range for a BcBigDig. And 2205 // it is not negative. | 2214 2215 // This is also guaranteed to not error because num is in the range 2216 // [0, UCHAR_MAX], which is definitely in range for a BcBigDig. And 2217 // it is not negative. |
2206 val = bc_num_bigdig2(&num); 2207 2208num_err: 2209 BC_SIG_MAYLOCK; 2210 bc_num_free(&num); 2211 BC_LONGJMP_CONT; 2212 return (uchar) val; | 2218 return (uchar) bc_num_bigdig2(&p->asciify); |
2213} 2214 2215/** | 2219} 2220 2221/** |
2216 * Executes the "asciify" command in dc. 2217 * @param p The program. 2218 * @param fidx The index of the current function. | 2222 * Executes the "asciify" command in bc and dc. 2223 * @param p The program. |
2219 */ 2220static void | 2224 */ 2225static void |
2221bc_program_asciify(BcProgram* p, size_t fidx) | 2226bc_program_asciify(BcProgram* p) |
2222{ 2223 BcResult *r, res; 2224 BcNum* n; | 2227{ 2228 BcResult *r, res; 2229 BcNum* n; |
2225 char str[2]; 2226 char* str2; | |
2227 uchar c; 2228 size_t idx; | 2230 uchar c; 2231 size_t idx; |
2232#if BC_ENABLED 2233 // This is in the outer scope because it has to be freed after a jump. 2234 char* temp_str; 2235#endif // BC_ENABLED |
|
2229 2230 // Check the stack. 2231 if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK); 2232 2233 assert(BC_PROG_STACK(&p->results, 1)); 2234 2235 // Get the top of the results stack. 2236 bc_program_operand(p, &r, &n, 0); 2237 2238 assert(n != NULL); | 2236 2237 // Check the stack. 2238 if (BC_ERR(!BC_PROG_STACK(&p->results, 1))) bc_err(BC_ERR_EXEC_STACK); 2239 2240 assert(BC_PROG_STACK(&p->results, 1)); 2241 2242 // Get the top of the results stack. 2243 bc_program_operand(p, &r, &n, 0); 2244 2245 assert(n != NULL); |
2246 assert(BC_IS_BC || r->t != BC_RESULT_ARRAY); |
|
2239 | 2247 |
2240 // Asciify. 2241 if (BC_PROG_NUM(r, n)) c = bc_program_asciifyNum(p, n); 2242 else | 2248#if BC_ENABLED 2249 // Handle arrays in bc specially. 2250 if (r->t == BC_RESULT_ARRAY) |
2243 { | 2251 { |
2244 // Get the string itself, then the first character. 2245 str2 = bc_program_string(p, n); 2246 c = (uchar) str2[0]; | 2252 // Yes, this is one place where we need to cast the number from 2253 // bc_program_num() to a vector. 2254 BcVec* v = (BcVec*) n; 2255 size_t i; 2256 2257 // XXX: If this is changed, you should also change the similar code in 2258 // bc_program_builtin(). 2259 2260 // Dereference the array, if necessary. 2261 if (v->size == sizeof(uchar)) 2262 { 2263 v = bc_program_dereference(p, v); 2264 } 2265 2266 assert(v->size == sizeof(BcNum)); 2267 2268 // Allocate the string and set the jump for it. 2269 BC_SIG_LOCK; 2270 temp_str = bc_vm_malloc(v->len + 1); 2271 BC_SETJMP_LOCKED(vm, exit); 2272 BC_SIG_UNLOCK; 2273 2274 // Convert the array. 2275 for (i = 0; i < v->len; ++i) 2276 { 2277 BcNum* num = (BcNum*) bc_vec_item(v, i); 2278 2279 if (BC_PROG_STR(num)) 2280 { 2281 temp_str[i] = (bc_program_string(p, num))[0]; 2282 } 2283 else 2284 { 2285 temp_str[i] = (char) bc_program_asciifyNum(p, num); 2286 } 2287 } 2288 2289 temp_str[v->len] = '\0'; 2290 2291 // Store the string in the slab and map, and free the temp string. 2292 BC_SIG_LOCK; 2293 idx = bc_program_addString(p, temp_str); 2294 free(temp_str); 2295 BC_UNSETJMP(vm); 2296 BC_SIG_UNLOCK; |
2247 } | 2297 } |
2298 else 2299#endif // BC_ENABLED 2300 { 2301 char str[2]; 2302 char* str2; |
|
2248 | 2303 |
2249 // Fill the resulting string. 2250 str[0] = (char) c; 2251 str[1] = '\0'; | 2304 // Asciify. 2305 if (BC_PROG_NUM(r, n)) c = bc_program_asciifyNum(p, n); 2306 else 2307 { 2308 // Get the string itself, then the first character. 2309 str2 = bc_program_string(p, n); 2310 c = (uchar) str2[0]; 2311 } |
2252 | 2312 |
2253 // Add the string to the data structures. 2254 BC_SIG_LOCK; 2255 idx = bc_program_addString(p, str, fidx); 2256 BC_SIG_UNLOCK; | 2313 // Fill the resulting string. 2314 str[0] = (char) c; 2315 str[1] = '\0'; |
2257 | 2316 |
2317 // Add the string to the data structures. 2318 BC_SIG_LOCK; 2319 idx = bc_program_addString(p, str); 2320 BC_SIG_UNLOCK; 2321 } 2322 |
|
2258 // Set the result 2259 res.t = BC_RESULT_STR; 2260 bc_num_clear(&res.d.n); | 2323 // Set the result 2324 res.t = BC_RESULT_STR; 2325 bc_num_clear(&res.d.n); |
2261 res.d.n.rdx = fidx; | |
2262 res.d.n.scale = idx; 2263 2264 // Pop and push. 2265 bc_vec_pop(&p->results); 2266 bc_vec_push(&p->results, &res); | 2326 res.d.n.scale = idx; 2327 2328 // Pop and push. 2329 bc_vec_pop(&p->results); 2330 bc_vec_push(&p->results, &res); |
2331 2332 return; 2333 2334#if BC_ENABLED 2335exit: 2336 free(temp_str); 2337#endif // BC_ENABLED |
|
2267} 2268 2269/** 2270 * Streams a number or a string to stdout. 2271 * @param p The program. 2272 */ 2273static void 2274bc_program_printStream(BcProgram* p) --- 85 unchanged lines hidden (view full) --- 2360 // Adjust the value. 2361 if (calls >= val) val = 0; 2362 else val -= (BcBigDig) calls; 2363 } 2364 2365 // If we don't have enough executions, just quit. 2366 if (i == p->stack.len) 2367 { | 2338} 2339 2340/** 2341 * Streams a number or a string to stdout. 2342 * @param p The program. 2343 */ 2344static void 2345bc_program_printStream(BcProgram* p) --- 85 unchanged lines hidden (view full) --- 2431 // Adjust the value. 2432 if (calls >= val) val = 0; 2433 else val -= (BcBigDig) calls; 2434 } 2435 2436 // If we don't have enough executions, just quit. 2437 if (i == p->stack.len) 2438 { |
2368 vm.status = BC_STATUS_QUIT; | 2439 vm->status = BC_STATUS_QUIT; |
2369 BC_JMP; 2370 } 2371 else 2372 { 2373 // We can always pop the last item we reached on the tail call stack 2374 // because these are for tail calls. That means that any executions that 2375 // we would not have quit in that position on the stack would have quit 2376 // anyway. --- 52 unchanged lines hidden (view full) --- 2429 2430 // Get the operand. 2431 bc_program_operand(p, &r, &n, 0); 2432 2433 // If execution is conditional... 2434 if (cond) 2435 { 2436 bool exec; | 2440 BC_JMP; 2441 } 2442 else 2443 { 2444 // We can always pop the last item we reached on the tail call stack 2445 // because these are for tail calls. That means that any executions that 2446 // we would not have quit in that position on the stack would have quit 2447 // anyway. --- 52 unchanged lines hidden (view full) --- 2500 2501 // Get the operand. 2502 bc_program_operand(p, &r, &n, 0); 2503 2504 // If execution is conditional... 2505 if (cond) 2506 { 2507 bool exec; |
2437 size_t idx, then_idx, else_idx; | 2508 size_t then_idx; 2509 // These are volatile to quiet warnings on GCC about clobbering with 2510 // longjmp(). 2511 volatile size_t else_idx; 2512 volatile size_t idx; |
2438 2439 // Get the index of the "then" var and "else" var. 2440 then_idx = bc_program_index(code, bgn); 2441 else_idx = bc_program_index(code, bgn); 2442 2443 // Figure out if we should execute. 2444 exec = (r->d.n.len != 0); 2445 2446 idx = exec ? then_idx : else_idx; 2447 2448 BC_SIG_LOCK; | 2513 2514 // Get the index of the "then" var and "else" var. 2515 then_idx = bc_program_index(code, bgn); 2516 else_idx = bc_program_index(code, bgn); 2517 2518 // Figure out if we should execute. 2519 exec = (r->d.n.len != 0); 2520 2521 idx = exec ? then_idx : else_idx; 2522 2523 BC_SIG_LOCK; |
2449 BC_SETJMP_LOCKED(exit); | 2524 BC_SETJMP_LOCKED(vm, exit); |
2450 2451 // If we are supposed to execute, execute. If else_idx == SIZE_MAX, that 2452 // means there was no else clause, so if execute is false and else does 2453 // not exist, we don't execute. The goto skips all of the setup for the 2454 // execution. 2455 if (exec || (else_idx != SIZE_MAX)) 2456 { 2457 n = bc_vec_top(bc_program_vec(p, idx, BC_TYPE_VAR)); 2458 } 2459 else goto exit; 2460 2461 if (BC_ERR(!BC_PROG_STR(n))) bc_err(BC_ERR_EXEC_TYPE); 2462 | 2525 2526 // If we are supposed to execute, execute. If else_idx == SIZE_MAX, that 2527 // means there was no else clause, so if execute is false and else does 2528 // not exist, we don't execute. The goto skips all of the setup for the 2529 // execution. 2530 if (exec || (else_idx != SIZE_MAX)) 2531 { 2532 n = bc_vec_top(bc_program_vec(p, idx, BC_TYPE_VAR)); 2533 } 2534 else goto exit; 2535 2536 if (BC_ERR(!BC_PROG_STR(n))) bc_err(BC_ERR_EXEC_TYPE); 2537 |
2463 BC_UNSETJMP; | 2538 BC_UNSETJMP(vm); |
2464 BC_SIG_UNLOCK; 2465 } 2466 else 2467 { 2468 // In non-conditional situations, only the top of stack can be executed, 2469 // and in those cases, variables are not allowed to be "on the stack"; 2470 // they are only put on the stack to be assigned to. 2471 assert(r->t != BC_RESULT_VAR); --- 12 unchanged lines hidden (view full) --- 2484 BC_SIG_UNLOCK; 2485 f = bc_vec_item(&p->fns, fidx); 2486 2487 // If the function has not been parsed yet... 2488 if (!f->code.len) 2489 { 2490 BC_SIG_LOCK; 2491 | 2539 BC_SIG_UNLOCK; 2540 } 2541 else 2542 { 2543 // In non-conditional situations, only the top of stack can be executed, 2544 // and in those cases, variables are not allowed to be "on the stack"; 2545 // they are only put on the stack to be assigned to. 2546 assert(r->t != BC_RESULT_VAR); --- 12 unchanged lines hidden (view full) --- 2559 BC_SIG_UNLOCK; 2560 f = bc_vec_item(&p->fns, fidx); 2561 2562 // If the function has not been parsed yet... 2563 if (!f->code.len) 2564 { 2565 BC_SIG_LOCK; 2566 |
2492 if (!BC_PARSE_IS_INITED(&vm.read_prs, p)) | 2567 if (!BC_PARSE_IS_INITED(&vm->read_prs, p)) |
2493 { | 2568 { |
2494 bc_parse_init(&vm.read_prs, p, fidx); | 2569 bc_parse_init(&vm->read_prs, p, fidx); |
2495 2496 // Initialize this too because bc_vm_shutdown() expects them to be 2497 // initialized togther. | 2570 2571 // Initialize this too because bc_vm_shutdown() expects them to be 2572 // initialized togther. |
2498 bc_vec_init(&vm.read_buf, sizeof(char), BC_DTOR_NONE); | 2573 bc_vec_init(&vm->read_buf, sizeof(char), BC_DTOR_NONE); |
2499 } 2500 // This needs to be updated because the parser could have been used 2501 // somewhere else | 2574 } 2575 // This needs to be updated because the parser could have been used 2576 // somewhere else |
2502 else bc_parse_updateFunc(&vm.read_prs, fidx); | 2577 else bc_parse_updateFunc(&vm->read_prs, fidx); |
2503 | 2578 |
2504 bc_lex_file(&vm.read_prs.l, vm.file); | 2579 bc_lex_file(&vm->read_prs.l, vm->file); |
2505 | 2580 |
2506 BC_SETJMP_LOCKED(err); | 2581 BC_SETJMP_LOCKED(vm, err); |
2507 2508 BC_SIG_UNLOCK; 2509 | 2582 2583 BC_SIG_UNLOCK; 2584 |
2510 // Parse. 2511 bc_parse_text(&vm.read_prs, str, false, false); | 2585 // Parse. Only one expression is needed, so stdin isn't used. 2586 bc_parse_text(&vm->read_prs, str, BC_MODE_FILE); |
2512 2513 BC_SIG_LOCK; | 2587 2588 BC_SIG_LOCK; |
2514 vm.expr(&vm.read_prs, BC_PARSE_NOCALL); | 2589 vm->expr(&vm->read_prs, BC_PARSE_NOCALL); |
2515 | 2590 |
2516 BC_UNSETJMP; | 2591 BC_UNSETJMP(vm); |
2517 2518 // We can just assert this here because 2519 // dc should parse everything until EOF. | 2592 2593 // We can just assert this here because 2594 // dc should parse everything until EOF. |
2520 assert(vm.read_prs.l.t == BC_LEX_EOF); | 2595 assert(vm->read_prs.l.t == BC_LEX_EOF); |
2521 2522 BC_SIG_UNLOCK; 2523 } 2524 2525 // Set the instruction pointer. 2526 ip.idx = 0; 2527 ip.len = p->results.len; 2528 ip.func = fidx; --- 32 unchanged lines hidden (view full) --- 2561 2562 f = bc_vec_item(&p->fns, fidx); 2563 2564 // Make sure to erase the bytecode vector so dc knows it is not parsed. 2565 bc_vec_popAll(&f->code); 2566 2567exit: 2568 bc_vec_pop(&p->results); | 2596 2597 BC_SIG_UNLOCK; 2598 } 2599 2600 // Set the instruction pointer. 2601 ip.idx = 0; 2602 ip.len = p->results.len; 2603 ip.func = fidx; --- 32 unchanged lines hidden (view full) --- 2636 2637 f = bc_vec_item(&p->fns, fidx); 2638 2639 // Make sure to erase the bytecode vector so dc knows it is not parsed. 2640 bc_vec_popAll(&f->code); 2641 2642exit: 2643 bc_vec_pop(&p->results); |
2569 BC_LONGJMP_CONT; | 2644 BC_LONGJMP_CONT(vm); |
2570} 2571 2572/** 2573 * Prints every item on the results stack, one per line. 2574 * @param p The program. 2575 */ 2576static void 2577bc_program_printStack(BcProgram* p) --- 33 unchanged lines hidden (view full) --- 2611static void 2612bc_program_globalSetting(BcProgram* p, uchar inst) 2613{ 2614 BcBigDig val; 2615 2616 // Make sure the instruction is valid. 2617 assert(inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO); 2618 | 2645} 2646 2647/** 2648 * Prints every item on the results stack, one per line. 2649 * @param p The program. 2650 */ 2651static void 2652bc_program_printStack(BcProgram* p) --- 33 unchanged lines hidden (view full) --- 2686static void 2687bc_program_globalSetting(BcProgram* p, uchar inst) 2688{ 2689 BcBigDig val; 2690 2691 // Make sure the instruction is valid. 2692 assert(inst >= BC_INST_LINE_LENGTH && inst <= BC_INST_LEADING_ZERO); 2693 |
2619 if (inst == BC_INST_LINE_LENGTH) val = (BcBigDig) vm.line_len; | 2694 if (inst == BC_INST_LINE_LENGTH) val = (BcBigDig) vm->line_len; |
2620#if BC_ENABLED 2621 else if (inst == BC_INST_GLOBAL_STACKS) val = (BC_G != 0); 2622#endif // BC_ENABLED 2623 else val = (BC_Z != 0); 2624 2625 // Push the global. 2626 bc_program_pushBigdig(p, val, BC_RESULT_TEMP); 2627} --- 28 unchanged lines hidden (view full) --- 2656 * Adds a function to the fns array. The function's ID must have already been 2657 * inserted into the map. 2658 * @param p The program. 2659 * @param id_ptr The ID of the function as inserted into the map. 2660 */ 2661static void 2662bc_program_addFunc(BcProgram* p, BcId* id_ptr) 2663{ | 2695#if BC_ENABLED 2696 else if (inst == BC_INST_GLOBAL_STACKS) val = (BC_G != 0); 2697#endif // BC_ENABLED 2698 else val = (BC_Z != 0); 2699 2700 // Push the global. 2701 bc_program_pushBigdig(p, val, BC_RESULT_TEMP); 2702} --- 28 unchanged lines hidden (view full) --- 2731 * Adds a function to the fns array. The function's ID must have already been 2732 * inserted into the map. 2733 * @param p The program. 2734 * @param id_ptr The ID of the function as inserted into the map. 2735 */ 2736static void 2737bc_program_addFunc(BcProgram* p, BcId* id_ptr) 2738{ |
2664 BcInstPtr* ip; | |
2665 BcFunc* f; 2666 2667 BC_SIG_ASSERT_LOCKED; 2668 2669 // Push and init. 2670 f = bc_vec_pushEmpty(&p->fns); 2671 bc_func_init(f, id_ptr->name); | 2739 BcFunc* f; 2740 2741 BC_SIG_ASSERT_LOCKED; 2742 2743 // Push and init. 2744 f = bc_vec_pushEmpty(&p->fns); 2745 bc_func_init(f, id_ptr->name); |
2672 2673 // This is to make sure pointers are updated if the array was moved. 2674 if (p->stack.len) 2675 { 2676 ip = bc_vec_top(&p->stack); 2677 bc_program_setVecs(p, (BcFunc*) bc_vec_item(&p->fns, ip->func)); 2678 } | |
2679} 2680 2681size_t 2682bc_program_insertFunc(BcProgram* p, const char* name) 2683{ 2684 BcId* id_ptr; 2685 bool new; 2686 size_t idx; --- 24 unchanged lines hidden (view full) --- 2711 2712 return idx; 2713} 2714 2715#ifndef NDEBUG 2716void 2717bc_program_free(BcProgram* p) 2718{ | 2746} 2747 2748size_t 2749bc_program_insertFunc(BcProgram* p, const char* name) 2750{ 2751 BcId* id_ptr; 2752 bool new; 2753 size_t idx; --- 24 unchanged lines hidden (view full) --- 2778 2779 return idx; 2780} 2781 2782#ifndef NDEBUG 2783void 2784bc_program_free(BcProgram* p) 2785{ |
2786#if BC_ENABLED |
|
2719 size_t i; | 2787 size_t i; |
2788#endif // BC_ENABLED |
|
2720 2721 BC_SIG_ASSERT_LOCKED; 2722 2723 assert(p != NULL); 2724 | 2789 2790 BC_SIG_ASSERT_LOCKED; 2791 2792 assert(p != NULL); 2793 |
2794#if BC_ENABLED |
|
2725 // Free the globals stacks. 2726 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i) 2727 { 2728 bc_vec_free(p->globals_v + i); 2729 } | 2795 // Free the globals stacks. 2796 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i) 2797 { 2798 bc_vec_free(p->globals_v + i); 2799 } |
2800#endif // BC_ENABLED |
|
2730 2731 bc_vec_free(&p->fns); 2732 bc_vec_free(&p->fn_map); 2733 bc_vec_free(&p->vars); 2734 bc_vec_free(&p->var_map); 2735 bc_vec_free(&p->arrs); 2736 bc_vec_free(&p->arr_map); 2737 bc_vec_free(&p->results); 2738 bc_vec_free(&p->stack); | 2801 2802 bc_vec_free(&p->fns); 2803 bc_vec_free(&p->fn_map); 2804 bc_vec_free(&p->vars); 2805 bc_vec_free(&p->var_map); 2806 bc_vec_free(&p->arrs); 2807 bc_vec_free(&p->arr_map); 2808 bc_vec_free(&p->results); 2809 bc_vec_free(&p->stack); |
2810 bc_vec_free(&p->consts); 2811 bc_vec_free(&p->const_map); 2812 bc_vec_free(&p->strs); 2813 bc_vec_free(&p->str_map); |
|
2739 | 2814 |
2815 bc_num_free(&p->asciify); 2816 |
|
2740#if BC_ENABLED 2741 if (BC_IS_BC) bc_num_free(&p->last); 2742#endif // BC_ENABLED 2743 2744#if BC_ENABLE_EXTRA_MATH 2745 bc_rand_free(&p->rng); 2746#endif // BC_ENABLE_EXTRA_MATH 2747 --- 17 unchanged lines hidden (view full) --- 2765 // NOLINTNEXTLINE 2766 memset(&ip, 0, sizeof(BcInstPtr)); 2767 2768 // Setup the globals stacks and the current values. 2769 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i) 2770 { 2771 BcBigDig val = i == BC_PROG_GLOBALS_SCALE ? 0 : BC_BASE; 2772 | 2817#if BC_ENABLED 2818 if (BC_IS_BC) bc_num_free(&p->last); 2819#endif // BC_ENABLED 2820 2821#if BC_ENABLE_EXTRA_MATH 2822 bc_rand_free(&p->rng); 2823#endif // BC_ENABLE_EXTRA_MATH 2824 --- 17 unchanged lines hidden (view full) --- 2842 // NOLINTNEXTLINE 2843 memset(&ip, 0, sizeof(BcInstPtr)); 2844 2845 // Setup the globals stacks and the current values. 2846 for (i = 0; i < BC_PROG_GLOBALS_LEN; ++i) 2847 { 2848 BcBigDig val = i == BC_PROG_GLOBALS_SCALE ? 0 : BC_BASE; 2849 |
2850#if BC_ENABLED |
|
2773 bc_vec_init(p->globals_v + i, sizeof(BcBigDig), BC_DTOR_NONE); 2774 bc_vec_push(p->globals_v + i, &val); | 2851 bc_vec_init(p->globals_v + i, sizeof(BcBigDig), BC_DTOR_NONE); 2852 bc_vec_push(p->globals_v + i, &val); |
2853#endif // BC_ENABLED |
|
2775 2776 p->globals[i] = val; 2777 } 2778 2779#if DC_ENABLED 2780 // dc-only setup. 2781 if (BC_IS_DC) 2782 { 2783 bc_vec_init(&p->tail_calls, sizeof(size_t), BC_DTOR_NONE); 2784 2785 // We want an item for the main function on the tail call stack. 2786 i = 0; 2787 bc_vec_push(&p->tail_calls, &i); 2788 } 2789#endif // DC_ENABLED 2790 2791 bc_num_setup(&p->strmb, p->strmb_num, BC_NUM_BIGDIG_LOG10); 2792 bc_num_bigdig2num(&p->strmb, BC_NUM_STREAM_BASE); 2793 | 2854 2855 p->globals[i] = val; 2856 } 2857 2858#if DC_ENABLED 2859 // dc-only setup. 2860 if (BC_IS_DC) 2861 { 2862 bc_vec_init(&p->tail_calls, sizeof(size_t), BC_DTOR_NONE); 2863 2864 // We want an item for the main function on the tail call stack. 2865 i = 0; 2866 bc_vec_push(&p->tail_calls, &i); 2867 } 2868#endif // DC_ENABLED 2869 2870 bc_num_setup(&p->strmb, p->strmb_num, BC_NUM_BIGDIG_LOG10); 2871 bc_num_bigdig2num(&p->strmb, BC_NUM_STREAM_BASE); 2872 |
2873 bc_num_init(&p->asciify, BC_NUM_DEF_SIZE); 2874 |
|
2794#if BC_ENABLE_EXTRA_MATH 2795 // We need to initialize srand() just in case /dev/urandom and /dev/random 2796 // are not available. 2797 srand((unsigned int) time(NULL)); 2798 bc_rand_init(&p->rng); 2799#endif // BC_ENABLE_EXTRA_MATH 2800 2801#if BC_ENABLED --- 16 unchanged lines hidden (view full) --- 2818 bc_map_init(&p->arr_map); 2819 2820 bc_vec_init(&p->results, sizeof(BcResult), BC_DTOR_RESULT); 2821 2822 // Push the first instruction pointer onto the execution stack. 2823 bc_vec_init(&p->stack, sizeof(BcInstPtr), BC_DTOR_NONE); 2824 bc_vec_push(&p->stack, &ip); 2825 | 2875#if BC_ENABLE_EXTRA_MATH 2876 // We need to initialize srand() just in case /dev/urandom and /dev/random 2877 // are not available. 2878 srand((unsigned int) time(NULL)); 2879 bc_rand_init(&p->rng); 2880#endif // BC_ENABLE_EXTRA_MATH 2881 2882#if BC_ENABLED --- 16 unchanged lines hidden (view full) --- 2899 bc_map_init(&p->arr_map); 2900 2901 bc_vec_init(&p->results, sizeof(BcResult), BC_DTOR_RESULT); 2902 2903 // Push the first instruction pointer onto the execution stack. 2904 bc_vec_init(&p->stack, sizeof(BcInstPtr), BC_DTOR_NONE); 2905 bc_vec_push(&p->stack, &ip); 2906 |
2826 // Make sure the pointers are properly set up. 2827 bc_program_setVecs(p, (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN)); | 2907 bc_vec_init(&p->consts, sizeof(BcConst), BC_DTOR_CONST); 2908 bc_map_init(&p->const_map); 2909 bc_vec_init(&p->strs, sizeof(char*), BC_DTOR_NONE); 2910 bc_map_init(&p->str_map); 2911} |
2828 | 2912 |
2829 assert(p->consts != NULL && p->strs != NULL); | 2913void 2914bc_program_printStackTrace(BcProgram* p) 2915{ 2916 size_t i, max_digits; 2917 2918 max_digits = bc_vm_numDigits(p->stack.len - 1); 2919 2920 for (i = 0; i < p->stack.len; ++i) 2921 { 2922 BcInstPtr* ip = bc_vec_item_rev(&p->stack, i); 2923 BcFunc* f = bc_vec_item(&p->fns, ip->func); 2924 size_t j, digits; 2925 2926 digits = bc_vm_numDigits(i); 2927 2928 bc_file_puts(&vm->ferr, bc_flush_none, " "); 2929 2930 for (j = 0; j < max_digits - digits; ++j) 2931 { 2932 bc_file_putchar(&vm->ferr, bc_flush_none, ' '); 2933 } 2934 2935 bc_file_printf(&vm->ferr, "%zu: %s", i, f->name); 2936 2937#if BC_ENABLED 2938 if (BC_IS_BC && ip->func != BC_PROG_MAIN && ip->func != BC_PROG_READ) 2939 { 2940 bc_file_puts(&vm->ferr, bc_flush_none, "()"); 2941 } 2942#endif // BC_ENABLED 2943 2944 bc_file_putchar(&vm->ferr, bc_flush_none, '\n'); 2945 } |
2830} 2831 2832void 2833bc_program_reset(BcProgram* p) 2834{ 2835 BcFunc* f; 2836 BcInstPtr* ip; 2837 2838 BC_SIG_ASSERT_LOCKED; 2839 2840 // Pop all but the last execution and all results. 2841 bc_vec_npop(&p->stack, p->stack.len - 1); 2842 bc_vec_popAll(&p->results); 2843 | 2946} 2947 2948void 2949bc_program_reset(BcProgram* p) 2950{ 2951 BcFunc* f; 2952 BcInstPtr* ip; 2953 2954 BC_SIG_ASSERT_LOCKED; 2955 2956 // Pop all but the last execution and all results. 2957 bc_vec_npop(&p->stack, p->stack.len - 1); 2958 bc_vec_popAll(&p->results); 2959 |
2960#if DC_ENABLED 2961 // We need to pop tail calls too. 2962 if (BC_IS_DC) bc_vec_npop(&p->tail_calls, p->tail_calls.len - 1); 2963#endif // DC_ENABLED 2964 |
|
2844#if BC_ENABLED 2845 // Clear the globals' stacks. 2846 if (BC_G) bc_program_popGlobals(p, true); 2847#endif // BC_ENABLED 2848 2849 // Clear the bytecode vector of the main function. 2850 f = bc_vec_item(&p->fns, BC_PROG_MAIN); 2851 bc_vec_npop(&f->code, f->code.len); 2852 2853 // Reset the instruction pointer. 2854 ip = bc_vec_top(&p->stack); | 2965#if BC_ENABLED 2966 // Clear the globals' stacks. 2967 if (BC_G) bc_program_popGlobals(p, true); 2968#endif // BC_ENABLED 2969 2970 // Clear the bytecode vector of the main function. 2971 f = bc_vec_item(&p->fns, BC_PROG_MAIN); 2972 bc_vec_npop(&f->code, f->code.len); 2973 2974 // Reset the instruction pointer. 2975 ip = bc_vec_top(&p->stack); |
2855 bc_program_setVecs(p, f); | |
2856 // NOLINTNEXTLINE 2857 memset(ip, 0, sizeof(BcInstPtr)); 2858 | 2976 // NOLINTNEXTLINE 2977 memset(ip, 0, sizeof(BcInstPtr)); 2978 |
2859 // Write the ready message for a signal, and clear the signal. 2860 if (vm.sig) | 2979 if (BC_SIG_INTERRUPT(vm)) |
2861 { | 2980 { |
2862 bc_file_printf(&vm.fout, "%s", bc_program_ready_msg); 2863 bc_file_flush(&vm.fout, bc_flush_err); 2864 vm.sig = 0; | 2981 // Write the ready message for a signal. 2982 bc_file_printf(&vm->fout, "%s", bc_program_ready_msg); 2983 bc_file_flush(&vm->fout, bc_flush_err); |
2865 } | 2984 } |
2985 2986 // Clear the signal. 2987 vm->sig = 0; |
|
2866} 2867 2868void 2869bc_program_exec(BcProgram* p) 2870{ 2871 size_t idx; 2872 BcResult r; 2873 BcResult* ptr; --- 7 unchanged lines hidden (view full) --- 2881#endif // BC_ENABLED 2882#if !BC_HAS_COMPUTED_GOTO 2883#ifndef NDEBUG 2884 size_t jmp_bufs_len; 2885#endif // NDEBUG 2886#endif // !BC_HAS_COMPUTED_GOTO 2887 2888#if BC_HAS_COMPUTED_GOTO | 2988} 2989 2990void 2991bc_program_exec(BcProgram* p) 2992{ 2993 size_t idx; 2994 BcResult r; 2995 BcResult* ptr; --- 7 unchanged lines hidden (view full) --- 3003#endif // BC_ENABLED 3004#if !BC_HAS_COMPUTED_GOTO 3005#ifndef NDEBUG 3006 size_t jmp_bufs_len; 3007#endif // NDEBUG 3008#endif // !BC_HAS_COMPUTED_GOTO 3009 3010#if BC_HAS_COMPUTED_GOTO |
3011 3012#if BC_GCC 3013#pragma GCC diagnostic ignored "-Wpedantic" 3014#endif // BC_GCC 3015 3016#if BC_CLANG 3017#pragma clang diagnostic ignored "-Wgnu-label-as-value" 3018#endif // BC_CLANG 3019 |
|
2889 BC_PROG_LBLS; 2890 BC_PROG_LBLS_ASSERT; 2891 | 3020 BC_PROG_LBLS; 3021 BC_PROG_LBLS_ASSERT; 3022 |
3023#if BC_CLANG 3024#pragma clang diagnostic warning "-Wgnu-label-as-value" 3025#endif // BC_CLANG 3026 3027#if BC_GCC 3028#pragma GCC diagnostic warning "-Wpedantic" 3029#endif // BC_GCC 3030 |
|
2892 // BC_INST_INVALID is a marker for the end so that we don't have to have an 2893 // execution loop. 2894 func = (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN); 2895 bc_vec_pushByte(&func->code, BC_INST_INVALID); 2896#endif // BC_HAS_COMPUTED_GOTO 2897 | 3031 // BC_INST_INVALID is a marker for the end so that we don't have to have an 3032 // execution loop. 3033 func = (BcFunc*) bc_vec_item(&p->fns, BC_PROG_MAIN); 3034 bc_vec_pushByte(&func->code, BC_INST_INVALID); 3035#endif // BC_HAS_COMPUTED_GOTO 3036 |
3037 BC_SETJMP(vm, end); 3038 |
|
2898 ip = bc_vec_top(&p->stack); 2899 func = (BcFunc*) bc_vec_item(&p->fns, ip->func); 2900 code = func->code.v; 2901 | 3039 ip = bc_vec_top(&p->stack); 3040 func = (BcFunc*) bc_vec_item(&p->fns, ip->func); 3041 code = func->code.v; 3042 |
2902 // Ensure the pointers are correct. 2903 BC_SIG_LOCK; 2904 bc_program_setVecs(p, func); 2905 BC_SIG_UNLOCK; 2906 | |
2907#if !BC_HAS_COMPUTED_GOTO 2908 2909#ifndef NDEBUG | 3043#if !BC_HAS_COMPUTED_GOTO 3044 3045#ifndef NDEBUG |
2910 jmp_bufs_len = vm.jmp_bufs.len; | 3046 jmp_bufs_len = vm->jmp_bufs.len; |
2911#endif // NDEBUG 2912 2913 // This loop is the heart of the execution engine. It *is* the engine. For 2914 // computed goto, it is ignored. 2915 while (ip->idx < func->code.len) 2916#endif // !BC_HAS_COMPUTED_GOTO 2917 { 2918 BC_SIG_ASSERT_NOT_LOCKED; 2919 2920#if BC_HAS_COMPUTED_GOTO 2921 | 3047#endif // NDEBUG 3048 3049 // This loop is the heart of the execution engine. It *is* the engine. For 3050 // computed goto, it is ignored. 3051 while (ip->idx < func->code.len) 3052#endif // !BC_HAS_COMPUTED_GOTO 3053 { 3054 BC_SIG_ASSERT_NOT_LOCKED; 3055 3056#if BC_HAS_COMPUTED_GOTO 3057 |
3058#if BC_GCC 3059#pragma GCC diagnostic ignored "-Wpedantic" 3060#endif // BC_GCC 3061 3062#if BC_CLANG 3063#pragma clang diagnostic ignored "-Wgnu-label-as-value" 3064#endif // BC_CLANG 3065 |
|
2922 BC_PROG_JUMP(inst, code, ip); 2923 2924#else // BC_HAS_COMPUTED_GOTO 2925 2926 // Get the next instruction and increment the index. 2927 inst = (uchar) code[(ip->idx)++]; 2928 2929#endif // BC_HAS_COMPUTED_GOTO 2930 2931#if BC_DEBUG_CODE | 3066 BC_PROG_JUMP(inst, code, ip); 3067 3068#else // BC_HAS_COMPUTED_GOTO 3069 3070 // Get the next instruction and increment the index. 3071 inst = (uchar) code[(ip->idx)++]; 3072 3073#endif // BC_HAS_COMPUTED_GOTO 3074 3075#if BC_DEBUG_CODE |
2932 bc_file_printf(&vm.ferr, "inst: %s\n", bc_inst_names[inst]); 2933 bc_file_flush(&vm.ferr, bc_flush_none); | 3076 bc_file_printf(&vm->ferr, "inst: %s\n", bc_inst_names[inst]); 3077 bc_file_flush(&vm->ferr, bc_flush_none); |
2934#endif // BC_DEBUG_CODE 2935 2936#if !BC_HAS_COMPUTED_GOTO 2937 switch (inst) 2938#endif // !BC_HAS_COMPUTED_GOTO 2939 { 2940#if BC_ENABLED 2941 // This just sets up the condition for the unconditional jump below, --- 44 unchanged lines hidden (view full) --- 2986 bc_program_call(p, code, &ip->idx); 2987 2988 // Because we changed the execution stack and where we are 2989 // executing, we have to update all of this. 2990 BC_SIG_LOCK; 2991 ip = bc_vec_top(&p->stack); 2992 func = bc_vec_item(&p->fns, ip->func); 2993 code = func->code.v; | 3078#endif // BC_DEBUG_CODE 3079 3080#if !BC_HAS_COMPUTED_GOTO 3081 switch (inst) 3082#endif // !BC_HAS_COMPUTED_GOTO 3083 { 3084#if BC_ENABLED 3085 // This just sets up the condition for the unconditional jump below, --- 44 unchanged lines hidden (view full) --- 3130 bc_program_call(p, code, &ip->idx); 3131 3132 // Because we changed the execution stack and where we are 3133 // executing, we have to update all of this. 3134 BC_SIG_LOCK; 3135 ip = bc_vec_top(&p->stack); 3136 func = bc_vec_item(&p->fns, ip->func); 3137 code = func->code.v; |
2994 bc_program_setVecs(p, func); | |
2995 BC_SIG_UNLOCK; 2996 2997 BC_PROG_JUMP(inst, code, ip); 2998 } 2999 3000 // clang-format off 3001 BC_PROG_LBL(BC_INST_INC): 3002 BC_PROG_LBL(BC_INST_DEC): 3003 // clang-format on 3004 { 3005 bc_program_incdec(p, inst); 3006 BC_PROG_JUMP(inst, code, ip); 3007 } 3008 3009 // clang-format off 3010 BC_PROG_LBL(BC_INST_HALT): 3011 // clang-format on 3012 { | 3138 BC_SIG_UNLOCK; 3139 3140 BC_PROG_JUMP(inst, code, ip); 3141 } 3142 3143 // clang-format off 3144 BC_PROG_LBL(BC_INST_INC): 3145 BC_PROG_LBL(BC_INST_DEC): 3146 // clang-format on 3147 { 3148 bc_program_incdec(p, inst); 3149 BC_PROG_JUMP(inst, code, ip); 3150 } 3151 3152 // clang-format off 3153 BC_PROG_LBL(BC_INST_HALT): 3154 // clang-format on 3155 { |
3013 vm.status = BC_STATUS_QUIT; | 3156 vm->status = BC_STATUS_QUIT; |
3014 3015 // Just jump out. The jump series will take care of everything. 3016 BC_JMP; 3017 3018 BC_PROG_JUMP(inst, code, ip); 3019 } 3020 3021 // clang-format off --- 5 unchanged lines hidden (view full) --- 3027 bc_program_return(p, inst); 3028 3029 // Because we changed the execution stack and where we are 3030 // executing, we have to update all of this. 3031 BC_SIG_LOCK; 3032 ip = bc_vec_top(&p->stack); 3033 func = bc_vec_item(&p->fns, ip->func); 3034 code = func->code.v; | 3157 3158 // Just jump out. The jump series will take care of everything. 3159 BC_JMP; 3160 3161 BC_PROG_JUMP(inst, code, ip); 3162 } 3163 3164 // clang-format off --- 5 unchanged lines hidden (view full) --- 3170 bc_program_return(p, inst); 3171 3172 // Because we changed the execution stack and where we are 3173 // executing, we have to update all of this. 3174 BC_SIG_LOCK; 3175 ip = bc_vec_top(&p->stack); 3176 func = bc_vec_item(&p->fns, ip->func); 3177 code = func->code.v; |
3035 bc_program_setVecs(p, func); | |
3036 BC_SIG_UNLOCK; 3037 3038 BC_PROG_JUMP(inst, code, ip); 3039 } 3040#endif // BC_ENABLED 3041 3042 // clang-format off 3043 BC_PROG_LBL(BC_INST_BOOL_OR): --- 11 unchanged lines hidden (view full) --- 3055 } 3056 3057 // clang-format off 3058 BC_PROG_LBL(BC_INST_READ): 3059 // clang-format on 3060 { 3061 // We want to flush output before 3062 // this in case there is a prompt. | 3178 BC_SIG_UNLOCK; 3179 3180 BC_PROG_JUMP(inst, code, ip); 3181 } 3182#endif // BC_ENABLED 3183 3184 // clang-format off 3185 BC_PROG_LBL(BC_INST_BOOL_OR): --- 11 unchanged lines hidden (view full) --- 3197 } 3198 3199 // clang-format off 3200 BC_PROG_LBL(BC_INST_READ): 3201 // clang-format on 3202 { 3203 // We want to flush output before 3204 // this in case there is a prompt. |
3063 bc_file_flush(&vm.fout, bc_flush_save); | 3205 bc_file_flush(&vm->fout, bc_flush_save); |
3064 3065 bc_program_read(p); 3066 3067 // Because we changed the execution stack and where we are 3068 // executing, we have to update all of this. 3069 BC_SIG_LOCK; 3070 ip = bc_vec_top(&p->stack); 3071 func = bc_vec_item(&p->fns, ip->func); 3072 code = func->code.v; | 3206 3207 bc_program_read(p); 3208 3209 // Because we changed the execution stack and where we are 3210 // executing, we have to update all of this. 3211 BC_SIG_LOCK; 3212 ip = bc_vec_top(&p->stack); 3213 func = bc_vec_item(&p->fns, ip->func); 3214 code = func->code.v; |
3073 bc_program_setVecs(p, func); | |
3074 BC_SIG_UNLOCK; 3075 3076 BC_PROG_JUMP(inst, code, ip); 3077 } 3078 3079#if BC_ENABLE_EXTRA_MATH 3080 // clang-format off 3081 BC_PROG_LBL(BC_INST_RAND): --- 6 unchanged lines hidden (view full) --- 3088 3089 // clang-format off 3090 BC_PROG_LBL(BC_INST_MAXIBASE): 3091 BC_PROG_LBL(BC_INST_MAXOBASE): 3092 BC_PROG_LBL(BC_INST_MAXSCALE): 3093#if BC_ENABLE_EXTRA_MATH 3094 BC_PROG_LBL(BC_INST_MAXRAND): 3095#endif // BC_ENABLE_EXTRA_MATH | 3215 BC_SIG_UNLOCK; 3216 3217 BC_PROG_JUMP(inst, code, ip); 3218 } 3219 3220#if BC_ENABLE_EXTRA_MATH 3221 // clang-format off 3222 BC_PROG_LBL(BC_INST_RAND): --- 6 unchanged lines hidden (view full) --- 3229 3230 // clang-format off 3231 BC_PROG_LBL(BC_INST_MAXIBASE): 3232 BC_PROG_LBL(BC_INST_MAXOBASE): 3233 BC_PROG_LBL(BC_INST_MAXSCALE): 3234#if BC_ENABLE_EXTRA_MATH 3235 BC_PROG_LBL(BC_INST_MAXRAND): 3236#endif // BC_ENABLE_EXTRA_MATH |
3096 // clang-format on | 3237 // clang-format on |
3097 { | 3238 { |
3098 BcBigDig dig = vm.maxes[inst - BC_INST_MAXIBASE]; | 3239 BcBigDig dig = vm->maxes[inst - BC_INST_MAXIBASE]; |
3099 bc_program_pushBigdig(p, dig, BC_RESULT_TEMP); 3100 BC_PROG_JUMP(inst, code, ip); 3101 } 3102 3103 // clang-format off 3104 BC_PROG_LBL(BC_INST_LINE_LENGTH): 3105#if BC_ENABLED 3106 BC_PROG_LBL(BC_INST_GLOBAL_STACKS): --- 42 unchanged lines hidden (view full) --- 3149 } 3150#endif // BC_ENABLE_EXTRA_MATH 3151 3152 // clang-format off 3153 BC_PROG_LBL(BC_INST_LENGTH): 3154 BC_PROG_LBL(BC_INST_SCALE_FUNC): 3155 BC_PROG_LBL(BC_INST_SQRT): 3156 BC_PROG_LBL(BC_INST_ABS): | 3240 bc_program_pushBigdig(p, dig, BC_RESULT_TEMP); 3241 BC_PROG_JUMP(inst, code, ip); 3242 } 3243 3244 // clang-format off 3245 BC_PROG_LBL(BC_INST_LINE_LENGTH): 3246#if BC_ENABLED 3247 BC_PROG_LBL(BC_INST_GLOBAL_STACKS): --- 42 unchanged lines hidden (view full) --- 3290 } 3291#endif // BC_ENABLE_EXTRA_MATH 3292 3293 // clang-format off 3294 BC_PROG_LBL(BC_INST_LENGTH): 3295 BC_PROG_LBL(BC_INST_SCALE_FUNC): 3296 BC_PROG_LBL(BC_INST_SQRT): 3297 BC_PROG_LBL(BC_INST_ABS): |
3298 BC_PROG_LBL(BC_INST_IS_NUMBER): 3299 BC_PROG_LBL(BC_INST_IS_STRING): |
|
3157#if BC_ENABLE_EXTRA_MATH 3158 BC_PROG_LBL(BC_INST_IRAND): 3159#endif // BC_ENABLE_EXTRA_MATH | 3300#if BC_ENABLE_EXTRA_MATH 3301 BC_PROG_LBL(BC_INST_IRAND): 3302#endif // BC_ENABLE_EXTRA_MATH |
3160 // clang-format on | 3303 // clang-format on |
3161 { 3162 bc_program_builtin(p, inst); 3163 BC_PROG_JUMP(inst, code, ip); 3164 } 3165 3166 // clang-format off 3167 BC_PROG_LBL(BC_INST_ASCIIFY): 3168 // clang-format on 3169 { | 3304 { 3305 bc_program_builtin(p, inst); 3306 BC_PROG_JUMP(inst, code, ip); 3307 } 3308 3309 // clang-format off 3310 BC_PROG_LBL(BC_INST_ASCIIFY): 3311 // clang-format on 3312 { |
3170 bc_program_asciify(p, ip->func); | 3313 bc_program_asciify(p); |
3171 3172 // Because we changed the execution stack and where we are 3173 // executing, we have to update all of this. 3174 BC_SIG_LOCK; 3175 ip = bc_vec_top(&p->stack); 3176 func = bc_vec_item(&p->fns, ip->func); 3177 code = func->code.v; | 3314 3315 // Because we changed the execution stack and where we are 3316 // executing, we have to update all of this. 3317 BC_SIG_LOCK; 3318 ip = bc_vec_top(&p->stack); 3319 func = bc_vec_item(&p->fns, ip->func); 3320 code = func->code.v; |
3178 bc_program_setVecs(p, func); | |
3179 BC_SIG_UNLOCK; 3180 3181 BC_PROG_JUMP(inst, code, ip); 3182 } 3183 3184 // clang-format off 3185 BC_PROG_LBL(BC_INST_NUM): 3186 // clang-format on 3187 { 3188 bc_program_const(p, code, &ip->idx); 3189 BC_PROG_JUMP(inst, code, ip); 3190 } 3191 3192 // clang-format off 3193 BC_PROG_LBL(BC_INST_ZERO): 3194 BC_PROG_LBL(BC_INST_ONE): 3195#if BC_ENABLED 3196 BC_PROG_LBL(BC_INST_LAST): 3197#endif // BC_ENABLED | 3321 BC_SIG_UNLOCK; 3322 3323 BC_PROG_JUMP(inst, code, ip); 3324 } 3325 3326 // clang-format off 3327 BC_PROG_LBL(BC_INST_NUM): 3328 // clang-format on 3329 { 3330 bc_program_const(p, code, &ip->idx); 3331 BC_PROG_JUMP(inst, code, ip); 3332 } 3333 3334 // clang-format off 3335 BC_PROG_LBL(BC_INST_ZERO): 3336 BC_PROG_LBL(BC_INST_ONE): 3337#if BC_ENABLED 3338 BC_PROG_LBL(BC_INST_LAST): 3339#endif // BC_ENABLED |
3198 // clang-format on | 3340 // clang-format on |
3199 { 3200 r.t = BC_RESULT_ZERO + (inst - BC_INST_ZERO); 3201 bc_vec_push(&p->results, &r); 3202 BC_PROG_JUMP(inst, code, ip); 3203 } 3204 3205 // clang-format off 3206 BC_PROG_LBL(BC_INST_PRINT): 3207 BC_PROG_LBL(BC_INST_PRINT_POP): 3208#if BC_ENABLED 3209 BC_PROG_LBL(BC_INST_PRINT_STR): 3210#endif // BC_ENABLED | 3341 { 3342 r.t = BC_RESULT_ZERO + (inst - BC_INST_ZERO); 3343 bc_vec_push(&p->results, &r); 3344 BC_PROG_JUMP(inst, code, ip); 3345 } 3346 3347 // clang-format off 3348 BC_PROG_LBL(BC_INST_PRINT): 3349 BC_PROG_LBL(BC_INST_PRINT_POP): 3350#if BC_ENABLED 3351 BC_PROG_LBL(BC_INST_PRINT_STR): 3352#endif // BC_ENABLED |
3211 // clang-format on | 3353 // clang-format on |
3212 { 3213 bc_program_print(p, inst, 0); 3214 3215 // We want to flush right away to save the output for history, 3216 // if history must preserve it when taking input. | 3354 { 3355 bc_program_print(p, inst, 0); 3356 3357 // We want to flush right away to save the output for history, 3358 // if history must preserve it when taking input. |
3217 bc_file_flush(&vm.fout, bc_flush_save); | 3359 bc_file_flush(&vm->fout, bc_flush_save); |
3218 3219 BC_PROG_JUMP(inst, code, ip); 3220 } 3221 3222 // clang-format off 3223 BC_PROG_LBL(BC_INST_STR): 3224 // clang-format on 3225 { 3226 // Set up the result and push. 3227 r.t = BC_RESULT_STR; 3228 bc_num_clear(&r.d.n); | 3360 3361 BC_PROG_JUMP(inst, code, ip); 3362 } 3363 3364 // clang-format off 3365 BC_PROG_LBL(BC_INST_STR): 3366 // clang-format on 3367 { 3368 // Set up the result and push. 3369 r.t = BC_RESULT_STR; 3370 bc_num_clear(&r.d.n); |
3229 r.d.n.rdx = bc_program_index(code, &ip->idx); | |
3230 r.d.n.scale = bc_program_index(code, &ip->idx); 3231 bc_vec_push(&p->results, &r); 3232 BC_PROG_JUMP(inst, code, ip); 3233 } 3234 3235 // clang-format off 3236 BC_PROG_LBL(BC_INST_POWER): 3237 BC_PROG_LBL(BC_INST_MULTIPLY): 3238 BC_PROG_LBL(BC_INST_DIVIDE): 3239 BC_PROG_LBL(BC_INST_MODULUS): 3240 BC_PROG_LBL(BC_INST_PLUS): 3241 BC_PROG_LBL(BC_INST_MINUS): 3242#if BC_ENABLE_EXTRA_MATH 3243 BC_PROG_LBL(BC_INST_PLACES): 3244 BC_PROG_LBL(BC_INST_LSHIFT): 3245 BC_PROG_LBL(BC_INST_RSHIFT): 3246#endif // BC_ENABLE_EXTRA_MATH | 3371 r.d.n.scale = bc_program_index(code, &ip->idx); 3372 bc_vec_push(&p->results, &r); 3373 BC_PROG_JUMP(inst, code, ip); 3374 } 3375 3376 // clang-format off 3377 BC_PROG_LBL(BC_INST_POWER): 3378 BC_PROG_LBL(BC_INST_MULTIPLY): 3379 BC_PROG_LBL(BC_INST_DIVIDE): 3380 BC_PROG_LBL(BC_INST_MODULUS): 3381 BC_PROG_LBL(BC_INST_PLUS): 3382 BC_PROG_LBL(BC_INST_MINUS): 3383#if BC_ENABLE_EXTRA_MATH 3384 BC_PROG_LBL(BC_INST_PLACES): 3385 BC_PROG_LBL(BC_INST_LSHIFT): 3386 BC_PROG_LBL(BC_INST_RSHIFT): 3387#endif // BC_ENABLE_EXTRA_MATH |
3247 // clang-format on | 3388 // clang-format on |
3248 { 3249 bc_program_op(p, inst); 3250 BC_PROG_JUMP(inst, code, ip); 3251 } 3252 3253 // clang-format off 3254 BC_PROG_LBL(BC_INST_NEG): 3255 BC_PROG_LBL(BC_INST_BOOL_NOT): 3256#if BC_ENABLE_EXTRA_MATH 3257 BC_PROG_LBL(BC_INST_TRUNC): 3258#endif // BC_ENABLE_EXTRA_MATH | 3389 { 3390 bc_program_op(p, inst); 3391 BC_PROG_JUMP(inst, code, ip); 3392 } 3393 3394 // clang-format off 3395 BC_PROG_LBL(BC_INST_NEG): 3396 BC_PROG_LBL(BC_INST_BOOL_NOT): 3397#if BC_ENABLE_EXTRA_MATH 3398 BC_PROG_LBL(BC_INST_TRUNC): 3399#endif // BC_ENABLE_EXTRA_MATH |
3259 // clang-format on | 3400 // clang-format on |
3260 { 3261 bc_program_unary(p, inst); 3262 BC_PROG_JUMP(inst, code, ip); 3263 } 3264 3265 // clang-format off 3266#if BC_ENABLED 3267 BC_PROG_LBL(BC_INST_ASSIGN_POWER): --- 115 unchanged lines hidden (view full) --- 3383 bc_vec_pop(&p->tail_calls); 3384 3385 // Because we changed the execution stack and where we are 3386 // executing, we have to update all of this. 3387 BC_SIG_LOCK; 3388 ip = bc_vec_top(&p->stack); 3389 func = bc_vec_item(&p->fns, ip->func); 3390 code = func->code.v; | 3401 { 3402 bc_program_unary(p, inst); 3403 BC_PROG_JUMP(inst, code, ip); 3404 } 3405 3406 // clang-format off 3407#if BC_ENABLED 3408 BC_PROG_LBL(BC_INST_ASSIGN_POWER): --- 115 unchanged lines hidden (view full) --- 3524 bc_vec_pop(&p->tail_calls); 3525 3526 // Because we changed the execution stack and where we are 3527 // executing, we have to update all of this. 3528 BC_SIG_LOCK; 3529 ip = bc_vec_top(&p->stack); 3530 func = bc_vec_item(&p->fns, ip->func); 3531 code = func->code.v; |
3391 bc_program_setVecs(p, func); | |
3392 BC_SIG_UNLOCK; 3393 3394 BC_PROG_JUMP(inst, code, ip); 3395 } 3396 3397 // clang-format off 3398 BC_PROG_LBL(BC_INST_EXECUTE): 3399 BC_PROG_LBL(BC_INST_EXEC_COND): --- 4 unchanged lines hidden (view full) --- 3404 bc_program_execStr(p, code, &ip->idx, cond, func->code.len); 3405 3406 // Because we changed the execution stack and where we are 3407 // executing, we have to update all of this. 3408 BC_SIG_LOCK; 3409 ip = bc_vec_top(&p->stack); 3410 func = bc_vec_item(&p->fns, ip->func); 3411 code = func->code.v; | 3532 BC_SIG_UNLOCK; 3533 3534 BC_PROG_JUMP(inst, code, ip); 3535 } 3536 3537 // clang-format off 3538 BC_PROG_LBL(BC_INST_EXECUTE): 3539 BC_PROG_LBL(BC_INST_EXEC_COND): --- 4 unchanged lines hidden (view full) --- 3544 bc_program_execStr(p, code, &ip->idx, cond, func->code.len); 3545 3546 // Because we changed the execution stack and where we are 3547 // executing, we have to update all of this. 3548 BC_SIG_LOCK; 3549 ip = bc_vec_top(&p->stack); 3550 func = bc_vec_item(&p->fns, ip->func); 3551 code = func->code.v; |
3412 bc_program_setVecs(p, func); | |
3413 BC_SIG_UNLOCK; 3414 3415 BC_PROG_JUMP(inst, code, ip); 3416 } 3417 3418 // clang-format off 3419 BC_PROG_LBL(BC_INST_PRINT_STACK): 3420 // clang-format on --- 62 unchanged lines hidden (view full) --- 3483 BC_PROG_JUMP(inst, code, ip); 3484 } 3485 3486 // clang-format off 3487 BC_PROG_LBL(BC_INST_PUSH_TO_VAR): 3488 // clang-format on 3489 { 3490 idx = bc_program_index(code, &ip->idx); | 3552 BC_SIG_UNLOCK; 3553 3554 BC_PROG_JUMP(inst, code, ip); 3555 } 3556 3557 // clang-format off 3558 BC_PROG_LBL(BC_INST_PRINT_STACK): 3559 // clang-format on --- 62 unchanged lines hidden (view full) --- 3622 BC_PROG_JUMP(inst, code, ip); 3623 } 3624 3625 // clang-format off 3626 BC_PROG_LBL(BC_INST_PUSH_TO_VAR): 3627 // clang-format on 3628 { 3629 idx = bc_program_index(code, &ip->idx); |
3491 bc_program_copyToVar(p, idx, BC_TYPE_VAR, true); | 3630 bc_program_copyToVar(p, idx, BC_TYPE_VAR); |
3492 BC_PROG_JUMP(inst, code, ip); 3493 } 3494 3495 // clang-format off 3496 BC_PROG_LBL(BC_INST_QUIT): 3497 BC_PROG_LBL(BC_INST_NQUIT): 3498 // clang-format on 3499 { 3500 bc_program_nquit(p, inst); 3501 3502 // Because we changed the execution stack and where we are 3503 // executing, we have to update all of this. 3504 BC_SIG_LOCK; 3505 ip = bc_vec_top(&p->stack); 3506 func = bc_vec_item(&p->fns, ip->func); 3507 code = func->code.v; | 3631 BC_PROG_JUMP(inst, code, ip); 3632 } 3633 3634 // clang-format off 3635 BC_PROG_LBL(BC_INST_QUIT): 3636 BC_PROG_LBL(BC_INST_NQUIT): 3637 // clang-format on 3638 { 3639 bc_program_nquit(p, inst); 3640 3641 // Because we changed the execution stack and where we are 3642 // executing, we have to update all of this. 3643 BC_SIG_LOCK; 3644 ip = bc_vec_top(&p->stack); 3645 func = bc_vec_item(&p->fns, ip->func); 3646 code = func->code.v; |
3508 bc_program_setVecs(p, func); | |
3509 BC_SIG_UNLOCK; 3510 3511 BC_PROG_JUMP(inst, code, ip); 3512 } 3513 3514 // clang-format off 3515 BC_PROG_LBL(BC_INST_EXEC_STACK_LEN): 3516 // clang-format on 3517 { 3518 bc_program_execStackLen(p); 3519 BC_PROG_JUMP(inst, code, ip); 3520 } 3521#endif // DC_ENABLED 3522 3523#if BC_HAS_COMPUTED_GOTO 3524 // clang-format off 3525 BC_PROG_LBL(BC_INST_INVALID): 3526 // clang-format on 3527 { | 3647 BC_SIG_UNLOCK; 3648 3649 BC_PROG_JUMP(inst, code, ip); 3650 } 3651 3652 // clang-format off 3653 BC_PROG_LBL(BC_INST_EXEC_STACK_LEN): 3654 // clang-format on 3655 { 3656 bc_program_execStackLen(p); 3657 BC_PROG_JUMP(inst, code, ip); 3658 } 3659#endif // DC_ENABLED 3660 3661#if BC_HAS_COMPUTED_GOTO 3662 // clang-format off 3663 BC_PROG_LBL(BC_INST_INVALID): 3664 // clang-format on 3665 { |
3528 return; | 3666 goto end; |
3529 } 3530#else // BC_HAS_COMPUTED_GOTO 3531 default: 3532 { 3533 BC_UNREACHABLE | 3667 } 3668#else // BC_HAS_COMPUTED_GOTO 3669 default: 3670 { 3671 BC_UNREACHABLE |
3534#ifndef NDEBUG | 3672#if !defined(NDEBUG) && !BC_CLANG |
3535 abort(); | 3673 abort(); |
3536#endif // NDEBUG | 3674#endif // !defined(NDEBUG) && !BC_CLANG |
3537 } 3538#endif // BC_HAS_COMPUTED_GOTO 3539 } 3540 | 3675 } 3676#endif // BC_HAS_COMPUTED_GOTO 3677 } 3678 |
3541#if !BC_HAS_COMPUTED_GOTO | 3679#if BC_HAS_COMPUTED_GOTO 3680 3681#if BC_CLANG 3682#pragma clang diagnostic warning "-Wgnu-label-as-value" 3683#endif // BC_CLANG 3684 3685#if BC_GCC 3686#pragma GCC diagnostic warning "-Wpedantic" 3687#endif // BC_GCC 3688 3689#else // BC_HAS_COMPUTED_GOTO 3690 |
3542#ifndef NDEBUG 3543 // This is to allow me to use a debugger to see the last instruction, 3544 // which will point to which function was the problem. But it's also a 3545 // good smoke test for error handling changes. | 3691#ifndef NDEBUG 3692 // This is to allow me to use a debugger to see the last instruction, 3693 // which will point to which function was the problem. But it's also a 3694 // good smoke test for error handling changes. |
3546 assert(jmp_bufs_len == vm.jmp_bufs.len); | 3695 assert(jmp_bufs_len == vm->jmp_bufs.len); |
3547#endif // NDEBUG | 3696#endif // NDEBUG |
3548#endif // !BC_HAS_COMPUTED_GOTO | 3697 3698#endif // BC_HAS_COMPUTED_GOTO |
3549 } | 3699 } |
3700 3701end: 3702 BC_SIG_MAYLOCK; 3703 3704 // This is here just to print a stack trace on interrupts. This is for 3705 // finding infinite loops. 3706 if (BC_SIG_INTERRUPT(vm)) 3707 { 3708 BcStatus s; 3709 3710 bc_file_putchar(&vm->ferr, bc_flush_none, '\n'); 3711 3712 bc_program_printStackTrace(p); 3713 3714 s = bc_file_flushErr(&vm->ferr, bc_flush_err); 3715 if (BC_ERR(s != BC_STATUS_SUCCESS && vm->status == BC_STATUS_SUCCESS)) 3716 { 3717 vm->status = (sig_atomic_t) s; 3718 } 3719 } 3720 3721 BC_LONGJMP_CONT(vm); |
|
3550} 3551 3552#if BC_DEBUG_CODE 3553#if BC_ENABLED && DC_ENABLED 3554void 3555bc_program_printStackDebug(BcProgram* p) 3556{ | 3722} 3723 3724#if BC_DEBUG_CODE 3725#if BC_ENABLED && DC_ENABLED 3726void 3727bc_program_printStackDebug(BcProgram* p) 3728{ |
3557 bc_file_puts(&vm.fout, bc_flush_err, "-------------- Stack ----------\n"); | 3729 bc_file_puts(&vm->fout, bc_flush_err, "-------------- Stack ----------\n"); |
3558 bc_program_printStack(p); | 3730 bc_program_printStack(p); |
3559 bc_file_puts(&vm.fout, bc_flush_err, "-------------- Stack End ------\n"); | 3731 bc_file_puts(&vm->fout, bc_flush_err, "-------------- Stack End ------\n"); |
3560} 3561 3562static void 3563bc_program_printIndex(const char* restrict code, size_t* restrict bgn) 3564{ 3565 uchar byte, i, bytes = (uchar) code[(*bgn)++]; 3566 ulong val = 0; 3567 --- 65 unchanged lines hidden (view full) --- 3633 f = bc_vec_item(&p->fns, ip.func); 3634 code = f->code.v; 3635 3636 bc_vm_printf("func[%zu]:\n", ip.func); 3637 while (ip.idx < f->code.len) 3638 { 3639 bc_program_printInst(p, code, &ip.idx); 3640 } | 3732} 3733 3734static void 3735bc_program_printIndex(const char* restrict code, size_t* restrict bgn) 3736{ 3737 uchar byte, i, bytes = (uchar) code[(*bgn)++]; 3738 ulong val = 0; 3739 --- 65 unchanged lines hidden (view full) --- 3805 f = bc_vec_item(&p->fns, ip.func); 3806 code = f->code.v; 3807 3808 bc_vm_printf("func[%zu]:\n", ip.func); 3809 while (ip.idx < f->code.len) 3810 { 3811 bc_program_printInst(p, code, &ip.idx); 3812 } |
3641 bc_file_puts(&vm.fout, bc_flush_err, "\n\n"); | 3813 bc_file_puts(&vm->fout, bc_flush_err, "\n\n"); |
3642 } 3643} 3644#endif // BC_ENABLED && DC_ENABLED 3645#endif // BC_DEBUG_CODE | 3814 } 3815} 3816#endif // BC_ENABLED && DC_ENABLED 3817#endif // BC_DEBUG_CODE |