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