📄 eval.c
字号:
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(debug_flag[2]) { fprintf(stderr," evaluated %s \n",showoperator(p->op)); } }/* * Evaluate a list of commands. */public evalcmdlist(cl)Cmdlist cl;{ Command c; foreach (Command, c, cl) evalcmd(c); endfor}/* * Push "len" bytes onto the expression stack from address "addr" * in the process. If there isn't room on the stack, print an error message. */public rpush(addr, len)Address addr;int len;{ if (not canpush(len)) { error("expression too large to evaluate"); } else { chksp(); dread(sp, addr, len); sp += len; }}/* * Check if the stack has n bytes available. */public Boolean canpush(n)Integer n;{ return (Boolean) (sp + n < &stack[STACKSIZE]);}/* * Push a small scalar of the given type onto the stack. */public pushsmall(t, v)Symbol t;long v;{ register Integer s; s = size(t); switch (s) { case sizeof(char): push(char, v); break; case sizeof(short): push(short, v); break; case sizeof(long): push(long, v); break; default: panic("bad size %d in popsmall", s); }}/* * Pop an item of the given type which is assumed to be no larger * than a long and return it expanded into a long. */public long popsmall(t)Symbol t;{ long r; switch (size(t)) { case sizeof(char): r = (long) pop(char); break; case sizeof(short): r = (long) pop(short); break; case sizeof(long): r = pop(long); break; default: panic("popsmall: size is %d", size(t)); } return r;}/* * Evaluate a conditional expression. */public Boolean cond(p)Node p;{ register Boolean b; if (p == nil) { b = true; } else { eval(p); b = (Boolean) pop(Boolrep); } return b;}/* * Return the address corresponding to a given tree. */public Address lval(p)Node p;{ if (p->op == O_RVAL) { eval(p->value.arg[0]); } else { eval(p); } return (Address) (pop(long));}/* * Process a trace command, translating into the appropriate events * and associated actions. */public trace(p)Node p;{ Node exp, place, cond; Node left; exp = p->value.arg[0]; place = p->value.arg[1]; cond = p->value.arg[2]; if (exp == nil) { traceall(p->op, place, cond); } else if (exp->op == O_QLINE or exp->op == O_LCON) { traceinst(p->op, exp, cond); } else if (place != nil and place->op == O_QLINE) { traceat(p->op, exp, place, cond); } else { left = exp; if (left->op == O_RVAL or left->op == O_CALL) { left = left->value.arg[0]; } if (left->op == O_SYM and isblock(left->value.sym)) { traceproc(p->op, left->value.sym, place, cond); } else { tracedata(p->op, exp, place, cond); } }}/* * Set a breakpoint that will turn on tracing. */private traceall(op, place, cond)Operator op;Node place;Node cond;{ Symbol s; Node event; Command action; if (place == nil) { s = program; } else { s = place->value.sym; } event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s)); action = build(O_PRINTSRCPOS, build(O_QLINE, nil, build(O_LCON, (op == O_TRACE) ? 1 : 0))); if (cond != nil) { action = build(O_IF, cond, buildcmdlist(action)); } action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action)); action->value.trace.event = addevent(event, buildcmdlist(action)); if (isstdin()) { printevent(action->value.trace.event); }}/* * Set up the appropriate breakpoint for tracing an instruction. */private traceinst(op, exp, cond)Operator op;Node exp;Node cond;{ Node event, wh; Command action; Event e; if (exp->op == O_LCON) { wh = build(O_QLINE, build(O_SCON, cursource), exp); } else { wh = exp; } if (op == O_TRACEI) { event = build(O_EQ, build(O_SYM, pcsym), wh); } else { event = build(O_EQ, build(O_SYM, linesym), wh); } action = build(O_PRINTSRCPOS, wh); if (cond) { action = build(O_IF, cond, buildcmdlist(action)); } e = addevent(event, buildcmdlist(action)); if (isstdin()) { printevent(e); }}/* * Set a breakpoint to print an expression at a given line or address. */private traceat(op, exp, place, cond)Operator op;Node exp;Node place;Node cond;{ Node event; Command action; Event e; if (op == O_TRACEI) { event = build(O_EQ, build(O_SYM, pcsym), place); } else { event = build(O_EQ, build(O_SYM, linesym), place); } action = build(O_PRINTSRCPOS, exp); if (cond != nil) { action = build(O_IF, cond, buildcmdlist(action)); } e = addevent(event, buildcmdlist(action)); if (isstdin()) { printevent(e); }}/* * Construct event for tracing a procedure. * * What we want here is * * when $proc = p do * if <condition> then * printcall; * once $pc = $retaddr do * printrtn; * end; * end if; * end; * * Note that "once" is like "when" except that the event * deletes itself as part of its associated action. */private traceproc(op, p, place, cond)Operator op;Symbol p;Node place;Node cond;{ Node event; Command action; Cmdlist actionlist; Event e; action = build(O_PRINTCALL, p); actionlist = list_alloc(); cmdlist_append(action, actionlist); event = build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)); action = build(O_ONCE, event, buildcmdlist(build(O_PRINTRTN, p))); cmdlist_append(action, actionlist); if (cond != nil) { actionlist = buildcmdlist(build(O_IF, cond, actionlist)); } event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p)); e = addevent(event, actionlist); if (isstdin()) { printevent(e); }}/* * Set up breakpoint for tracing data. */private tracedata(op, exp, place, cond)Operator op;Node exp;Node place;Node cond;{ Symbol p; Node event; Command action; p = (place == nil) ? tcontainer(exp) : place->value.sym; if (p == nil) { p = program; } action = build(O_PRINTIFCHANGED, exp); if (cond != nil) { action = build(O_IF, cond, buildcmdlist(action)); } action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action)); event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p)); action->value.trace.event = addevent(event, buildcmdlist(action)); if (isstdin()) { printevent(action->value.trace.event); }}/* * Setting and unsetting of stops. */public stop(p)Node p;{ Node exp, place, cond, t; Symbol s; Command action; Event e; exp = p->value.arg[0]; place = p->value.arg[1]; cond = p->value.arg[2]; if (exp != nil) { stopvar(p->op, exp, place, cond); } else { action = build(O_STOPX); if (cond != nil) { action = build(O_IF, cond, buildcmdlist(action)); } 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), buildcmdlist(action)); e = addevent(t, buildcmdlist(action)); action->value.trace.event = e; } else { e = addevent(t, buildcmdlist(action)); } if (isstdin()) { printevent(e); } } else { stopinst(p->op, place, cond, action); } }}private stopinst(op, place, cond, action)Operator op;Node place;Node cond;Command action;{ Node event; Event e; if (op == O_STOP) { event = build(O_EQ, build(O_SYM, linesym), place); } else { event = build(O_EQ, build(O_SYM, pcsym), place); } e = addevent(event, buildcmdlist(action)); if (isstdin()) { printevent(e); }}/* * Implement stopping on assignment to a variable by adding it to * the variable list. */private stopvar(op, exp, place, cond)Operator op;Node exp;Node place;Node cond;{ Symbol p; Node event; Command action; 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_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)); if (isstdin()) { printevent(action->value.trace.event); }}/* * Assign the value of an expression to a variable (or term). */public assign(var, exp)Node var;Node exp;{ Address addr; integer varsize, expsize; char cvalue; short svalue; long lvalue; float fvalue; if (not compatible(var->nodetype, exp->nodetype)) { error("incompatible types"); } 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); switch (varsize) { case sizeof(char): cvalue = lvalue; dwrite(&cvalue, addr, sizeof(cvalue)); break; case sizeof(short): svalue = lvalue; dwrite(&svalue, addr, sizeof(svalue)); break; default: panic("bad size %d", varsize); } } else { if (expsize <= varsize) { sp -= expsize; dwrite(sp, addr, expsize); } else { sp -= expsize; dwrite(sp, addr, varsize); } } }}/* * Send some nasty mail to the current support person. */public gripe(){ typedef Operation(); Operation *old; int pid, status; extern int versionNumber; char subject[100]; char *maintainer = "linton@berkeley"; 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 %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."); }}/* * Give the user some help. */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 <line#> - trace execution of the line"); 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("status - print trace/stop's in effect"); puts("delete <number> - remove trace or stop of given number"); 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("gripe - send mail to the person in charge of dbx"); puts("quit - exit dbx");}/* * Divert output to the given file name. * Cannot redirect to an existing file. */private int so_fd;private Boolean notstdout;public setout(filename)String filename;{ File f; f = fopen(filename, "r"); if (f != nil) { fclose(f); error("%s: file already exists", filename); } else { so_fd = dup(1); close(1); if (creat(filename, 0666) == nil) { unsetout(); error("can't create %s", filename); } notstdout = true; }}/* * Revert output to standard output. */public unsetout(){ fflush(stdout); close(1); if (dup(so_fd) != 1) { panic("standard out dup failed"); } close(so_fd); notstdout = false;}/* * Determine is standard output is currently being redirected * to a file (as far as we know). */public Boolean isredirected(){ return notstdout;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -