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