save & restore all tty settings
[unix-history] / usr / src / old / dbx / events.c
CommitLineData
4298caf5
ML
1/* Copyright (c) 1982 Regents of the University of California */
2
c2e3c60c 3static char sccsid[] = "@(#)events.c 1.6 (Berkeley) %G%";
4298caf5
ML
4
5/*
6 * Event/breakpoint managment.
7 */
8
9#include "defs.h"
10#include "events.h"
11#include "main.h"
12#include "symbols.h"
13#include "tree.h"
14#include "eval.h"
15#include "source.h"
16#include "mappings.h"
2fd0f574 17#include "runtime.h"
4298caf5
ML
18#include "process.h"
19#include "machine.h"
20#include "lists.h"
21
22#ifndef public
23typedef struct Event *Event;
24typedef struct Breakpoint *Breakpoint;
25
26Boolean inst_tracing;
27Boolean single_stepping;
28Boolean isstopped;
29
30#include "symbols.h"
31
32Symbol linesym;
33Symbol procsym;
34Symbol pcsym;
35Symbol retaddrsym;
36
37#define addevent(cond, cmdlist) event_alloc(false, cond, cmdlist)
38#define event_once(cond, cmdlist) event_alloc(true, cond, cmdlist)
39
40#endif
41
42struct Event {
43 unsigned int id;
44 Boolean temporary;
45 Node condition;
46 Cmdlist actions;
47};
48
49struct Breakpoint {
50 Event event;
51 Address bpaddr;
52 Lineno bpline;
53 Cmdlist actions;
54};
55
56typedef List Eventlist;
57typedef List Bplist;
58
59#define eventlist_append(event, el) list_append(list_item(event), nil, el)
60#define bplist_append(bp, bl) list_append(list_item(bp), nil, bl)
61
62private Eventlist eventlist; /* list of active events */
63private Bplist bplist; /* list of active breakpoints */
64private Integer eventid; /* id number of next allocated event */
65private Integer trid; /* id number of next allocated trace */
66
67typedef struct Trcmd {
68 Integer trid;
69 Event event;
70 Cmdlist cmdlist;
71} *Trcmd;
72
73private List eachline; /* commands to execute after each line */
74private List eachinst; /* commands to execute after each instruction */
75
76private Breakpoint bp_alloc();
77
78/*
79 * Initialize breakpoint information.
80 */
81
82private Symbol builtinsym(str, class, type)
83String str;
84Symclass class;
85Symbol type;
86{
87 Symbol s;
88
89 s = insert(identname(str, true));
90 s->language = findlanguage(".s");
91 s->class = class;
92 s->type = type;
93 return s;
94}
95
96public bpinit()
97{
98 linesym = builtinsym("$line", VAR, t_int);
99 procsym = builtinsym("$proc", PROC, nil);
100 pcsym = lookup(identname("$pc", true));
101 if (pcsym == nil) {
102 panic("can't find $pc");
103 }
104 retaddrsym = builtinsym("$retaddr", VAR, t_int);
105 eventlist = list_alloc();
106 bplist = list_alloc();
107 eachline = list_alloc();
108 eachinst = list_alloc();
109}
110
111/*
112 * Trap an event and do the associated commands when it occurs.
113 */
114
115public Event event_alloc(istmp, econd, cmdlist)
116Boolean istmp;
117Node econd;
118Cmdlist cmdlist;
119{
120 register Event e;
121
122 e = new(Event);
252b7653 123 e->id = ++eventid;
4298caf5
ML
124 e->temporary = istmp;
125 e->condition = econd;
126 e->actions = cmdlist;
252b7653
SL
127 if (tracebpts) {
128 debugevent("event_alloc: new", e);
129 putchar('\n');
130 fflush(stdout);
131 }
4298caf5
ML
132 eventlist_append(e, eventlist);
133 translate(e);
134 return e;
135}
136
137/*
138 * Delete the event with the given id.
2fd0f574 139 * Returns whether it's successful or not.
4298caf5
ML
140 */
141
2fd0f574 142public boolean delevent (id)
4298caf5
ML
143unsigned int id;
144{
145 Event e;
146 Breakpoint bp;
147 Trcmd t;
2fd0f574 148 boolean found;
4298caf5 149
2fd0f574 150 found = false;
4298caf5
ML
151 foreach (Event, e, eventlist)
152 if (e->id == id) {
2fd0f574 153 found = true;
4298caf5
ML
154 foreach (Breakpoint, bp, bplist)
155 if (bp->event == e) {
252b7653
SL
156 if (tracebpts)
157 debugbpt("delevent: deleting", bp);
4298caf5
ML
158 list_delete(list_curitem(bplist), bplist);
159 }
160 endfor
2fd0f574 161 list_delete(list_curitem(eventlist), eventlist);
4298caf5
ML
162 break;
163 }
164 endfor
165 foreach (Trcmd, t, eachline)
166 if (t->event->id == id) {
2fd0f574 167 found = true;
4298caf5
ML
168 printrmtr(t);
169 list_delete(list_curitem(eachline), eachline);
170 }
171 endfor
172 foreach (Trcmd, t, eachinst)
173 if (t->event->id == id) {
2fd0f574 174 found = true;
4298caf5
ML
175 printrmtr(t);
176 list_delete(list_curitem(eachinst), eachinst);
177 }
178 endfor
179 if (list_size(eachinst) == 0) {
180 inst_tracing = false;
181 if (list_size(eachline) == 0) {
182 single_stepping = false;
183 }
184 }
2fd0f574 185 return found;
4298caf5
ML
186}
187
188/*
189 * Translate an event into the appropriate breakpoints and actions.
190 * While we're at it, turn on the breakpoints if the condition is true.
191 */
192
193private translate(e)
194Event e;
195{
196 Breakpoint bp;
197 Symbol s;
198 Node place;
199 Lineno line;
200 Address addr;
201
202 checkref(e->condition);
203 switch (e->condition->op) {
204 case O_EQ:
205 if (e->condition->value.arg[0]->op == O_SYM) {
206 s = e->condition->value.arg[0]->value.sym;
207 place = e->condition->value.arg[1];
208 if (s == linesym) {
209 if (place->op == O_QLINE) {
210 line = place->value.arg[1]->value.lcon;
2fd0f574 211 addr = objaddr(line, place->value.arg[0]->value.scon);
4298caf5
ML
212 } else {
213 eval(place);
214 line = pop(long);
215 addr = objaddr(line, cursource);
216 }
217 if (addr == NOADDR) {
2fd0f574
SL
218 if (not delevent(e->id)) {
219 printf("!! dbx.translate: can't undo event %d?\n",
220 e->id);
221 }
4298caf5
ML
222 beginerrmsg();
223 fprintf(stderr, "no executable code at line ");
224 prtree(stderr, place);
225 enderrmsg();
226 }
227 bp = bp_alloc(e, addr, line, e->actions);
228 } else if (s == procsym) {
229 eval(place);
230 s = pop(Symbol);
231 bp = bp_alloc(e, codeloc(s), 0, e->actions);
232 if (isactive(s) and pc != codeloc(program)) {
233 evalcmdlist(e->actions);
234 }
235 } else if (s == pcsym) {
236 eval(place);
237 bp = bp_alloc(e, pop(Address), 0, e->actions);
238 } else {
239 condbp(e);
240 }
241 } else {
242 condbp(e);
243 }
244 break;
245
246 /*
247 * These should be handled specially.
248 * But for now I'm ignoring the problem.
249 */
250 case O_AND:
251 case O_OR:
252 default:
253 condbp(e);
254 break;
255 }
256}
257
258/*
259 * Create a breakpoint for a condition that cannot be pinpointed
260 * to happening at a particular address, but one for which we
261 * must single step and check the condition after each statement.
262 */
263
264private condbp(e)
265Event e;
266{
267 Symbol p;
268 Breakpoint bp;
269 Cmdlist actions;
270
271 p = tcontainer(e->condition);
272 if (p == nil) {
273 p = program;
274 }
275 actions = buildcmdlist(build(O_IF, e->condition, e->actions));
276 actions = buildcmdlist(build(O_TRACEON, false, actions));
277 bp = bp_alloc(e, codeloc(p), 0, actions);
278}
279
280/*
281 * Determine the deepest nested subprogram that still contains
282 * all elements in the given expression.
283 */
284
285public Symbol tcontainer(exp)
286Node exp;
287{
288 Integer i;
289 Symbol s, t, u, v;
290
291 checkref(exp);
292 s = nil;
293 if (exp->op == O_SYM) {
294 s = container(exp->value.sym);
295 } else if (not isleaf(exp->op)) {
296 for (i = 0; i < nargs(exp->op); i++) {
297 t = tcontainer(exp->value.arg[i]);
298 if (t != nil) {
299 if (s == nil) {
300 s = t;
301 } else {
302 u = s;
303 v = t;
304 while (u != v and u != nil) {
305 u = container(u);
306 v = container(v);
307 }
308 if (u == nil) {
309 panic("bad ancestry for \"%s\"", symname(s));
310 } else {
311 s = u;
312 }
313 }
314 }
315 }
316 }
317 return s;
318}
319
e1bc702e
ML
320/*
321 * Determine if the given function can be executed at full speed.
322 * This can only be done if there are no breakpoints within the function.
323 */
324
325public Boolean canskip(f)
326Symbol f;
327{
328 Breakpoint p;
329 Boolean ok;
330
331 ok = true;
332 foreach (Breakpoint, p, bplist)
333 if (whatblock(p->bpaddr) == f) {
334 ok = false;
335 break;
336 }
337 endfor
338 return ok;
339}
340
4298caf5
ML
341/*
342 * Print out what's currently being traced by looking at
343 * the currently active events.
344 *
345 * Some convolution here to translate internal representation
346 * of events back into something more palatable.
347 */
348
349public status()
350{
351 Event e;
4298caf5
ML
352
353 foreach (Event, e, eventlist)
354 if (not e->temporary) {
e1bc702e 355 printevent(e);
4298caf5
ML
356 }
357 endfor
358}
359
e1bc702e
ML
360public printevent(e)
361Event e;
362{
363 Command cmd;
364
365 if (not isredirected()) {
2fd0f574 366 printeventid(e->id);
e1bc702e
ML
367 }
368 cmd = list_element(Command, list_head(e->actions));
369 if (cmd->op == O_PRINTCALL) {
370 printf("trace ");
371 printname(stdout, cmd->value.sym);
372 } else {
373 if (list_size(e->actions) > 1) {
374 printf("{ ");
375 }
376 foreach (Command, cmd, e->actions)
377 printcmd(stdout, cmd);
378 if (not list_islast()) {
379 printf("; ");
380 }
381 endfor
382 if (list_size(e->actions) > 1) {
383 printf(" }");
384 }
385 printcond(e->condition);
386 }
387 printf("\n");
388}
389
2fd0f574
SL
390private printeventid (id)
391integer id;
392{
393 printf("[%d] ", id);
394}
395
4298caf5
ML
396/*
397 * Print out a condition.
398 */
399
400private printcond(cond)
401Node cond;
402{
403 Symbol s;
404 Node place;
405
406 if (cond->op == O_EQ and cond->value.arg[0]->op == O_SYM) {
407 s = cond->value.arg[0]->value.sym;
408 place = cond->value.arg[1];
409 if (s == procsym) {
410 if (place->value.sym != program) {
411 printf(" in ");
412 printname(stdout, place->value.sym);
413 }
414 } else if (s == linesym) {
415 printf(" at ");
416 prtree(stdout, place);
417 } else if (s == pcsym or s == retaddrsym) {
418 printf("i at ");
419 prtree(stdout, place);
420 } else {
421 printf(" when ");
422 prtree(stdout, cond);
423 }
424 } else {
425 printf(" when ");
426 prtree(stdout, cond);
427 }
428}
429
430/*
431 * Add a breakpoint to the list and return it.
432 */
433
434private Breakpoint bp_alloc(e, addr, line, actions)
435Event e;
436Address addr;
437Lineno line;
438Cmdlist actions;
439{
440 register Breakpoint p;
441
442 p = new(Breakpoint);
443 p->event = e;
444 p->bpaddr = addr;
445 p->bpline = line;
446 p->actions = actions;
252b7653
SL
447 if (tracebpts)
448 debugbpt("bp_alloc: new", p);
4298caf5
ML
449 bplist_append(p, bplist);
450 return p;
451}
452
453/*
454 * Free all storage in the event and breakpoint tables.
455 */
456
457public bpfree()
458{
459 register Event e;
460
461 fixbps();
462 foreach (Event, e, eventlist)
2fd0f574
SL
463 if (not delevent(e->id)) {
464 printf("!! dbx.bpfree: can't delete event %d\n", e->id);
465 }
4298caf5
ML
466 list_delete(list_curitem(eventlist), eventlist);
467 endfor
468}
469
470/*
471 * Determine if the program stopped at a known breakpoint
472 * and if so do the associated commands.
473 */
474
475public Boolean bpact()
476{
477 register Breakpoint p;
478 Boolean found;
2fd0f574 479 integer eventId;
4298caf5
ML
480
481 found = false;
482 foreach (Breakpoint, p, bplist)
483 if (p->bpaddr == pc) {
252b7653
SL
484 if (tracebpts)
485 debugbpt("bpact: found", p);
4298caf5 486 found = true;
4298caf5 487 evalcmdlist(p->actions);
252b7653
SL
488 eventId = p->event->id;
489 if (p->event->temporary and not delevent(p->event->id))
490 printf("!! dbx.bpact: can't find event %d\n", eventId);
4298caf5
ML
491 }
492 endfor
493 if (isstopped) {
2fd0f574
SL
494 if (found) {
495 printeventid(eventId);
496 }
4298caf5
ML
497 printstatus();
498 }
499 fflush(stdout);
500 return found;
501}
502
503/*
504 * Begin single stepping and executing the given commands after each step.
505 * If the first argument is true step by instructions, otherwise
506 * step by source lines.
507 *
508 * We automatically set a breakpoint at the end of the current procedure
509 * to turn off the given tracing.
510 */
511
512public traceon(inst, event, cmdlist)
513Boolean inst;
514Event event;
515Cmdlist cmdlist;
516{
517 register Trcmd trcmd;
4298caf5 518 Cmdlist actions;
e1bc702e 519 Address ret;
4298caf5
ML
520
521 trcmd = new(Trcmd);
252b7653 522 trcmd->trid = ++trid;
4298caf5
ML
523 trcmd->event = event;
524 trcmd->cmdlist = cmdlist;
252b7653
SL
525 if (tracebpts)
526 debugtrace("traceon: adding", trcmd);
4298caf5
ML
527 single_stepping = true;
528 if (inst) {
529 inst_tracing = true;
530 list_append(list_item(trcmd), nil, eachinst);
531 } else {
532 list_append(list_item(trcmd), nil, eachline);
533 }
e1bc702e
ML
534 ret = return_addr();
535 if (ret != 0) {
252b7653
SL
536 /*
537 * Must create new temporary event for traceoff action;
538 * otherwise traceoff will take place but the breakpoint
539 * won't be deleted. This results in a panic the next
540 * time we enter the region where tracing takes place since
541 * the associate trace id (of the traceoff command) no
542 * longer exists.
543 */
544 event_once(build(O_EQ, build(O_SYM, pcsym), build(O_LCON, ret)),
545 buildcmdlist(build(O_TRACEOFF, trcmd->trid)));
4298caf5
ML
546 }
547}
548
549/*
550 * Turn off some kind of tracing.
551 * Strictly an internal command, this cannot be invoked by the user.
552 */
553
554public traceoff(id)
555Integer id;
556{
557 register Trcmd t;
558 register Boolean found;
559
560 found = false;
561 foreach (Trcmd, t, eachline)
562 if (t->trid == id) {
563 printrmtr(t);
564 list_delete(list_curitem(eachline), eachline);
565 found = true;
566 break;
567 }
568 endfor
569 if (not found) {
570 foreach (Trcmd, t, eachinst)
571 if (t->event->id == id) {
572 printrmtr(t);
573 list_delete(list_curitem(eachinst), eachinst);
574 found = true;
575 break;
576 }
577 endfor
578 if (not found) {
252b7653 579 debugallevents("traceoff");
4298caf5
ML
580 panic("missing trid %d", id);
581 }
582 }
583 if (list_size(eachinst) == 0) {
584 inst_tracing = false;
585 if (list_size(eachline) == 0) {
586 single_stepping = false;
587 }
588 }
589}
590
591/*
592 * If breakpoints are being traced, note that a Trcmd is being deleted.
593 */
594
595private printrmtr(t)
596Trcmd t;
597{
252b7653
SL
598 if (tracebpts)
599 debugtrace("removing", t);
600}
601
602/*
603 * Debugging routines.
604 */
605debugallevents(s)
606String s;
607{
608 register Trcmd t;
609 register Event e;
610 register Breakpoint bp;
611
612 if (s)
613 printf("%s:\n", s);
614 if (eachline) {
615 printf("Traces (eachline):\n");
616 foreach (Trcmd, t, eachline)
617 debugtrace("\t", t);
618 endfor
619 }
620 if (eachinst) {
621 printf("Trace (eachinst):\n");
622 foreach (Trcmd, t, eachinst)
623 debugtrace("\t", t);
624 endfor
4298caf5 625 }
252b7653
SL
626 if (bplist) {
627 printf("Breakpoints:\n");
628 foreach (Breakpoint, bp, bplist)
629 debugbpt("\t", bp);
630 endfor
631 }
632 if (eventlist) {
633 printf("Events:\n");
634 foreach (Event, e, eventlist)
635 debugevent("\t", e);
636 putchar('\n');
637 endfor
638 }
639 fflush(stdout);
640}
641
642private debugtrace(s, t)
643String s;
644Trcmd t;
645{
646
647 if (s)
648 printf("%s ", s);
649 printf("trace %d ", t->trid);
650 debugevent("for", t->event);
651 printf("\n");
652 fflush(stdout);
653}
654
655private debugbpt(s, bp)
656String s;
657Breakpoint bp;
658{
659
660 if (s)
661 printf("%s ", s);
662 debugevent("breakpoint for", bp->event);
663 printf("; loc 0x%x", bp->bpaddr);
664 if (bp->actions)
665 debugactions(" ", bp->actions, nil);
666 putchar('\n');
667 fflush(stdout);
668}
669
670private debugevent(s, e)
671String s;
672Event e;
673{
674
675 if (s)
676 printf("%s ", s);
677 if (e == nil) {
678 printf("nil event");
679 return;
680 }
681 if (e->temporary)
682 printf("temporary ");
683 printf("event %d", e->id);
684}
685
686debugactions(s, cl, condition)
687String s;
688Cmdlist cl;
689Node condition;
690{
691 Command c;
692
693 if (s)
694 printf("%s ", s);
695 c = list_element(Command, list_head(cl));
696 if (c->op == O_PRINTCALL) {
697 printf("trace ");
698 printname(stdout, c->value.sym);
699 return;
700 }
701 if (list_size(cl) > 1)
702 printf("{ ");
703 foreach (Command, c, cl)
704 printcmd(stdout, c);
705 if (not list_islast())
706 printf("; ");
707 endfor
708 if (list_size(cl) > 1)
709 printf(" }");
710 if (condition)
711 printcond(condition);
4298caf5
ML
712}
713
714/*
715 * Print out news during single step tracing.
716 */
717
718public printnews()
719{
720 register Trcmd t;
721
722 foreach (Trcmd, t, eachline)
723 evalcmdlist(t->cmdlist);
724 endfor
725 foreach (Trcmd, t, eachinst)
726 evalcmdlist(t->cmdlist);
727 endfor
728 bpact();
729}
730
731/*
732 * A procedure call/return has occurred while single-stepping,
733 * note it if we're tracing lines.
734 */
735
736private Boolean chklist();
737
738public callnews(iscall)
739Boolean iscall;
740{
741 if (not chklist(eachline, iscall)) {
742 chklist(eachinst, iscall);
743 }
744}
745
746private Boolean chklist(list, iscall)
747List list;
748Boolean iscall;
749{
750 register Trcmd t;
751 register Command cmd;
752
2fd0f574 753 setcurfunc(whatblock(pc));
4298caf5
ML
754 foreach (Trcmd, t, list)
755 foreach (Command, cmd, t->cmdlist)
756 if (cmd->op == O_PRINTSRCPOS and
757 (cmd->value.arg[0] == nil or cmd->value.arg[0]->op == O_QLINE)) {
4298caf5
ML
758 if (iscall) {
759 printentry(curfunc);
760 } else {
761 printexit(curfunc);
762 }
763 return true;
764 }
765 endfor
766 endfor
767 return false;
768}
769
770/*
771 * When tracing variables we keep a copy of their most recent value
772 * and compare it to the current one each time a breakpoint occurs.
773 * MAXTRSIZE is the maximum size variable we allow.
774 */
775
776#define MAXTRSIZE 512
777
778/*
779 * List of variables being watched.
780 */
781
782typedef struct Trinfo *Trinfo;
783
784struct Trinfo {
785 Node variable;
786 Address traddr;
787 Symbol trblock;
788 char *trvalue;
789};
790
791private List trinfolist;
792
793/*
794 * Find the trace information record associated with the given record.
795 * If there isn't one then create it and add it to the list.
796 */
797
798private Trinfo findtrinfo(p)
799Node p;
800{
801 register Trinfo tp;
802 Boolean isnew;
803
804 isnew = true;
805 if (trinfolist == nil) {
806 trinfolist = list_alloc();
807 } else {
808 foreach (Trinfo, tp, trinfolist)
809 if (tp->variable == p) {
810 isnew = false;
811 break;
812 }
813 endfor
814 }
815 if (isnew) {
816 if (tracebpts) {
817 printf("adding trinfo for \"");
818 prtree(stdout, p);
819 printf("\"\n");
820 }
821 tp = new(Trinfo);
822 tp->variable = p;
823 tp->traddr = lval(p);
824 tp->trvalue = nil;
825 list_append(list_item(tp), nil, trinfolist);
826 }
827 return tp;
828}
829
c2e3c60c
SL
830#define cast(size, loc, val) \
831 switch (size) { \
832 case sizeof (char): *(char *)(loc) = (val); break; \
833 case sizeof (short): *(short *)(loc) = (val); break; \
834 default: *(int *)(loc) = (val); break; \
835 }
4298caf5
ML
836/*
837 * Print out the value of a variable if it has changed since the
838 * last time we checked.
839 */
840
841public printifchanged(p)
842Node p;
843{
844 register Trinfo tp;
845 register int n;
846 char buff[MAXTRSIZE];
847 static Lineno prevline;
848
849 tp = findtrinfo(p);
850 n = size(p->nodetype);
c2e3c60c
SL
851 if (p->op == O_SYM and isreg(p->value.sym)) {
852 int regval = address(p->value.sym, nil);
853
854 cast(n, buff, regval);
855 } else
856 dread(buff, tp->traddr, n);
4298caf5
ML
857 if (tp->trvalue == nil) {
858 tp->trvalue = newarr(char, n);
859 mov(buff, tp->trvalue, n);
860 mov(buff, sp, n);
861 sp += n;
862 printf("initially (at line %d):\t", curline);
863 prtree(stdout, p);
864 printf(" = ");
865 printval(p->nodetype);
866 putchar('\n');
867 } else if (cmp(tp->trvalue, buff, n) != 0) {
868 mov(buff, tp->trvalue, n);
869 mov(buff, sp, n);
870 sp += n;
871 printf("after line %d:\t", prevline);
872 prtree(stdout, p);
873 printf(" = ");
874 printval(p->nodetype);
875 putchar('\n');
876 }
877 prevline = curline;
878}
879
880/*
881 * Stop if the value of the given expression has changed.
882 */
883
884public stopifchanged(p)
885Node p;
886{
887 register Trinfo tp;
888 register int n;
889 char buff[MAXTRSIZE];
890 static Lineno prevline;
891
892 tp = findtrinfo(p);
893 n = size(p->nodetype);
894 dread(buff, tp->traddr, n);
895 if (tp->trvalue == nil) {
896 tp->trvalue = newarr(char, n);
897 mov(buff, tp->trvalue, n);
898 isstopped = true;
899 } else if (cmp(tp->trvalue, buff, n) != 0) {
900 mov(buff, tp->trvalue, n);
2fd0f574
SL
901 mov(buff, sp, n);
902 sp += n;
903 printf("after line %d:\t", prevline);
904 prtree(stdout, p);
905 printf(" = ");
906 printval(p->nodetype);
907 putchar('\n');
4298caf5
ML
908 isstopped = true;
909 }
910 prevline = curline;
911}
912
913/*
914 * Free the tracing table.
915 */
916
917public trfree()
918{
919 register Trinfo tp;
920
921 foreach (Trinfo, tp, trinfolist)
922 dispose(tp->trvalue);
923 dispose(tp);
924 list_delete(list_curitem(trinfolist), trinfolist);
925 endfor
926}
927
928/*
929 * Fix up breakpoint information before continuing execution.
930 *
931 * It's necessary to destroy events and breakpoints that were created
932 * temporarily and still exist because the program terminated abnormally.
933 */
934
935public fixbps()
936{
937 register Event e;
938 register Trcmd t;
939
940 single_stepping = false;
941 inst_tracing = false;
942 trfree();
943 foreach (Event, e, eventlist)
944 if (e->temporary) {
2fd0f574
SL
945 if (not delevent(e->id)) {
946 printf("!! dbx.fixbps: can't find event %d\n", e->id);
947 }
4298caf5
ML
948 }
949 endfor
950 foreach (Trcmd, t, eachline)
951 printrmtr(t);
952 list_delete(list_curitem(eachline), eachline);
953 endfor
954 foreach (Trcmd, t, eachinst)
955 printrmtr(t);
956 list_delete(list_curitem(eachinst), eachinst);
957 endfor
958}
959
960/*
961 * Set all breakpoints in object code.
962 */
963
964public setallbps()
965{
966 register Breakpoint p;
967
968 foreach (Breakpoint, p, bplist)
969 setbp(p->bpaddr);
970 endfor
971}
972
973/*
974 * Undo damage done by "setallbps".
975 */
976
977public unsetallbps()
978{
979 register Breakpoint p;
980
981 foreach (Breakpoint, p, bplist)
982 unsetbp(p->bpaddr);
983 endfor
984}