📄 storage.c
字号:
/* storage.c: Code and data storage manipulations. This includes labels. *//* This file is part of bc written for MINIX. Copyright (C) 1991, 1992 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License , or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. You may contact the author by: e-mail: phil@cs.wwu.edu us-mail: Philip A. Nelson Computer Science Department, 9062 Western Washington University Bellingham, WA 98226-9062 *************************************************************************/#include "bcdefs.h"#include "global.h"#include "proto.h"/* Initialize the storage at the beginning of the run. */voidinit_storage (){ /* Functions: we start with none and ask for more. */ f_count = 0; more_functions (); f_names[0] = "(main)"; /* Variables. */ v_count = 0; more_variables (); /* Arrays. */ a_count = 0; more_arrays (); /* Other things... */ ex_stack = NULL; fn_stack = NULL; i_base = 10; o_base = 10; scale = 0; c_code = FALSE; init_numbers();}/* Three functions for increasing the number of functions, variables, or arrays that are needed. This adds another 32 of the requested object. */voidmore_functions (VOID){ int old_count; int indx1, indx2; bc_function *old_f; bc_function *f; char **old_names; /* Save old information. */ old_count = f_count; old_f = functions; old_names = f_names; /* Add a fixed amount and allocate new space. */ f_count += STORE_INCR; functions = (bc_function *) bc_malloc (f_count*sizeof (bc_function)); f_names = (char **) bc_malloc (f_count*sizeof (char *)); /* Copy old ones. */ for (indx1 = 0; indx1 < old_count; indx1++) { functions[indx1] = old_f[indx1]; f_names[indx1] = old_names[indx1]; } /* Initialize the new ones. */ for (; indx1 < f_count; indx1++) { f = &functions[indx1]; f->f_defined = FALSE; for (indx2 = 0; indx2 < BC_MAX_SEGS; indx2++) f->f_body [indx2] = NULL; f->f_code_size = 0; f->f_label = NULL; f->f_autos = NULL; f->f_params = NULL; } /* Free the old elements. */ if (old_count != 0) { free (old_f); free (old_names); }}voidmore_variables (){ int indx; int old_count; bc_var **old_var; char **old_names; /* Save the old values. */ old_count = v_count; old_var = variables; old_names = v_names; /* Increment by a fixed amount and allocate. */ v_count += STORE_INCR; variables = (bc_var **) bc_malloc (v_count*sizeof(bc_var *)); v_names = (char **) bc_malloc (v_count*sizeof(char *)); /* Copy the old variables. */ for (indx = 3; indx < old_count; indx++) variables[indx] = old_var[indx]; /* Initialize the new elements. */ for (; indx < v_count; indx++) variables[indx] = NULL; /* Free the old elements. */ if (old_count != 0) { free (old_var); free (old_names); }}voidmore_arrays (){ int indx; int old_count; bc_var_array **old_ary; char **old_names; /* Save the old values. */ old_count = a_count; old_ary = arrays; old_names = a_names; /* Increment by a fixed amount and allocate. */ a_count += STORE_INCR; arrays = (bc_var_array **) bc_malloc (a_count*sizeof(bc_var_array *)); a_names = (char **) bc_malloc (a_count*sizeof(char *)); /* Copy the old arrays. */ for (indx = 1; indx < old_count; indx++) arrays[indx] = old_ary[indx]; /* Initialize the new elements. */ for (; indx < v_count; indx++) arrays[indx] = NULL; /* Free the old elements. */ if (old_count != 0) { free (old_ary); free (old_names); }}/* clear_func clears out function FUNC and makes it ready to redefine. */voidclear_func (func) char func;{ bc_function *f; int indx; bc_label_group *lg; /* Set the pointer to the function. */ f = &functions[func]; f->f_defined = FALSE; /* Clear the code segments. */ for (indx = 0; indx < BC_MAX_SEGS; indx++) { if (f->f_body[indx] != NULL) { free (f->f_body[indx]); f->f_body[indx] = NULL; } } f->f_code_size = 0; if (f->f_autos != NULL) { free_args (f->f_autos); f->f_autos = NULL; } if (f->f_params != NULL) { free_args (f->f_params); f->f_params = NULL; } while (f->f_label != NULL) { lg = f->f_label->l_next; free (f->f_label); f->f_label = lg; }}/* Pop the function execution stack and return the top. */intfpop(){ fstack_rec *temp; int retval; if (fn_stack != NULL) { temp = fn_stack; fn_stack = temp->s_next; retval = temp->s_val; free (temp); } return (retval);}/* Push VAL on to the function stack. */voidfpush (val) int val;{ fstack_rec *temp; temp = (fstack_rec *) bc_malloc (sizeof (fstack_rec)); temp->s_next = fn_stack; temp->s_val = val; fn_stack = temp;}/* Pop and discard the top element of the regular execution stack. */voidpop (){ estack_rec *temp; if (ex_stack != NULL) { temp = ex_stack; ex_stack = temp->s_next; free_num (&temp->s_num); free (temp); }}/* Push a copy of NUM on to the regular execution stack. */voidpush_copy (num) bc_num num;{ estack_rec *temp; temp = (estack_rec *) bc_malloc (sizeof (estack_rec)); temp->s_num = copy_num (num); temp->s_next = ex_stack; ex_stack = temp;}/* Push NUM on to the regular execution stack. Do NOT push a copy. */voidpush_num (num) bc_num num;{ estack_rec *temp; temp = (estack_rec *) bc_malloc (sizeof (estack_rec)); temp->s_num = num; temp->s_next = ex_stack; ex_stack = temp;}/* Make sure the ex_stack has at least DEPTH elements on it. Return TRUE if it has at least DEPTH elements, otherwise return FALSE. */charcheck_stack (depth) int depth;{ estack_rec *temp; temp = ex_stack; while ((temp != NULL) && (depth > 0)) { temp = temp->s_next; depth--; } if (depth > 0) { rt_error ("Stack error."); return FALSE; } return TRUE;}/* The following routines manipulate simple variables and array variables. *//* get_var returns a pointer to the variable VAR_NAME. If one does not exist, one is created. */bc_var *get_var (var_name) int var_name;{ bc_var *var_ptr; var_ptr = variables[var_name]; if (var_ptr == NULL) { var_ptr = variables[var_name] = (bc_var *) bc_malloc (sizeof (bc_var)); init_num (&var_ptr->v_value); } return var_ptr;}/* get_array_num returns the address of the bc_num in the array structure. If more structure is requried to get to the index, this routine does the work to create that structure. VAR_INDEX is a zero based index into the arrays storage array. INDEX is the index into the bc array. */bc_num *get_array_num (var_index, index) int var_index; long index;{ bc_var_array *ary_ptr; bc_array *a_var; bc_array_node *temp; int log, ix, ix1; int sub [NODE_DEPTH]; /* Get the array entry. */ ary_ptr = arrays[var_index]; if (ary_ptr == NULL) { ary_ptr = arrays[var_index] = (bc_var_array *) bc_malloc (sizeof (bc_var_array)); ary_ptr->a_value = NULL; ary_ptr->a_next = NULL; ary_ptr->a_param = FALSE; } a_var = ary_ptr->a_value; if (a_var == NULL) { a_var = ary_ptr->a_value = (bc_array *) bc_malloc (sizeof (bc_array)); a_var->a_tree = NULL; a_var->a_depth = 0; } /* Get the index variable. */ sub[0] = index & NODE_MASK; ix = index >> NODE_SHIFT; log = 1; while (ix > 0 || log < a_var->a_depth) { sub[log] = ix & NODE_MASK; ix >>= NODE_SHIFT; log++; } /* Build any tree that is necessary. */ while (log > a_var->a_depth) { temp = (bc_array_node *) bc_malloc (sizeof(bc_array_node)); if (a_var->a_depth != 0) { temp->n_items.n_down[0] = a_var->a_tree; for (ix=1; ix < NODE_SIZE; ix++) temp->n_items.n_down[ix] = NULL; } else { for (ix=0; ix < NODE_SIZE; ix++) temp->n_items.n_num[ix] = copy_num(_zero_); } a_var->a_tree = temp; a_var->a_depth++; } /* Find the indexed variable. */ temp = a_var->a_tree; while ( log-- > 1) { ix1 = sub[log]; if (temp->n_items.n_down[ix1] == NULL) { temp->n_items.n_down[ix1] = (bc_array_node *) bc_malloc (sizeof(bc_array_node)); temp = temp->n_items.n_down[ix1]; if (log > 1) for (ix=0; ix < NODE_SIZE; ix++) temp->n_items.n_down[ix] = NULL; else for (ix=0; ix < NODE_SIZE; ix++) temp->n_items.n_num[ix] = copy_num(_zero_); } else temp = temp->n_items.n_down[ix1]; } /* Return the address of the indexed variable. */ return &(temp->n_items.n_num[sub[0]]);}/* Store the top of the execution stack into VAR_NAME. This includes the special variables ibase, obase, and scale. */voidstore_var (var_name) int var_name;{ bc_var *var_ptr; long temp; char toobig; if (var_name > 2) { /* It is a simple variable. */ var_ptr = get_var (var_name); if (var_ptr != NULL) { free_num(&var_ptr->v_value); var_ptr->v_value = copy_num (ex_stack->s_num); } } else { /* It is a special variable... */ toobig = FALSE; if (is_neg (ex_stack->s_num)) { switch (var_name) { case 0: rt_warn ("negative ibase, set to 2"); temp = 2; break; case 1: rt_warn ("negative obase, set to 2"); temp = 2; break; case 2: rt_warn ("negative scale, set to 0");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -