📄 eval.c
字号:
/************************************************************************ * * * Copyright (c) 1986 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * * * Modification History * * * * 011 - Added support for vectors. * * (L Miller, 18JAN90) * * * * 010 - Fixed 009: check for FIELD before isbitfield. * * (jlr, April 13, 1989) * * * * 009 - Added code to handle bitfields to assign(). * * (Jon Reeves, January 21, 1989) * * * * 008 - Merged in 4.3 changes. * * (vjh, April 29, 1986) * * * * 007 - Fixed another bug in trace. * * (vjh, August 7, 1985) * * * * 006 - Fixed bugs/problems related to tracing (search for 006). * * (vjh, July 23, 1985) * * * * 005 - Added test under O_CATCH and O_IGNORE in eval(), to * * insure that the signal number is within the * * appropriate range. * * (vjh, June 14, 1985) * * * * 004 - Removed test after calling firstaddr() in eval(), under * * the O_LIST case. Testing for source is done by check() * * immediately after the O_LIST node is built. * * (vjh, May 30, 1985) * * * * 003 - Removed gripe(). * * (vjh, May 10, 1985) * * * * 002 - Added support for "delete *". * * (vjh, April 25, 1985) * * * * 001 - Require a flag INHOUSE to be defined to allow commands * * "psym", "gripe", and "debug" to work. These are all * * tools used in debugging dbx. * * (Victoria Holt, April 15, 1985) * * * ************************************************************************//* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. *//* Based on: "@(#)eval.c 5.3 (Berkeley) 6/21/85" */#ifndef lintstatic char sccsid[] = "@(#)eval.c 4.2 ULTRIX 11/9/90";#endif not lint/*static char rcsid[] = "$Header: eval.c,v 1.5 84/12/26 10:39:08 linton Exp $";*//* * 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 "main.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, callflag; File file; String str; Vreg v; 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_VREG: s = p->value.sym; if (not (p->nodetype == t_addr)) { /* Start vector support */ if (not canpush(sizeof (struct Vreg))) { error("expression too large to evaluate"); } else { chksp(); v = vreg(s->symvalue.raddr.reg); switch(s->symvalue.raddr.reg) { case VMR: push(Vquad, *(Vquad *)v); break; case VCR: case VAER: case VLR: push(long, (long)v); break; default: push(struct Vreg, *v); break; } } /* End of vector support */ } else { push(Address, address(s, nil)); } 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); /* Start vector support */ if (p->nodetype == t_vquad) { push(Vquad, *(Vquad *) addr); /* End of vector support */ } else rpush(addr, len); break; /* * Move the stack pointer so that the top of the stack has * something corresponding to the size of the current node type. * If this new type is bigger than the subtree (len > 0), * then the stack is padded with nulls. If it's smaller, * the stack is just dropped by the appropriate amount. */ case O_TYPERENAME: if(p->nodetype->type == t_vint || p->nodetype->type->type == t_vint) { if(p->value.arg[0]->nodetype->type->type != t_vquad) { if(streq(ident(p->value.arg[0]->nodetype->name), "$vmr")) { sp -= 8; } else { sp -= size(p->value.arg[0]->nodetype); } error("rename to vint illegal in this context"); } } if(p->nodetype->type == t_vhex || p->nodetype->type->type == t_vhex) { if(p->value.arg[0]->nodetype->type->type != t_vquad) { if(streq(ident(p->value.arg[0]->nodetype->name), "$vmr")) { sp -= 8; } else { sp -= size(p->value.arg[0]->nodetype); } error("rename to vhex illegal in this context"); } } if(p->nodetype->type == t_vfloat || p->nodetype->type->type == t_vfloat) { if(p->value.arg[0]->nodetype->type->type != t_vquad) { if(streq(ident(p->value.arg[0]->nodetype->name), "$vmr")) { sp -= 8; } else { sp -= size(p->value.arg[0]->nodetype); } error("rename to vfloat illegal in this context"); } } len = size(p->nodetype) - size(p->value.arg[0]->nodetype); if (len > 0) { for (n = 0; n < len; n++) { *sp++ = '\0'; } } else if (len < 0) { sp -= len; } 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_GE: push(Boolrep, r0 >= r1); break; case O_GEF: push(Boolrep, fr0 <= fr1); 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.beginaddr->op == O_QLINE) { r0 = objaddr(r0, cursource); if(r0 == NOADDR || r0 == ADDRNOEXEC){ beginerrmsg(); if (r0 == NOADDR) fprintf(stderr, "beyond end of file at line "); else fprintf(stderr, "no executable code found at line "); prtree(stderr, p->value.examine.beginaddr); enderrmsg(); break; } } 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_TMASK: case O_FMASK: { Symbol t; for (n1 = p->value.arg[0]; n1 != nil; n1 = n1->value.arg[1]) { t = n1->value.arg[0]->nodetype; if(((streq(ident(t->name), "$vquad")) || (streq(ident(t->name), "$vmr")) || (streq(ident(t->name), "$vcr")) || (streq(ident(t->name), "$vaer")) || (streq(ident(t->name), "$vlr")))) { error("incorrect symbol for mask operation"); } if((p->value.arg[1]) && (p->value.arg[1]->op != O_SCON)) { error("illegal mask"); break; } if(n1->value.arg[0]->op != O_VREG) { error("rename illegal for mask operation"); break; } eval(n1->value.arg[0]); printval_with_mask(n1->value.arg[0]->nodetype, p->op, p->value.arg[1]); } putchar('\n'); 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_PRINTF:#define MAXARGLIST 200 { char *argv[MAXARGLIST]; int i; long nsize; for (i=0, n1=p->value.arg[0]; n1!=nil; n1=n1->value.arg[1]) { if((i == 0) && (n1->value.arg[0]->op != O_SCON)) { error("missing format"); } if(n1->nodetype->class == ARRAY) { argv[i++] = sp; eval(n1->value.arg[0]); } else if ((nsize = size(n1->value.arg[0]->nodetype))> 4) { if (nsize/4 > MAXARGLIST) error ("printf argument size (%d) exceeds max(%d)\n", nsize, 4*MAXARGLIST); eval(n1->value.arg[0]); nsize = (nsize + 3) & ~3; /* round */ popn (nsize, &argv[i]); i += nsize / 4; } else { eval(n1->value.arg[0]); argv[i++] =(char *)popsmall(n1->value.arg[0]->nodetype); } } argv[i] = NULL; print_formatted(p, argv); for (i=0, n1=p->value.arg[0]; n1!=nil; i++,n1=n1->value.arg[1]){ if(n1->nodetype->class == ARRAY) { sp -= size(n1->nodetype); } } } break; case O_PSYM:# ifdef INHOUSE if (p->value.arg[0]->op == O_SYM) { psym(p->value.arg[0]->value.sym); } else { psym(p->value.arg[0]->nodetype); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -