📄 code.c
字号:
/* * ============================================================================= * ALADDIN Version 1.0 : * code.c : Functions for Stack Machine * * Copyright (C) 1995 by Mark Austin, Xiaoguang Chen, and Wane-Jang Lin * Institute for Systems Research, * University of Maryland, College Park, MD 20742 * * This software is provided "as is" without express or implied warranty. * Permission is granted to use this software for any on any computer system * and to redistribute it freely, subject to the following restrictions: * * 1. The authors are not responsible for the consequences of use of * this software, even if they arise from defects in the software. * 2. The origin of this software must not be misrepresented, either * by explicit claim or by omission. * 3. Altered versions must be plainly marked as such, and must not * be misrepresented as being the original software. * 4. This notice is to remain intact. * * Written by: Mark Austin, Xiaoguang Chen, and Wane-Jang Lin December 1995 * ============================================================================= */#include <stdio.h>#include <math.h>#include <string.h>#include "defs.h"#include "miscellaneous.h"#include "units.h"#include "matrix.h"#include "fe_database.h"#include "symbol.h"#include "code.h"#include "fe_functions.h"#include "y.tab.h"/* Setup Program Stack */#define NSTACK 200#define NPROG 5500#define NFRAME 500/* Setup Stack Frame for Program Machine */static DATUM stack[NSTACK];static DATUM *stackp;Inst prog[NPROG];Inst *progp;Inst *pc;Inst *progbase = prog;int returning;static int iBREAK_FLAG = 0;typedef struct Frame { SYMBOL *sp; Inst *retpc; DATUM *argn; int nargs;} Frame;Frame frame_in_code[NFRAME];Frame *fp;/* Initialise the pointers stackp and progp to top of their stacks. */int Init_Code(){ progp = progbase; stackp = stack; fp = frame_in_code; returning = 0;}/* Push a data type Datum onto the interpreter and increment stackp to point to the address to which will be assigned the next element to be pushed onto stack.*/#ifdef __STDC__int Push( DATUM d )#elseint Push(d)DATUM d;#endif{ if(stackp >= &stack[NSTACK]) EXECUTION_ERROR("ERROR >> stack overflow", (char *) 0); *stackp++ = d; /* *stackp=d; stackp++; */}DATUM Pop(){ if(stackp == stack) EXECUTION_ERROR("ERROR >> stack underflow ", (char *) 0); return *--stackp; /* stackp--; return *stackp */}int Pop_Eval(){ Pop();}#ifdef __STDC__int Execute( Inst *p )#elseint Execute(p)Inst *p;#endif{ for(pc = p; *pc != STOP && !returning; ) { pc = pc+1; if(Check_Break()) break; (*(*(pc-1)))(); }}/* Push_constant() pushes a data type Datum onto the interpreter stack, and increments the pointer to prog.*/int Push_Constant(){DATUM d; d.q = (QUANTITY *) MyCalloc(1,sizeof(QUANTITY)); if(CheckUnits() == ON) d.q->dimen = (DIMENSIONS *) MyCalloc(1,sizeof(DIMENSIONS)); else d.q->dimen = (DIMENSIONS *)NULL; d.q->value = ((SYMBOL *) *pc)->u.value; pc = pc+1; Push(d);}int Push_Variable(){DATUM d; d.sym = (SYMBOL *)(*pc); pc = pc+1; Push(d);}int Push_String(){DATUM d; d.sym = (SYMBOL *) SaveString((char *)(*pc)); pc = pc+1; Push(d);}int Push_Matrix(){DATUM d; d.sym = (SYMBOL *)(*pc); pc = pc+1; Push(d);}/* * --------------------------------------------------------- * Callback Functions for Looping and Conditional Constructs * --------------------------------------------------------- */int While_Code() {DATUM d;Inst *savepc = pc; Execute(savepc + 2); /* test condition */ d = Pop(); while(d.q->value) { if(Check_Break()) break; Execute(*((Inst **)(savepc))); /* body of code */ if(returning || Check_Break()) break; Execute(savepc + 2); /* test condition */ if(CheckUnits()==ON) { free((char *)d.q->dimen->units_name); free((char *)d.q->dimen); } free((char *)d.q); d = Pop(); } if(CheckUnits()==ON) { free((char *)d.q->dimen->units_name); free((char *)d.q->dimen); } free((char *)d.q); if(returning == 0) pc = *((Inst **)(savepc + 1)); /* next statement */ After_Break();}int If_Code() {DATUM d;Inst *savepc = pc; Execute(savepc + 3); /* condition part */ d = Pop(); if(d.q->value) { Execute(*((Inst **)(savepc))); } else if(*((Inst **)(savepc + 1))) { Execute(*((Inst **)(savepc+1))); } if(CheckUnits()==ON) { free((char *)d.q->dimen->units_name); free((char *)d.q->dimen); } free((char *)d.q); if(!returning) pc = *((Inst **)(savepc + 2)); /* next statement */}int For_Code() {DATUM d;Inst *savepc = pc; Execute(*((Inst **) savepc)) ; /* initiation */ Execute(*((Inst **) (savepc+1))) ; /* cond */ d = Pop(); while(d.q->value) { if(Check_Break()) break; Execute(*((Inst **)(savepc+2))); /* body of loop */ Execute(*((Inst **)(savepc+3))); /* increments */ if(returning || Check_Break()) break; Execute(*((Inst **) (savepc+1))) ; /* cond */ if(CheckUnits()==ON) { free((char *)d.q->dimen->units_name); free((char *)d.q->dimen); } free((char *)d.q); d = Pop(); } if(CheckUnits()==ON) { free((char *)d.q->dimen->units_name); free((char *)d.q->dimen); } free((char *)d.q); if(!returning) pc = *((Inst **)(savepc + 4)); /* next statement */ After_Break();}/* ========================================= *//* Put Function or Procedure in Symbol Table *//* ========================================= */#ifdef __STDC__int define( SYMBOL *sp )#elseint define(sp)SYMBOL *sp;#endif{ sp->u.defn = (Inst) progbase; /* start of code */ progbase = progp; /* next code starts here */}/* Call a function */int Call(){SYMBOL *sp = (SYMBOL *) pc[0]; if(fp++ >= &frame_in_code[NFRAME - 1]) EXECUTION_ERROR(sp->cpSymName, "ERROR >> Call nested too deeply"); fp->sp = sp; fp->nargs = (int) pc[1]; fp->retpc = pc + 2; fp->argn = stackp - 1; Execute((Inst *) sp->u.defn); returning = 0;}int Ret(){int i;DATUM d; for(i = 0; i < fp->nargs; i++) { d = Pop(); if(CheckUnits()==ON) { free((char *)d.q->dimen->units_name); free((char *)d.q->dimen); } free((char *)d.q); } pc = (Inst *) fp->retpc; --fp; returning = 1;}/* * ---------------------------------------------------------------------- * The function code() builds up the machine stack prog, adding data * types Inst to it. In practice the arguments to code() are pointers * to the functions defined later on in code.c, and pointers to * data types Symbol, which have been coerced by the use of the * cast Inst. * ---------------------------------------------------------------------- */ #ifdef __STDC__Inst *Code( Inst f )#elseInst *Code(f)Inst f;#endif{Inst *oprogp = progp; if(progp >= &prog[NPROG]) EXECUTION_ERROR("ERROR >> program too big", (char *) 0); *progp++ = f; return oprogp;}/* * ------------------------------------ * Functions for Engineering Quantities * ------------------------------------ */ int Quantity_Add(){DATUM d1, d2, d3;int UnitsType; d2 = Pop(); /* second item, d2.q */ d1 = Pop(); /* first item, d1.q */ switch(CheckUnits()) { case ON: if(SameUnits(d1.q->dimen, d2.q->dimen) == TRUE) { UnitsType = CheckUnitsType(); if(d2.q->dimen->units_type == UnitsType || d2.q->dimen->units_type == SI_US ) { d2.q->value = d2.q->value + d1.q->value; free((char *) d1.q->dimen->units_name); free((char *) d1.q->dimen); free((char *) d1.q); Push(d2); } else { d1.q->value = d2.q->value + d1.q->value; free((char *) d2.q->dimen->units_name); free((char *) d2.q->dimen); free((char *) d2.q); Push(d1); } } else FatalError("In Add() : Inconsistent Dimensions",(char *)NULL); break; case OFF: d2.q->value = d2.q->value + d1.q->value; free((char *) d1.q); Push(d2); break; default: FatalError("In Add() : CheckUnits is not ON or OFF",(char *)NULL); break; }}int Quantity_Sub(){DATUM d1, d2;int UnitsType; d2 = Pop(); /* 2nd quantity, d2.q */ d1 = Pop(); /* 1st quantity, d1.q */ switch( CheckUnits() ) { case ON: if(SameUnits(d1.q->dimen, d2.q->dimen) == TRUE) { UnitsType = CheckUnitsType(); if(d2.q->dimen->units_type == UnitsType || d2.q->dimen->units_type == SI_US ) { d2.q->value = d1.q->value - d2.q->value; free((char *) d1.q->dimen->units_name); free((char *) d1.q->dimen); free((char *) d1.q); Push(d2); } else { d1.q->value = d1.q->value - d2.q->value; free((char *) d2.q->dimen->units_name); free((char *) d2.q->dimen); free((char *) d2.q); Push(d1); } } else FatalError("In Sub() : Inconsistent Dimensions",(char *)NULL); break; case OFF: d1.q->value = d1.q->value - d2.q->value; free((char *) d2.q); Push(d1); break; default: FatalError("In Sub() : CheckUnits is not ON or OFF",(char *)NULL); break; }}int Quantity_Mul(){DATUM d1, d2, d3;int length; d2 = Pop(); /* 2nd quantity, d2.q */ d1 = Pop(); /* 1st quantity, d1.q */ d3.q = (QUANTITY *) MyCalloc(1,sizeof(QUANTITY)); switch( CheckUnits() ) { case ON: d3.q->value = d1.q->value*d2.q->value; d3.q->dimen = UnitsMult( d1.q->dimen, d2.q->dimen ); free((char *) d2.q->dimen->units_name); free((char *) d2.q->dimen); free((char *) d1.q->dimen->units_name); free((char *) d1.q->dimen); break; case OFF: d3.q->value = d1.q->value*d2.q->value; break; default: FatalError("In Mul() : CheckUnits is not ON or OFF",(char *)NULL); break; } free((char *) d2.q); free((char *) d1.q); Push(d3);}int Quantity_Div(){DATUM d1, d2, d;int length; d2 = Pop(); /* 2nd quantity, d2.q */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -