⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eval.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)eval.c	5.7 (Berkeley) 6/1/90";#endif /* not lint *//* * Tree evaluation. */#include "defs.h"#include "tree.h"#include "operators.h"#include "debug.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 *//* * Command-level evaluation. */public Node topnode;public topeval (p)Node p;{    if (traceeval) {	fprintf(stderr, "topeval(");	prtree(stderr, p);	fprintf(stderr, ")\n");	fflush(stderr);    }    topnode = p;    eval(p);}/* * 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;    Node n1, n2;    boolean b;    File file;    String str;    checkref(p);    if (traceeval) {	fprintf(stderr, "begin eval %s\n", opname(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));		}		if (isvarparam(s) and not isopenarray(s)) {		    rpush(address(s, nil), sizeof(Address));		} else {		    push(Address, address(s, nil));		}	    } else if (isblock(s)) {		push(Symbol, s);	    } else if (isconst(s)) {		eval(constval(s));	    } else {		error("can't evaluate a %s", classname(s));	    }	    break;	case O_LCON:	case O_CCON:	    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:	    s = p->value.arg[0]->nodetype;	    p->value.arg[0]->nodetype = t_addr;	    eval(p->value.arg[0]);	    p->value.arg[0]->nodetype = s;	    n = pop(Address);	    eval(p->value.arg[1]);	    evalindex(s, n, popsmall(p->value.arg[1]->nodetype));	    break;	case O_DOT:	    s = p->value.arg[1]->value.sym;	    eval(p->value.arg[0]);	    n = pop(long);	    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");	    }	    len = size(p->nodetype);	    rpush(addr, len);	    break;	case O_TYPERENAME:	    loophole(size(p->value.arg[0]->nodetype), size(p->nodetype));	    break;	case O_COMMA:	    eval(p->value.arg[0]);	    if (p->value.arg[1] != nil) {		eval(p->value.arg[1]);	    }	    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:	    list(p);	    break;	case O_FUNC:	    func(p->value.arg[0]);	    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 (n2 == nil) {		if (n1 == nil) {		    alias(nil, nil, nil);		} else {		    alias(n1->value.name, nil, nil);		}	    } else if (n2->op == O_NAME) {		str = ident(n2->value.name);		alias(n1->value.name, nil, strdup(str));	    } else {		if (n1->op == O_COMMA) {		    alias(			n1->value.arg[0]->value.name,			(List) n1->value.arg[1],			n2->value.scon		    );		} else {		    alias(n1->value.name, nil, n2->value.scon);		}	    }	    break;	case O_UNALIAS:	    unalias(p->value.arg[0]->value.name);	    break;	case O_CALLPROC:	    callproc(p, false);	    break;	case O_CALL:	    callproc(p, true);	    break;	case O_CATCH:	    if (p->value.lcon == 0) {		printsigscaught(process);	    } else {		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:	    if (p->value.arg[0] == nil) {		dumpall();	    } else {		s = p->value.arg[0]->value.sym;		if (s == curfunc) {		    dump(nil);		} else {		    dump(s);		}	    }	    break;	case O_GRIPE:	    gripe();	    break;	case O_HELP:	    help();	    break;	case O_IGNORE:	    if (p->value.lcon == 0) {		printsigsignored(process);	    } else {		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_SET:	    set(p->value.arg[0], p->value.arg[1]);	    break;	case O_SEARCH:	    search(p->value.arg[0]->value.lcon, p->value.arg[1]->value.scon);	    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_UNSET:	    undefvar(p->value.arg[0]->value.name);	    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 {		    if (canReadSource()) {			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;	case O_TRACEON:	    traceon(p->value.trace.inst, p->value.trace.event,		p->value.trace.actions);	    break;	case O_TRACEOFF:	    traceoff(p->value.lcon);	    break;	default:	    panic("eval: bad op %d", p->op);    }    if (traceeval) { 	fprintf(stderr, "end eval %s\n", opname(p->op));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -