BSD 4_3 release
[unix-history] / usr / src / ucb / pascal / pdx / breakpoint / bpact.c
CommitLineData
d8be300a
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
d1a17f17 6
d8be300a 7#ifndef lint
95f51977 8static char sccsid[] = "@(#)bpact.c 5.1 (Berkeley) 6/5/85";
d8be300a 9#endif not lint
d1a17f17
ML
10/*
11 * Routines for doing the right thing when a breakpoint is reached.
12 */
13
14#include "defs.h"
15#include "breakpoint.h"
16#include "sym.h"
17#include "tree.h"
18#include "source.h"
19#include "mappings.h"
20#include "runtime.h"
21#include "process.h"
22#include "machine.h"
23#include "main.h"
24#include "bp.rep"
25#include "tree/tree.rep"
26
27typedef enum { SAVE, NOSAVE } SAVEBP;
28
29LOCAL SAVEBP handlebp();
30
31/*
32 * A "delayed" breakpoint is one that has an action involving execution
33 * of code, e.g. at a CALL we want to step from the beginning of the
34 * procedure to the first line before printing parameters.
35 */
36
37LOCAL short delayed;
38
39#define NONE 0
40#define DELAY_CALL 1
41#define DELAY_STOP 2
42
43/*
44 * Take action at a breakpoint; if it's not a breakpoint return FALSE.
45 *
46 * As we go through the list of breakpoints, we have to remember
47 * the previous one so that "handlebp" can delete breakpoints on
48 * the fly if necessary.
49 *
50 * If the breakpoint is a STOP_BP, handlebp will set "isstopped". After
51 * going through the loop, bpact checks if "isstopped" is set and calls
52 * printstatus if it is. This is so multiple breakpoints at the same
53 * address, one of which is a STOP_BP, still work.
54 */
55
56#define isswitch(bptype) ( \
57 bptype == ALL_ON || bptype == ALL_OFF || \
58 bptype == TERM_ON || bptype == TERM_OFF || \
59 bptype == BLOCK_ON || bptype == BLOCK_OFF || \
60 bptype == STOP_ON || bptype == STOP_OFF \
61)
62
63BOOLEAN bpact()
64{
65 register BPINFO *p;
66 BPINFO *prev, *next;
67 BOOLEAN found;
68 ADDRESS oldpc;
69
70 delayed = NONE;
71 found = FALSE;
72 prev = NIL;
73 for (p = bphead; p != NIL; p = next) {
74 next = p->bpnext;
75 if (p->bpaddr == pc) {
76 prbpfound(p);
77 found = TRUE;
78 if (p->bpcond == NIL || isswitch(p->bptype) || cond(p->bpcond)) {
79 prbphandled();
80 if (handlebp(p) == NOSAVE) {
81 prbpnosave();
82 if (prev == NIL) {
83 bphead = next;
84 } else {
85 prev->bpnext = next;
86 }
87 dispose(p);
88 } else {
89 prbpsave();
90 prev = p;
91 }
92 } else {
93 prev = p;
94 }
95 } else {
96 prev = p;
97 }
98 }
99 if (delayed != NONE) {
100 oldpc = pc;
101 runtofirst();
102 if ((delayed&DELAY_CALL) == DELAY_CALL) {
103 SYM *s, *t;
104
105 s = curfunc;
106 t = whatblock(return_addr());
107 if (t == NIL) {
108 panic("can't find block for caller addr %d", caller_addr());
109 }
110 printcall(s, t);
111 addbp(return_addr(), RETURN, s, NIL, NIL, 0);
112 }
113 if (pc != oldpc) {
114 bpact();
115 }
116 if (isstopped) {
117 printstatus();
118 }
119 } else {
120 if (isstopped) {
121 printstatus();
122 }
123 }
124 fflush(stdout);
125 return(found);
126}
127
128/*
129 * Handle an expected breakpoint appropriately, return whether
130 * or not to save the breakpoint.
131 */
132
133LOCAL SAVEBP handlebp(p)
134BPINFO *p;
135{
136 register SYM *s, *t;
137 SAVEBP r;
138
139 r = SAVE;
140 switch(p->bptype) {
141 case ALL_ON:
142 curfunc = p->bpblock;
143 addcond(TRPRINT, p->bpcond);
144 if (p->bpline >= 0) {
145 tracing++;
146 } else {
147 inst_tracing++;
148 }
149 addbp(return_addr(), ALL_OFF, curfunc, p->bpcond, NIL, 0);
150 break;
151
152 case ALL_OFF:
153 r = NOSAVE;
154 if (p->bpline >= 0) {
155 tracing--;
156 } else {
157 inst_tracing--;
158 }
159 delcond(TRPRINT, p->bpcond);
160 curfunc = p->bpblock;
161 break;
162
163 case STOP_ON:
164 var_tracing++;
165 curfunc = p->bpblock;
166 if (p->bpnode != NIL) {
167 addvar(TRSTOP, p->bpnode, p->bpcond);
168 } else if (p->bpcond != NIL) {
169 addcond(TRSTOP, p->bpcond);
170 }
171 addbp(return_addr(), STOP_OFF, curfunc, p->bpcond, p->bpnode, 0);
172 break;
173
174 case STOP_OFF:
175 r = NOSAVE;
176 delcond(TRSTOP, p->bpcond);
177 var_tracing--;
178 curfunc = p->bpblock;
179 break;
180
181 case INST:
182 curline = p->bpline;
183 if (curline > 0) {
184 printf("trace: ");
185 printlines(curline, curline);
186 } else {
187 printf("inst trace: ");
188 printinst(pc, pc);
189 }
190 break;
191
192 case STOP_BP:
193 if (p->bpblock != NIL) {
194 delayed |= DELAY_STOP;
195 curfunc = p->bpblock;
196 }
197 curline = p->bpline;
198 isstopped = TRUE;
199 break;
200
201 case BLOCK_ON: {
202 BPINFO *nbp;
203
204 s = p->bpblock;
205 t = p->bpnode->nameval;
206 nbp = newbp(codeloc(t), CALL, t, p->bpcond, NIL, 0);
207 addbp(return_addr(), BLOCK_OFF, (SYM *) nbp, NIL, NIL, 0);
208 break;
209 }
210
211 case BLOCK_OFF: {
212 BPINFO *oldbp;
213
214 r = NOSAVE;
215 oldbp = (BPINFO *) p->bpblock;
216 delbp(oldbp->bpid);
217 break;
218 }
219
220 case CALL:
221 delayed |= DELAY_CALL;
222 curfunc = p->bpblock;
223 break;
224
225 case RETURN:
226 r = NOSAVE;
227 s = p->bpblock;
228 printrtn(s);
229 break;
230
231 case TERM_ON: {
232 ADDRESS addr;
233
234 curfunc = p->bpblock;
235 addvar(TRPRINT, p->bpnode, p->bpcond);
236 addr = return_addr();
237 addbp(addr, TERM_OFF, curfunc, p->bpcond, p->bpnode, 0);
238 var_tracing++;
239 break;
240 }
241
242 case TERM_OFF:
243 r = NOSAVE;
244 var_tracing--;
245 delvar(TRPRINT, p->bpnode, p->bpcond);
246 curfunc = p->bpblock;
247 break;
248
249 case AT_BP:
250 printf("at line %d: ", p->bpline);
251 eval(p->bpnode);
252 prtree(p->bpnode);
253 printf(" = ");
254 printval(p->bpnode->nodetype);
255 putchar('\n');
256 break;
257
258 /*
259 * Returning from a called procedure.
260 * Further breakpoint processing is not done, since if
261 * there were any it wouldn't be associated with the call.
262 */
263 case CALLPROC:
264 procreturn(p->bpblock);
265 delbp(p->bpid);
266 erecover();
267 /* NOTREACHED */
268
269 case END_BP:
270 r = NOSAVE;
271 endprogram();
272
273 default:
274 panic("unknown bptype %d in cont", p->bptype);
275 /* NOTREACHED */
276 }
277 return(r);
278}
279
280/*
281 * Internal trace routines.
282 */
283
284LOCAL char *prbptype[] ={
285 "ALL_ON", "ALL_OFF", "INST", "CALL", "RETURN", "BLOCK_ON", "BLOCK_OFF",
286 "TERM_ON", "TERM_OFF", "AT_BP", "STOP_BP", "CALLPROC", "END_BP",
287 "STOP_ON", "STOP_OFF",
288};
289
290LOCAL prbpfound(p)
291BPINFO *p;
292{
293 if (option('b')) {
294 printf("%s breakpoint found at pc %d, line %d -- ",
295 prbptype[(int) p->bptype], p->bpaddr, p->bpline);
296 }
297}
298
299LOCAL prbphandled()
300{
301 if (option('b')) {
302 printf("handled, ");
303 }
304}
305
306LOCAL prbpnosave()
307{
308 if (option('b')) {
309 printf("not saved\n");
310 fflush(stdout);
311 }
312}
313
314LOCAL prbpsave()
315{
316 if (option('b')) {
317 printf("saved\n");
318 fflush(stdout);
319 }
320}