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