date and time created 82/01/18 19:21:44 by linton
authorMark Linton <linton@ucbvax.Berkeley.EDU>
Tue, 19 Jan 1982 11:21:44 +0000 (03:21 -0800)
committerMark Linton <linton@ucbvax.Berkeley.EDU>
Tue, 19 Jan 1982 11:21:44 +0000 (03:21 -0800)
SCCS-vsn: usr.bin/pascal/pdx/tree/tracestop.c 1.1

usr/src/usr.bin/pascal/pdx/tree/tracestop.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/pascal/pdx/tree/tracestop.c b/usr/src/usr.bin/pascal/pdx/tree/tracestop.c
new file mode 100644 (file)
index 0000000..5fade14
--- /dev/null
@@ -0,0 +1,345 @@
+/* Copyright (c) 1982 Regents of the University of California */
+
+static char sccsid[] = "@(#)tracestop.c 1.1 %G%";
+
+/*
+ * Handle trace and stop commands.
+ */
+
+#include "defs.h"
+#include "breakpoint.h"
+#include "sym.h"
+#include "tree.h"
+#include "runtime.h"
+#include "source.h"
+#include "object.h"
+#include "mappings.h"
+#include "machine.h"
+#include "tree.rep"
+
+LOCAL SYM *tcontainer();
+
+/*
+ * Process a trace/untrace command, basically checking arguments
+ * and translate to a call of the appropriate routine.
+ */
+
+trace(cmd, exp, where, cond)
+int cmd;
+NODE *exp;
+NODE *where;
+NODE *cond;
+{
+       if (exp == NIL) {
+               traceall(cmd, where, cond);
+       } else if (exp->op == O_LCON || exp->op == O_QLINE) {
+               traceinst(cmd, exp, where, cond);
+       } else if (where!=NIL && (where->op==O_QLINE || where->op==O_LCON)) {
+               traceat(cmd, exp, where, cond);
+       } else {
+               tracedata(cmd, exp, where, cond);
+       }
+       if (where != NIL) {
+               tfree(where);
+       }
+}
+
+/*
+ * Set a breakpoint that will turn on tracing.
+ *
+ * A line number of 0 in the breakpoint information structure
+ * means it's a normal trace.
+ *
+ * A line number of -1 indicates that we want to trace at the instruction
+ * rather than source line level.
+ *
+ * If location is NIL, turn on tracing because if the user
+ * has the program stopped somewhere and says "trace",
+ * he/she wants to see tracing after continuing execution.
+ */
+
+LOCAL traceall(cmd, where, cond)
+int cmd;
+NODE *where;
+NODE *cond;
+{
+       SYM *s;
+       LINENO line;
+
+       if (where != NIL && where->op != O_NAME) {
+               error("bad location for trace");
+       }
+       if (cmd == O_TRACE) {
+               line = 0;
+       } else {
+               line = -1;
+       }
+       if (where == NIL) {
+               switch (cmd) {
+                       case O_TRACE:
+                               if (tracing != 0) {
+                                       error("already tracing lines");
+                               }
+                               tracing++;
+                               addcond(TRPRINT, cond);
+                               break;
+
+                       case O_TRACEI:
+                               if (inst_tracing != 0) {
+                                       error("already tracing instructions");
+                               }
+                               inst_tracing++;
+                               addcond(TRPRINT, cond);
+                               break;
+
+                       default:
+                               panic("bad cmd in traceall");
+                               break;
+               }
+               s = program;
+       } else if (where->op != O_NAME) {
+               trerror("found %t, expected procedure or function", where);
+       } else {
+               s = where->nameval;
+               if (!isblock(s)) {
+                       error("\"%s\" is not a procedure or function", name(s));
+               }
+       }
+       addbp(codeloc(s), ALL_ON, s, cond, NIL, line);
+}
+
+/*
+ * Set up the appropriate breakpoint for tracing an instruction.
+ */
+
+LOCAL traceinst(cmd, exp, where, cond)
+int cmd;
+NODE *exp;
+NODE *where;
+NODE *cond;
+{
+       LINENO line;
+       ADDRESS addr;
+
+       if (where != NIL) {
+               error("unexpected \"at\" or \"in\"");
+       }
+       if (cmd == O_TRACEI) {
+               if (exp->op == O_QLINE) {
+                       addr = (ADDRESS) exp->right->lconval;
+               } else if (exp->op == O_LCON) {
+                       addr = (ADDRESS) exp->lconval;
+               } else {
+                       trerror("expected integer constant, found %t", exp);
+               }
+               line = -1;
+       } else {
+               if (exp->op == O_QLINE) {
+                       line = (LINENO) exp->right->lconval;
+                       addr = objaddr(line, exp->left->sconval);
+               } else {
+                       line = (LINENO) exp->lconval;
+                       addr = objaddr(line, cursource);
+               }
+               if (addr == (ADDRESS) -1) {
+                       error("can't trace line %d", line);
+               }
+       }
+       tfree(exp);
+       addbp(addr, INST, NIL, cond, NIL, line);
+}
+
+/*
+ * set a breakpoint to print an expression at a given line or address
+ */
+
+LOCAL traceat(cmd, exp, where, cond)
+int cmd;
+NODE *exp;
+NODE *where;
+NODE *cond;
+{
+       LINENO line;
+       ADDRESS addr;
+
+       if (cmd == O_TRACEI) {
+               if (where->op != O_LCON) {
+                       trerror("expected integer constant, found %t", where);
+               }
+               line = -1;
+               addr = (ADDRESS) where->lconval;
+       } else {
+               line = (LINENO) where->right->lconval;
+               addr = objaddr(line, where->left->sconval);
+               if (addr == (ADDRESS) -1) {
+                       error("can't trace at line %d", line);
+               }
+       }
+       addbp(addr, AT_BP, NIL, cond, exp, line);
+}
+
+/*
+ * Set up breakpoint for tracing data.
+ *
+ * The tracing of blocks lies somewhere between instruction and data;
+ * it's here since a block cannot be distinguished from other terms.
+ *
+ * As in "traceall", if the "block" is the main program then the
+ * user didn't actually specify a block.  This means we want to
+ * turn tracing on ourselves because if the program is stopped
+ * we want to be on regardless of whether they say "cont" or "run".
+ */
+
+LOCAL tracedata(cmd, exp, block, cond)
+int cmd;
+NODE *exp;
+NODE *block;
+NODE *cond;
+{
+       SYM *s, *t;
+
+       if (exp->op != O_RVAL && exp->op != O_CALL) {
+               error("can't trace expressions");
+       }
+       if (block == NIL) {
+               t = tcontainer(exp->left);
+       } else if (block->op == O_NAME) {
+               t = block->nameval;
+       } else {
+               trerror("found %t, expected procedure or function", block);
+       }
+       if (exp->left->op == O_NAME) {
+               s = exp->left->nameval;
+               if (isblock(s)) {
+                       addbp(codeloc(t), BLOCK_ON, t, cond, exp->left, 0);
+                       if (t == program) {
+                               addbp(codeloc(s), CALL, s, cond, NIL, 0);
+                       }
+                       return;
+               }
+       }
+       addbp(codeloc(t), TERM_ON, t, cond, exp, 0);
+       if (curfunc == t) {
+               var_tracing++;
+               addvar(TRPRINT, exp, cond);
+               addbp(return_addr(), TERM_OFF, t, cond, exp, 0);
+       }
+}
+
+/*
+ * Setting and unsetting of stops.
+ */
+
+stop(cmd, exp, where, cond)
+int cmd;
+NODE *exp;
+NODE *where;
+NODE *cond;
+{
+       SYM *s;
+       LINENO n;
+
+       if (exp != NIL) {
+               stopvar(cmd, exp, where, cond);
+       } else if (cond != NIL) {
+               if (where == NIL) {
+                       s = program;
+               } else if (where->op == O_NAME) {
+                       s = where->nameval;
+               } else {
+                       error("bad location for stop");
+               }
+               n = codeloc(s);
+               addbp(n, STOP_ON, s, cond, NIL, n);
+               addcond(TRSTOP, cond);
+               var_tracing++;
+       } else if (where->op == O_NAME) {
+               s = where->nameval;
+               if (!isblock(s)) {
+                       error("\"%s\" is not a procedure or function", name(s));
+               }
+               n = codeloc(s);
+               addbp(n, STOP_BP, s, cond, NIL, srcline(firstline(s)));
+       } else {
+               stopinst(cmd, where, cond);
+       }
+       if (where != NIL) {
+               tfree(where);
+       }
+}
+
+LOCAL stopinst(cmd, where, cond)
+int cmd;
+NODE *where;
+NODE *cond;
+{
+       LINENO line;
+       ADDRESS addr;
+
+       if (where->op != O_QLINE) {
+               error("expected line number");
+       }
+       if (cmd == O_STOP) {
+               line = (LINENO) where->right->lconval;
+               addr = objaddr(line, where->left->sconval);
+               if (addr == (ADDRESS) -1) {
+                       error("can't stop at that line");
+               }
+       } else {
+               line = -1;
+               addr = (ADDRESS) where->right->lconval;
+       }
+       addbp(addr, STOP_BP, NIL, cond, NIL, line);
+}
+
+/*
+ * Implement stopping on assignment to a variable by adding it to
+ * the variable list.
+ */
+
+LOCAL stopvar(cmd, exp, where, cond)
+int cmd;
+NODE *exp;
+NODE *where;
+NODE *cond;
+{
+       SYM *s;
+
+       if (exp->op != O_RVAL) {
+               trerror("found %t, expected variable", exp);
+       }
+       if (cmd == O_STOPI) {
+               inst_tracing++;
+       }
+       var_tracing++;
+       addvar(TRSTOP, exp, cond);
+       if (where == NIL) {
+               s = program;
+       } else if (where->op == O_NAME) {
+               s = where->nameval;
+       } else {
+               error("bad location for stop");
+       }
+       addbp(codeloc(s), STOP_ON, s, cond, exp, 0);
+}
+
+/*
+ * Figure out the block that contains the symbols
+ * in the given variable expression.
+ */
+
+LOCAL SYM *tcontainer(var)
+NODE *var;
+{
+       NODE *p;
+
+       p = var;
+       while (p->op != O_NAME) {
+               if (isleaf(p->op)) {
+                       panic("unexpected op %d in tcontainer", p->op);
+                       /* NOTREACHED */
+               }
+               p = p->left;
+       }
+       return container(p->nameval);
+}