Annotation of 43BSDReno/pgrm/dbx/events.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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