148103Sbostic /*-
2*62122Sbostic  * Copyright (c) 1980, 1993
3*62122Sbostic  *	The Regents of the University of California.  All rights reserved.
448103Sbostic  *
548103Sbostic  * %sccs.include.redist.c%
622282Sdist  */
75470Slinton 
822282Sdist #ifndef lint
9*62122Sbostic static char sccsid[] = "@(#)trinfo.c	8.1 (Berkeley) 06/06/93";
1048103Sbostic #endif /* not lint */
115470Slinton 
125470Slinton /*
135470Slinton  * Trace information management.
145470Slinton  *
155470Slinton  * The trace information is a list of variables that are being
165470Slinton  * traced or whose value changing should cause a stop.
175470Slinton  */
185470Slinton 
195470Slinton #include "defs.h"
205470Slinton #include "breakpoint.h"
215470Slinton #include "process.h"
225470Slinton #include "machine.h"
235470Slinton #include "sym.h"
245470Slinton #include "tree.h"
255470Slinton #include "source.h"
265470Slinton #include "object.h"
275470Slinton #include "tree/tree.rep"
2830843Smckusick #include "process/process.rep"
2930843Smckusick #include "process/pxinfo.h"
305470Slinton 
315470Slinton /*
325470Slinton  * When tracing variables we keep a copy of their most recent value
335470Slinton  * and compare it to the current one each time a breakpoint occurs.
345470Slinton  * MAXTRSIZE is the maximum size variable we allow.
355470Slinton  */
365470Slinton 
375470Slinton #define MAXTRSIZE 512
385470Slinton 
395470Slinton /*
405470Slinton  * The tracing structure is a list of information about all the
415470Slinton  * variables that are being traced.
425470Slinton  */
435470Slinton 
445470Slinton typedef struct trinfo {
455760Slinton     TRTYPE trtype;
465760Slinton     ADDRESS traddr;
475760Slinton     SYM *trblock;
485760Slinton     NODE *trvar;
495760Slinton     NODE *trcond;
505760Slinton     char *trvalue;
515760Slinton     struct trinfo *trnext;
525470Slinton } TRINFO;
535470Slinton 
545470Slinton LOCAL TRINFO *trhead;
555470Slinton 
565470Slinton /*
575470Slinton  * add a variable to be traced
585470Slinton  */
595470Slinton 
addvar(trtype,node,cond)605470Slinton addvar(trtype, node, cond)
615470Slinton TRTYPE trtype;
625470Slinton NODE *node;
635470Slinton NODE *cond;
645470Slinton {
655760Slinton     register TRINFO *tp;
665470Slinton 
675760Slinton     tp = alloc(1, TRINFO);
685760Slinton     tp->trtype = trtype;
695760Slinton     tp->traddr = (ADDRESS) -1;
705760Slinton     tp->trblock = curfunc;
715760Slinton     tp->trvar = node;
725760Slinton     tp->trcond = cond;
735760Slinton     tp->trvalue = NIL;
745760Slinton     tp->trnext = trhead;
755760Slinton     trhead = tp;
765470Slinton }
775470Slinton 
785470Slinton /*
795470Slinton  * remove a variable from the trace list
805470Slinton  */
815470Slinton 
delvar(trtype,node,cond)825470Slinton delvar(trtype, node, cond)
835470Slinton TRTYPE trtype;
845470Slinton NODE *node;
855470Slinton NODE *cond;
865470Slinton {
875760Slinton     register TRINFO *tp, *last;
885470Slinton 
895760Slinton     last = NIL;
905760Slinton     for (tp = trhead; tp != NIL; tp = tp->trnext) {
915760Slinton 	if (tp->trtype == trtype &&
925760Slinton 	    tr_equal(tp->trvar, node) &&
935760Slinton 	    tr_equal(tp->trcond, cond)) {
945760Slinton 	    break;
955470Slinton 	}
965760Slinton     }
975760Slinton     if (tp == NIL) {
985760Slinton 	trerror("can't delete term %t", node);
995760Slinton     }
1005760Slinton     if (last == NIL) {
1015760Slinton 	trhead = tp->trnext;
1025760Slinton     } else {
1035760Slinton 	last->trnext = tp->trnext;
1045760Slinton     }
1055760Slinton     if (tp->trvalue != NIL) {
1065760Slinton 	free(tp->trvalue);
1075760Slinton     }
1085760Slinton     free(tp);
1095470Slinton }
1105470Slinton 
1115470Slinton /*
1125470Slinton  * Print out any news about variables in the list whose
1135470Slinton  * values have changed.
1145470Slinton  */
1155470Slinton 
prvarnews()1165470Slinton prvarnews()
1175470Slinton {
1185760Slinton     register TRINFO *tp;
1195760Slinton     register NODE *p;
1205760Slinton     register int n;
1215760Slinton     SYM *s;
1225760Slinton     char buff[MAXTRSIZE];
1235760Slinton     static LINENO prevline;
1245470Slinton 
1255760Slinton     for (tp = trhead; tp != NIL; tp = tp->trnext) {
1265760Slinton 	if (tp->trcond != NIL && !cond(tp->trcond)) {
1275760Slinton 	    continue;
1285470Slinton 	}
1295760Slinton 	s = curfunc;
1305760Slinton 	while (s != NIL && s != tp->trblock) {
1315760Slinton 	    s = container(s);
1325760Slinton 	}
1335760Slinton 	if (s == NIL) {
1345760Slinton 	    continue;
1355760Slinton 	}
1365760Slinton 	p = tp->trvar;
1375760Slinton 	if (tp->traddr == (ADDRESS) -1) {
1385760Slinton 	    tp->traddr = lval(p->left);
1395760Slinton 	}
1405760Slinton 	n = size(p->nodetype);
1415760Slinton 	dread(buff, tp->traddr, n);
1425760Slinton 	if (tp->trvalue == NIL) {
1435760Slinton 	    tp->trvalue = alloc(n, char);
1445760Slinton 	    mov(buff, tp->trvalue, n);
1455760Slinton 	    mov(buff, sp, n);
1465760Slinton 	    sp += n;
14730843Smckusick #ifdef tahoe
14830843Smckusick 	    alignstack();
14930843Smckusick #endif
1505760Slinton 	    if (tp->trtype == TRPRINT) {
1515760Slinton 		printf("initially (at ");
1525760Slinton 		printwhere(curline, srcfilename(pc));
1535760Slinton 		printf("):\t");
1545760Slinton 		prtree(p);
1555760Slinton 		printf(" = ");
1565760Slinton 		printval(p->nodetype);
1575760Slinton 		putchar('\n');
1585760Slinton 	    }
1595760Slinton 	} else if (cmp(tp->trvalue, buff, n) != 0) {
1605760Slinton 	    mov(buff, tp->trvalue, n);
1615760Slinton 	    mov(buff, sp, n);
1625760Slinton 	    sp += n;
16330843Smckusick #ifdef tahoe
16430843Smckusick 	    alignstack();
16530843Smckusick #endif
1665760Slinton 	    printf("after ");
1675760Slinton 	    printwhere(prevline, srcfilename(pc));
1685760Slinton 	    printf(":\t");
1695760Slinton 	    prtree(p);
1705760Slinton 	    printf(" = ");
1715760Slinton 	    printval(p->nodetype);
1725760Slinton 	    putchar('\n');
1735760Slinton 	    if (tp->trtype == TRSTOP) {
1745760Slinton 		isstopped = TRUE;
1755760Slinton 		curline = srcline(pc);
1765760Slinton 		printstatus();
1775760Slinton 	    }
1785760Slinton 	}
1795760Slinton     }
1805760Slinton     prevline = curline;
1815470Slinton }
1825470Slinton 
1835470Slinton /*
1845470Slinton  * Free the table.  Note that trvar and trcond fields are not freed,
1855470Slinton  * this is because they are the same as in the breakpoint table and
1865470Slinton  * are freed by the bpfree routine.
1875470Slinton  */
1885470Slinton 
trfree()1895470Slinton trfree()
1905470Slinton {
1915760Slinton     register TRINFO *tp, *next;
1925470Slinton 
1935760Slinton     for (tp = trhead; tp != NIL; tp = next) {
1945760Slinton 	next = tp->trnext;
1955760Slinton 	if (tp->trvalue != NIL) {
1965760Slinton 	    free(tp->trvalue);
1975470Slinton 	}
1985760Slinton 	free(tp);
1995760Slinton     }
2005760Slinton     trhead = NIL;
2015470Slinton }
202