📄 execute.c
字号:
/* execute.c - run a bc program. *//* 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 <signal.h>#include "global.h"#include "proto.h"/* The SIGINT interrupt handling routine. */int had_sigint;voidstop_execution (sig) int sig;{ had_sigint = TRUE; printf ("\n"); rt_error ("interrupted execution");}/* Get the current byte and advance the PC counter. */unsigned charbyte (pc) program_counter *pc;{ int seg, offset; seg = pc->pc_addr >> BC_SEG_LOG; offset = pc->pc_addr++ % BC_SEG_SIZE; return (functions[pc->pc_func].f_body[seg][offset]);}/* The routine that actually runs the machine. */voidexecute (){ int label_num, l_gp, l_off; bc_label_group *gp; char inst, ch; int new_func; int var_name; int const_base; bc_num temp_num; arg_list *auto_list; /* Initialize this run... */ pc.pc_func = 0; pc.pc_addr = 0; runtime_error = FALSE; init_num (&temp_num); /* Set up the interrupt mechanism for an interactive session. */ if (interactive) { signal (SIGINT, stop_execution); had_sigint = FALSE; } while (pc.pc_addr < functions[pc.pc_func].f_code_size && !runtime_error) { inst = byte(&pc);#if DEBUG > 3 { /* Print out address and the stack before each instruction.*/ int depth; estack_rec *temp = ex_stack; printf ("func=%d addr=%d inst=%c\n",pc.pc_func, pc.pc_addr, inst); if (temp == NULL) printf ("empty stack.\n", inst); else { depth = 1; while (temp != NULL) { printf (" %d = ", depth); out_num (temp->s_num, 10, out_char); depth++; temp = temp->s_next; } } }#endif switch ( inst ) { case 'A' : /* increment array variable (Add one). */ var_name = byte(&pc); if ((var_name & 0x80) != 0) var_name = ((var_name << 8) & 0x7f) + byte(&pc); incr_array (var_name); break; case 'B' : /* Branch to a label if TOS != 0. Remove value on TOS. */ case 'Z' : /* Branch to a label if TOS == 0. Remove value on TOS. */ c_code = !is_zero (ex_stack->s_num); pop (); case 'J' : /* Jump to a label. */ label_num = byte(&pc); /* Low order bits first. */ label_num += byte(&pc) << 8; if (inst == 'J' || (inst == 'B' && c_code) || (inst == 'Z' && !c_code)) { gp = functions[pc.pc_func].f_label; l_gp = label_num >> BC_LABEL_LOG; l_off = label_num % BC_LABEL_GROUP; while (l_gp-- > 0) gp = gp->l_next; pc.pc_addr = gp->l_adrs[l_off]; } break; case 'C' : /* Call a function. */ /* Get the function number. */ new_func = byte(&pc); if ((new_func & 0x80) != 0) new_func = ((new_func << 8) & 0x7f) + byte(&pc); /* Check to make sure it is defined. */ if (!functions[new_func].f_defined) { rt_error ("Function %s not defined.", f_names[new_func]); break; } /* Check and push parameters. */ process_params (&pc, new_func); /* Push auto variables. */ for (auto_list = functions[new_func].f_autos; auto_list != NULL; auto_list = auto_list->next) auto_var (auto_list->av_name); /* Push pc and ibase. */ fpush (pc.pc_func); fpush (pc.pc_addr); fpush (i_base); /* Reset pc to start of function. */ pc.pc_func = new_func; pc.pc_addr = 0; break; case 'D' : /* Duplicate top of stack */ push_copy (ex_stack->s_num); break; case 'K' : /* Push a constant */ /* Get the input base and convert it to a bc number. */ if (pc.pc_func == 0) const_base = i_base; else const_base = fn_stack->s_val; if (const_base == 10) push_b10_const (&pc); else push_constant (prog_char, const_base); break; case 'L' : /* load array variable */ var_name = byte(&pc); if ((var_name & 0x80) != 0) var_name = ((var_name << 8) & 0x7f) + byte(&pc); load_array (var_name); break; case 'M' : /* decrement array variable (Minus!) */ var_name = byte(&pc); if ((var_name & 0x80) != 0) var_name = ((var_name << 8) & 0x7f) + byte(&pc); decr_array (var_name); break; case 'O' : /* Write a string to the output with processing. */ while ((ch = byte(&pc)) != '"') if (ch != '\\') out_char (ch); else { ch = byte(&pc); if (ch == '"') break; switch (ch) { case 'n': out_char ('\n'); break; case 't': out_char ('\t'); break; case 'r': out_char ('\r'); break; case 'b': out_char (007); break; case 'f': out_char ('\f'); break; case '\\': out_char ('\\'); break; default: break; } } if (interactive) fflush (stdout); break; case 'R' : /* Return from function */ if (pc.pc_func != 0) { /* "Pop" autos and parameters. */ pop_vars(functions[pc.pc_func].f_autos); pop_vars(functions[pc.pc_func].f_params); /* reset the pc. */ fpop (); pc.pc_addr = fpop (); pc.pc_func = fpop (); } else rt_error ("Return from main program."); break; case 'S' : /* store array variable */ var_name = byte(&pc); if ((var_name & 0x80) != 0) var_name = ((var_name << 8) & 0x7f) + byte(&pc); store_array (var_name); break; case 'T' : /* Test tos for zero */ c_code = is_zero (ex_stack->s_num); assign (c_code); break; case 'W' : /* Write the value on the top of the stack. */ case 'P' : /* Write the value on the top of the stack. No newline. */ out_num (ex_stack->s_num, o_base, out_char); if (inst == 'W') out_char ('\n'); store_var (3); /* Special variable "last". */ if (interactive) fflush (stdout); break; case 'c' : /* Call special function. */ new_func = byte(&pc); switch (new_func) { case 'L': /* Length function. */ /* For the number 0.xxxx, 0 is not significant. */ if (ex_stack->s_num->n_len == 1 && ex_stack->s_num->n_scale != 0 && ex_stack->s_num->n_value[0] == 0 ) int2num (&ex_stack->s_num, ex_stack->s_num->n_scale); else int2num (&ex_stack->s_num, ex_stack->s_num->n_len + ex_stack->s_num->n_scale); break; case 'S': /* Scale function. */ int2num (&ex_stack->s_num, ex_stack->s_num->n_scale); break; case 'R': /* Square Root function. */ if (!bc_sqrt (&ex_stack->s_num, scale)) rt_error ("Square root of a negative number"); break; case 'I': /* Read function. */ push_constant (input_char, i_base); break; } break; case 'd' : /* Decrement number */ var_name = byte(&pc); if ((var_name & 0x80) != 0) var_name = ((var_name << 8) & 0x7f) + byte(&pc); decr_var (var_name); break; case 'h' : /* Halt the machine. */ exit (0); case 'i' : /* increment number */ var_name = byte(&pc); if ((var_name & 0x80) != 0) var_name = ((var_name << 8) & 0x7f) + byte(&pc); incr_var (var_name); break; case 'l' : /* load variable */ var_name = byte(&pc); if ((var_name & 0x80) != 0) var_name = ((var_name << 8) & 0x7f) + byte(&pc); load_var (var_name); break; case 'n' : /* Negate top of stack. */ bc_sub (_zero_, ex_stack->s_num, &ex_stack->s_num); break; case 'p' : /* Pop the execution stack. */ pop (); break; case 's' : /* store variable */ var_name = byte(&pc); if ((var_name & 0x80) != 0) var_name = ((var_name << 8) & 0x7f) + byte(&pc); store_var (var_name); break; case 'w' : /* Write a string to the output. */ while ((ch = byte(&pc)) != '"') out_char (ch); if (interactive) fflush (stdout); break; case 'x' : /* Exchange Top of Stack with the one under the tos. */ if (check_stack(2)) { bc_num temp = ex_stack->s_num; ex_stack->s_num = ex_stack->s_next->s_num; ex_stack->s_next->s_num = temp; } break; case '0' : /* Load Constant 0. */ push_copy (_zero_); break; case '1' : /* Load Constant 0. */ push_copy (_one_); break; case '!' : /* Negate the boolean value on top of the stack. */ c_code = is_zero (ex_stack->s_num); assign (c_code); break; case '&' : /* compare greater than */ if (check_stack(2)) { c_code = !is_zero (ex_stack->s_next->s_num) && !is_zero (ex_stack->s_num); pop (); assign (c_code); } break; case '|' : /* compare greater than */ if (check_stack(2)) { c_code = !is_zero (ex_stack->s_next->s_num) || !is_zero (ex_stack->s_num); pop (); assign (c_code); } break; case '+' : /* add */ if (check_stack(2)) { bc_add (ex_stack->s_next->s_num, ex_stack->s_num, &temp_num); pop(); pop(); push_num (temp_num); init_num (&temp_num); } break; case '-' : /* subtract */ if (check_stack(2)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -