1 /*
2  * Copyright (c) 1980 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[] = "@(#)trinfo.c	5.1 (Berkeley) 06/05/85";
9 #endif not lint
10 
11 /*
12  * Trace information management.
13  *
14  * The trace information is a list of variables that are being
15  * traced or whose value changing should cause a stop.
16  */
17 
18 #include "defs.h"
19 #include "breakpoint.h"
20 #include "process.h"
21 #include "machine.h"
22 #include "sym.h"
23 #include "tree.h"
24 #include "source.h"
25 #include "object.h"
26 #include "tree/tree.rep"
27 
28 /*
29  * When tracing variables we keep a copy of their most recent value
30  * and compare it to the current one each time a breakpoint occurs.
31  * MAXTRSIZE is the maximum size variable we allow.
32  */
33 
34 #define MAXTRSIZE 512
35 
36 /*
37  * The tracing structure is a list of information about all the
38  * variables that are being traced.
39  */
40 
41 typedef struct trinfo {
42     TRTYPE trtype;
43     ADDRESS traddr;
44     SYM *trblock;
45     NODE *trvar;
46     NODE *trcond;
47     char *trvalue;
48     struct trinfo *trnext;
49 } TRINFO;
50 
51 LOCAL TRINFO *trhead;
52 
53 /*
54  * add a variable to be traced
55  */
56 
57 addvar(trtype, node, cond)
58 TRTYPE trtype;
59 NODE *node;
60 NODE *cond;
61 {
62     register TRINFO *tp;
63 
64     tp = alloc(1, TRINFO);
65     tp->trtype = trtype;
66     tp->traddr = (ADDRESS) -1;
67     tp->trblock = curfunc;
68     tp->trvar = node;
69     tp->trcond = cond;
70     tp->trvalue = NIL;
71     tp->trnext = trhead;
72     trhead = tp;
73 }
74 
75 /*
76  * remove a variable from the trace list
77  */
78 
79 delvar(trtype, node, cond)
80 TRTYPE trtype;
81 NODE *node;
82 NODE *cond;
83 {
84     register TRINFO *tp, *last;
85 
86     last = NIL;
87     for (tp = trhead; tp != NIL; tp = tp->trnext) {
88 	if (tp->trtype == trtype &&
89 	    tr_equal(tp->trvar, node) &&
90 	    tr_equal(tp->trcond, cond)) {
91 	    break;
92 	}
93     }
94     if (tp == NIL) {
95 	trerror("can't delete term %t", node);
96     }
97     if (last == NIL) {
98 	trhead = tp->trnext;
99     } else {
100 	last->trnext = tp->trnext;
101     }
102     if (tp->trvalue != NIL) {
103 	free(tp->trvalue);
104     }
105     free(tp);
106 }
107 
108 /*
109  * Print out any news about variables in the list whose
110  * values have changed.
111  */
112 
113 prvarnews()
114 {
115     register TRINFO *tp;
116     register NODE *p;
117     register int n;
118     SYM *s;
119     char buff[MAXTRSIZE];
120     static LINENO prevline;
121 
122     for (tp = trhead; tp != NIL; tp = tp->trnext) {
123 	if (tp->trcond != NIL && !cond(tp->trcond)) {
124 	    continue;
125 	}
126 	s = curfunc;
127 	while (s != NIL && s != tp->trblock) {
128 	    s = container(s);
129 	}
130 	if (s == NIL) {
131 	    continue;
132 	}
133 	p = tp->trvar;
134 	if (tp->traddr == (ADDRESS) -1) {
135 	    tp->traddr = lval(p->left);
136 	}
137 	n = size(p->nodetype);
138 	dread(buff, tp->traddr, n);
139 	if (tp->trvalue == NIL) {
140 	    tp->trvalue = alloc(n, char);
141 	    mov(buff, tp->trvalue, n);
142 	    mov(buff, sp, n);
143 	    sp += n;
144 	    if (tp->trtype == TRPRINT) {
145 		printf("initially (at ");
146 		printwhere(curline, srcfilename(pc));
147 		printf("):\t");
148 		prtree(p);
149 		printf(" = ");
150 		printval(p->nodetype);
151 		putchar('\n');
152 	    }
153 	} else if (cmp(tp->trvalue, buff, n) != 0) {
154 	    mov(buff, tp->trvalue, n);
155 	    mov(buff, sp, n);
156 	    sp += n;
157 	    printf("after ");
158 	    printwhere(prevline, srcfilename(pc));
159 	    printf(":\t");
160 	    prtree(p);
161 	    printf(" = ");
162 	    printval(p->nodetype);
163 	    putchar('\n');
164 	    if (tp->trtype == TRSTOP) {
165 		isstopped = TRUE;
166 		curline = srcline(pc);
167 		printstatus();
168 	    }
169 	}
170     }
171     prevline = curline;
172 }
173 
174 /*
175  * Free the table.  Note that trvar and trcond fields are not freed,
176  * this is because they are the same as in the breakpoint table and
177  * are freed by the bpfree routine.
178  */
179 
180 trfree()
181 {
182     register TRINFO *tp, *next;
183 
184     for (tp = trhead; tp != NIL; tp = next) {
185 	next = tp->trnext;
186 	if (tp->trvalue != NIL) {
187 	    free(tp->trvalue);
188 	}
189 	free(tp);
190     }
191     trhead = NIL;
192 }
193