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: }

Defined functions

bp_alloc defined in line 443; used 6 times
bpact defined in line 491; used 7 times
bpfree defined in line 473; used 1 times
bpinit defined in line 106; used 2 times
builtinsym defined in line 92; used 3 times
callnews defined in line 660; used 2 times
canskip defined in line 334; used 1 times
chklist defined in line 668; used 3 times
condbp defined in line 273; used 3 times
delevent defined in line 149; used 6 times
event_alloc defined in line 125; used 2 times
findtrinfo defined in line 720; used 2 times
fixbps defined in line 850; used 2 times
printcond defined in line 409; used 1 times
printevent defined in line 369; used 9 times
printeventid defined in line 399; used 2 times
printifchanged defined in line 757; used 1 times
printrmtr defined in line 624; used 6 times
setallbps defined in line 879; used 2 times
status defined in line 358; used 5 times
stopifchanged defined in line 799; used 1 times
tcontainer defined in line 294; used 4 times
traceoff defined in line 583; used 1 times
traceon defined in line 539; used 1 times
translate defined in line 202; used 1 times
trfree defined in line 832; used 1 times
unsetallbps defined in line 892; used 2 times

Defined variables

curevent defined in line 73; used 2 times
eventid defined in line 74; used 2 times
rcsid defined in line 11; never used
sccsid defined in line 8; never used
trid defined in line 75; used 8 times

Defined struct's

Breakpoint defined in line 57; used 1 times
  • in line 32
Event defined in line 50; used 1 times
  • in line 31
Trcmd defined in line 77; never used
Trinfo defined in line 706; used 1 times

Defined typedef's

Breakpoint defined in line 32; used 17 times
Event defined in line 31; used 20 times
Trcmd defined in line 81; used 17 times
Trinfo defined in line 704; used 8 times

Defined macros

MAXTRSIZE defined in line 698; used 2 times
addevent defined in line 45; never used
bplist_append defined in line 69; used 1 times
event_once defined in line 46; never used
eventlist_append defined in line 68; used 1 times
Last modified: 1985-05-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2590
Valid CSS Valid XHTML 1.0 Strict