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

unix.superglobalmegacorp.com

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