📄 eval.c
字号:
/*#@(#)eval.c 4.1 Ultrix 7/17/90*//* Copyright (c) 1982 Regents of the University of California */static char sccsid[] = "@(#)eval.c 1.10 8/17/83";static char rcsid[] = "$Header: eval.c,v 1.3 84/03/27 10:20:23 linton Exp $";/* * Tree evaluation. */#include "defs.h"#include "tree.h"#include "operators.h"#include "eval.h"#include "events.h"#include "symbols.h"#include "scanner.h"#include "source.h"#include "object.h"#include "mappings.h"#include "process.h"#include "runtime.h"#include "machine.h"#include <signal.h>#ifndef public#include "machine.h"#define STACKSIZE 20000typedef Char Stack;#define push(type, value) { \ ((type *) (sp += sizeof(type)))[-1] = (value); \}#define pop(type) ( \ (*((type *) (sp -= sizeof(type)))) \)#define popn(n, dest) { \ sp -= n; \ bcopy(sp, dest, n); \}#define alignstack() { \ sp = (Stack *) (( ((int) sp) + sizeof(int) - 1)&~(sizeof(int) - 1)); \}#endifpublic Stack stack[STACKSIZE];public Stack *sp = &stack[0];public Boolean useInstLoc = false;#define chksp() \{ \ if (sp < &stack[0]) { \ panic("stack underflow"); \ } \}#define poparg(n, r, fr) { \ eval(p->value.arg[n]); \ if (isreal(p->op)) { \ if (size(p->value.arg[n]->nodetype) == sizeof(float)) { \ fr = pop(float); \ } else { \ fr = pop(double); \ } \ } else if (isint(p->op)) { \ r = popsmall(p->value.arg[n]->nodetype); \ } \}#define Boolrep char /* underlying representation type for booleans *//* * Evaluate a parse tree leaving the value on the top of the stack. */public eval(p)register Node p;{ long r0, r1; double fr0, fr1; Address addr; long i, n; int len; Symbol s, f; Node n1, n2; Boolean b; File file; checkref(p); if (debug_flag[2]) { fprintf(stderr," evaluating %s \n",showoperator(p->op)); } switch (degree(p->op)) { case BINARY: poparg(1, r1, fr1); poparg(0, r0, fr0); break; case UNARY: poparg(0, r0, fr0); break; default: /* do nothing */; } switch (p->op) { case O_SYM: s = p->value.sym; if (s == retaddrsym) { push(long, return_addr()); } else { if (isvariable(s)) { if (s != program and not isactive(container(s))) { error("\"%s\" is not active", symname(s)); } push(long, address(s, nil)); } else if (isblock(s)) { push(Symbol, s); } else { error("can't evaluate a %s", classname(s)); } } break; case O_LCON: r0 = p->value.lcon; pushsmall(p->nodetype, r0); break; case O_FCON: push(double, p->value.fcon); break; case O_SCON: len = size(p->nodetype); mov(p->value.scon, sp, len); sp += len; break; case O_INDEX: n = pop(long); i = evalindex(p->value.arg[0]->nodetype, popsmall(p->value.arg[1]->nodetype)); push(long, n + i*size(p->nodetype)); break; case O_DOT: s = p->value.arg[1]->value.sym; n = lval(p->value.arg[0]); push(long, n + (s->symvalue.field.offset div 8)); break; /* * Get the value of the expression addressed by the top of the stack. * Push the result back on the stack. */ case O_INDIR: case O_RVAL: addr = pop(long); if (addr == 0) { error("reference through nil pointer"); } if (p->op == O_INDIR) { len = sizeof(long); } else { len = size(p->nodetype); } rpush(addr, len); break; /* * Effectively, we want to pop n bytes off for the evaluated subtree * and push len bytes on for the new type of the same tree. */ case O_TYPERENAME: n = size(p->value.arg[0]->nodetype); len = size(p->nodetype); sp = sp - n + len; break; case O_COMMA: break; case O_ITOF: push(double, (double) r0); break; case O_ADD: push(long, r0+r1); break; case O_ADDF: push(double, fr0+fr1); break; case O_SUB: push(long, r0-r1); break; case O_SUBF: push(double, fr0-fr1); break; case O_NEG: push(long, -r0); break; case O_NEGF: push(double, -fr0); break; case O_MUL: push(long, r0*r1); break; case O_MULF: push(double, fr0*fr1); break; case O_DIVF: if (fr1 == 0) { error("error: division by 0"); } push(double, fr0 / fr1); break; case O_DIV: if (r1 == 0) { error("error: div by 0"); } push(long, r0 div r1); break; case O_MOD: if (r1 == 0) { error("error: mod by 0"); } push(long, r0 mod r1); break; case O_LT: push(Boolrep, r0 < r1); break; case O_LTF: push(Boolrep, fr0 < fr1); break; case O_LE: push(Boolrep, r0 <= r1); break; case O_LEF: push(Boolrep, fr0 <= fr1); break; case O_GT: push(Boolrep, r0 > r1); break; case O_GTF: push(Boolrep, fr0 > fr1); break; case O_EQ: push(Boolrep, r0 == r1); break; case O_EQF: push(Boolrep, fr0 == fr1); break; case O_NE: push(Boolrep, r0 != r1); break; case O_NEF: push(Boolrep, fr0 != fr1); break; case O_AND: push(Boolrep, r0 and r1); break; case O_OR: push(Boolrep, r0 or r1); break; case O_ASSIGN: assign(p->value.arg[0], p->value.arg[1]); break; case O_CHFILE: if (p->value.scon == nil) { printf("%s\n", cursource); } else { file = opensource(p->value.scon); if (file == nil) { error("can't read \"%s\"", p->value.scon); } else { fclose(file); setsource(p->value.scon); } } break; case O_CONT: cont(p->value.lcon); printnews(); break; case O_LIST: if (p->value.arg[0]->op == O_SYM) { f = p->value.arg[0]->value.sym; addr = firstline(f); if (addr == NOADDR) { error("no source lines for \"%s\"", symname(f)); } setsource(srcfilename(addr)); r0 = srcline(addr) - 5; r1 = r0 + 10; if (r0 < 1) { r0 = 1; } } else { eval(p->value.arg[0]); r0 = pop(long); eval(p->value.arg[1]); r1 = pop(long); } printlines((Lineno) r0, (Lineno) r1); break; case O_FUNC: if (p->value.arg[0] == nil) { printname(stdout, curfunc); putchar('\n'); } else { s = p->value.arg[0]->value.sym; if (isroutine(s)) { setcurfunc(s); } else { find(f, s->name) where isroutine(f) endfind(f); if (f == nil) { error("%s is not a procedure or function", symname(s)); } setcurfunc(f); } addr = codeloc(curfunc); if (addr != NOADDR) { setsource(srcfilename(addr)); cursrcline = srcline(addr) - 5; if (cursrcline < 1) { cursrcline = 1; } } } break; case O_EXAMINE: eval(p->value.examine.beginaddr); r0 = pop(long); if (p->value.examine.endaddr == nil) { n = p->value.examine.count; if (n == 0) { printvalue(r0, p->value.examine.mode); } else if (streq(p->value.examine.mode, "i")) { printninst(n, (Address) r0); } else { printndata(n, (Address) r0, p->value.examine.mode); } } else { eval(p->value.examine.endaddr); r1 = pop(long); if (streq(p->value.examine.mode, "i")) { printinst((Address)r0, (Address)r1); } else { printdata((Address)r0, (Address)r1, p->value.examine.mode); } } break; case O_PRINT: for (n1 = p->value.arg[0]; n1 != nil; n1 = n1->value.arg[1]) { eval(n1->value.arg[0]); printval(n1->value.arg[0]->nodetype); putchar(' '); } putchar('\n'); break; case O_PSYM: if (p->value.arg[0]->op == O_SYM) { psym(p->value.arg[0]->value.sym); } else { psym(p->value.arg[0]->nodetype); } break; case O_QLINE: eval(p->value.arg[1]); break; case O_STEP: b = inst_tracing; inst_tracing = (Boolean) (not p->value.step.source); if (p->value.step.skipcalls) { next(); } else { stepc(); } inst_tracing = b; useInstLoc = (Boolean) (not p->value.step.source); printnews(); break; case O_WHATIS: if (p->value.arg[0]->op == O_SYM) { printdecl(p->value.arg[0]->value.sym); } else { printdecl(p->value.arg[0]->nodetype); } break; case O_WHERE: wherecmd(); break; case O_WHEREIS: if (p->value.arg[0]->op == O_SYM) { printwhereis(stdout,p->value.arg[0]->value.sym); } else { printwhereis(stdout,p->value.arg[0]->nodetype); } break; case O_WHICH: if (p->value.arg[0]->op == O_SYM) { printwhich(stdout,p->value.arg[0]->value.sym); } else { printwhich(stdout,p->value.arg[0]->nodetype); } putchar('\n'); break; case O_ALIAS: n1 = p->value.arg[0]; n2 = p->value.arg[1]; if (n1 == nil) { print_alias(nil); } else if (n2 == nil) { print_alias(n1->value.name); } else { enter_alias(n1->value.name, n2->value.name); } break; case O_CALL: callproc(p->value.arg[0], p->value.arg[1]); break; case O_CATCH: psigtrace(process, p->value.lcon, true); break; case O_EDIT: edit(p->value.scon); break; case O_DEBUG: debug(p); break; case O_DOWN: checkref(p->value.arg[0]); assert(p->value.arg[0]->op == O_LCON); down(p->value.arg[0]->value.lcon); break; case O_DUMP: dump(); break; case O_GRIPE: gripe(); break; case O_HELP: help(); break; case O_IGNORE: psigtrace(process, p->value.lcon, false); break; case O_RETURN: if (p->value.arg[0] == nil) { rtnfunc(nil); } else { assert(p->value.arg[0]->op == O_SYM); rtnfunc(p->value.arg[0]->value.sym); } break; case O_RUN: run(); break; case O_SOURCE: setinput(p->value.scon); break; case O_STATUS: status(); break; case O_TRACE: case O_TRACEI: trace(p); break; case O_STOP: case O_STOPI: stop(p); break; case O_UP: checkref(p->value.arg[0]); assert(p->value.arg[0]->op == O_LCON); up(p->value.arg[0]->value.lcon); break; case O_ADDEVENT: addevent(p->value.event.cond, p->value.event.actions); break; case O_DELETE: n1 = p->value.arg[0]; while (n1->op == O_COMMA) { n2 = n1->value.arg[0]; assert(n2->op == O_LCON); if (not delevent((unsigned int) n2->value.lcon)) { error("unknown event %ld", n2->value.lcon); } n1 = n1->value.arg[1]; } assert(n1->op == O_LCON); if (not delevent((unsigned int) n1->value.lcon)) { error("unknown event %ld", n1->value.lcon); } break; case O_ENDX: endprogram(); break; case O_IF: if (cond(p->value.event.cond)) { evalcmdlist(p->value.event.actions); } break; case O_ONCE: event_once(p->value.event.cond, p->value.event.actions); break; case O_PRINTCALL: printcall(p->value.sym, whatblock(return_addr())); break; case O_PRINTIFCHANGED: printifchanged(p->value.arg[0]); break; case O_PRINTRTN: printrtn(p->value.sym); break; case O_PRINTSRCPOS: getsrcpos(); if (p->value.arg[0] == nil) { printsrcpos(); putchar('\n'); printlines(curline, curline); } else if (p->value.arg[0]->op == O_QLINE) { if (p->value.arg[0]->value.arg[1]->value.lcon == 0) { printf("tracei: "); printinst(pc, pc); } else { printf("trace: "); printlines(curline, curline); } } else { printsrcpos(); printf(": "); eval(p->value.arg[0]); prtree(stdout, p->value.arg[0]); printf(" = "); printval(p->value.arg[0]->nodetype); putchar('\n'); } break; case O_PROCRTN: procreturn(p->value.sym); break; case O_STOPIFCHANGED: stopifchanged(p->value.arg[0]); break; case O_STOPX: isstopped = true; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -