|
|
1.1 root 1: /* Copyright (c) 1982 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)tracestop.c 1.1 1/18/82";
4:
5: /*
6: * Handle trace and stop commands.
7: */
8:
9: #include "defs.h"
10: #include "breakpoint.h"
11: #include "sym.h"
12: #include "tree.h"
13: #include "runtime.h"
14: #include "source.h"
15: #include "object.h"
16: #include "mappings.h"
17: #include "machine.h"
18: #include "tree.rep"
19:
20: LOCAL SYM *tcontainer();
21:
22: /*
23: * Process a trace/untrace command, basically checking arguments
24: * and translate to a call of the appropriate routine.
25: */
26:
27: trace(cmd, exp, where, cond)
28: int cmd;
29: NODE *exp;
30: NODE *where;
31: NODE *cond;
32: {
33: if (exp == NIL) {
34: traceall(cmd, where, cond);
35: } else if (exp->op == O_LCON || exp->op == O_QLINE) {
36: traceinst(cmd, exp, where, cond);
37: } else if (where!=NIL && (where->op==O_QLINE || where->op==O_LCON)) {
38: traceat(cmd, exp, where, cond);
39: } else {
40: tracedata(cmd, exp, where, cond);
41: }
42: if (where != NIL) {
43: tfree(where);
44: }
45: }
46:
47: /*
48: * Set a breakpoint that will turn on tracing.
49: *
50: * A line number of 0 in the breakpoint information structure
51: * means it's a normal trace.
52: *
53: * A line number of -1 indicates that we want to trace at the instruction
54: * rather than source line level.
55: *
56: * If location is NIL, turn on tracing because if the user
57: * has the program stopped somewhere and says "trace",
58: * he/she wants to see tracing after continuing execution.
59: */
60:
61: LOCAL traceall(cmd, where, cond)
62: int cmd;
63: NODE *where;
64: NODE *cond;
65: {
66: SYM *s;
67: LINENO line;
68:
69: if (where != NIL && where->op != O_NAME) {
70: error("bad location for trace");
71: }
72: if (cmd == O_TRACE) {
73: line = 0;
74: } else {
75: line = -1;
76: }
77: if (where == NIL) {
78: switch (cmd) {
79: case O_TRACE:
80: if (tracing != 0) {
81: error("already tracing lines");
82: }
83: tracing++;
84: addcond(TRPRINT, cond);
85: break;
86:
87: case O_TRACEI:
88: if (inst_tracing != 0) {
89: error("already tracing instructions");
90: }
91: inst_tracing++;
92: addcond(TRPRINT, cond);
93: break;
94:
95: default:
96: panic("bad cmd in traceall");
97: break;
98: }
99: s = program;
100: } else if (where->op != O_NAME) {
101: trerror("found %t, expected procedure or function", where);
102: } else {
103: s = where->nameval;
104: if (!isblock(s)) {
105: error("\"%s\" is not a procedure or function", name(s));
106: }
107: }
108: addbp(codeloc(s), ALL_ON, s, cond, NIL, line);
109: }
110:
111: /*
112: * Set up the appropriate breakpoint for tracing an instruction.
113: */
114:
115: LOCAL traceinst(cmd, exp, where, cond)
116: int cmd;
117: NODE *exp;
118: NODE *where;
119: NODE *cond;
120: {
121: LINENO line;
122: ADDRESS addr;
123:
124: if (where != NIL) {
125: error("unexpected \"at\" or \"in\"");
126: }
127: if (cmd == O_TRACEI) {
128: if (exp->op == O_QLINE) {
129: addr = (ADDRESS) exp->right->lconval;
130: } else if (exp->op == O_LCON) {
131: addr = (ADDRESS) exp->lconval;
132: } else {
133: trerror("expected integer constant, found %t", exp);
134: }
135: line = -1;
136: } else {
137: if (exp->op == O_QLINE) {
138: line = (LINENO) exp->right->lconval;
139: addr = objaddr(line, exp->left->sconval);
140: } else {
141: line = (LINENO) exp->lconval;
142: addr = objaddr(line, cursource);
143: }
144: if (addr == (ADDRESS) -1) {
145: error("can't trace line %d", line);
146: }
147: }
148: tfree(exp);
149: addbp(addr, INST, NIL, cond, NIL, line);
150: }
151:
152: /*
153: * set a breakpoint to print an expression at a given line or address
154: */
155:
156: LOCAL traceat(cmd, exp, where, cond)
157: int cmd;
158: NODE *exp;
159: NODE *where;
160: NODE *cond;
161: {
162: LINENO line;
163: ADDRESS addr;
164:
165: if (cmd == O_TRACEI) {
166: if (where->op != O_LCON) {
167: trerror("expected integer constant, found %t", where);
168: }
169: line = -1;
170: addr = (ADDRESS) where->lconval;
171: } else {
172: line = (LINENO) where->right->lconval;
173: addr = objaddr(line, where->left->sconval);
174: if (addr == (ADDRESS) -1) {
175: error("can't trace at line %d", line);
176: }
177: }
178: addbp(addr, AT_BP, NIL, cond, exp, line);
179: }
180:
181: /*
182: * Set up breakpoint for tracing data.
183: *
184: * The tracing of blocks lies somewhere between instruction and data;
185: * it's here since a block cannot be distinguished from other terms.
186: *
187: * As in "traceall", if the "block" is the main program then the
188: * user didn't actually specify a block. This means we want to
189: * turn tracing on ourselves because if the program is stopped
190: * we want to be on regardless of whether they say "cont" or "run".
191: */
192:
193: LOCAL tracedata(cmd, exp, block, cond)
194: int cmd;
195: NODE *exp;
196: NODE *block;
197: NODE *cond;
198: {
199: SYM *s, *t;
200:
201: if (exp->op != O_RVAL && exp->op != O_CALL) {
202: error("can't trace expressions");
203: }
204: if (block == NIL) {
205: t = tcontainer(exp->left);
206: } else if (block->op == O_NAME) {
207: t = block->nameval;
208: } else {
209: trerror("found %t, expected procedure or function", block);
210: }
211: if (exp->left->op == O_NAME) {
212: s = exp->left->nameval;
213: if (isblock(s)) {
214: addbp(codeloc(t), BLOCK_ON, t, cond, exp->left, 0);
215: if (t == program) {
216: addbp(codeloc(s), CALL, s, cond, NIL, 0);
217: }
218: return;
219: }
220: }
221: addbp(codeloc(t), TERM_ON, t, cond, exp, 0);
222: if (curfunc == t) {
223: var_tracing++;
224: addvar(TRPRINT, exp, cond);
225: addbp(return_addr(), TERM_OFF, t, cond, exp, 0);
226: }
227: }
228:
229: /*
230: * Setting and unsetting of stops.
231: */
232:
233: stop(cmd, exp, where, cond)
234: int cmd;
235: NODE *exp;
236: NODE *where;
237: NODE *cond;
238: {
239: SYM *s;
240: LINENO n;
241:
242: if (exp != NIL) {
243: stopvar(cmd, exp, where, cond);
244: } else if (cond != NIL) {
245: if (where == NIL) {
246: s = program;
247: } else if (where->op == O_NAME) {
248: s = where->nameval;
249: } else {
250: error("bad location for stop");
251: }
252: n = codeloc(s);
253: addbp(n, STOP_ON, s, cond, NIL, n);
254: addcond(TRSTOP, cond);
255: var_tracing++;
256: } else if (where->op == O_NAME) {
257: s = where->nameval;
258: if (!isblock(s)) {
259: error("\"%s\" is not a procedure or function", name(s));
260: }
261: n = codeloc(s);
262: addbp(n, STOP_BP, s, cond, NIL, srcline(firstline(s)));
263: } else {
264: stopinst(cmd, where, cond);
265: }
266: if (where != NIL) {
267: tfree(where);
268: }
269: }
270:
271: LOCAL stopinst(cmd, where, cond)
272: int cmd;
273: NODE *where;
274: NODE *cond;
275: {
276: LINENO line;
277: ADDRESS addr;
278:
279: if (where->op != O_QLINE) {
280: error("expected line number");
281: }
282: if (cmd == O_STOP) {
283: line = (LINENO) where->right->lconval;
284: addr = objaddr(line, where->left->sconval);
285: if (addr == (ADDRESS) -1) {
286: error("can't stop at that line");
287: }
288: } else {
289: line = -1;
290: addr = (ADDRESS) where->right->lconval;
291: }
292: addbp(addr, STOP_BP, NIL, cond, NIL, line);
293: }
294:
295: /*
296: * Implement stopping on assignment to a variable by adding it to
297: * the variable list.
298: */
299:
300: LOCAL stopvar(cmd, exp, where, cond)
301: int cmd;
302: NODE *exp;
303: NODE *where;
304: NODE *cond;
305: {
306: SYM *s;
307:
308: if (exp->op != O_RVAL) {
309: trerror("found %t, expected variable", exp);
310: }
311: if (cmd == O_STOPI) {
312: inst_tracing++;
313: }
314: var_tracing++;
315: addvar(TRSTOP, exp, cond);
316: if (where == NIL) {
317: s = program;
318: } else if (where->op == O_NAME) {
319: s = where->nameval;
320: } else {
321: error("bad location for stop");
322: }
323: addbp(codeloc(s), STOP_ON, s, cond, exp, 0);
324: }
325:
326: /*
327: * Figure out the block that contains the symbols
328: * in the given variable expression.
329: */
330:
331: LOCAL SYM *tcontainer(var)
332: NODE *var;
333: {
334: NODE *p;
335:
336: p = var;
337: while (p->op != O_NAME) {
338: if (isleaf(p->op)) {
339: panic("unexpected op %d in tcontainer", p->op);
340: /* NOTREACHED */
341: }
342: p = p->left;
343: }
344: return container(p->nameval);
345: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.