1*22282Sdist /*
2*22282Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22282Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22282Sdist  * specifies the terms and conditions for redistribution.
5*22282Sdist  */
65470Slinton 
7*22282Sdist #ifndef lint
8*22282Sdist static char sccsid[] = "@(#)trinfo.c	5.1 (Berkeley) 06/05/85";
9*22282Sdist #endif not lint
105470Slinton 
115470Slinton /*
125470Slinton  * Trace information management.
135470Slinton  *
145470Slinton  * The trace information is a list of variables that are being
155470Slinton  * traced or whose value changing should cause a stop.
165470Slinton  */
175470Slinton 
185470Slinton #include "defs.h"
195470Slinton #include "breakpoint.h"
205470Slinton #include "process.h"
215470Slinton #include "machine.h"
225470Slinton #include "sym.h"
235470Slinton #include "tree.h"
245470Slinton #include "source.h"
255470Slinton #include "object.h"
265470Slinton #include "tree/tree.rep"
275470Slinton 
285470Slinton /*
295470Slinton  * When tracing variables we keep a copy of their most recent value
305470Slinton  * and compare it to the current one each time a breakpoint occurs.
315470Slinton  * MAXTRSIZE is the maximum size variable we allow.
325470Slinton  */
335470Slinton 
345470Slinton #define MAXTRSIZE 512
355470Slinton 
365470Slinton /*
375470Slinton  * The tracing structure is a list of information about all the
385470Slinton  * variables that are being traced.
395470Slinton  */
405470Slinton 
415470Slinton typedef struct trinfo {
425760Slinton     TRTYPE trtype;
435760Slinton     ADDRESS traddr;
445760Slinton     SYM *trblock;
455760Slinton     NODE *trvar;
465760Slinton     NODE *trcond;
475760Slinton     char *trvalue;
485760Slinton     struct trinfo *trnext;
495470Slinton } TRINFO;
505470Slinton 
515470Slinton LOCAL TRINFO *trhead;
525470Slinton 
535470Slinton /*
545470Slinton  * add a variable to be traced
555470Slinton  */
565470Slinton 
575470Slinton addvar(trtype, node, cond)
585470Slinton TRTYPE trtype;
595470Slinton NODE *node;
605470Slinton NODE *cond;
615470Slinton {
625760Slinton     register TRINFO *tp;
635470Slinton 
645760Slinton     tp = alloc(1, TRINFO);
655760Slinton     tp->trtype = trtype;
665760Slinton     tp->traddr = (ADDRESS) -1;
675760Slinton     tp->trblock = curfunc;
685760Slinton     tp->trvar = node;
695760Slinton     tp->trcond = cond;
705760Slinton     tp->trvalue = NIL;
715760Slinton     tp->trnext = trhead;
725760Slinton     trhead = tp;
735470Slinton }
745470Slinton 
755470Slinton /*
765470Slinton  * remove a variable from the trace list
775470Slinton  */
785470Slinton 
795470Slinton delvar(trtype, node, cond)
805470Slinton TRTYPE trtype;
815470Slinton NODE *node;
825470Slinton NODE *cond;
835470Slinton {
845760Slinton     register TRINFO *tp, *last;
855470Slinton 
865760Slinton     last = NIL;
875760Slinton     for (tp = trhead; tp != NIL; tp = tp->trnext) {
885760Slinton 	if (tp->trtype == trtype &&
895760Slinton 	    tr_equal(tp->trvar, node) &&
905760Slinton 	    tr_equal(tp->trcond, cond)) {
915760Slinton 	    break;
925470Slinton 	}
935760Slinton     }
945760Slinton     if (tp == NIL) {
955760Slinton 	trerror("can't delete term %t", node);
965760Slinton     }
975760Slinton     if (last == NIL) {
985760Slinton 	trhead = tp->trnext;
995760Slinton     } else {
1005760Slinton 	last->trnext = tp->trnext;
1015760Slinton     }
1025760Slinton     if (tp->trvalue != NIL) {
1035760Slinton 	free(tp->trvalue);
1045760Slinton     }
1055760Slinton     free(tp);
1065470Slinton }
1075470Slinton 
1085470Slinton /*
1095470Slinton  * Print out any news about variables in the list whose
1105470Slinton  * values have changed.
1115470Slinton  */
1125470Slinton 
1135470Slinton prvarnews()
1145470Slinton {
1155760Slinton     register TRINFO *tp;
1165760Slinton     register NODE *p;
1175760Slinton     register int n;
1185760Slinton     SYM *s;
1195760Slinton     char buff[MAXTRSIZE];
1205760Slinton     static LINENO prevline;
1215470Slinton 
1225760Slinton     for (tp = trhead; tp != NIL; tp = tp->trnext) {
1235760Slinton 	if (tp->trcond != NIL && !cond(tp->trcond)) {
1245760Slinton 	    continue;
1255470Slinton 	}
1265760Slinton 	s = curfunc;
1275760Slinton 	while (s != NIL && s != tp->trblock) {
1285760Slinton 	    s = container(s);
1295760Slinton 	}
1305760Slinton 	if (s == NIL) {
1315760Slinton 	    continue;
1325760Slinton 	}
1335760Slinton 	p = tp->trvar;
1345760Slinton 	if (tp->traddr == (ADDRESS) -1) {
1355760Slinton 	    tp->traddr = lval(p->left);
1365760Slinton 	}
1375760Slinton 	n = size(p->nodetype);
1385760Slinton 	dread(buff, tp->traddr, n);
1395760Slinton 	if (tp->trvalue == NIL) {
1405760Slinton 	    tp->trvalue = alloc(n, char);
1415760Slinton 	    mov(buff, tp->trvalue, n);
1425760Slinton 	    mov(buff, sp, n);
1435760Slinton 	    sp += n;
1445760Slinton 	    if (tp->trtype == TRPRINT) {
1455760Slinton 		printf("initially (at ");
1465760Slinton 		printwhere(curline, srcfilename(pc));
1475760Slinton 		printf("):\t");
1485760Slinton 		prtree(p);
1495760Slinton 		printf(" = ");
1505760Slinton 		printval(p->nodetype);
1515760Slinton 		putchar('\n');
1525760Slinton 	    }
1535760Slinton 	} else if (cmp(tp->trvalue, buff, n) != 0) {
1545760Slinton 	    mov(buff, tp->trvalue, n);
1555760Slinton 	    mov(buff, sp, n);
1565760Slinton 	    sp += n;
1575760Slinton 	    printf("after ");
1585760Slinton 	    printwhere(prevline, srcfilename(pc));
1595760Slinton 	    printf(":\t");
1605760Slinton 	    prtree(p);
1615760Slinton 	    printf(" = ");
1625760Slinton 	    printval(p->nodetype);
1635760Slinton 	    putchar('\n');
1645760Slinton 	    if (tp->trtype == TRSTOP) {
1655760Slinton 		isstopped = TRUE;
1665760Slinton 		curline = srcline(pc);
1675760Slinton 		printstatus();
1685760Slinton 	    }
1695760Slinton 	}
1705760Slinton     }
1715760Slinton     prevline = curline;
1725470Slinton }
1735470Slinton 
1745470Slinton /*
1755470Slinton  * Free the table.  Note that trvar and trcond fields are not freed,
1765470Slinton  * this is because they are the same as in the breakpoint table and
1775470Slinton  * are freed by the bpfree routine.
1785470Slinton  */
1795470Slinton 
1805470Slinton trfree()
1815470Slinton {
1825760Slinton     register TRINFO *tp, *next;
1835470Slinton 
1845760Slinton     for (tp = trhead; tp != NIL; tp = next) {
1855760Slinton 	next = tp->trnext;
1865760Slinton 	if (tp->trvalue != NIL) {
1875760Slinton 	    free(tp->trvalue);
1885470Slinton 	}
1895760Slinton 	free(tp);
1905760Slinton     }
1915760Slinton     trhead = NIL;
1925470Slinton }
193