xref: /plan9/sys/src/cmd/spin/guided.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier /***** spin: guided.c *****/
2*219b2ee8SDavid du Colombier 
3*219b2ee8SDavid du Colombier /* Copyright (c) 1991,1995 by AT&T Corporation.  All Rights Reserved.     */
4*219b2ee8SDavid du Colombier /* This software is for educational purposes only.                        */
5*219b2ee8SDavid du Colombier /* Permission is given to distribute this code provided that this intro-  */
6*219b2ee8SDavid du Colombier /* ductory message is not removed and no monies are exchanged.            */
7*219b2ee8SDavid du Colombier /* No guarantee is expressed or implied by the distribution of this code. */
8*219b2ee8SDavid du Colombier /* Software written by Gerard J. Holzmann as part of the book:            */
9*219b2ee8SDavid du Colombier /* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4,     */
10*219b2ee8SDavid du Colombier /* Prentice Hall, Englewood Cliffs, NJ, 07632.                            */
11*219b2ee8SDavid du Colombier /* Send bug-reports and/or questions to: gerard@research.att.com          */
12*219b2ee8SDavid du Colombier 
13*219b2ee8SDavid du Colombier #include "spin.h"
14*219b2ee8SDavid du Colombier #include <sys/types.h>
15*219b2ee8SDavid du Colombier #include <sys/stat.h>
16*219b2ee8SDavid du Colombier #include "y.tab.h"
17*219b2ee8SDavid du Colombier 
18*219b2ee8SDavid du Colombier extern int	nproc, nstop, Tval, Rvous, Have_claim, m_loss;
19*219b2ee8SDavid du Colombier extern RunList	*run, *X;
20*219b2ee8SDavid du Colombier extern Element	*Al_El;
21*219b2ee8SDavid du Colombier extern Symbol	*Fname, *oFname;
22*219b2ee8SDavid du Colombier extern int	verbose, lineno, xspin;
23*219b2ee8SDavid du Colombier extern int	depth;
24*219b2ee8SDavid du Colombier 
25*219b2ee8SDavid du Colombier int	TstOnly = 0;
26*219b2ee8SDavid du Colombier 
27*219b2ee8SDavid du Colombier FILE *fd;
28*219b2ee8SDavid du Colombier 
29*219b2ee8SDavid du Colombier void
30*219b2ee8SDavid du Colombier whichproc(int p)
31*219b2ee8SDavid du Colombier {	RunList *oX;
32*219b2ee8SDavid du Colombier 
33*219b2ee8SDavid du Colombier 	for (oX = run; oX; oX = oX->nxt)
34*219b2ee8SDavid du Colombier 		if (oX->pid == p)
35*219b2ee8SDavid du Colombier 		{	printf("(%s) ", oX->n->name);
36*219b2ee8SDavid du Colombier 			break;
37*219b2ee8SDavid du Colombier 		}
38*219b2ee8SDavid du Colombier }
39*219b2ee8SDavid du Colombier 
40*219b2ee8SDavid du Colombier int
41*219b2ee8SDavid du Colombier newer(char *f1, char *f2)
42*219b2ee8SDavid du Colombier {	struct stat x, y;
43*219b2ee8SDavid du Colombier 
44*219b2ee8SDavid du Colombier 	if (stat(f1, (struct stat *)&x) < 0) return 0;
45*219b2ee8SDavid du Colombier 	if (stat(f2, (struct stat *)&y) < 0) return 1;
46*219b2ee8SDavid du Colombier 	if (x.st_mtime < y.st_mtime) return 0;
47*219b2ee8SDavid du Colombier 
48*219b2ee8SDavid du Colombier 	return 1;
49*219b2ee8SDavid du Colombier }
50*219b2ee8SDavid du Colombier 
51*219b2ee8SDavid du Colombier void
52*219b2ee8SDavid du Colombier match_trail(void)
53*219b2ee8SDavid du Colombier {	int i, pno, nst;
54*219b2ee8SDavid du Colombier 	Element *dothis;
55*219b2ee8SDavid du Colombier 	char snap[256];
56*219b2ee8SDavid du Colombier 
57*219b2ee8SDavid du Colombier 	sprintf(snap, "%s.trail", oFname->name);
58*219b2ee8SDavid du Colombier 	if (!(fd = fopen(snap, "r")))
59*219b2ee8SDavid du Colombier 	{	printf("spin -t: cannot find %s\n", snap);
60*219b2ee8SDavid du Colombier 		exit(1);
61*219b2ee8SDavid du Colombier 	}
62*219b2ee8SDavid du Colombier 
63*219b2ee8SDavid du Colombier 	if (xspin == 0 && newer(oFname->name, snap))
64*219b2ee8SDavid du Colombier 	printf("Warning, \"%s\" newer than %s\n", oFname->name, snap);
65*219b2ee8SDavid du Colombier 
66*219b2ee8SDavid du Colombier 	Tval = m_loss = 1; /* timeouts and losses may be part of trail */
67*219b2ee8SDavid du Colombier 
68*219b2ee8SDavid du Colombier 	while (fscanf(fd, "%d:%d:%d\n", &depth, &pno, &nst) == 3)
69*219b2ee8SDavid du Colombier 	{	if (depth == -2)
70*219b2ee8SDavid du Colombier 		{	start_claim(pno);
71*219b2ee8SDavid du Colombier 			continue;
72*219b2ee8SDavid du Colombier 		}
73*219b2ee8SDavid du Colombier 		if (depth == -1)
74*219b2ee8SDavid du Colombier 		{	if (verbose)
75*219b2ee8SDavid du Colombier 			printf("<<<<<START OF CYCLE>>>>>\n");
76*219b2ee8SDavid du Colombier 			continue;
77*219b2ee8SDavid du Colombier 		}
78*219b2ee8SDavid du Colombier 		if (Have_claim)
79*219b2ee8SDavid du Colombier 		{	if (pno == 0)	/* verifier has claim at 0 */
80*219b2ee8SDavid du Colombier 				pno = Have_claim;
81*219b2ee8SDavid du Colombier 			else
82*219b2ee8SDavid du Colombier 			{	if (pno <= Have_claim)
83*219b2ee8SDavid du Colombier 					pno -= 1;
84*219b2ee8SDavid du Colombier 		}	}
85*219b2ee8SDavid du Colombier 
86*219b2ee8SDavid du Colombier 		for (dothis = Al_El; dothis; dothis = dothis->Nxt)
87*219b2ee8SDavid du Colombier 		{	if (dothis->Seqno == nst)
88*219b2ee8SDavid du Colombier 				break;
89*219b2ee8SDavid du Colombier 		}
90*219b2ee8SDavid du Colombier 		if (!dothis)
91*219b2ee8SDavid du Colombier 		{	printf("%3d: proc %d, no matching transition %d\n",
92*219b2ee8SDavid du Colombier 				depth, pno, nst);
93*219b2ee8SDavid du Colombier 			lost_trail();
94*219b2ee8SDavid du Colombier 		}
95*219b2ee8SDavid du Colombier 		i = nproc - nstop;
96*219b2ee8SDavid du Colombier 		if (dothis->n->ntyp == '@')
97*219b2ee8SDavid du Colombier 		{	if (pno == i-1)
98*219b2ee8SDavid du Colombier 			{	run = run->nxt;
99*219b2ee8SDavid du Colombier 				nstop++;
100*219b2ee8SDavid du Colombier 				if (verbose&32 || verbose&4)
101*219b2ee8SDavid du Colombier 				printf("%3d: proc %d dies\n", depth, pno);
102*219b2ee8SDavid du Colombier 				continue;
103*219b2ee8SDavid du Colombier 			}
104*219b2ee8SDavid du Colombier 			if (pno <= 1) continue;	/* init dies before never */
105*219b2ee8SDavid du Colombier 			printf("%3d: stop error, proc %d (i=%d) trans %d, %c\n",
106*219b2ee8SDavid du Colombier 				depth, pno, i, nst, dothis->n->ntyp);
107*219b2ee8SDavid du Colombier 			lost_trail();
108*219b2ee8SDavid du Colombier 		}
109*219b2ee8SDavid du Colombier 		for (X = run; X; X = X->nxt)
110*219b2ee8SDavid du Colombier 		{	if (--i == pno)
111*219b2ee8SDavid du Colombier 				break;
112*219b2ee8SDavid du Colombier 		}
113*219b2ee8SDavid du Colombier 		if (!X)
114*219b2ee8SDavid du Colombier 		{	printf("%3d: no process %d ", depth, pno);
115*219b2ee8SDavid du Colombier 			if (Have_claim && pno == Have_claim)
116*219b2ee8SDavid du Colombier 				printf("(state %d)\n", nst);
117*219b2ee8SDavid du Colombier 			else
118*219b2ee8SDavid du Colombier 				printf("(proc .%d state %d)\n", pno, nst);
119*219b2ee8SDavid du Colombier 			lost_trail();
120*219b2ee8SDavid du Colombier 		}
121*219b2ee8SDavid du Colombier 		X->pc  = dothis;
122*219b2ee8SDavid du Colombier 		lineno = dothis->n->ln;
123*219b2ee8SDavid du Colombier 		Fname  = dothis->n->fn;
124*219b2ee8SDavid du Colombier 		if (verbose&32 || verbose&4)
125*219b2ee8SDavid du Colombier 		{	p_talk(X->pc, 1);
126*219b2ee8SDavid du Colombier 			printf("	[");
127*219b2ee8SDavid du Colombier 			comment(stdout, X->pc->n, 0);
128*219b2ee8SDavid du Colombier 			printf("]\n");
129*219b2ee8SDavid du Colombier 		}
130*219b2ee8SDavid du Colombier 		if (dothis->n->ntyp == GOTO)
131*219b2ee8SDavid du Colombier 			X->pc = get_lab(dothis->n,1);
132*219b2ee8SDavid du Colombier 		else
133*219b2ee8SDavid du Colombier 		{	if (dothis->n->ntyp == D_STEP)
134*219b2ee8SDavid du Colombier 			{	Element *g = dothis;
135*219b2ee8SDavid du Colombier 				do {
136*219b2ee8SDavid du Colombier 					g = eval_sub(g);
137*219b2ee8SDavid du Colombier 				} while (g && g != dothis->nxt);
138*219b2ee8SDavid du Colombier 				if (!g)
139*219b2ee8SDavid du Colombier 				{	printf("%3d: d_step failed %d->%d\n",
140*219b2ee8SDavid du Colombier 					depth, dothis->Seqno, dothis->nxt->Seqno);
141*219b2ee8SDavid du Colombier 					wrapup(1);
142*219b2ee8SDavid du Colombier 				}
143*219b2ee8SDavid du Colombier 				X->pc = g;
144*219b2ee8SDavid du Colombier 			} else
145*219b2ee8SDavid du Colombier 			{	(void) eval(dothis->n);
146*219b2ee8SDavid du Colombier 				X->pc = dothis->nxt;
147*219b2ee8SDavid du Colombier 			}
148*219b2ee8SDavid du Colombier 		}
149*219b2ee8SDavid du Colombier 		if (X->pc) X->pc = huntele(X->pc, 0);
150*219b2ee8SDavid du Colombier 		if (verbose&32 || verbose&4)
151*219b2ee8SDavid du Colombier 		{	if (verbose&1) dumpglobals();
152*219b2ee8SDavid du Colombier 			if (verbose&2) dumplocal(X);
153*219b2ee8SDavid du Colombier 			if (xspin) printf("\n");	/* xspin looks for these */
154*219b2ee8SDavid du Colombier 		}
155*219b2ee8SDavid du Colombier 	}
156*219b2ee8SDavid du Colombier 	printf("spin: trail ends after %d steps\n", depth);
157*219b2ee8SDavid du Colombier 	wrapup(0);
158*219b2ee8SDavid du Colombier }
159*219b2ee8SDavid du Colombier 
160*219b2ee8SDavid du Colombier void
161*219b2ee8SDavid du Colombier lost_trail(void)
162*219b2ee8SDavid du Colombier {	int d, p, n, l;
163*219b2ee8SDavid du Colombier 
164*219b2ee8SDavid du Colombier 	while (fscanf(fd, "%d:%d:%d:%d\n", &d, &p, &n, &l) == 4)
165*219b2ee8SDavid du Colombier 	{	printf("step %d: proc  %d ", d, p); whichproc(p);
166*219b2ee8SDavid du Colombier 		printf("(state %d) - d %d\n", n, l);
167*219b2ee8SDavid du Colombier 	}
168*219b2ee8SDavid du Colombier 	wrapup(1);	/* no return */
169*219b2ee8SDavid du Colombier }
170*219b2ee8SDavid du Colombier 
171*219b2ee8SDavid du Colombier int
172*219b2ee8SDavid du Colombier pc_value(Lextok *n)
173*219b2ee8SDavid du Colombier {	int i = nproc - nstop;
174*219b2ee8SDavid du Colombier 	int pid = eval(n);
175*219b2ee8SDavid du Colombier 	RunList *Y;
176*219b2ee8SDavid du Colombier 
177*219b2ee8SDavid du Colombier 	for (Y = run; Y; Y = Y->nxt)
178*219b2ee8SDavid du Colombier 	{	if (--i == pid)
179*219b2ee8SDavid du Colombier 			return Y->pc->seqno;
180*219b2ee8SDavid du Colombier 	}
181*219b2ee8SDavid du Colombier 	return 0;
182*219b2ee8SDavid du Colombier }
183