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

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

unix.superglobalmegacorp.com

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