📄 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 )
#else
int 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 )
#else
int 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 )
#else
int 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 )
#else
Inst *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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -