xref: /plan9-contrib/sys/src/cmd/spin/guided.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
1219b2ee8SDavid du Colombier /***** spin: guided.c *****/
2219b2ee8SDavid du Colombier 
3*de2caf28SDavid du Colombier /*
4*de2caf28SDavid du Colombier  * This file is part of the public release of Spin. It is subject to the
5*de2caf28SDavid du Colombier  * terms in the LICENSE file that is included in this source directory.
6*de2caf28SDavid du Colombier  * Tool documentation is available at http://spinroot.com
7*de2caf28SDavid du Colombier  */
8219b2ee8SDavid du Colombier 
9219b2ee8SDavid du Colombier #include "spin.h"
10219b2ee8SDavid du Colombier #include <sys/types.h>
11219b2ee8SDavid du Colombier #include <sys/stat.h>
12*de2caf28SDavid du Colombier #include <limits.h>
13219b2ee8SDavid du Colombier #include "y.tab.h"
14219b2ee8SDavid du Colombier 
15*de2caf28SDavid du Colombier extern RunList	*run_lst, *X_lst;
16219b2ee8SDavid du Colombier extern Element	*Al_El;
17219b2ee8SDavid du Colombier extern Symbol	*Fname, *oFname;
18312a1df1SDavid du Colombier extern int	verbose, lineno, xspin, jumpsteps, depth, merger, cutoff;
19312a1df1SDavid du Colombier extern int	nproc, nstop, Tval, ntrail, columns;
20*de2caf28SDavid du Colombier extern short	Have_claim, Skip_claim, has_code;
217dd7cddfSDavid du Colombier extern void ana_src(int, int);
2200d97012SDavid du Colombier extern char	**trailfilename;
23219b2ee8SDavid du Colombier 
24*de2caf28SDavid du Colombier int	TstOnly = 0, prno;
25219b2ee8SDavid du Colombier 
267dd7cddfSDavid du Colombier static int	lastclaim = -1;
277dd7cddfSDavid du Colombier static FILE	*fd;
287dd7cddfSDavid du Colombier static void	lost_trail(void);
29219b2ee8SDavid du Colombier 
307dd7cddfSDavid du Colombier static void
whichproc(int p)31219b2ee8SDavid du Colombier whichproc(int p)
32219b2ee8SDavid du Colombier {	RunList *oX;
33219b2ee8SDavid du Colombier 
34*de2caf28SDavid du Colombier 	for (oX = run_lst; oX; oX = oX->nxt)
35219b2ee8SDavid du Colombier 		if (oX->pid == p)
36219b2ee8SDavid du Colombier 		{	printf("(%s) ", oX->n->name);
37219b2ee8SDavid du Colombier 			break;
38219b2ee8SDavid du Colombier 		}
39219b2ee8SDavid du Colombier }
40219b2ee8SDavid du Colombier 
417dd7cddfSDavid du Colombier static int
newer(char * f1,char * f2)42219b2ee8SDavid du Colombier newer(char *f1, char *f2)
43f3793cddSDavid du Colombier {
44f3793cddSDavid du Colombier #if defined(WIN32) || defined(WIN64)
45f3793cddSDavid du Colombier 	struct _stat x, y;
46f3793cddSDavid du Colombier #else
47f3793cddSDavid du Colombier 	struct stat x, y;
48f3793cddSDavid du Colombier #endif
49219b2ee8SDavid du Colombier 
50219b2ee8SDavid du Colombier 	if (stat(f1, (struct stat *)&x) < 0) return 0;
51219b2ee8SDavid du Colombier 	if (stat(f2, (struct stat *)&y) < 0) return 1;
52219b2ee8SDavid du Colombier 	if (x.st_mtime < y.st_mtime) return 0;
53219b2ee8SDavid du Colombier 
54219b2ee8SDavid du Colombier 	return 1;
55219b2ee8SDavid du Colombier }
56219b2ee8SDavid du Colombier 
57219b2ee8SDavid du Colombier void
hookup(void)587dd7cddfSDavid du Colombier hookup(void)
597dd7cddfSDavid du Colombier {	Element *e;
60219b2ee8SDavid du Colombier 
617dd7cddfSDavid du Colombier 	for (e = Al_El; e; e = e->Nxt)
62312a1df1SDavid du Colombier 		if (e->n
63312a1df1SDavid du Colombier 		&& (e->n->ntyp == ATOMIC
64312a1df1SDavid du Colombier 		||  e->n->ntyp == NON_ATOMIC
65312a1df1SDavid du Colombier 		||  e->n->ntyp == D_STEP))
667dd7cddfSDavid du Colombier 			(void) huntstart(e);
67219b2ee8SDavid du Colombier }
68219b2ee8SDavid du Colombier 
69312a1df1SDavid du Colombier int
not_claim(void)70312a1df1SDavid du Colombier not_claim(void)
71312a1df1SDavid du Colombier {
72*de2caf28SDavid du Colombier 	return (!Have_claim || !X_lst || X_lst->pid != 0);
73*de2caf28SDavid du Colombier }
74*de2caf28SDavid du Colombier 
75*de2caf28SDavid du Colombier int globmin = INT_MAX;
76*de2caf28SDavid du Colombier int globmax = 0;
77*de2caf28SDavid du Colombier 
78*de2caf28SDavid du Colombier int
find_min(Sequence * s)79*de2caf28SDavid du Colombier find_min(Sequence *s)
80*de2caf28SDavid du Colombier {	SeqList *l;
81*de2caf28SDavid du Colombier 	Element *e;
82*de2caf28SDavid du Colombier 
83*de2caf28SDavid du Colombier 	if (s->minel < 0)
84*de2caf28SDavid du Colombier 	{	s->minel = INT_MAX;
85*de2caf28SDavid du Colombier 		for (e = s->frst; e; e = e->nxt)
86*de2caf28SDavid du Colombier 		{	if (e->status & 512)
87*de2caf28SDavid du Colombier 			{	continue;
88*de2caf28SDavid du Colombier 			}
89*de2caf28SDavid du Colombier 			e->status |= 512;
90*de2caf28SDavid du Colombier 
91*de2caf28SDavid du Colombier 			if (e->n->ntyp == ATOMIC
92*de2caf28SDavid du Colombier 			||  e->n->ntyp == NON_ATOMIC
93*de2caf28SDavid du Colombier 			||  e->n->ntyp == D_STEP)
94*de2caf28SDavid du Colombier 			{	int n = find_min(e->n->sl->this);
95*de2caf28SDavid du Colombier 				if (n < s->minel)
96*de2caf28SDavid du Colombier 				{	s->minel = n;
97*de2caf28SDavid du Colombier 				}
98*de2caf28SDavid du Colombier 			} else if (e->Seqno < s->minel)
99*de2caf28SDavid du Colombier 			{	s->minel = e->Seqno;
100*de2caf28SDavid du Colombier 			}
101*de2caf28SDavid du Colombier 			for (l = e->sub; l; l = l->nxt)
102*de2caf28SDavid du Colombier 			{	int n = find_min(l->this);
103*de2caf28SDavid du Colombier 				if (n < s->minel)
104*de2caf28SDavid du Colombier 				{	s->minel = n;
105*de2caf28SDavid du Colombier 		}	}	}
106*de2caf28SDavid du Colombier 	}
107*de2caf28SDavid du Colombier 	if (s->minel < globmin)
108*de2caf28SDavid du Colombier 	{	globmin = s->minel;
109*de2caf28SDavid du Colombier 	}
110*de2caf28SDavid du Colombier 	return s->minel;
111*de2caf28SDavid du Colombier }
112*de2caf28SDavid du Colombier 
113*de2caf28SDavid du Colombier int
find_max(Sequence * s)114*de2caf28SDavid du Colombier find_max(Sequence *s)
115*de2caf28SDavid du Colombier {
116*de2caf28SDavid du Colombier 	if (s->last->Seqno > globmax)
117*de2caf28SDavid du Colombier 	{	globmax = s->last->Seqno;
118*de2caf28SDavid du Colombier 	}
119*de2caf28SDavid du Colombier 	return s->last->Seqno;
120312a1df1SDavid du Colombier }
121312a1df1SDavid du Colombier 
1227dd7cddfSDavid du Colombier void
match_trail(void)1237dd7cddfSDavid du Colombier match_trail(void)
1247dd7cddfSDavid du Colombier {	int i, a, nst;
1257dd7cddfSDavid du Colombier 	Element *dothis;
126312a1df1SDavid du Colombier 	char snap[512], *q;
127312a1df1SDavid du Colombier 
128*de2caf28SDavid du Colombier 	if (has_code)
129*de2caf28SDavid du Colombier 	{	printf("spin: important:\n");
130*de2caf28SDavid du Colombier 		printf("  =======================================warning====\n");
131*de2caf28SDavid du Colombier 		printf("  this model contains embedded c code statements\n");
132*de2caf28SDavid du Colombier 		printf("  these statements will not be executed when the trail\n");
133*de2caf28SDavid du Colombier 		printf("  is replayed in this way -- they are just printed,\n");
134*de2caf28SDavid du Colombier 		printf("  which will likely lead to inaccurate variable values.\n");
135*de2caf28SDavid du Colombier 		printf("  for an accurate replay use: ./pan -r\n");
136*de2caf28SDavid du Colombier 		printf("  =======================================warning====\n\n");
137*de2caf28SDavid du Colombier 	}
138*de2caf28SDavid du Colombier 
139312a1df1SDavid du Colombier 	/*
140312a1df1SDavid du Colombier 	 * if source model name is leader.pml
141312a1df1SDavid du Colombier 	 * look for the trail file under these names:
142312a1df1SDavid du Colombier 	 *	leader.pml.trail
143312a1df1SDavid du Colombier 	 *	leader.pml.tra
144312a1df1SDavid du Colombier 	 *	leader.trail
145312a1df1SDavid du Colombier 	 *	leader.tra
146312a1df1SDavid du Colombier 	 */
1477dd7cddfSDavid du Colombier 
14800d97012SDavid du Colombier 	if (trailfilename)
14900d97012SDavid du Colombier 	{	if (strlen(*trailfilename) < sizeof(snap))
15000d97012SDavid du Colombier 		{	strcpy(snap, (const char *) *trailfilename);
15100d97012SDavid du Colombier 		} else
15200d97012SDavid du Colombier 		{	fatal("filename %s too long", *trailfilename);
15300d97012SDavid du Colombier 		}
15400d97012SDavid du Colombier 	} else
15500d97012SDavid du Colombier 	{	if (ntrail)
1567dd7cddfSDavid du Colombier 			sprintf(snap, "%s%d.trail", oFname->name, ntrail);
1577dd7cddfSDavid du Colombier 		else
1587dd7cddfSDavid du Colombier 			sprintf(snap, "%s.trail", oFname->name);
15900d97012SDavid du Colombier 	}
160312a1df1SDavid du Colombier 
161312a1df1SDavid du Colombier 	if ((fd = fopen(snap, "r")) == NULL)
162312a1df1SDavid du Colombier 	{	snap[strlen(snap)-2] = '\0';	/* .tra */
163312a1df1SDavid du Colombier 		if ((fd = fopen(snap, "r")) == NULL)
164312a1df1SDavid du Colombier 		{	if ((q = strchr(oFname->name, '.')) != NULL)
165312a1df1SDavid du Colombier 			{	*q = '\0';
166312a1df1SDavid du Colombier 				if (ntrail)
167312a1df1SDavid du Colombier 					sprintf(snap, "%s%d.trail",
168312a1df1SDavid du Colombier 						oFname->name, ntrail);
169312a1df1SDavid du Colombier 				else
170312a1df1SDavid du Colombier 					sprintf(snap, "%s.trail",
171312a1df1SDavid du Colombier 						oFname->name);
172312a1df1SDavid du Colombier 				*q = '.';
173312a1df1SDavid du Colombier 
174312a1df1SDavid du Colombier 				if ((fd = fopen(snap, "r")) != NULL)
175312a1df1SDavid du Colombier 					goto okay;
176312a1df1SDavid du Colombier 
177312a1df1SDavid du Colombier 				snap[strlen(snap)-2] = '\0';	/* last try */
178312a1df1SDavid du Colombier 				if ((fd = fopen(snap, "r")) != NULL)
179312a1df1SDavid du Colombier 					goto okay;
180312a1df1SDavid du Colombier 			}
181312a1df1SDavid du Colombier 			printf("spin: cannot find trail file\n");
1827dd7cddfSDavid du Colombier 			alldone(1);
1837dd7cddfSDavid du Colombier 	}	}
184312a1df1SDavid du Colombier okay:
185219b2ee8SDavid du Colombier 	if (xspin == 0 && newer(oFname->name, snap))
186*de2caf28SDavid du Colombier 	{	printf("spin: warning, \"%s\" is newer than %s\n",
1877dd7cddfSDavid du Colombier 			oFname->name, snap);
188*de2caf28SDavid du Colombier 	}
189312a1df1SDavid du Colombier 	Tval = 1;
190312a1df1SDavid du Colombier 
191312a1df1SDavid du Colombier 	/*
192312a1df1SDavid du Colombier 	 * sets Tval because timeouts may be part of trail
193312a1df1SDavid du Colombier 	 * this used to also set m_loss to 1, but that is
194312a1df1SDavid du Colombier 	 * better handled with the runtime -m flag
195312a1df1SDavid du Colombier 	 */
196219b2ee8SDavid du Colombier 
1977dd7cddfSDavid du Colombier 	hookup();
1987dd7cddfSDavid du Colombier 
199*de2caf28SDavid du Colombier 	while (fscanf(fd, "%d:%d:%d\n", &depth, &prno, &nst) == 3)
200*de2caf28SDavid du Colombier 	{	if (depth == -2)
201219b2ee8SDavid du Colombier 		{	if (verbose)
202*de2caf28SDavid du Colombier 			{	printf("starting claim %d\n", prno);
203*de2caf28SDavid du Colombier 			}
204*de2caf28SDavid du Colombier 			start_claim(prno);
205*de2caf28SDavid du Colombier 			continue;
206*de2caf28SDavid du Colombier 		}
207*de2caf28SDavid du Colombier 		if (depth == -4)
208*de2caf28SDavid du Colombier 		{	if (verbose&32)
209*de2caf28SDavid du Colombier 			{	printf("using statement merging\n");
210*de2caf28SDavid du Colombier 			}
211*de2caf28SDavid du Colombier 			merger = 1;
212*de2caf28SDavid du Colombier 			ana_src(0, 1);
213*de2caf28SDavid du Colombier 			continue;
214*de2caf28SDavid du Colombier 		}
215*de2caf28SDavid du Colombier 		if (depth == -1)
216*de2caf28SDavid du Colombier 		{	if (1 || verbose)
2177dd7cddfSDavid du Colombier 			{	if (columns == 2)
2187dd7cddfSDavid du Colombier 				dotag(stdout, " CYCLE>\n");
2197dd7cddfSDavid du Colombier 				else
2207dd7cddfSDavid du Colombier 				dotag(stdout, "<<<<<START OF CYCLE>>>>>\n");
2217dd7cddfSDavid du Colombier 			}
222219b2ee8SDavid du Colombier 			continue;
223219b2ee8SDavid du Colombier 		}
224*de2caf28SDavid du Colombier 		if (depth <= -5
225*de2caf28SDavid du Colombier 		&&  depth >= -8)
226*de2caf28SDavid du Colombier 		{	printf("spin: used search permutation, replay with ./pan -r\n");
227*de2caf28SDavid du Colombier 			return;	/* permuted: -5, -6, -7, -8 */
228*de2caf28SDavid du Colombier 		}
229312a1df1SDavid du Colombier 
230312a1df1SDavid du Colombier 		if (cutoff > 0 && depth >= cutoff)
231312a1df1SDavid du Colombier 		{	printf("-------------\n");
232312a1df1SDavid du Colombier 			printf("depth-limit (-u%d steps) reached\n", cutoff);
233312a1df1SDavid du Colombier 			break;
234312a1df1SDavid du Colombier 		}
235312a1df1SDavid du Colombier 
236*de2caf28SDavid du Colombier 		if (Skip_claim && prno == 0) continue;
237219b2ee8SDavid du Colombier 
238219b2ee8SDavid du Colombier 		for (dothis = Al_El; dothis; dothis = dothis->Nxt)
239219b2ee8SDavid du Colombier 		{	if (dothis->Seqno == nst)
240219b2ee8SDavid du Colombier 				break;
241219b2ee8SDavid du Colombier 		}
242219b2ee8SDavid du Colombier 		if (!dothis)
2437dd7cddfSDavid du Colombier 		{	printf("%3d: proc %d, no matching stmnt %d\n",
244*de2caf28SDavid du Colombier 				depth, prno - Have_claim, nst);
245219b2ee8SDavid du Colombier 			lost_trail();
246219b2ee8SDavid du Colombier 		}
247312a1df1SDavid du Colombier 
2487dd7cddfSDavid du Colombier 		i = nproc - nstop + Skip_claim;
249312a1df1SDavid du Colombier 
250219b2ee8SDavid du Colombier 		if (dothis->n->ntyp == '@')
251*de2caf28SDavid du Colombier 		{	if (prno == i-1)
252*de2caf28SDavid du Colombier 			{	run_lst = run_lst->nxt;
253219b2ee8SDavid du Colombier 				nstop++;
2547dd7cddfSDavid du Colombier 				if (verbose&4)
2557dd7cddfSDavid du Colombier 				{	if (columns == 2)
2567dd7cddfSDavid du Colombier 					{	dotag(stdout, "<end>\n");
2577dd7cddfSDavid du Colombier 						continue;
2587dd7cddfSDavid du Colombier 					}
259*de2caf28SDavid du Colombier 					if (Have_claim && prno == 0)
260312a1df1SDavid du Colombier 					printf("%3d: claim terminates\n",
261312a1df1SDavid du Colombier 						depth);
262312a1df1SDavid du Colombier 					else
2637dd7cddfSDavid du Colombier 					printf("%3d: proc %d terminates\n",
264*de2caf28SDavid du Colombier 						depth, prno - Have_claim);
2657dd7cddfSDavid du Colombier 				}
266219b2ee8SDavid du Colombier 				continue;
267219b2ee8SDavid du Colombier 			}
268*de2caf28SDavid du Colombier 			if (prno <= 1) continue;	/* init dies before never */
2697dd7cddfSDavid du Colombier 			printf("%3d: stop error, ", depth);
2707dd7cddfSDavid du Colombier 			printf("proc %d (i=%d) trans %d, %c\n",
271*de2caf28SDavid du Colombier 				prno - Have_claim, i, nst, dothis->n->ntyp);
272219b2ee8SDavid du Colombier 			lost_trail();
273219b2ee8SDavid du Colombier 		}
27400d97012SDavid du Colombier 
275*de2caf28SDavid du Colombier 		if (0 && !xspin && (verbose&32))
276*de2caf28SDavid du Colombier 		{	printf("step %d i=%d pno %d stmnt %d\n", depth, i, prno, nst);
27700d97012SDavid du Colombier 		}
27800d97012SDavid du Colombier 
279*de2caf28SDavid du Colombier 		for (X_lst = run_lst; X_lst; X_lst = X_lst->nxt)
280*de2caf28SDavid du Colombier 		{	if (--i == prno)
281219b2ee8SDavid du Colombier 				break;
282219b2ee8SDavid du Colombier 		}
28300d97012SDavid du Colombier 
284*de2caf28SDavid du Colombier 		if (!X_lst)
28500d97012SDavid du Colombier 		{	if (verbose&32)
286*de2caf28SDavid du Colombier 			{	printf("%3d: no process %d (stmnt %d)\n", depth, prno - Have_claim, nst);
28700d97012SDavid du Colombier 				printf(" max %d (%d - %d + %d) claim %d ",
28800d97012SDavid du Colombier 					nproc - nstop + Skip_claim,
28900d97012SDavid du Colombier 					nproc, nstop, Skip_claim, Have_claim);
29000d97012SDavid du Colombier 				printf("active processes:\n");
291*de2caf28SDavid du Colombier 				for (X_lst = run_lst; X_lst; X_lst = X_lst->nxt)
292*de2caf28SDavid du Colombier 				{	printf("\tpid %d\tproctype %s\n", X_lst->pid, X_lst->n->name);
29300d97012SDavid du Colombier 				}
29400d97012SDavid du Colombier 				printf("\n");
29500d97012SDavid du Colombier 				continue;
29600d97012SDavid du Colombier 			} else
297*de2caf28SDavid du Colombier 			{	printf("%3d:\tproc  %d (?) ", depth, prno);
298219b2ee8SDavid du Colombier 				lost_trail();
299219b2ee8SDavid du Colombier 			}
30000d97012SDavid du Colombier 		} else
301*de2caf28SDavid du Colombier 		{	int min_seq = find_min(X_lst->ps);
302*de2caf28SDavid du Colombier 			int max_seq = find_max(X_lst->ps);
303*de2caf28SDavid du Colombier 
304*de2caf28SDavid du Colombier 			if (nst < min_seq || nst > max_seq)
305*de2caf28SDavid du Colombier 			{	printf("%3d: error: invalid statement", depth);
306*de2caf28SDavid du Colombier 				if (verbose&32)
307*de2caf28SDavid du Colombier 				{	printf(": pid %d:%d (%s:%d:%d) stmnt %d (valid range %d .. %d)",
308*de2caf28SDavid du Colombier 					prno, X_lst->pid, X_lst->n->name, X_lst->tn, X_lst->b,
309*de2caf28SDavid du Colombier 					nst, min_seq, max_seq);
310*de2caf28SDavid du Colombier 				}
311*de2caf28SDavid du Colombier 				printf("\n");
312*de2caf28SDavid du Colombier 				continue;
313*de2caf28SDavid du Colombier 				/* lost_trail(); */
314*de2caf28SDavid du Colombier 			}
315*de2caf28SDavid du Colombier 			X_lst->pc  = dothis;
31600d97012SDavid du Colombier 		}
31700d97012SDavid du Colombier 
318219b2ee8SDavid du Colombier 		lineno = dothis->n->ln;
319219b2ee8SDavid du Colombier 		Fname  = dothis->n->fn;
320312a1df1SDavid du Colombier 
3217dd7cddfSDavid du Colombier 		if (dothis->n->ntyp == D_STEP)
3227dd7cddfSDavid du Colombier 		{	Element *g, *og = dothis;
3237dd7cddfSDavid du Colombier 			do {
3247dd7cddfSDavid du Colombier 				g = eval_sub(og);
3257dd7cddfSDavid du Colombier 				if (g && depth >= jumpsteps
326312a1df1SDavid du Colombier 				&& ((verbose&32) || ((verbose&4) && not_claim())))
3277dd7cddfSDavid du Colombier 				{	if (columns != 2)
3287dd7cddfSDavid du Colombier 					{	p_talk(og, 1);
3297dd7cddfSDavid du Colombier 
3307dd7cddfSDavid du Colombier 						if (og->n->ntyp == D_STEP)
3317dd7cddfSDavid du Colombier 						og = og->n->sl->this->frst;
3327dd7cddfSDavid du Colombier 
3337dd7cddfSDavid du Colombier 						printf("\t[");
3347dd7cddfSDavid du Colombier 						comment(stdout, og->n, 0);
335219b2ee8SDavid du Colombier 						printf("]\n");
336219b2ee8SDavid du Colombier 					}
3377dd7cddfSDavid du Colombier 					if (verbose&1) dumpglobals();
338*de2caf28SDavid du Colombier 					if (verbose&2) dumplocal(X_lst, 0);
3397dd7cddfSDavid du Colombier 					if (xspin) printf("\n");
3407dd7cddfSDavid du Colombier 				}
3417dd7cddfSDavid du Colombier 				og = g;
3427dd7cddfSDavid du Colombier 			} while (g && g != dothis->nxt);
343*de2caf28SDavid du Colombier 			if (X_lst != NULL)
344*de2caf28SDavid du Colombier 			{	X_lst->pc = g?huntele(g, 0, -1):g;
345f3793cddSDavid du Colombier 			}
3467dd7cddfSDavid du Colombier 		} else
3477dd7cddfSDavid du Colombier 		{
348312a1df1SDavid du Colombier keepgoing:		if (dothis->merge_start)
3497dd7cddfSDavid du Colombier 				a = dothis->merge_start;
3507dd7cddfSDavid du Colombier 			else
3517dd7cddfSDavid du Colombier 				a = dothis->merge;
3527dd7cddfSDavid du Colombier 
353*de2caf28SDavid du Colombier 			if (X_lst != NULL)
354*de2caf28SDavid du Colombier 			{	X_lst->pc = eval_sub(dothis);
355*de2caf28SDavid du Colombier 				if (X_lst->pc) X_lst->pc = huntele(X_lst->pc, 0, a);
356f3793cddSDavid du Colombier 			}
357312a1df1SDavid du Colombier 
3587dd7cddfSDavid du Colombier 			if (depth >= jumpsteps
359312a1df1SDavid du Colombier 			&& ((verbose&32) || ((verbose&4) && not_claim())))	/* -v or -p */
3607dd7cddfSDavid du Colombier 			{	if (columns != 2)
3617dd7cddfSDavid du Colombier 				{	p_talk(dothis, 1);
3627dd7cddfSDavid du Colombier 
3637dd7cddfSDavid du Colombier 					if (dothis->n->ntyp == D_STEP)
3647dd7cddfSDavid du Colombier 					dothis = dothis->n->sl->this->frst;
3657dd7cddfSDavid du Colombier 
3667dd7cddfSDavid du Colombier 					printf("\t[");
3677dd7cddfSDavid du Colombier 					comment(stdout, dothis->n, 0);
3687dd7cddfSDavid du Colombier 					printf("]");
3697dd7cddfSDavid du Colombier 					if (a && (verbose&32))
3707dd7cddfSDavid du Colombier 					printf("\t<merge %d now @%d>",
3717dd7cddfSDavid du Colombier 						dothis->merge,
372*de2caf28SDavid du Colombier 						(X_lst && X_lst->pc)?X_lst->pc->seqno:-1);
3737dd7cddfSDavid du Colombier 					printf("\n");
3747dd7cddfSDavid du Colombier 				}
3757dd7cddfSDavid du Colombier 				if (verbose&1) dumpglobals();
376*de2caf28SDavid du Colombier 				if (verbose&2) dumplocal(X_lst, 0);
3777dd7cddfSDavid du Colombier 				if (xspin) printf("\n");
378312a1df1SDavid du Colombier 
379*de2caf28SDavid du Colombier 				if (X_lst && !X_lst->pc)
380*de2caf28SDavid du Colombier 				{	X_lst->pc = dothis;
381312a1df1SDavid du Colombier 					printf("\ttransition failed\n");
382312a1df1SDavid du Colombier 					a = 0;	/* avoid inf loop */
383312a1df1SDavid du Colombier 				}
3847dd7cddfSDavid du Colombier 			}
385*de2caf28SDavid du Colombier 			if (a && X_lst && X_lst->pc && X_lst->pc->seqno != a)
386*de2caf28SDavid du Colombier 			{	dothis = X_lst->pc;
3877dd7cddfSDavid du Colombier 				goto keepgoing;
388312a1df1SDavid du Colombier 		}	}
3897dd7cddfSDavid du Colombier 
390*de2caf28SDavid du Colombier 		if (Have_claim && X_lst && X_lst->pid == 0
39100d97012SDavid du Colombier 		&&  dothis->n
3927dd7cddfSDavid du Colombier 		&&  lastclaim != dothis->n->ln)
3937dd7cddfSDavid du Colombier 		{	lastclaim = dothis->n->ln;
3947dd7cddfSDavid du Colombier 			if (columns == 2)
3957dd7cddfSDavid du Colombier 			{	char t[128];
3967dd7cddfSDavid du Colombier 				sprintf(t, "#%d", lastclaim);
3977dd7cddfSDavid du Colombier 				pstext(0, t);
3987dd7cddfSDavid du Colombier 			} else
3997dd7cddfSDavid du Colombier 			{
4007dd7cddfSDavid du Colombier 				printf("Never claim moves to line %d\t[", lastclaim);
4017dd7cddfSDavid du Colombier 				comment(stdout, dothis->n, 0);
4027dd7cddfSDavid du Colombier 				printf("]\n");
403312a1df1SDavid du Colombier 	}	}	}
404219b2ee8SDavid du Colombier 	printf("spin: trail ends after %d steps\n", depth);
405219b2ee8SDavid du Colombier 	wrapup(0);
406219b2ee8SDavid du Colombier }
407219b2ee8SDavid du Colombier 
4087dd7cddfSDavid du Colombier static void
lost_trail(void)409219b2ee8SDavid du Colombier lost_trail(void)
410219b2ee8SDavid du Colombier {	int d, p, n, l;
411219b2ee8SDavid du Colombier 
412219b2ee8SDavid du Colombier 	while (fscanf(fd, "%d:%d:%d:%d\n", &d, &p, &n, &l) == 4)
413219b2ee8SDavid du Colombier 	{	printf("step %d: proc  %d ", d, p); whichproc(p);
414219b2ee8SDavid du Colombier 		printf("(state %d) - d %d\n", n, l);
415219b2ee8SDavid du Colombier 	}
416219b2ee8SDavid du Colombier 	wrapup(1);	/* no return */
417219b2ee8SDavid du Colombier }
418219b2ee8SDavid du Colombier 
419219b2ee8SDavid du Colombier int
pc_value(Lextok * n)420219b2ee8SDavid du Colombier pc_value(Lextok *n)
421219b2ee8SDavid du Colombier {	int i = nproc - nstop;
422219b2ee8SDavid du Colombier 	int pid = eval(n);
423219b2ee8SDavid du Colombier 	RunList *Y;
424219b2ee8SDavid du Colombier 
425*de2caf28SDavid du Colombier 	for (Y = run_lst; Y; Y = Y->nxt)
426219b2ee8SDavid du Colombier 	{	if (--i == pid)
427219b2ee8SDavid du Colombier 			return Y->pc->seqno;
428219b2ee8SDavid du Colombier 	}
429219b2ee8SDavid du Colombier 	return 0;
430219b2ee8SDavid du Colombier }
431