15470Slinton /* Copyright (c) 1982 Regents of the University of California */ 25470Slinton 3*5760Slinton static char sccsid[] = "@(#)trinfo.c 1.2 02/11/82"; 45470Slinton 55470Slinton /* 65470Slinton * Trace information management. 75470Slinton * 85470Slinton * The trace information is a list of variables that are being 95470Slinton * traced or whose value changing should cause a stop. 105470Slinton */ 115470Slinton 125470Slinton #include "defs.h" 135470Slinton #include "breakpoint.h" 145470Slinton #include "process.h" 155470Slinton #include "machine.h" 165470Slinton #include "sym.h" 175470Slinton #include "tree.h" 185470Slinton #include "source.h" 195470Slinton #include "object.h" 205470Slinton #include "tree/tree.rep" 215470Slinton 225470Slinton /* 235470Slinton * When tracing variables we keep a copy of their most recent value 245470Slinton * and compare it to the current one each time a breakpoint occurs. 255470Slinton * MAXTRSIZE is the maximum size variable we allow. 265470Slinton */ 275470Slinton 285470Slinton #define MAXTRSIZE 512 295470Slinton 305470Slinton /* 315470Slinton * The tracing structure is a list of information about all the 325470Slinton * variables that are being traced. 335470Slinton */ 345470Slinton 355470Slinton typedef struct trinfo { 36*5760Slinton TRTYPE trtype; 37*5760Slinton ADDRESS traddr; 38*5760Slinton SYM *trblock; 39*5760Slinton NODE *trvar; 40*5760Slinton NODE *trcond; 41*5760Slinton char *trvalue; 42*5760Slinton struct trinfo *trnext; 435470Slinton } TRINFO; 445470Slinton 455470Slinton LOCAL TRINFO *trhead; 465470Slinton 475470Slinton /* 485470Slinton * add a variable to be traced 495470Slinton */ 505470Slinton 515470Slinton addvar(trtype, node, cond) 525470Slinton TRTYPE trtype; 535470Slinton NODE *node; 545470Slinton NODE *cond; 555470Slinton { 56*5760Slinton register TRINFO *tp; 575470Slinton 58*5760Slinton tp = alloc(1, TRINFO); 59*5760Slinton tp->trtype = trtype; 60*5760Slinton tp->traddr = (ADDRESS) -1; 61*5760Slinton tp->trblock = curfunc; 62*5760Slinton tp->trvar = node; 63*5760Slinton tp->trcond = cond; 64*5760Slinton tp->trvalue = NIL; 65*5760Slinton tp->trnext = trhead; 66*5760Slinton trhead = tp; 675470Slinton } 685470Slinton 695470Slinton /* 705470Slinton * remove a variable from the trace list 715470Slinton */ 725470Slinton 735470Slinton delvar(trtype, node, cond) 745470Slinton TRTYPE trtype; 755470Slinton NODE *node; 765470Slinton NODE *cond; 775470Slinton { 78*5760Slinton register TRINFO *tp, *last; 795470Slinton 80*5760Slinton last = NIL; 81*5760Slinton for (tp = trhead; tp != NIL; tp = tp->trnext) { 82*5760Slinton if (tp->trtype == trtype && 83*5760Slinton tr_equal(tp->trvar, node) && 84*5760Slinton tr_equal(tp->trcond, cond)) { 85*5760Slinton break; 865470Slinton } 87*5760Slinton } 88*5760Slinton if (tp == NIL) { 89*5760Slinton trerror("can't delete term %t", node); 90*5760Slinton } 91*5760Slinton if (last == NIL) { 92*5760Slinton trhead = tp->trnext; 93*5760Slinton } else { 94*5760Slinton last->trnext = tp->trnext; 95*5760Slinton } 96*5760Slinton if (tp->trvalue != NIL) { 97*5760Slinton free(tp->trvalue); 98*5760Slinton } 99*5760Slinton free(tp); 1005470Slinton } 1015470Slinton 1025470Slinton /* 1035470Slinton * Print out any news about variables in the list whose 1045470Slinton * values have changed. 1055470Slinton */ 1065470Slinton 1075470Slinton prvarnews() 1085470Slinton { 109*5760Slinton register TRINFO *tp; 110*5760Slinton register NODE *p; 111*5760Slinton register int n; 112*5760Slinton SYM *s; 113*5760Slinton char buff[MAXTRSIZE]; 114*5760Slinton static LINENO prevline; 1155470Slinton 116*5760Slinton for (tp = trhead; tp != NIL; tp = tp->trnext) { 117*5760Slinton if (tp->trcond != NIL && !cond(tp->trcond)) { 118*5760Slinton continue; 1195470Slinton } 120*5760Slinton s = curfunc; 121*5760Slinton while (s != NIL && s != tp->trblock) { 122*5760Slinton s = container(s); 123*5760Slinton } 124*5760Slinton if (s == NIL) { 125*5760Slinton continue; 126*5760Slinton } 127*5760Slinton p = tp->trvar; 128*5760Slinton if (tp->traddr == (ADDRESS) -1) { 129*5760Slinton tp->traddr = lval(p->left); 130*5760Slinton } 131*5760Slinton n = size(p->nodetype); 132*5760Slinton dread(buff, tp->traddr, n); 133*5760Slinton if (tp->trvalue == NIL) { 134*5760Slinton tp->trvalue = alloc(n, char); 135*5760Slinton mov(buff, tp->trvalue, n); 136*5760Slinton mov(buff, sp, n); 137*5760Slinton sp += n; 138*5760Slinton if (tp->trtype == TRPRINT) { 139*5760Slinton printf("initially (at "); 140*5760Slinton printwhere(curline, srcfilename(pc)); 141*5760Slinton printf("):\t"); 142*5760Slinton prtree(p); 143*5760Slinton printf(" = "); 144*5760Slinton printval(p->nodetype); 145*5760Slinton putchar('\n'); 146*5760Slinton } 147*5760Slinton } else if (cmp(tp->trvalue, buff, n) != 0) { 148*5760Slinton mov(buff, tp->trvalue, n); 149*5760Slinton mov(buff, sp, n); 150*5760Slinton sp += n; 151*5760Slinton printf("after "); 152*5760Slinton printwhere(prevline, srcfilename(pc)); 153*5760Slinton printf(":\t"); 154*5760Slinton prtree(p); 155*5760Slinton printf(" = "); 156*5760Slinton printval(p->nodetype); 157*5760Slinton putchar('\n'); 158*5760Slinton if (tp->trtype == TRSTOP) { 159*5760Slinton isstopped = TRUE; 160*5760Slinton curline = srcline(pc); 161*5760Slinton printstatus(); 162*5760Slinton } 163*5760Slinton } 164*5760Slinton } 165*5760Slinton prevline = curline; 1665470Slinton } 1675470Slinton 1685470Slinton /* 1695470Slinton * Free the table. Note that trvar and trcond fields are not freed, 1705470Slinton * this is because they are the same as in the breakpoint table and 1715470Slinton * are freed by the bpfree routine. 1725470Slinton */ 1735470Slinton 1745470Slinton trfree() 1755470Slinton { 176*5760Slinton register TRINFO *tp, *next; 1775470Slinton 178*5760Slinton for (tp = trhead; tp != NIL; tp = next) { 179*5760Slinton next = tp->trnext; 180*5760Slinton if (tp->trvalue != NIL) { 181*5760Slinton free(tp->trvalue); 1825470Slinton } 183*5760Slinton free(tp); 184*5760Slinton } 185*5760Slinton trhead = NIL; 1865470Slinton } 187