-/* Copyright (c) 1982 Regents of the University of California */
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)eval.c 5.5 (Berkeley) %G%";
+#endif not lint
-static char sccsid[] = "@(#)eval.c 1.8 %G%";
+static char rcsid[] = "$Header: eval.c,v 1.2 87/03/25 19:48:33 donn 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 "object.h"
#include "mappings.h"
#include "process.h"
+#include "runtime.h"
#include "machine.h"
#include <signal.h>
(*((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)); \
}
public Stack stack[STACKSIZE];
public Stack *sp = &stack[0];
+public Boolean useInstLoc = false;
#define chksp() \
{ \
#define poparg(n, r, fr) { \
eval(p->value.arg[n]); \
if (isreal(p->op)) { \
- fr = pop(double); \
+ 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.
*/
Address addr;
long i, n;
int len;
- Symbol s, f;
+ Symbol s;
Node n1, n2;
- Boolean b;
+ boolean b;
File file;
+ String str;
checkref(p);
- if (debug_flag[2]) {
- fprintf(stderr," evaluating %s \n",showoperator(p->op));
+ if (traceeval) {
+ fprintf(stderr, "begin eval %s\n", opname(p->op));
}
switch (degree(p->op)) {
case BINARY:
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 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 {
- error("can't evaluate a %s", classname(s));
+ 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;
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));
+ 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;
- n = lval(p->value.arg[0]);
+ eval(p->value.arg[0]);
+ n = pop(long);
push(long, n + (s->symvalue.field.offset div 8));
break;
if (addr == 0) {
error("reference through nil pointer");
}
- if (p->op == O_INDIR) {
- len = sizeof(long);
- } else {
- len = size(p->nodetype);
- }
+ len = size(p->nodetype);
rpush(addr, len);
- addr = pop(long);
- push(long, addr);
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;
+ 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:
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);
+ list(p);
break;
case O_FUNC:
- if (p->value.arg[0] == nil) {
- printname(stdout, curfunc);
- putchar('\n');
- } else {
- s = p->value.arg[0]->value.sym;
- find(f, s->name) where
- f->class == FUNC or f->class == PROC
- endfind(f);
- if (f == nil) {
- error("%s is not a procedure or function", symname(s));
- }
- curfunc = f;
- addr = codeloc(curfunc);
- if (addr != NOADDR) {
- setsource(srcfilename(addr));
- cursrcline = srcline(addr) - 5;
- if (cursrcline < 1) {
- cursrcline = 1;
- }
- }
- }
+ func(p->value.arg[0]);
break;
case O_EXAMINE:
stepc();
}
inst_tracing = b;
+ useInstLoc = (Boolean) (not p->value.step.source);
printnews();
break;
case O_WHEREIS:
if (p->value.arg[0]->op == O_SYM) {
- printwhereis(stdout,p->value.arg[0]->value.sym);
+ printwhereis(stdout, p->value.arg[0]->value.sym);
} else {
- printwhereis(stdout,p->value.arg[0]->nodetype);
+ 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);
+ printwhich(stdout, p->value.arg[0]->value.sym);
} else {
- printwhich(stdout,p->value.arg[0]->nodetype);
+ 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);
+ 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 {
- enter_alias(n1->value.name, n2->value.name);
+ 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->value.arg[0], p->value.arg[1]);
+ callproc(p, true);
break;
case O_CATCH:
- psigtrace(process, p->value.lcon, true);
+ if (p->value.lcon == 0) {
+ printsigscaught(process);
+ } else {
+ psigtrace(process, p->value.lcon, true);
+ }
break;
case O_EDIT:
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();
+ 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:
break;
case O_IGNORE:
- psigtrace(process, p->value.lcon, false);
+ 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;
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:
- delevent((unsigned int) p->value.lcon);
+ 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:
printf("tracei: ");
printinst(pc, pc);
} else {
- printf("trace: ");
- printlines(curline, curline);
+ if (canReadSource()) {
+ printf("trace: ");
+ printlines(curline, curline);
+ }
}
} else {
printsrcpos();
default:
panic("eval: bad op %d", p->op);
}
- if(debug_flag[2]) {
- fprintf(stderr," evaluated %s \n",showoperator(p->op));
- }
-
+ if (traceeval) {
+ fprintf(stderr, "end eval %s\n", opname(p->op));
+ }
}
/*
public long popsmall(t)
Symbol t;
{
+ register integer n;
long r;
- switch (size(t)) {
- case sizeof(char):
+ n = size(t);
+ if (n == sizeof(char)) {
+ if (t->class == RANGE and t->symvalue.rangev.lower >= 0) {
+ r = (long) pop(unsigned char);
+ } else {
r = (long) pop(char);
- break;
-
- case sizeof(short):
+ }
+ } else if (n == sizeof(short)) {
+ if (t->class == RANGE and t->symvalue.rangev.lower >= 0) {
+ r = (long) pop(unsigned short);
+ } else {
r = (long) pop(short);
- break;
-
- case sizeof(long):
- r = pop(long);
- break;
-
- default:
- panic("popsmall: size is %d", size(t));
+ }
+ } else if (n == sizeof(long)) {
+ r = pop(long);
+ } else {
+ error("[internal error: size %d in popsmall]", n);
}
return r;
}
public Boolean cond(p)
Node p;
{
- register Boolean b;
+ Boolean b;
+ int i;
if (p == nil) {
b = true;
} else {
eval(p);
- b = (Boolean) pop(Boolrep);
+ i = pop(Boolrep);
+ b = (Boolean) i;
}
return b;
}
Event e;
if (exp->op == O_LCON) {
- wh = build(O_QLINE, build(O_SCON, cursource), exp);
+ wh = build(O_QLINE, build(O_SCON, strdup(cursource)), exp);
} else {
wh = exp;
}
Node event;
Command action;
+ if (size(exp->nodetype) > MAXTRSIZE) {
+ error("expression too large to trace (limit is %d bytes)", MAXTRSIZE);
+ }
p = (place == nil) ? tcontainer(exp) : place->value.sym;
if (p == nil) {
p = program;
if (cond != nil) {
action = build(O_IF, cond, buildcmdlist(action));
}
- if (place != nil and place->op == O_SYM) {
- s = place->value.sym;
+ if (place == nil or place->op == O_SYM) {
+ if (place == nil) {
+ s = program;
+ } else {
+ s = place->value.sym;
+ }
t = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s));
if (cond != nil) {
action = build(O_TRACEON, (p->op == O_STOPI),
Node event;
Command action;
- p = (place == nil) ? tcontainer(exp) : place->value.sym;
- if (p == nil) {
- p = program;
+ if (size(exp->nodetype) > MAXTRSIZE) {
+ error("expression too large to trace (limit is %d bytes)", MAXTRSIZE);
+ }
+ if (place == nil) {
+ if (exp->op == O_LCON) {
+ p = program;
+ } else {
+ p = tcontainer(exp);
+ if (p == nil) {
+ p = program;
+ }
+ }
+ } else {
+ p = place->value.sym;
+ }
+ action = build(O_STOPIFCHANGED, exp);
+ if (cond != nil) {
+ action = build(O_IF, cond, buildcmdlist(action));
}
- action = build(O_IF, cond, buildcmdlist(build(O_STOPIFCHANGED, exp)));
action = build(O_TRACEON, (op == O_STOPI), buildcmdlist(action));
event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));
action->value.trace.event = addevent(event, buildcmdlist(action));
Node exp;
{
Address addr;
- int varsize;
+ integer varsize, expsize;
char cvalue;
short svalue;
long lvalue;
+ float fvalue;
- if (not compatible(var->nodetype, exp->nodetype)) {
- error("incompatible types");
+ if (var->op == O_SYM and regnum(var->value.sym) != -1) {
+ eval(exp);
+ setreg(regnum(var->value.sym), pop(Address));
+ } else {
+ addr = lval(var);
+ varsize = size(var->nodetype);
+ expsize = size(exp->nodetype);
+ eval(exp);
+ if (varsize == sizeof(float) and expsize == sizeof(double)) {
+ fvalue = (float) pop(double);
+ dwrite(&fvalue, addr, sizeof(fvalue));
+ } else {
+ if (varsize < sizeof(long)) {
+ lvalue = 0;
+ popn(expsize, &lvalue);
+ if (varsize == sizeof(char)) {
+ cvalue = lvalue;
+ dwrite(&cvalue, addr, sizeof(cvalue));
+ } else if (varsize == sizeof(short)) {
+ svalue = lvalue;
+ dwrite(&svalue, addr, sizeof(svalue));
+ } else {
+ error("[internal error: bad size %d in assign]", varsize);
+ }
+ } else {
+ if (expsize <= varsize) {
+ sp -= expsize;
+ dwrite(sp, addr, expsize);
+ } else {
+ sp -= expsize;
+ dwrite(sp, addr, varsize);
+ }
+ }
+ }
}
- addr = lval(var);
- eval(exp);
- varsize = size(var->nodetype);
- if (varsize < sizeof(long)) {
- lvalue = pop(long);
- switch (varsize) {
- case sizeof(char):
- cvalue = lvalue;
- dwrite(&cvalue, addr, varsize);
- break;
-
- case sizeof(short):
- svalue = lvalue;
- dwrite(&svalue, addr, varsize);
- break;
-
- default:
- panic("bad size %d", varsize);
+}
+
+/*
+ * Set a debugger variable.
+ */
+
+private set (var, exp)
+Node var, exp;
+{
+ Symbol t;
+
+ if (var == nil) {
+ defvar(nil, nil);
+ } else if (exp == nil) {
+ defvar(var->value.name, nil);
+ } else if (var->value.name == identname("$frame", true)) {
+ t = exp->nodetype;
+ if (not compatible(t, t_int) and not compatible(t, t_addr)) {
+ error("$frame must be an address");
}
+ eval(exp);
+ getnewregs(pop(Address));
} else {
- sp -= varsize;
- dwrite(sp, addr, varsize);
+ defvar(var->value.name, unrval(exp));
}
}
-#define DEF_EDITOR "vi"
-
/*
- * Invoke an editor on the given file. Which editor to use might change
- * installation to installation. For now, we use "vi". In any event,
- * the environment variable "EDITOR" overrides any default.
+ * Execute a list command.
*/
-public edit(filename)
-String filename;
+private list (p)
+Node p;
{
- extern String getenv();
- String ed, src;
- File f;
- Symbol s;
+ Symbol f;
Address addr;
- char buff[10];
+ Lineno line, l1, l2;
- ed = getenv("EDITOR");
- if (ed == nil) {
- ed = DEF_EDITOR;
+ 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));
+ line = srcline(addr);
+ getsrcwindow(line, &l1, &l2);
+ } else {
+ eval(p->value.arg[0]);
+ l1 = (Lineno) (pop(long));
+ eval(p->value.arg[1]);
+ l2 = (Lineno) (pop(long));
}
- if (filename == nil) {
- call(ed, stdin, stdout, cursource, nil);
+ printlines(l1, l2);
+}
+
+/*
+ * Execute a func command.
+ */
+
+private func (p)
+Node p;
+{
+ Symbol s, f;
+ Address addr;
+
+ if (p == nil) {
+ printname(stdout, curfunc);
+ putchar('\n');
} else {
- f = fopen(filename, "r");
- if (f == nil) {
- s = which(identname(filename, true));
- if (not isblock(s)) {
- error("can't read \"%s\"", filename);
- }
- addr = firstline(s);
- if (addr == NOADDR) {
- error("no source for \"%s\"", filename);
- }
- src = srcfilename(addr);
- sprintf(buff, "+%d", srcline(addr));
- call(ed, stdin, stdout, buff, src, nil);
+ s = p->value.sym;
+ if (isroutine(s)) {
+ setcurfunc(s);
} else {
- fclose(f);
- call(ed, stdin, stdout, filename, nil);
+ 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);
}
}
}
/*
- * Send some nasty mail to the current support person.
+ * Send a message to the current support person.
*/
public gripe()
{
typedef Operation();
Operation *old;
-
- char *maintainer = "linton@ucbarpa";
-
- puts("Type control-D to end your message. Be sure to include");
- puts("your name and the name of the file you are debugging.");
- putchar('\n');
- old = signal(SIGINT, SIG_DFL);
- call("Mail", stdin, stdout, maintainer, nil);
- signal(SIGINT, old);
- puts("Thank you.");
+ int pid, status;
+ extern int versionNumber;
+ char subject[100];
+
+# ifdef MAINTAINER
+ puts("Type control-D to end your message. Be sure to include");
+ puts("your name and the name of the file you are debugging.");
+ putchar('\n');
+ old = signal(SIGINT, SIG_DFL);
+ sprintf(subject, "dbx (version 3.%d) gripe", versionNumber);
+ pid = back("Mail", stdin, stdout, "-s", subject, MAINTAINER, nil);
+ signal(SIGINT, SIG_IGN);
+ pwait(pid, &status);
+ signal(SIGINT, old);
+ if (status == 0) {
+ puts("Thank you.");
+ } else {
+ puts("\nMail not sent.");
+ }
+# else
+ puts("Sorry, no dbx maintainer available to gripe to.");
+ puts("Try contacting your system manager.");
+# endif
}
/*
public help()
{
puts("run - begin execution of the program");
+ puts("print <exp> - print the value of the expression");
+ puts("where - print currently active procedures");
+ puts("stop at <line> - suspend execution at the line");
+ puts("stop in <proc> - suspend execution when <proc> is called");
puts("cont - continue execution");
puts("step - single step one line");
puts("next - step to next line (skip over calls)");
puts("trace <proc> - trace calls to the procedure");
puts("trace <var> - trace changes to the variable");
puts("trace <exp> at <line#> - print <exp> when <line> is reached");
- puts("stop at <line> - suspend execution at the line");
- puts("stop in <proc> - suspend execution when <proc> is called");
puts("status - print trace/stop's in effect");
puts("delete <number> - remove trace or stop of given number");
- puts("call <proc> - call the procedure");
- puts("where - print currently active procedures");
- puts("print <exp> - print the value of the expression");
+ puts("call <proc> - call a procedure in program");
puts("whatis <name> - print the declaration of the name");
puts("list <line>, <line> - list source lines");
- puts("edit <proc> - edit file containing <proc>");
puts("gripe - send mail to the person in charge of dbx");
puts("quit - exit dbx");
}