Annotation of 42BSD/ucb/dbx/events.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.