5762556 [rkeene@sledge /home/rkeene/devel/old/bc-dos/bc]$ cat -n storage.c
   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 }
5762557 [rkeene@sledge /home/rkeene/devel/old/bc-dos/bc]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 1997-04-10 21:37:32