1 /* $NetBSD: storage.c,v 1.1 2017/04/10 02:28:23 phil Exp $ */ 2 3 /* 4 * Copyright (C) 1991-1994, 1997, 2006, 2008, 2012-2017 Free Software Foundation, Inc. 5 * Copyright (C) 2016-2017 Philip A. Nelson. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The names Philip A. Nelson and Free Software Foundation may not be 18 * used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY PHILIP A. NELSON ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL PHILIP A. NELSON OR THE FREE SOFTWARE FOUNDATION BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 * THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* storage.c: Code and data storage manipulations. This includes labels. */ 35 36 #include "bcdefs.h" 37 #include "proto.h" 38 39 /* Local prototypes */ 40 static bc_array_node *copy_tree (bc_array_node *ary_node, int depth); 41 static bc_array *copy_array (bc_array *ary); 42 43 44 /* Initialize the storage at the beginning of the run. */ 45 46 void 47 init_storage (void) 48 { 49 50 /* Functions: we start with none and ask for more. */ 51 f_count = 0; 52 more_functions (); 53 f_names[0] = strdup("(main)"); 54 55 /* Variables. */ 56 v_count = 0; 57 more_variables (); 58 59 /* Arrays. */ 60 a_count = 0; 61 more_arrays (); 62 63 /* Other things... */ 64 ex_stack = NULL; 65 fn_stack = NULL; 66 i_base = 10; 67 o_base = 10; 68 scale = 0; 69 #if defined(READLINE) || defined(LIBEDIT) 70 n_history = -1; 71 #endif 72 c_code = FALSE; 73 bc_init_numbers(); 74 } 75 76 /* Three functions for increasing the number of functions, variables, or 77 arrays that are needed. This adds another 32 of the requested object. */ 78 79 void 80 more_functions (void) 81 { 82 int old_count; 83 int indx; 84 bc_function *old_f; 85 bc_function *f; 86 char **old_names; 87 88 /* Save old information. */ 89 old_count = f_count; 90 old_f = functions; 91 old_names = f_names; 92 93 /* Add a fixed amount and allocate new space. */ 94 f_count += STORE_INCR; 95 functions = bc_malloc (f_count*sizeof (bc_function)); 96 f_names = bc_malloc (f_count*sizeof (char *)); 97 98 /* Copy old ones. */ 99 for (indx = 0; indx < old_count; indx++) 100 { 101 functions[indx] = old_f[indx]; 102 f_names[indx] = old_names[indx]; 103 } 104 105 /* Initialize the new ones. */ 106 for (; indx < f_count; indx++) 107 { 108 f = &functions[indx]; 109 f->f_defined = FALSE; 110 f->f_void = FALSE; 111 f->f_body = bc_malloc (BC_START_SIZE); 112 f->f_body_size = BC_START_SIZE; 113 f->f_code_size = 0; 114 f->f_label = NULL; 115 f->f_autos = NULL; 116 f->f_params = NULL; 117 } 118 119 /* Free the old elements. */ 120 if (old_count != 0) 121 { 122 free (old_f); 123 free (old_names); 124 } 125 } 126 127 void 128 more_variables (void) 129 { 130 int indx; 131 int old_count; 132 bc_var **old_var; 133 char **old_names; 134 135 /* Save the old values. */ 136 old_count = v_count; 137 old_var = variables; 138 old_names = v_names; 139 140 /* Increment by a fixed amount and allocate. */ 141 v_count += STORE_INCR; 142 variables = bc_malloc (v_count*sizeof(bc_var *)); 143 v_names = bc_malloc (v_count*sizeof(char *)); 144 145 /* Copy the old variables. */ 146 for (indx = 3; indx < old_count; indx++) 147 { 148 variables[indx] = old_var[indx]; 149 v_names[indx] = old_names[indx]; 150 } 151 152 /* Initialize the new elements. */ 153 for (; indx < v_count; indx++) 154 variables[indx] = NULL; 155 156 /* Free the old elements. */ 157 if (old_count != 0) 158 { 159 free (old_var); 160 free (old_names); 161 } 162 } 163 164 void 165 more_arrays (void) 166 { 167 int indx; 168 int old_count; 169 bc_var_array **old_ary; 170 char **old_names; 171 172 /* Save the old values. */ 173 old_count = a_count; 174 old_ary = arrays; 175 old_names = a_names; 176 177 /* Increment by a fixed amount and allocate. */ 178 a_count += STORE_INCR; 179 arrays = bc_malloc (a_count*sizeof(bc_var_array *)); 180 a_names = bc_malloc (a_count*sizeof(char *)); 181 182 /* Copy the old arrays. */ 183 for (indx = 1; indx < old_count; indx++) 184 { 185 arrays[indx] = old_ary[indx]; 186 a_names[indx] = old_names[indx]; 187 } 188 189 190 /* Initialize the new elements. */ 191 for (; indx < a_count; indx++) 192 arrays[indx] = NULL; 193 194 /* Free the old elements. */ 195 if (old_count != 0) 196 { 197 free (old_ary); 198 free (old_names); 199 } 200 } 201 202 203 /* clear_func clears out function FUNC and makes it ready to redefine. */ 204 205 void 206 clear_func (int func) 207 { 208 bc_function *f; 209 bc_label_group *lg; 210 211 /* Set the pointer to the function. */ 212 f = &functions[func]; 213 f->f_defined = FALSE; 214 /* XXX restore f_body to initial size??? */ 215 f->f_code_size = 0; 216 if (f->f_autos != NULL) 217 { 218 free_args (f->f_autos); 219 f->f_autos = NULL; 220 } 221 if (f->f_params != NULL) 222 { 223 free_args (f->f_params); 224 f->f_params = NULL; 225 } 226 while (f->f_label != NULL) 227 { 228 lg = f->f_label->l_next; 229 free (f->f_label); 230 f->f_label = lg; 231 } 232 } 233 234 235 /* Pop the function execution stack and return the top. */ 236 237 int 238 fpop(void) 239 { 240 fstack_rec *temp; 241 int retval; 242 243 if (fn_stack != NULL) 244 { 245 temp = fn_stack; 246 fn_stack = temp->s_next; 247 retval = temp->s_val; 248 free (temp); 249 } 250 else 251 { 252 retval = 0; 253 rt_error ("function stack underflow, contact maintainer."); 254 } 255 return (retval); 256 } 257 258 259 /* Push VAL on to the function stack. */ 260 261 void 262 fpush (int val) 263 { 264 fstack_rec *temp; 265 266 temp = bc_malloc (sizeof (fstack_rec)); 267 temp->s_next = fn_stack; 268 temp->s_val = val; 269 fn_stack = temp; 270 } 271 272 273 /* Pop and discard the top element of the regular execution stack. */ 274 275 void 276 pop (void) 277 { 278 estack_rec *temp; 279 280 if (ex_stack != NULL) 281 { 282 temp = ex_stack; 283 ex_stack = temp->s_next; 284 bc_free_num (&temp->s_num); 285 free (temp); 286 } 287 } 288 289 290 /* Push a copy of NUM on to the regular execution stack. */ 291 292 void 293 push_copy (bc_num num) 294 { 295 estack_rec *temp; 296 297 temp = bc_malloc (sizeof (estack_rec)); 298 temp->s_num = bc_copy_num (num); 299 temp->s_next = ex_stack; 300 ex_stack = temp; 301 } 302 303 304 /* Push NUM on to the regular execution stack. Do NOT push a copy. */ 305 306 void 307 push_num (bc_num num) 308 { 309 estack_rec *temp; 310 311 temp = bc_malloc (sizeof (estack_rec)); 312 temp->s_num = num; 313 temp->s_next = ex_stack; 314 ex_stack = temp; 315 } 316 317 318 /* Make sure the ex_stack has at least DEPTH elements on it. 319 Return TRUE if it has at least DEPTH elements, otherwise 320 return FALSE. */ 321 322 char 323 check_stack (int depth) 324 { 325 estack_rec *temp; 326 327 temp = ex_stack; 328 while ((temp != NULL) && (depth > 0)) 329 { 330 temp = temp->s_next; 331 depth--; 332 } 333 if (depth > 0) 334 { 335 rt_error ("Stack error."); 336 return FALSE; 337 } 338 return TRUE; 339 } 340 341 342 /* The following routines manipulate simple variables and 343 array variables. */ 344 345 /* get_var returns a pointer to the variable VAR_NAME. If one does not 346 exist, one is created. */ 347 348 bc_var * 349 get_var (int var_name) 350 { 351 bc_var *var_ptr; 352 353 var_ptr = variables[var_name]; 354 if (var_ptr == NULL) 355 { 356 var_ptr = variables[var_name] = bc_malloc (sizeof (bc_var)); 357 bc_init_num (&var_ptr->v_value); 358 } 359 return var_ptr; 360 } 361 362 363 /* get_array_num returns the address of the bc_num in the array 364 structure. If more structure is requried to get to the index, 365 this routine does the work to create that structure. VAR_INDEX 366 is a zero based index into the arrays storage array. INDEX is 367 the index into the bc array. */ 368 369 bc_num * 370 get_array_num (int var_index, unsigned long idx) 371 { 372 bc_var_array *ary_ptr; 373 bc_array *a_var; 374 bc_array_node *temp; 375 int log; 376 unsigned int ix, ix1; 377 int sub [NODE_DEPTH]; 378 379 /* Get the array entry. */ 380 ary_ptr = arrays[var_index]; 381 if (ary_ptr == NULL) 382 { 383 ary_ptr = arrays[var_index] = bc_malloc (sizeof (bc_var_array)); 384 ary_ptr->a_value = NULL; 385 ary_ptr->a_next = NULL; 386 ary_ptr->a_param = FALSE; 387 } 388 389 a_var = ary_ptr->a_value; 390 if (a_var == NULL) { 391 a_var = ary_ptr->a_value = bc_malloc (sizeof (bc_array)); 392 a_var->a_tree = NULL; 393 a_var->a_depth = 0; 394 } 395 396 /* Get the index variable. */ 397 sub[0] = idx & NODE_MASK; 398 ix = idx >> NODE_SHIFT; 399 log = 1; 400 while (ix > 0 || log < a_var->a_depth) 401 { 402 sub[log] = ix & NODE_MASK; 403 ix >>= NODE_SHIFT; 404 log++; 405 } 406 407 /* Build any tree that is necessary. */ 408 while (log > a_var->a_depth) 409 { 410 temp = bc_malloc (sizeof(bc_array_node)); 411 if (a_var->a_depth != 0) 412 { 413 temp->n_items.n_down[0] = a_var->a_tree; 414 for (ix=1; ix < NODE_SIZE; ix++) 415 temp->n_items.n_down[ix] = NULL; 416 } 417 else 418 { 419 for (ix=0; ix < NODE_SIZE; ix++) 420 temp->n_items.n_num[ix] = bc_copy_num(_zero_); 421 } 422 a_var->a_tree = temp; 423 a_var->a_depth++; 424 } 425 426 /* Find the indexed variable. */ 427 temp = a_var->a_tree; 428 while ( log-- > 1) 429 { 430 ix1 = sub[log]; 431 if (temp->n_items.n_down[ix1] == NULL) 432 { 433 temp->n_items.n_down[ix1] = bc_malloc (sizeof(bc_array_node)); 434 temp = temp->n_items.n_down[ix1]; 435 if (log > 1) 436 for (ix=0; ix < NODE_SIZE; ix++) 437 temp->n_items.n_down[ix] = NULL; 438 else 439 for (ix=0; ix < NODE_SIZE; ix++) 440 temp->n_items.n_num[ix] = bc_copy_num(_zero_); 441 } 442 else 443 temp = temp->n_items.n_down[ix1]; 444 } 445 446 /* Return the address of the indexed variable. */ 447 return &(temp->n_items.n_num[sub[0]]); 448 } 449 450 451 /* Store the top of the execution stack into VAR_NAME. 452 This includes the special variables ibase, obase, and scale. */ 453 454 void 455 store_var (int var_name) 456 { 457 bc_var *var_ptr; 458 long temp; 459 char toobig; 460 461 if (var_name > 3) 462 { 463 /* It is a simple variable. */ 464 var_ptr = get_var (var_name); 465 if (var_ptr != NULL) 466 { 467 bc_free_num(&var_ptr->v_value); 468 var_ptr->v_value = bc_copy_num (ex_stack->s_num); 469 } 470 } 471 else 472 { 473 /* It is a special variable... */ 474 toobig = FALSE; 475 temp = 0; 476 if (bc_is_neg (ex_stack->s_num)) 477 { 478 switch (var_name) 479 { 480 case 0: 481 rt_warn ("negative ibase, set to 2"); 482 temp = 2; 483 break; 484 case 1: 485 rt_warn ("negative obase, set to 2"); 486 temp = 2; 487 break; 488 case 2: 489 rt_warn ("negative scale, set to 0"); 490 temp = 0; 491 break; 492 #if defined(READLINE) || defined(LIBEDIT) 493 case 3: 494 temp = -1; 495 break; 496 #endif 497 } 498 } 499 else 500 { 501 temp = bc_num2long (ex_stack->s_num); 502 if (!bc_is_zero (ex_stack->s_num) && temp == 0) 503 toobig = TRUE; 504 } 505 switch (var_name) 506 { 507 case 0: 508 if (temp < 2 && !toobig) 509 { 510 i_base = 2; 511 rt_warn ("ibase too small, set to 2"); 512 } 513 else 514 if (temp > 16 || toobig) 515 { 516 if (std_only) 517 { 518 i_base = 16; 519 rt_warn ("ibase too large, set to 16"); 520 } 521 else if (temp > 36 || toobig) 522 { 523 i_base = 36; 524 rt_warn ("ibase too large, set to 36"); 525 } 526 else 527 { 528 if (temp >= 16 && warn_not_std) 529 rt_warn ("ibase larger than 16 is non-standard"); 530 i_base = temp; 531 } 532 } 533 else 534 i_base = (int) temp; 535 break; 536 537 case 1: 538 if (temp < 2 && !toobig) 539 { 540 o_base = 2; 541 rt_warn ("obase too small, set to 2"); 542 } 543 else 544 if (temp > BC_BASE_MAX || toobig) 545 { 546 o_base = BC_BASE_MAX; 547 rt_warn ("obase too large, set to %d", BC_BASE_MAX); 548 } 549 else 550 o_base = (int) temp; 551 break; 552 553 case 2: 554 /* WARNING: The following if statement may generate a compiler 555 warning if INT_MAX == LONG_MAX. This is NOT a problem. */ 556 if (temp > BC_SCALE_MAX || toobig ) 557 { 558 scale = BC_SCALE_MAX; 559 rt_warn ("scale too large, set to %d", BC_SCALE_MAX); 560 } 561 else 562 scale = (int) temp; 563 break; 564 565 #if defined(READLINE) || defined(LIBEDIT) 566 case 3: 567 if (toobig) 568 { 569 temp = -1; 570 rt_warn ("history too large, set to unlimited"); 571 UNLIMIT_HISTORY; 572 } 573 else 574 { 575 n_history = temp; 576 if (temp < 0) 577 UNLIMIT_HISTORY; 578 else 579 HISTORY_SIZE(n_history); 580 } 581 #endif 582 } 583 } 584 } 585 586 587 /* Store the top of the execution stack into array VAR_NAME. 588 VAR_NAME is the name of an array, and the next to the top 589 of stack for the index into the array. */ 590 591 void 592 store_array (int var_name) 593 { 594 bc_num *num_ptr; 595 long idx; 596 597 if (!check_stack(2)) return; 598 idx = bc_num2long (ex_stack->s_next->s_num); 599 if (idx < 0 || idx > BC_DIM_MAX || 600 (idx == 0 && !bc_is_zero(ex_stack->s_next->s_num))) 601 rt_error ("Array %s subscript out of bounds.", a_names[var_name]); 602 else 603 { 604 num_ptr = get_array_num (var_name, idx); 605 if (num_ptr != NULL) 606 { 607 bc_free_num (num_ptr); 608 *num_ptr = bc_copy_num (ex_stack->s_num); 609 bc_free_num (&ex_stack->s_next->s_num); 610 ex_stack->s_next->s_num = ex_stack->s_num; 611 bc_init_num (&ex_stack->s_num); 612 pop(); 613 } 614 } 615 } 616 617 618 /* Load a copy of VAR_NAME on to the execution stack. This includes 619 the special variables ibase, obase and scale. */ 620 621 void 622 load_var (int var_name) 623 { 624 bc_var *var_ptr; 625 626 switch (var_name) 627 { 628 629 case 0: 630 /* Special variable ibase. */ 631 push_copy (_zero_); 632 bc_int2num (&ex_stack->s_num, i_base); 633 break; 634 635 case 1: 636 /* Special variable obase. */ 637 push_copy (_zero_); 638 bc_int2num (&ex_stack->s_num, o_base); 639 break; 640 641 case 2: 642 /* Special variable scale. */ 643 push_copy (_zero_); 644 bc_int2num (&ex_stack->s_num, scale); 645 break; 646 647 #if defined(READLINE) || defined(LIBEDIT) 648 case 3: 649 /* Special variable history. */ 650 push_copy (_zero_); 651 bc_int2num (&ex_stack->s_num, n_history); 652 break; 653 #endif 654 655 default: 656 /* It is a simple variable. */ 657 var_ptr = variables[var_name]; 658 if (var_ptr != NULL) 659 push_copy (var_ptr->v_value); 660 else 661 push_copy (_zero_); 662 } 663 } 664 665 666 /* Load a copy of VAR_NAME on to the execution stack. This includes 667 the special variables ibase, obase and scale. */ 668 669 void 670 load_array (int var_name) 671 { 672 bc_num *num_ptr; 673 long idx; 674 675 if (!check_stack(1)) return; 676 idx = bc_num2long (ex_stack->s_num); 677 if (idx < 0 || idx > BC_DIM_MAX || 678 (idx == 0 && !bc_is_zero(ex_stack->s_num))) 679 rt_error ("Array %s subscript out of bounds.", a_names[var_name]); 680 else 681 { 682 num_ptr = get_array_num (var_name, idx); 683 if (num_ptr != NULL) 684 { 685 pop(); 686 push_copy (*num_ptr); 687 } 688 } 689 } 690 691 692 /* Decrement VAR_NAME by one. This includes the special variables 693 ibase, obase, and scale. */ 694 695 void 696 decr_var (int var_name) 697 { 698 bc_var *var_ptr; 699 700 switch (var_name) 701 { 702 703 case 0: /* ibase */ 704 if (i_base > 2) 705 i_base--; 706 else 707 rt_warn ("ibase too small in --"); 708 break; 709 710 case 1: /* obase */ 711 if (o_base > 2) 712 o_base--; 713 else 714 rt_warn ("obase too small in --"); 715 break; 716 717 case 2: /* scale */ 718 if (scale > 0) 719 scale--; 720 else 721 rt_warn ("scale can not be negative in -- "); 722 break; 723 724 #if defined(READLINE) || defined(LIBEDIT) 725 case 3: /* history */ 726 n_history--; 727 if (n_history >= 0) 728 HISTORY_SIZE(n_history); 729 else 730 { 731 n_history = -1; 732 rt_warn ("history is negative, set to unlimited"); 733 UNLIMIT_HISTORY; 734 } 735 break; 736 #endif 737 738 default: /* It is a simple variable. */ 739 var_ptr = get_var (var_name); 740 if (var_ptr != NULL) 741 bc_sub (var_ptr->v_value,_one_,&var_ptr->v_value, 0); 742 } 743 } 744 745 746 /* Decrement VAR_NAME by one. VAR_NAME is an array, and the top of 747 the execution stack is the index and it is popped off the stack. */ 748 749 void 750 decr_array (int var_name) 751 { 752 bc_num *num_ptr; 753 long idx; 754 755 /* It is an array variable. */ 756 if (!check_stack (1)) return; 757 idx = bc_num2long (ex_stack->s_num); 758 if (idx < 0 || idx > BC_DIM_MAX || 759 (idx == 0 && !bc_is_zero (ex_stack->s_num))) 760 rt_error ("Array %s subscript out of bounds.", a_names[var_name]); 761 else 762 { 763 num_ptr = get_array_num (var_name, idx); 764 if (num_ptr != NULL) 765 { 766 pop (); 767 bc_sub (*num_ptr, _one_, num_ptr, 0); 768 } 769 } 770 } 771 772 773 /* Increment VAR_NAME by one. This includes the special variables 774 ibase, obase, and scale. */ 775 776 void 777 incr_var (int var_name) 778 { 779 bc_var *var_ptr; 780 781 switch (var_name) 782 { 783 784 case 0: /* ibase */ 785 if (i_base < 16) 786 i_base++; 787 else 788 rt_warn ("ibase too big in ++"); 789 break; 790 791 case 1: /* obase */ 792 if (o_base < BC_BASE_MAX) 793 o_base++; 794 else 795 rt_warn ("obase too big in ++"); 796 break; 797 798 case 2: 799 if (scale < BC_SCALE_MAX) 800 scale++; 801 else 802 rt_warn ("Scale too big in ++"); 803 break; 804 805 #if defined(READLINE) || defined(LIBEDIT) 806 case 3: /* history */ 807 n_history++; 808 if (n_history > 0) 809 HISTORY_SIZE(n_history); 810 else 811 { 812 n_history = -1; 813 rt_warn ("history set to unlimited"); 814 UNLIMIT_HISTORY; 815 } 816 break; 817 #endif 818 819 default: /* It is a simple variable. */ 820 var_ptr = get_var (var_name); 821 if (var_ptr != NULL) 822 bc_add (var_ptr->v_value, _one_, &var_ptr->v_value, 0); 823 824 } 825 } 826 827 828 /* Increment VAR_NAME by one. VAR_NAME is an array and top of 829 execution stack is the index and is popped off the stack. */ 830 831 void 832 incr_array (int var_name) 833 { 834 bc_num *num_ptr; 835 long idx; 836 837 if (!check_stack (1)) return; 838 idx = bc_num2long (ex_stack->s_num); 839 if (idx < 0 || idx > BC_DIM_MAX || 840 (idx == 0 && !bc_is_zero (ex_stack->s_num))) 841 rt_error ("Array %s subscript out of bounds.", a_names[var_name]); 842 else 843 { 844 num_ptr = get_array_num (var_name, idx); 845 if (num_ptr != NULL) 846 { 847 pop (); 848 bc_add (*num_ptr, _one_, num_ptr, 0); 849 } 850 } 851 } 852 853 854 /* Routines for processing autos variables and parameters. */ 855 856 /* NAME is an auto variable that needs to be pushed on its stack. */ 857 858 void 859 auto_var (int name) 860 { 861 bc_var *v_temp; 862 bc_var_array *a_temp; 863 int ix; 864 865 if (name > 0) 866 { 867 /* A simple variable. */ 868 ix = name; 869 v_temp = bc_malloc (sizeof (bc_var)); 870 v_temp->v_next = variables[ix]; 871 bc_init_num (&v_temp->v_value); 872 variables[ix] = v_temp; 873 } 874 else 875 { 876 /* An array variable. */ 877 ix = -name; 878 a_temp = bc_malloc (sizeof (bc_var_array)); 879 a_temp->a_next = arrays[ix]; 880 a_temp->a_value = NULL; 881 a_temp->a_param = FALSE; 882 arrays[ix] = a_temp; 883 } 884 } 885 886 887 /* Free_a_tree frees everything associated with an array variable tree. 888 This is used when popping an array variable off its auto stack. */ 889 890 void 891 free_a_tree (bc_array_node *root, int depth) 892 { 893 int ix; 894 895 if (root != NULL) 896 { 897 if (depth > 1) 898 for (ix = 0; ix < NODE_SIZE; ix++) 899 free_a_tree (root->n_items.n_down[ix], depth-1); 900 else 901 for (ix = 0; ix < NODE_SIZE; ix++) 902 bc_free_num ( &(root->n_items.n_num[ix])); 903 free (root); 904 } 905 } 906 907 908 /* LIST is an NULL terminated list of varible names that need to be 909 popped off their auto stacks. */ 910 911 void 912 pop_vars (arg_list *list) 913 { 914 bc_var *v_temp; 915 bc_var_array *a_temp; 916 int ix; 917 918 while (list != NULL) 919 { 920 ix = list->av_name; 921 if (ix > 0) 922 { 923 /* A simple variable. */ 924 v_temp = variables[ix]; 925 if (v_temp != NULL) 926 { 927 variables[ix] = v_temp->v_next; 928 bc_free_num (&v_temp->v_value); 929 free (v_temp); 930 } 931 } 932 else 933 { 934 /* An array variable. */ 935 ix = -ix; 936 a_temp = arrays[ix]; 937 if (a_temp != NULL) 938 { 939 arrays[ix] = a_temp->a_next; 940 if (!a_temp->a_param && a_temp->a_value != NULL) 941 { 942 free_a_tree (a_temp->a_value->a_tree, 943 a_temp->a_value->a_depth); 944 free (a_temp->a_value); 945 } 946 free (a_temp); 947 } 948 } 949 list = list->next; 950 } 951 } 952 953 /* COPY_NODE: Copies an array node for a call by value parameter. */ 954 static bc_array_node * 955 copy_tree (bc_array_node *ary_node, int depth) 956 { 957 bc_array_node *res = bc_malloc (sizeof(bc_array_node)); 958 int i; 959 960 if (depth > 1) 961 for (i=0; i<NODE_SIZE; i++) 962 if (ary_node->n_items.n_down[i] != NULL) 963 res->n_items.n_down[i] = 964 copy_tree (ary_node->n_items.n_down[i], depth - 1); 965 else 966 res->n_items.n_down[i] = NULL; 967 else 968 for (i=0; i<NODE_SIZE; i++) 969 if (ary_node->n_items.n_num[i] != NULL) 970 res->n_items.n_num[i] = bc_copy_num (ary_node->n_items.n_num[i]); 971 else 972 res->n_items.n_num[i] = NULL; 973 return res; 974 } 975 976 /* COPY_ARRAY: Copies an array for a call by value array parameter. 977 ARY is the pointer to the bc_array structure. */ 978 979 static bc_array * 980 copy_array (bc_array *ary) 981 { 982 bc_array *res = bc_malloc (sizeof(bc_array)); 983 res->a_depth = ary->a_depth; 984 res->a_tree = copy_tree (ary->a_tree, ary->a_depth); 985 return (res); 986 } 987 988 989 /* A call is being made to FUNC. The call types are at PC. Process 990 the parameters by doing an auto on the parameter variable and then 991 store the value at the new variable or put a pointer the the array 992 variable. */ 993 994 void 995 process_params (program_counter *progctr, int func) 996 { 997 char ch; 998 arg_list *params; 999 int ix, ix1; 1000 bc_var *v_temp; 1001 bc_var_array *a_src, *a_dest; 1002 1003 /* Get the parameter names from the function. */ 1004 params = functions[func].f_params; 1005 1006 while ((ch = byte(progctr)) != ':') 1007 { 1008 if (params != NULL) 1009 { 1010 if ((ch == '0') && params->av_name > 0) 1011 { 1012 /* A simple variable. */ 1013 ix = params->av_name; 1014 v_temp = bc_malloc (sizeof(bc_var)); 1015 v_temp->v_next = variables[ix]; 1016 v_temp->v_value = ex_stack->s_num; 1017 bc_init_num (&ex_stack->s_num); 1018 variables[ix] = v_temp; 1019 } 1020 else 1021 if ((ch == '1') && (params->av_name < 0)) 1022 { 1023 /* The variables is an array variable. */ 1024 1025 /* Compute source index and make sure some structure exists. */ 1026 ix = (int) bc_num2long (ex_stack->s_num); 1027 (void) get_array_num (ix, 0); 1028 1029 /* Push a new array and Compute Destination index */ 1030 auto_var (params->av_name); 1031 ix1 = -params->av_name; 1032 1033 /* Set up the correct pointers in the structure. */ 1034 if (ix == ix1) 1035 a_src = arrays[ix]->a_next; 1036 else 1037 a_src = arrays[ix]; 1038 a_dest = arrays[ix1]; 1039 if (params->arg_is_var) 1040 { 1041 a_dest->a_param = TRUE; 1042 a_dest->a_value = a_src->a_value; 1043 } 1044 else 1045 { 1046 a_dest->a_param = FALSE; 1047 a_dest->a_value = copy_array (a_src->a_value); 1048 } 1049 } 1050 else 1051 { 1052 if (params->av_name < 0) 1053 rt_error ("Parameter type mismatch parameter %s.", 1054 a_names[-params->av_name]); 1055 else 1056 rt_error ("Parameter type mismatch, parameter %s.", 1057 v_names[params->av_name]); 1058 params++; 1059 } 1060 pop (); 1061 } 1062 else 1063 { 1064 rt_error ("Parameter number mismatch"); 1065 return; 1066 } 1067 params = params->next; 1068 } 1069 if (params != NULL) 1070 rt_error ("Parameter number mismatch"); 1071 } 1072