· 9 years ago · Sep 16, 2016, 04:32 PM
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 /*
176 * Bug occurs at line 195.
177 *
178 * Bug is triggered when v_count is less than a_count.
179 *
180 * Basically, it's a typo and the loop invariant is supposed to be
181 * indx < a_count. a_count refers to number of arrays and v_count refers to
182 * number of variables. The bug happens when there are already many variables,
183 * and then some arrays are being initialised. When bc allocates space for the
184 * array, it calls more_arrays and then the out-of-bound access happens since
185 * v_count is now greater than a_count and hence greater than the allocated
186 * size of arrays.
187 *
188 * In order to reproduce the bug, you'd probably need to initialise 64
189 * variables and then 32 arrays. This is because the default a_count and
190 * v_count is 32.
191 */
192
193 /* Initialize the new elements. */
194 for (; indx < v_count; indx++)
195 arrays[indx] = NULL;
196
197 /* Free the old elements. */
198 if (old_count != 0)
199 {
200 free (old_ary);
201 free (old_names);
202 }
203}
204
205
206/* clear_func clears out function FUNC and makes it ready to redefine. */
207
208void
209clear_func (func)
210 int func;
211{
212 bc_function *f;
213 bc_label_group *lg;
214
215 /* Set the pointer to the function. */
216 f = &functions[func];
217 f->f_defined = FALSE;
218 /* XXX restore f_body to initial size??? */
219 f->f_code_size = 0;
220 if (f->f_autos != NULL)
221 {
222 free_args (f->f_autos);
223 f->f_autos = NULL;
224 }
225 if (f->f_params != NULL)
226 {
227 free_args (f->f_params);
228 f->f_params = NULL;
229 }
230 while (f->f_label != NULL)
231 {
232 lg = f->f_label->l_next;
233 free (f->f_label);
234 f->f_label = lg;
235 }
236}
237
238
239/* Pop the function execution stack and return the top. */
240
241int
242fpop()
243{
244 fstack_rec *temp;
245 int retval;
246
247 if (fn_stack != NULL)
248 {
249 temp = fn_stack;
250 fn_stack = temp->s_next;
251 retval = temp->s_val;
252 free (temp);
253 }
254 else
255 {
256 retval = 0;
257 rt_error ("function stack underflow, contact maintainer.");
258 }
259 return (retval);
260}
261
262
263/* Push VAL on to the function stack. */
264
265void
266fpush (val)
267 int val;
268{
269 fstack_rec *temp;
270
271 temp = (fstack_rec *) bc_malloc (sizeof (fstack_rec));
272 temp->s_next = fn_stack;
273 temp->s_val = val;
274 fn_stack = temp;
275}
276
277
278/* Pop and discard the top element of the regular execution stack. */
279
280void
281pop ()
282{
283 estack_rec *temp;
284
285 if (ex_stack != NULL)
286 {
287 temp = ex_stack;
288 ex_stack = temp->s_next;
289 bc_free_num (&temp->s_num);
290 free (temp);
291 }
292}
293
294
295/* Push a copy of NUM on to the regular execution stack. */
296
297void
298push_copy (num)
299 bc_num num;
300{
301 estack_rec *temp;
302
303 temp = (estack_rec *) bc_malloc (sizeof (estack_rec));
304 temp->s_num = bc_copy_num (num);
305 temp->s_next = ex_stack;
306 ex_stack = temp;
307}
308
309
310/* Push NUM on to the regular execution stack. Do NOT push a copy. */
311
312void
313push_num (num)
314 bc_num num;
315{
316 estack_rec *temp;
317
318 temp = (estack_rec *) bc_malloc (sizeof (estack_rec));
319 temp->s_num = num;
320 temp->s_next = ex_stack;
321 ex_stack = temp;
322}
323
324
325/* Make sure the ex_stack has at least DEPTH elements on it.
326 Return TRUE if it has at least DEPTH elements, otherwise
327 return FALSE. */
328
329char
330check_stack (depth)
331 int depth;
332{
333 estack_rec *temp;
334
335 temp = ex_stack;
336 while ((temp != NULL) && (depth > 0))
337 {
338 temp = temp->s_next;
339 depth--;
340 }
341 if (depth > 0)
342 {
343 rt_error ("Stack error.");
344 return FALSE;
345 }
346 return TRUE;
347}
348
349
350/* The following routines manipulate simple variables and
351 array variables. */
352
353/* get_var returns a pointer to the variable VAR_NAME. If one does not
354 exist, one is created. */
355
356bc_var *
357get_var (var_name)
358 int var_name;
359{
360 bc_var *var_ptr;
361
362 var_ptr = variables[var_name];
363 if (var_ptr == NULL)
364 {
365 var_ptr = variables[var_name] = (bc_var *) bc_malloc (sizeof (bc_var));
366 bc_init_num (&var_ptr->v_value);
367 }
368 return var_ptr;
369}
370
371
372/* get_array_num returns the address of the bc_num in the array
373 structure. If more structure is requried to get to the index,
374 this routine does the work to create that structure. VAR_INDEX
375 is a zero based index into the arrays storage array. INDEX is
376 the index into the bc array. */
377
378bc_num *
379get_array_num (var_index, index)
380 int var_index;
381 long index;
382{
383 bc_var_array *ary_ptr;
384 bc_array *a_var;
385 bc_array_node *temp;
386 int log, ix, ix1;
387 int sub [NODE_DEPTH];
388
389 /* Get the array entry. */
390 ary_ptr = arrays[var_index];
391 if (ary_ptr == NULL)
392 {
393 ary_ptr = arrays[var_index] =
394 (bc_var_array *) bc_malloc (sizeof (bc_var_array));
395 ary_ptr->a_value = NULL;
396 ary_ptr->a_next = NULL;
397 ary_ptr->a_param = FALSE;
398 }
399
400 a_var = ary_ptr->a_value;
401 if (a_var == NULL) {
402 a_var = ary_ptr->a_value = (bc_array *) bc_malloc (sizeof (bc_array));
403 a_var->a_tree = NULL;
404 a_var->a_depth = 0;
405 }
406
407 /* Get the index variable. */
408 sub[0] = index & NODE_MASK;
409 ix = index >> NODE_SHIFT;
410 log = 1;
411 while (ix > 0 || log < a_var->a_depth)
412 {
413 sub[log] = ix & NODE_MASK;
414 ix >>= NODE_SHIFT;
415 log++;
416 }
417
418 /* Build any tree that is necessary. */
419 while (log > a_var->a_depth)
420 {
421 temp = (bc_array_node *) bc_malloc (sizeof(bc_array_node));
422 if (a_var->a_depth != 0)
423 {
424 temp->n_items.n_down[0] = a_var->a_tree;
425 for (ix=1; ix < NODE_SIZE; ix++)
426 temp->n_items.n_down[ix] = NULL;
427 }
428 else
429 {
430 for (ix=0; ix < NODE_SIZE; ix++)
431 temp->n_items.n_num[ix] = bc_copy_num(_zero_);
432 }
433 a_var->a_tree = temp;
434 a_var->a_depth++;
435 }
436
437 /* Find the indexed variable. */
438 temp = a_var->a_tree;
439 while ( log-- > 1)
440 {
441 ix1 = sub[log];
442 if (temp->n_items.n_down[ix1] == NULL)
443 {
444 temp->n_items.n_down[ix1] =
445 (bc_array_node *) bc_malloc (sizeof(bc_array_node));
446 temp = temp->n_items.n_down[ix1];
447 if (log > 1)
448 for (ix=0; ix < NODE_SIZE; ix++)
449 temp->n_items.n_down[ix] = NULL;
450 else
451 for (ix=0; ix < NODE_SIZE; ix++)
452 temp->n_items.n_num[ix] = bc_copy_num(_zero_);
453 }
454 else
455 temp = temp->n_items.n_down[ix1];
456 }
457
458 /* Return the address of the indexed variable. */
459 return &(temp->n_items.n_num[sub[0]]);
460}
461
462
463/* Store the top of the execution stack into VAR_NAME.
464 This includes the special variables ibase, obase, and scale. */
465
466void
467store_var (var_name)
468 int var_name;
469{
470 bc_var *var_ptr;
471 long temp;
472 char toobig;
473
474 if (var_name > 3)
475 {
476 /* It is a simple variable. */
477 var_ptr = get_var (var_name);
478 if (var_ptr != NULL)
479 {
480 bc_free_num(&var_ptr->v_value);
481 var_ptr->v_value = bc_copy_num (ex_stack->s_num);
482 }
483 }
484 else
485 {
486 /* It is a special variable... */
487 toobig = FALSE;
488 temp = 0;
489 if (bc_is_neg (ex_stack->s_num))
490 {
491 switch (var_name)
492 {
493 case 0:
494 rt_warn ("negative ibase, set to 2");
495 temp = 2;
496 break;
497 case 1:
498 rt_warn ("negative obase, set to 2");
499 temp = 2;
500 break;
501 case 2:
502 rt_warn ("negative scale, set to 0");
503 temp = 0;
504 break;
505#if defined(READLINE) || defined(LIBEDIT)
506 case 3:
507 temp = -1;
508 break;
509#endif
510 }
511 }
512 else
513 {
514 temp = bc_num2long (ex_stack->s_num);
515 if (!bc_is_zero (ex_stack->s_num) && temp == 0)
516 toobig = TRUE;
517 }
518 switch (var_name)
519 {
520 case 0:
521 if (temp < 2 && !toobig)
522 {
523 i_base = 2;
524 rt_warn ("ibase too small, set to 2");
525 }
526 else
527 if (temp > 16 || toobig)
528 {
529 i_base = 16;
530 rt_warn ("ibase too large, set to 16");
531 }
532 else
533 i_base = (int) temp;
534 break;
535
536 case 1:
537 if (temp < 2 && !toobig)
538 {
539 o_base = 2;
540 rt_warn ("obase too small, set to 2");
541 }
542 else
543 if (temp > BC_BASE_MAX || toobig)
544 {
545 o_base = BC_BASE_MAX;
546 rt_warn ("obase too large, set to %d", BC_BASE_MAX);
547 }
548 else
549 o_base = (int) temp;
550 break;
551
552 case 2:
553 /* WARNING: The following if statement may generate a compiler
554 warning if INT_MAX == LONG_MAX. This is NOT a problem. */
555 if (temp > BC_SCALE_MAX || toobig )
556 {
557 scale = BC_SCALE_MAX;
558 rt_warn ("scale too large, set to %d", BC_SCALE_MAX);
559 }
560 else
561 scale = (int) temp;
562 break;
563
564#if defined(READLINE) || defined(LIBEDIT)
565 case 3:
566 if (toobig)
567 {
568 temp = -1;
569 rt_warn ("history too large, set to unlimited");
570 UNLIMIT_HISTORY;
571 }
572 else
573 {
574 n_history = temp;
575 if (temp < 0)
576 UNLIMIT_HISTORY;
577 else
578 HISTORY_SIZE(n_history);
579 }
580#endif
581 }
582 }
583}
584
585
586/* Store the top of the execution stack into array VAR_NAME.
587 VAR_NAME is the name of an array, and the next to the top
588 of stack for the index into the array. */
589
590void
591store_array (var_name)
592 int var_name;
593{
594 bc_num *num_ptr;
595 long index;
596
597 if (!check_stack(2)) return;
598 index = bc_num2long (ex_stack->s_next->s_num);
599 if (index < 0 || index > BC_DIM_MAX ||
600 (index == 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, index);
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
621void
622load_var (var_name)
623 int var_name;
624{
625 bc_var *var_ptr;
626
627 switch (var_name)
628 {
629
630 case 0:
631 /* Special variable ibase. */
632 push_copy (_zero_);
633 bc_int2num (&ex_stack->s_num, i_base);
634 break;
635
636 case 1:
637 /* Special variable obase. */
638 push_copy (_zero_);
639 bc_int2num (&ex_stack->s_num, o_base);
640 break;
641
642 case 2:
643 /* Special variable scale. */
644 push_copy (_zero_);
645 bc_int2num (&ex_stack->s_num, scale);
646 break;
647
648#if defined(READLINE) || defined(LIBEDIT)
649 case 3:
650 /* Special variable history. */
651 push_copy (_zero_);
652 bc_int2num (&ex_stack->s_num, n_history);
653 break;
654#endif
655
656 default:
657 /* It is a simple variable. */
658 var_ptr = variables[var_name];
659 if (var_ptr != NULL)
660 push_copy (var_ptr->v_value);
661 else
662 push_copy (_zero_);
663 }
664}
665
666
667/* Load a copy of VAR_NAME on to the execution stack. This includes
668 the special variables ibase, obase and scale. */
669
670void
671load_array (var_name)
672 int var_name;
673{
674 bc_num *num_ptr;
675 long index;
676
677 if (!check_stack(1)) return;
678 index = bc_num2long (ex_stack->s_num);
679 if (index < 0 || index > BC_DIM_MAX ||
680 (index == 0 && !bc_is_zero(ex_stack->s_num)))
681 rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
682 else
683 {
684 num_ptr = get_array_num (var_name, index);
685 if (num_ptr != NULL)
686 {
687 pop();
688 push_copy (*num_ptr);
689 }
690 }
691}
692
693
694/* Decrement VAR_NAME by one. This includes the special variables
695 ibase, obase, and scale. */
696
697void
698decr_var (var_name)
699 int var_name;
700{
701 bc_var *var_ptr;
702
703 switch (var_name)
704 {
705
706 case 0: /* ibase */
707 if (i_base > 2)
708 i_base--;
709 else
710 rt_warn ("ibase too small in --");
711 break;
712
713 case 1: /* obase */
714 if (o_base > 2)
715 o_base--;
716 else
717 rt_warn ("obase too small in --");
718 break;
719
720 case 2: /* scale */
721 if (scale > 0)
722 scale--;
723 else
724 rt_warn ("scale can not be negative in -- ");
725 break;
726
727#if defined(READLINE) || defined(LIBEDIT)
728 case 3: /* history */
729 n_history--;
730 if (n_history >= 0)
731 HISTORY_SIZE(n_history);
732 else
733 {
734 n_history = -1;
735 rt_warn ("history is negative, set to unlimited");
736 UNLIMIT_HISTORY;
737 }
738#endif
739
740 default: /* It is a simple variable. */
741 var_ptr = get_var (var_name);
742 if (var_ptr != NULL)
743 bc_sub (var_ptr->v_value,_one_,&var_ptr->v_value, 0);
744 }
745}
746
747
748/* Decrement VAR_NAME by one. VAR_NAME is an array, and the top of
749 the execution stack is the index and it is popped off the stack. */
750
751void
752decr_array (var_name)
753 int var_name;
754{
755 bc_num *num_ptr;
756 long index;
757
758 /* It is an array variable. */
759 if (!check_stack (1)) return;
760 index = bc_num2long (ex_stack->s_num);
761 if (index < 0 || index > BC_DIM_MAX ||
762 (index == 0 && !bc_is_zero (ex_stack->s_num)))
763 rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
764 else
765 {
766 num_ptr = get_array_num (var_name, index);
767 if (num_ptr != NULL)
768 {
769 pop ();
770 bc_sub (*num_ptr, _one_, num_ptr, 0);
771 }
772 }
773}
774
775
776/* Increment VAR_NAME by one. This includes the special variables
777 ibase, obase, and scale. */
778
779void
780incr_var (var_name)
781 int var_name;
782{
783 bc_var *var_ptr;
784
785 switch (var_name)
786 {
787
788 case 0: /* ibase */
789 if (i_base < 16)
790 i_base++;
791 else
792 rt_warn ("ibase too big in ++");
793 break;
794
795 case 1: /* obase */
796 if (o_base < BC_BASE_MAX)
797 o_base++;
798 else
799 rt_warn ("obase too big in ++");
800 break;
801
802 case 2:
803 if (scale < BC_SCALE_MAX)
804 scale++;
805 else
806 rt_warn ("Scale too big in ++");
807 break;
808
809#if defined(READLINE) || defined(LIBEDIT)
810 case 3: /* history */
811 n_history++;
812 if (n_history > 0)
813 HISTORY_SIZE(n_history);
814 else
815 {
816 n_history = -1;
817 rt_warn ("history set to unlimited");
818 UNLIMIT_HISTORY;
819 }
820#endif
821
822 default: /* It is a simple variable. */
823 var_ptr = get_var (var_name);
824 if (var_ptr != NULL)
825 bc_add (var_ptr->v_value, _one_, &var_ptr->v_value, 0);
826
827 }
828}
829
830
831/* Increment VAR_NAME by one. VAR_NAME is an array and top of
832 execution stack is the index and is popped off the stack. */
833
834void
835incr_array (var_name)
836 int var_name;
837{
838 bc_num *num_ptr;
839 long index;
840
841 if (!check_stack (1)) return;
842 index = bc_num2long (ex_stack->s_num);
843 if (index < 0 || index > BC_DIM_MAX ||
844 (index == 0 && !bc_is_zero (ex_stack->s_num)))
845 rt_error ("Array %s subscript out of bounds.", a_names[var_name]);
846 else
847 {
848 num_ptr = get_array_num (var_name, index);
849 if (num_ptr != NULL)
850 {
851 pop ();
852 bc_add (*num_ptr, _one_, num_ptr, 0);
853 }
854 }
855}
856
857
858/* Routines for processing autos variables and parameters. */
859
860/* NAME is an auto variable that needs to be pushed on its stack. */
861
862void
863auto_var (name)
864 int name;
865{
866 bc_var *v_temp;
867 bc_var_array *a_temp;
868 int ix;
869
870 if (name > 0)
871 {
872 /* A simple variable. */
873 ix = name;
874 v_temp = (bc_var *) bc_malloc (sizeof (bc_var));
875 v_temp->v_next = variables[ix];
876 bc_init_num (&v_temp->v_value);
877 variables[ix] = v_temp;
878 }
879 else
880 {
881 /* An array variable. */
882 ix = -name;
883 a_temp = (bc_var_array *) bc_malloc (sizeof (bc_var_array));
884 a_temp->a_next = arrays[ix];
885 a_temp->a_value = NULL;
886 a_temp->a_param = FALSE;
887 arrays[ix] = a_temp;
888 }
889}
890
891
892/* Free_a_tree frees everything associated with an array variable tree.
893 This is used when popping an array variable off its auto stack. */
894
895void
896free_a_tree ( root, depth )
897 bc_array_node *root;
898 int depth;
899{
900 int ix;
901
902 if (root != NULL)
903 {
904 if (depth > 1)
905 for (ix = 0; ix < NODE_SIZE; ix++)
906 free_a_tree (root->n_items.n_down[ix], depth-1);
907 else
908 for (ix = 0; ix < NODE_SIZE; ix++)
909 bc_free_num ( &(root->n_items.n_num[ix]));
910 free (root);
911 }
912}
913
914
915/* LIST is an NULL terminated list of varible names that need to be
916 popped off their auto stacks. */
917
918void
919pop_vars (list)
920 arg_list *list;
921{
922 bc_var *v_temp;
923 bc_var_array *a_temp;
924 int ix;
925
926 while (list != NULL)
927 {
928 ix = list->av_name;
929 if (ix > 0)
930 {
931 /* A simple variable. */
932 v_temp = variables[ix];
933 if (v_temp != NULL)
934 {
935 variables[ix] = v_temp->v_next;
936 bc_free_num (&v_temp->v_value);
937 free (v_temp);
938 }
939 }
940 else
941 {
942 /* An array variable. */
943 ix = -ix;
944 a_temp = arrays[ix];
945 if (a_temp != NULL)
946 {
947 arrays[ix] = a_temp->a_next;
948 if (!a_temp->a_param && a_temp->a_value != NULL)
949 {
950 free_a_tree (a_temp->a_value->a_tree,
951 a_temp->a_value->a_depth);
952 free (a_temp->a_value);
953 }
954 free (a_temp);
955 }
956 }
957 list = list->next;
958 }
959}
960
961/* COPY_NODE: Copies an array node for a call by value parameter. */
962bc_array_node *
963copy_tree (ary_node, depth)
964 bc_array_node *ary_node;
965 int depth;
966{
967 bc_array_node *res = (bc_array_node *) bc_malloc (sizeof(bc_array_node));
968 int i;
969
970 if (depth > 1)
971 for (i=0; i<NODE_SIZE; i++)
972 if (ary_node->n_items.n_down[i] != NULL)
973 res->n_items.n_down[i] =
974 copy_tree (ary_node->n_items.n_down[i], depth - 1);
975 else
976 res->n_items.n_down[i] = NULL;
977 else
978 for (i=0; i<NODE_SIZE; i++)
979 if (ary_node->n_items.n_num[i] != NULL)
980 res->n_items.n_num[i] = bc_copy_num (ary_node->n_items.n_num[i]);
981 else
982 res->n_items.n_num[i] = NULL;
983 return res;
984}
985
986/* COPY_ARRAY: Copies an array for a call by value array parameter.
987 ARY is the pointer to the bc_array structure. */
988
989bc_array *
990copy_array (ary)
991 bc_array *ary;
992{
993 bc_array *res = (bc_array *) bc_malloc (sizeof(bc_array));
994 res->a_depth = ary->a_depth;
995 res->a_tree = copy_tree (ary->a_tree, ary->a_depth);
996 return (res);
997}
998
999
1000/* A call is being made to FUNC. The call types are at PC. Process
1001 the parameters by doing an auto on the parameter variable and then
1002 store the value at the new variable or put a pointer the the array
1003 variable. */
1004
1005void
1006process_params (pc, func)
1007 program_counter *pc;
1008 int func;
1009{
1010 char ch;
1011 arg_list *params;
1012 int ix, ix1;
1013 bc_var *v_temp;
1014 bc_var_array *a_src, *a_dest;
1015 bc_num *n_temp;
1016
1017 /* Get the parameter names from the function. */
1018 params = functions[func].f_params;
1019
1020 while ((ch = byte(pc)) != ':')
1021 {
1022 if (params != NULL)
1023 {
1024 if ((ch == '0') && params->av_name > 0)
1025 {
1026 /* A simple variable. */
1027 ix = params->av_name;
1028 v_temp = (bc_var *) bc_malloc (sizeof(bc_var));
1029 v_temp->v_next = variables[ix];
1030 v_temp->v_value = ex_stack->s_num;
1031 bc_init_num (&ex_stack->s_num);
1032 variables[ix] = v_temp;
1033 }
1034 else
1035 if ((ch == '1') && (params->av_name < 0))
1036 {
1037 /* The variables is an array variable. */
1038
1039 /* Compute source index and make sure some structure exists. */
1040 ix = (int) bc_num2long (ex_stack->s_num);
1041 n_temp = get_array_num (ix, 0);
1042
1043 /* Push a new array and Compute Destination index */
1044 auto_var (params->av_name);
1045 ix1 = -params->av_name;
1046
1047 /* Set up the correct pointers in the structure. */
1048 if (ix == ix1)
1049 a_src = arrays[ix]->a_next;
1050 else
1051 a_src = arrays[ix];
1052 a_dest = arrays[ix1];
1053 if (params->arg_is_var)
1054 {
1055 a_dest->a_param = TRUE;
1056 a_dest->a_value = a_src->a_value;
1057 }
1058 else
1059 {
1060 a_dest->a_param = FALSE;
1061 a_dest->a_value = copy_array (a_src->a_value);
1062 }
1063 }
1064 else
1065 {
1066 if (params->av_name < 0)
1067 rt_error ("Parameter type mismatch parameter %s.",
1068 a_names[-params->av_name]);
1069 else
1070 rt_error ("Parameter type mismatch, parameter %s.",
1071 v_names[params->av_name]);
1072 params++;
1073 }
1074 pop ();
1075 }
1076 else
1077 {
1078 rt_error ("Parameter number mismatch");
1079 return;
1080 }
1081 params = params->next;
1082 }
1083 if (params != NULL)
1084 rt_error ("Parameter number mismatch");
1085}