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