1219b2ee8SDavid du Colombier /***** spin: run.c *****/
2219b2ee8SDavid du Colombier
3312a1df1SDavid du Colombier /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
47dd7cddfSDavid du Colombier /* All Rights Reserved. This software is for educational purposes only. */
5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6312a1df1SDavid du Colombier /* this code. Permission is given to distribute this code provided that */
7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged. */
8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann. For tool documentation see: */
9312a1df1SDavid du Colombier /* http://spinroot.com/ */
10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com */
11219b2ee8SDavid du Colombier
127dd7cddfSDavid du Colombier #include <stdlib.h>
13219b2ee8SDavid du Colombier #include "spin.h"
14219b2ee8SDavid du Colombier #include "y.tab.h"
15219b2ee8SDavid du Colombier
167dd7cddfSDavid du Colombier extern RunList *X, *run;
17219b2ee8SDavid du Colombier extern Symbol *Fname;
18219b2ee8SDavid du Colombier extern Element *LastStep;
197dd7cddfSDavid du Colombier extern int Rvous, lineno, Tval, interactive, MadeChoice;
207dd7cddfSDavid du Colombier extern int TstOnly, verbose, s_trail, xspin, jumpsteps, depth;
21*00d97012SDavid du Colombier extern int analyze, nproc, nstop, no_print, like_java;
22219b2ee8SDavid du Colombier
23219b2ee8SDavid du Colombier static long Seed = 1;
247dd7cddfSDavid du Colombier static int E_Check = 0, Escape_Check = 0;
257dd7cddfSDavid du Colombier
267dd7cddfSDavid du Colombier static int eval_sync(Element *);
277dd7cddfSDavid du Colombier static int pc_enabled(Lextok *n);
287dd7cddfSDavid du Colombier extern void sr_buf(int, int);
29219b2ee8SDavid du Colombier
30219b2ee8SDavid du Colombier void
Srand(unsigned int s)31219b2ee8SDavid du Colombier Srand(unsigned int s)
32219b2ee8SDavid du Colombier { Seed = s;
33219b2ee8SDavid du Colombier }
34219b2ee8SDavid du Colombier
35219b2ee8SDavid du Colombier long
Rand(void)36219b2ee8SDavid du Colombier Rand(void)
37219b2ee8SDavid du Colombier { /* CACM 31(10), Oct 1988 */
38219b2ee8SDavid du Colombier Seed = 16807*(Seed%127773) - 2836*(Seed/127773);
39219b2ee8SDavid du Colombier if (Seed <= 0) Seed += 2147483647;
40219b2ee8SDavid du Colombier return Seed;
41219b2ee8SDavid du Colombier }
42219b2ee8SDavid du Colombier
43219b2ee8SDavid du Colombier Element *
rev_escape(SeqList * e)447dd7cddfSDavid du Colombier rev_escape(SeqList *e)
457dd7cddfSDavid du Colombier { Element *r;
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier if (!e)
487dd7cddfSDavid du Colombier return (Element *) 0;
497dd7cddfSDavid du Colombier
50312a1df1SDavid du Colombier if ((r = rev_escape(e->nxt)) != ZE) /* reversed order */
517dd7cddfSDavid du Colombier return r;
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier return eval_sub(e->this->frst);
547dd7cddfSDavid du Colombier }
557dd7cddfSDavid du Colombier
567dd7cddfSDavid du Colombier Element *
eval_sub(Element * e)57219b2ee8SDavid du Colombier eval_sub(Element *e)
58219b2ee8SDavid du Colombier { Element *f, *g;
59219b2ee8SDavid du Colombier SeqList *z;
60*00d97012SDavid du Colombier int i, j, k, only_pos;
61219b2ee8SDavid du Colombier
62*00d97012SDavid du Colombier if (!e || !e->n)
63219b2ee8SDavid du Colombier return ZE;
64219b2ee8SDavid du Colombier #ifdef DEBUG
657dd7cddfSDavid du Colombier printf("\n\teval_sub(%d %s: line %d) ",
667dd7cddfSDavid du Colombier e->Seqno, e->esc?"+esc":"", e->n?e->n->ln:0);
67219b2ee8SDavid du Colombier comment(stdout, e->n, 0);
68219b2ee8SDavid du Colombier printf("\n");
69219b2ee8SDavid du Colombier #endif
70219b2ee8SDavid du Colombier if (e->n->ntyp == GOTO)
71219b2ee8SDavid du Colombier { if (Rvous) return ZE;
72*00d97012SDavid du Colombier LastStep = e;
73*00d97012SDavid du Colombier f = get_lab(e->n, 1);
74*00d97012SDavid du Colombier f = huntele(f, e->status, -1); /* 5.2.3: was missing */
75219b2ee8SDavid du Colombier cross_dsteps(e->n, f->n);
76*00d97012SDavid du Colombier #ifdef DEBUG
77*00d97012SDavid du Colombier printf("GOTO leads to %d\n", f->seqno);
78*00d97012SDavid du Colombier #endif
79219b2ee8SDavid du Colombier return f;
80219b2ee8SDavid du Colombier }
81219b2ee8SDavid du Colombier if (e->n->ntyp == UNLESS)
82219b2ee8SDavid du Colombier { /* escapes were distributed into sequence */
83219b2ee8SDavid du Colombier return eval_sub(e->sub->this->frst);
84219b2ee8SDavid du Colombier } else if (e->sub) /* true for IF, DO, and UNLESS */
85219b2ee8SDavid du Colombier { Element *has_else = ZE;
867dd7cddfSDavid du Colombier Element *bas_else = ZE;
87312a1df1SDavid du Colombier int nr_else = 0, nr_choices = 0;
88*00d97012SDavid du Colombier only_pos = -1;
89219b2ee8SDavid du Colombier
907dd7cddfSDavid du Colombier if (interactive
917dd7cddfSDavid du Colombier && !MadeChoice && !E_Check
927dd7cddfSDavid du Colombier && !Escape_Check
937dd7cddfSDavid du Colombier && !(e->status&(D_ATOM))
947dd7cddfSDavid du Colombier && depth >= jumpsteps)
95219b2ee8SDavid du Colombier { printf("Select stmnt (");
96219b2ee8SDavid du Colombier whoruns(0); printf(")\n");
977dd7cddfSDavid du Colombier if (nproc-nstop > 1)
98*00d97012SDavid du Colombier { printf("\tchoice 0: other process\n");
99*00d97012SDavid du Colombier nr_choices++;
100*00d97012SDavid du Colombier only_pos = 0;
101*00d97012SDavid du Colombier } }
102219b2ee8SDavid du Colombier for (z = e->sub, j=0; z; z = z->nxt)
103219b2ee8SDavid du Colombier { j++;
1047dd7cddfSDavid du Colombier if (interactive
1057dd7cddfSDavid du Colombier && !MadeChoice && !E_Check
1067dd7cddfSDavid du Colombier && !Escape_Check
1077dd7cddfSDavid du Colombier && !(e->status&(D_ATOM))
1087dd7cddfSDavid du Colombier && depth >= jumpsteps
109219b2ee8SDavid du Colombier && z->this->frst
1107dd7cddfSDavid du Colombier && (xspin || (verbose&32) || Enabled0(z->this->frst)))
1117dd7cddfSDavid du Colombier { if (z->this->frst->n->ntyp == ELSE)
1127dd7cddfSDavid du Colombier { has_else = (Rvous)?ZE:z->this->frst->nxt;
1137dd7cddfSDavid du Colombier nr_else = j;
1147dd7cddfSDavid du Colombier continue;
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier printf("\tchoice %d: ", j);
1177dd7cddfSDavid du Colombier #if 0
1187dd7cddfSDavid du Colombier if (z->this->frst->n)
1197dd7cddfSDavid du Colombier printf("line %d, ", z->this->frst->n->ln);
1207dd7cddfSDavid du Colombier #endif
121219b2ee8SDavid du Colombier if (!Enabled0(z->this->frst))
122219b2ee8SDavid du Colombier printf("unexecutable, ");
1237dd7cddfSDavid du Colombier else
124*00d97012SDavid du Colombier { nr_choices++;
125*00d97012SDavid du Colombier only_pos = j;
126*00d97012SDavid du Colombier }
127219b2ee8SDavid du Colombier comment(stdout, z->this->frst->n, 0);
128219b2ee8SDavid du Colombier printf("\n");
129219b2ee8SDavid du Colombier } }
1307dd7cddfSDavid du Colombier
1317dd7cddfSDavid du Colombier if (nr_choices == 0 && has_else)
132*00d97012SDavid du Colombier { printf("\tchoice %d: (else)\n", nr_else);
133*00d97012SDavid du Colombier only_pos = nr_else;
134*00d97012SDavid du Colombier }
135*00d97012SDavid du Colombier
136*00d97012SDavid du Colombier if (nr_choices <= 1 && only_pos != -1 && !MadeChoice)
137*00d97012SDavid du Colombier { MadeChoice = only_pos;
138*00d97012SDavid du Colombier }
1397dd7cddfSDavid du Colombier
1407dd7cddfSDavid du Colombier if (interactive && depth >= jumpsteps
1417dd7cddfSDavid du Colombier && !Escape_Check
1427dd7cddfSDavid du Colombier && !(e->status&(D_ATOM))
1437dd7cddfSDavid du Colombier && !E_Check)
1447dd7cddfSDavid du Colombier { if (!MadeChoice)
1457dd7cddfSDavid du Colombier { char buf[256];
1467dd7cddfSDavid du Colombier if (xspin)
147219b2ee8SDavid du Colombier printf("Make Selection %d\n\n", j);
148219b2ee8SDavid du Colombier else
149219b2ee8SDavid du Colombier printf("Select [0-%d]: ", j);
150219b2ee8SDavid du Colombier fflush(stdout);
151*00d97012SDavid du Colombier if (scanf("%64s", buf) <= 0)
152*00d97012SDavid du Colombier { printf("no input\n");
153*00d97012SDavid du Colombier return ZE;
154*00d97012SDavid du Colombier }
155*00d97012SDavid du Colombier if (isdigit((int)buf[0]))
1567dd7cddfSDavid du Colombier k = atoi(buf);
1577dd7cddfSDavid du Colombier else
1587dd7cddfSDavid du Colombier { if (buf[0] == 'q')
1597dd7cddfSDavid du Colombier alldone(0);
1607dd7cddfSDavid du Colombier k = -1;
1617dd7cddfSDavid du Colombier }
162219b2ee8SDavid du Colombier } else
1637dd7cddfSDavid du Colombier { k = MadeChoice;
1647dd7cddfSDavid du Colombier MadeChoice = 0;
165219b2ee8SDavid du Colombier }
166219b2ee8SDavid du Colombier if (k < 1 || k > j)
1677dd7cddfSDavid du Colombier { if (k != 0) printf("\tchoice outside range\n");
168219b2ee8SDavid du Colombier return ZE;
169219b2ee8SDavid du Colombier }
170219b2ee8SDavid du Colombier k--;
171219b2ee8SDavid du Colombier } else
1727dd7cddfSDavid du Colombier { if (e->n && e->n->indstep >= 0)
1737dd7cddfSDavid du Colombier k = 0; /* select 1st executable guard */
1747dd7cddfSDavid du Colombier else
175219b2ee8SDavid du Colombier k = Rand()%j; /* nondeterminism */
1767dd7cddfSDavid du Colombier }
177*00d97012SDavid du Colombier
1787dd7cddfSDavid du Colombier has_else = ZE;
1797dd7cddfSDavid du Colombier bas_else = ZE;
180219b2ee8SDavid du Colombier for (i = 0, z = e->sub; i < j+k; i++)
181219b2ee8SDavid du Colombier { if (z->this->frst
182219b2ee8SDavid du Colombier && z->this->frst->n->ntyp == ELSE)
1837dd7cddfSDavid du Colombier { bas_else = z->this->frst;
1847dd7cddfSDavid du Colombier has_else = (Rvous)?ZE:bas_else->nxt;
1857dd7cddfSDavid du Colombier if (!interactive || depth < jumpsteps
1867dd7cddfSDavid du Colombier || Escape_Check
1877dd7cddfSDavid du Colombier || (e->status&(D_ATOM)))
188219b2ee8SDavid du Colombier { z = (z->nxt)?z->nxt:e->sub;
189219b2ee8SDavid du Colombier continue;
1907dd7cddfSDavid du Colombier }
1917dd7cddfSDavid du Colombier }
192312a1df1SDavid du Colombier if (z->this->frst
193312a1df1SDavid du Colombier && ((z->this->frst->n->ntyp == ATOMIC
194312a1df1SDavid du Colombier || z->this->frst->n->ntyp == D_STEP)
195312a1df1SDavid du Colombier && z->this->frst->n->sl->this->frst->n->ntyp == ELSE))
196312a1df1SDavid du Colombier { bas_else = z->this->frst->n->sl->this->frst;
197312a1df1SDavid du Colombier has_else = (Rvous)?ZE:bas_else->nxt;
198312a1df1SDavid du Colombier if (!interactive || depth < jumpsteps
199312a1df1SDavid du Colombier || Escape_Check
200312a1df1SDavid du Colombier || (e->status&(D_ATOM)))
201312a1df1SDavid du Colombier { z = (z->nxt)?z->nxt:e->sub;
202312a1df1SDavid du Colombier continue;
203312a1df1SDavid du Colombier }
204312a1df1SDavid du Colombier }
205219b2ee8SDavid du Colombier if (i >= k)
206312a1df1SDavid du Colombier { if ((f = eval_sub(z->this->frst)) != ZE)
207219b2ee8SDavid du Colombier return f;
2087dd7cddfSDavid du Colombier else if (interactive && depth >= jumpsteps
2097dd7cddfSDavid du Colombier && !(e->status&(D_ATOM)))
2107dd7cddfSDavid du Colombier { if (!E_Check && !Escape_Check)
2117dd7cddfSDavid du Colombier printf("\tunexecutable\n");
212219b2ee8SDavid du Colombier return ZE;
213219b2ee8SDavid du Colombier } }
214219b2ee8SDavid du Colombier z = (z->nxt)?z->nxt:e->sub;
215219b2ee8SDavid du Colombier }
2167dd7cddfSDavid du Colombier LastStep = bas_else;
217219b2ee8SDavid du Colombier return has_else;
218219b2ee8SDavid du Colombier } else
219219b2ee8SDavid du Colombier { if (e->n->ntyp == ATOMIC
220219b2ee8SDavid du Colombier || e->n->ntyp == D_STEP)
221219b2ee8SDavid du Colombier { f = e->n->sl->this->frst;
222219b2ee8SDavid du Colombier g = e->n->sl->this->last;
223219b2ee8SDavid du Colombier g->nxt = e->nxt;
224219b2ee8SDavid du Colombier if (!(g = eval_sub(f))) /* atomic guard */
225219b2ee8SDavid du Colombier return ZE;
226219b2ee8SDavid du Colombier return g;
227219b2ee8SDavid du Colombier } else if (e->n->ntyp == NON_ATOMIC)
228219b2ee8SDavid du Colombier { f = e->n->sl->this->frst;
229219b2ee8SDavid du Colombier g = e->n->sl->this->last;
230219b2ee8SDavid du Colombier g->nxt = e->nxt; /* close it */
231219b2ee8SDavid du Colombier return eval_sub(f);
232219b2ee8SDavid du Colombier } else if (e->n->ntyp == '.')
2337dd7cddfSDavid du Colombier { if (!Rvous) return e->nxt;
2347dd7cddfSDavid du Colombier return eval_sub(e->nxt);
235219b2ee8SDavid du Colombier } else
236219b2ee8SDavid du Colombier { SeqList *x;
2377dd7cddfSDavid du Colombier if (!(e->status & (D_ATOM))
2387dd7cddfSDavid du Colombier && e->esc && verbose&32)
2397dd7cddfSDavid du Colombier { printf("Stmnt [");
240219b2ee8SDavid du Colombier comment(stdout, e->n, 0);
2417dd7cddfSDavid du Colombier printf("] has escape(s): ");
242219b2ee8SDavid du Colombier for (x = e->esc; x; x = x->nxt)
2437dd7cddfSDavid du Colombier { printf("[");
2447dd7cddfSDavid du Colombier g = x->this->frst;
2457dd7cddfSDavid du Colombier if (g->n->ntyp == ATOMIC
2467dd7cddfSDavid du Colombier || g->n->ntyp == NON_ATOMIC)
2477dd7cddfSDavid du Colombier g = g->n->sl->this->frst;
2487dd7cddfSDavid du Colombier comment(stdout, g->n, 0);
2497dd7cddfSDavid du Colombier printf("] ");
2507dd7cddfSDavid du Colombier }
2517dd7cddfSDavid du Colombier printf("\n");
2527dd7cddfSDavid du Colombier }
253312a1df1SDavid du Colombier #if 0
2547dd7cddfSDavid du Colombier if (!(e->status & D_ATOM)) /* escapes don't reach inside d_steps */
255312a1df1SDavid du Colombier /* 4.2.4: only the guard of a d_step can have an escape */
256312a1df1SDavid du Colombier #endif
257*00d97012SDavid du Colombier #if 1
258*00d97012SDavid du Colombier if (!s_trail) /* trail determines selections, new 5.2.5 */
259*00d97012SDavid du Colombier #endif
2607dd7cddfSDavid du Colombier { Escape_Check++;
2617dd7cddfSDavid du Colombier if (like_java)
262312a1df1SDavid du Colombier { if ((g = rev_escape(e->esc)) != ZE)
2637dd7cddfSDavid du Colombier { if (verbose&4)
2647dd7cddfSDavid du Colombier printf("\tEscape taken\n");
2657dd7cddfSDavid du Colombier Escape_Check--;
2667dd7cddfSDavid du Colombier return g;
2677dd7cddfSDavid du Colombier }
2687dd7cddfSDavid du Colombier } else
2697dd7cddfSDavid du Colombier { for (x = e->esc; x; x = x->nxt)
270312a1df1SDavid du Colombier { if ((g = eval_sub(x->this->frst)) != ZE)
271219b2ee8SDavid du Colombier { if (verbose&4)
272*00d97012SDavid du Colombier { printf("\tEscape taken ");
273*00d97012SDavid du Colombier if (g->n && g->n->fn)
274*00d97012SDavid du Colombier printf("%s:%d", g->n->fn->name, g->n->ln);
275*00d97012SDavid du Colombier printf("\n");
276*00d97012SDavid du Colombier }
2777dd7cddfSDavid du Colombier Escape_Check--;
278219b2ee8SDavid du Colombier return g;
2797dd7cddfSDavid du Colombier } } }
2807dd7cddfSDavid du Colombier Escape_Check--;
2817dd7cddfSDavid du Colombier }
2827dd7cddfSDavid du Colombier
283219b2ee8SDavid du Colombier switch (e->n->ntyp) {
284219b2ee8SDavid du Colombier case TIMEOUT: case RUN:
285312a1df1SDavid du Colombier case PRINT: case PRINTM:
286312a1df1SDavid du Colombier case C_CODE: case C_EXPR:
2877dd7cddfSDavid du Colombier case ASGN: case ASSERT:
288219b2ee8SDavid du Colombier case 's': case 'r': case 'c':
289219b2ee8SDavid du Colombier /* toplevel statements only */
290219b2ee8SDavid du Colombier LastStep = e;
291219b2ee8SDavid du Colombier default:
292219b2ee8SDavid du Colombier break;
293219b2ee8SDavid du Colombier }
2947dd7cddfSDavid du Colombier if (Rvous)
2957dd7cddfSDavid du Colombier {
2967dd7cddfSDavid du Colombier return (eval_sync(e))?e->nxt:ZE;
2977dd7cddfSDavid du Colombier }
298219b2ee8SDavid du Colombier return (eval(e->n))?e->nxt:ZE;
299219b2ee8SDavid du Colombier }
300219b2ee8SDavid du Colombier }
3017dd7cddfSDavid du Colombier return ZE; /* not reached */
302219b2ee8SDavid du Colombier }
303219b2ee8SDavid du Colombier
3047dd7cddfSDavid du Colombier static int
eval_sync(Element * e)305219b2ee8SDavid du Colombier eval_sync(Element *e)
306219b2ee8SDavid du Colombier { /* allow only synchronous receives
3077dd7cddfSDavid du Colombier and related node types */
308219b2ee8SDavid du Colombier Lextok *now = (e)?e->n:ZN;
309219b2ee8SDavid du Colombier
310219b2ee8SDavid du Colombier if (!now
311219b2ee8SDavid du Colombier || now->ntyp != 'r'
3127dd7cddfSDavid du Colombier || now->val >= 2 /* no rv with a poll */
313219b2ee8SDavid du Colombier || !q_is_sync(now))
3147dd7cddfSDavid du Colombier {
315219b2ee8SDavid du Colombier return 0;
3167dd7cddfSDavid du Colombier }
317219b2ee8SDavid du Colombier
318219b2ee8SDavid du Colombier LastStep = e;
319219b2ee8SDavid du Colombier return eval(now);
320219b2ee8SDavid du Colombier }
321219b2ee8SDavid du Colombier
3227dd7cddfSDavid du Colombier static int
assign(Lextok * now)323219b2ee8SDavid du Colombier assign(Lextok *now)
324219b2ee8SDavid du Colombier { int t;
325219b2ee8SDavid du Colombier
326219b2ee8SDavid du Colombier if (TstOnly) return 1;
327219b2ee8SDavid du Colombier
328219b2ee8SDavid du Colombier switch (now->rgt->ntyp) {
329219b2ee8SDavid du Colombier case FULL: case NFULL:
330219b2ee8SDavid du Colombier case EMPTY: case NEMPTY:
331219b2ee8SDavid du Colombier case RUN: case LEN:
332219b2ee8SDavid du Colombier t = BYTE;
333219b2ee8SDavid du Colombier break;
334219b2ee8SDavid du Colombier default:
335219b2ee8SDavid du Colombier t = Sym_typ(now->rgt);
336219b2ee8SDavid du Colombier break;
337219b2ee8SDavid du Colombier }
338219b2ee8SDavid du Colombier typ_ck(Sym_typ(now->lft), t, "assignment");
339219b2ee8SDavid du Colombier return setval(now->lft, eval(now->rgt));
340219b2ee8SDavid du Colombier }
341219b2ee8SDavid du Colombier
3427dd7cddfSDavid du Colombier static int
nonprogress(void)3437dd7cddfSDavid du Colombier nonprogress(void) /* np_ */
3447dd7cddfSDavid du Colombier { RunList *r;
3457dd7cddfSDavid du Colombier
3467dd7cddfSDavid du Colombier for (r = run; r; r = r->nxt)
3477dd7cddfSDavid du Colombier { if (has_lab(r->pc, 4)) /* 4=progress */
3487dd7cddfSDavid du Colombier return 0;
3497dd7cddfSDavid du Colombier }
3507dd7cddfSDavid du Colombier return 1;
3517dd7cddfSDavid du Colombier }
3527dd7cddfSDavid du Colombier
353219b2ee8SDavid du Colombier int
eval(Lextok * now)354219b2ee8SDavid du Colombier eval(Lextok *now)
355219b2ee8SDavid du Colombier {
356219b2ee8SDavid du Colombier if (now) {
357219b2ee8SDavid du Colombier lineno = now->ln;
358219b2ee8SDavid du Colombier Fname = now->fn;
359219b2ee8SDavid du Colombier #ifdef DEBUG
360219b2ee8SDavid du Colombier printf("eval ");
361219b2ee8SDavid du Colombier comment(stdout, now, 0);
362219b2ee8SDavid du Colombier printf("\n");
363219b2ee8SDavid du Colombier #endif
364219b2ee8SDavid du Colombier switch (now->ntyp) {
365219b2ee8SDavid du Colombier case CONST: return now->val;
366219b2ee8SDavid du Colombier case '!': return !eval(now->lft);
367219b2ee8SDavid du Colombier case UMIN: return -eval(now->lft);
368219b2ee8SDavid du Colombier case '~': return ~eval(now->lft);
369219b2ee8SDavid du Colombier
370219b2ee8SDavid du Colombier case '/': return (eval(now->lft) / eval(now->rgt));
371219b2ee8SDavid du Colombier case '*': return (eval(now->lft) * eval(now->rgt));
372219b2ee8SDavid du Colombier case '-': return (eval(now->lft) - eval(now->rgt));
373219b2ee8SDavid du Colombier case '+': return (eval(now->lft) + eval(now->rgt));
374219b2ee8SDavid du Colombier case '%': return (eval(now->lft) % eval(now->rgt));
375219b2ee8SDavid du Colombier case LT: return (eval(now->lft) < eval(now->rgt));
376219b2ee8SDavid du Colombier case GT: return (eval(now->lft) > eval(now->rgt));
377219b2ee8SDavid du Colombier case '&': return (eval(now->lft) & eval(now->rgt));
3787dd7cddfSDavid du Colombier case '^': return (eval(now->lft) ^ eval(now->rgt));
379219b2ee8SDavid du Colombier case '|': return (eval(now->lft) | eval(now->rgt));
380219b2ee8SDavid du Colombier case LE: return (eval(now->lft) <= eval(now->rgt));
381219b2ee8SDavid du Colombier case GE: return (eval(now->lft) >= eval(now->rgt));
382219b2ee8SDavid du Colombier case NE: return (eval(now->lft) != eval(now->rgt));
383219b2ee8SDavid du Colombier case EQ: return (eval(now->lft) == eval(now->rgt));
384219b2ee8SDavid du Colombier case OR: return (eval(now->lft) || eval(now->rgt));
385219b2ee8SDavid du Colombier case AND: return (eval(now->lft) && eval(now->rgt));
386219b2ee8SDavid du Colombier case LSHIFT: return (eval(now->lft) << eval(now->rgt));
387219b2ee8SDavid du Colombier case RSHIFT: return (eval(now->lft) >> eval(now->rgt));
388219b2ee8SDavid du Colombier case '?': return (eval(now->lft) ? eval(now->rgt->lft)
389219b2ee8SDavid du Colombier : eval(now->rgt->rgt));
390219b2ee8SDavid du Colombier
391312a1df1SDavid du Colombier case 'p': return remotevar(now); /* _p for remote reference */
392219b2ee8SDavid du Colombier case 'q': return remotelab(now);
393219b2ee8SDavid du Colombier case 'R': return qrecv(now, 0); /* test only */
394219b2ee8SDavid du Colombier case LEN: return qlen(now);
395219b2ee8SDavid du Colombier case FULL: return (qfull(now));
396219b2ee8SDavid du Colombier case EMPTY: return (qlen(now)==0);
397219b2ee8SDavid du Colombier case NFULL: return (!qfull(now));
398219b2ee8SDavid du Colombier case NEMPTY: return (qlen(now)>0);
3997dd7cddfSDavid du Colombier case ENABLED: if (s_trail) return 1;
4007dd7cddfSDavid du Colombier return pc_enabled(now->lft);
4017dd7cddfSDavid du Colombier case EVAL: return eval(now->lft);
402219b2ee8SDavid du Colombier case PC_VAL: return pc_value(now->lft);
4037dd7cddfSDavid du Colombier case NONPROGRESS: return nonprogress();
404219b2ee8SDavid du Colombier case NAME: return getval(now);
405219b2ee8SDavid du Colombier
406219b2ee8SDavid du Colombier case TIMEOUT: return Tval;
4077dd7cddfSDavid du Colombier case RUN: return TstOnly?1:enable(now);
408219b2ee8SDavid du Colombier
409219b2ee8SDavid du Colombier case 's': return qsend(now); /* send */
4107dd7cddfSDavid du Colombier case 'r': return qrecv(now, 1); /* receive or poll */
411219b2ee8SDavid du Colombier case 'c': return eval(now->lft); /* condition */
4127dd7cddfSDavid du Colombier case PRINT: return TstOnly?1:interprint(stdout, now);
413312a1df1SDavid du Colombier case PRINTM: return TstOnly?1:printm(stdout, now);
414219b2ee8SDavid du Colombier case ASGN: return assign(now);
415312a1df1SDavid du Colombier
416*00d97012SDavid du Colombier case C_CODE: if (!analyze)
417*00d97012SDavid du Colombier { printf("%s:\t", now->sym->name);
418*00d97012SDavid du Colombier plunk_inline(stdout, now->sym->name, 0, 1);
419*00d97012SDavid du Colombier }
420312a1df1SDavid du Colombier return 1; /* uninterpreted */
421312a1df1SDavid du Colombier
422*00d97012SDavid du Colombier case C_EXPR: if (!analyze)
423*00d97012SDavid du Colombier { printf("%s:\t", now->sym->name);
424312a1df1SDavid du Colombier plunk_expr(stdout, now->sym->name);
425312a1df1SDavid du Colombier printf("\n");
426*00d97012SDavid du Colombier }
427312a1df1SDavid du Colombier return 1; /* uninterpreted */
428312a1df1SDavid du Colombier
429219b2ee8SDavid du Colombier case ASSERT: if (TstOnly || eval(now->lft)) return 1;
430219b2ee8SDavid du Colombier non_fatal("assertion violated", (char *) 0);
4317dd7cddfSDavid du Colombier printf("spin: text of failed assertion: assert(");
4327dd7cddfSDavid du Colombier comment(stdout, now->lft, 0);
4337dd7cddfSDavid du Colombier printf(")\n");
4347dd7cddfSDavid du Colombier if (s_trail && !xspin) return 1;
435219b2ee8SDavid du Colombier wrapup(1); /* doesn't return */
436219b2ee8SDavid du Colombier
4377dd7cddfSDavid du Colombier case IF: case DO: case BREAK: case UNLESS: /* compound */
438219b2ee8SDavid du Colombier case '.': return 1; /* return label for compound */
439219b2ee8SDavid du Colombier case '@': return 0; /* stop state */
440219b2ee8SDavid du Colombier case ELSE: return 1; /* only hit here in guided trails */
441219b2ee8SDavid du Colombier default : printf("spin: bad node type %d (run)\n", now->ntyp);
4427dd7cddfSDavid du Colombier if (s_trail) printf("spin: trail file doesn't match spec?\n");
443219b2ee8SDavid du Colombier fatal("aborting", 0);
444219b2ee8SDavid du Colombier }}
445219b2ee8SDavid du Colombier return 0;
446219b2ee8SDavid du Colombier }
447219b2ee8SDavid du Colombier
448219b2ee8SDavid du Colombier int
printm(FILE * fd,Lextok * n)449312a1df1SDavid du Colombier printm(FILE *fd, Lextok *n)
450312a1df1SDavid du Colombier { extern char Buf[];
451312a1df1SDavid du Colombier int j;
452312a1df1SDavid du Colombier
453312a1df1SDavid du Colombier Buf[0] = '\0';
454312a1df1SDavid du Colombier if (!no_print)
455312a1df1SDavid du Colombier if (!s_trail || depth >= jumpsteps) {
456312a1df1SDavid du Colombier if (n->lft->ismtyp)
457312a1df1SDavid du Colombier j = n->lft->val;
458312a1df1SDavid du Colombier else
459312a1df1SDavid du Colombier j = eval(n->lft);
460312a1df1SDavid du Colombier sr_buf(j, 1);
461312a1df1SDavid du Colombier dotag(fd, Buf);
462312a1df1SDavid du Colombier }
463312a1df1SDavid du Colombier return 1;
464312a1df1SDavid du Colombier }
465312a1df1SDavid du Colombier
466312a1df1SDavid du Colombier int
interprint(FILE * fd,Lextok * n)4677dd7cddfSDavid du Colombier interprint(FILE *fd, Lextok *n)
468219b2ee8SDavid du Colombier { Lextok *tmp = n->lft;
469219b2ee8SDavid du Colombier char c, *s = n->sym->name;
470*00d97012SDavid du Colombier int i, j; char lbuf[512]; /* matches value in sr_buf() */
471*00d97012SDavid du Colombier extern char Buf[]; /* global, size 4096 */
472*00d97012SDavid du Colombier char tBuf[4096]; /* match size of global Buf[] */
473219b2ee8SDavid du Colombier
4747dd7cddfSDavid du Colombier Buf[0] = '\0';
4757dd7cddfSDavid du Colombier if (!no_print)
4767dd7cddfSDavid du Colombier if (!s_trail || depth >= jumpsteps) {
4777dd7cddfSDavid du Colombier for (i = 0; i < (int) strlen(s); i++)
478219b2ee8SDavid du Colombier switch (s[i]) {
479219b2ee8SDavid du Colombier case '\"': break; /* ignore */
480219b2ee8SDavid du Colombier case '\\':
481219b2ee8SDavid du Colombier switch(s[++i]) {
4827dd7cddfSDavid du Colombier case 't': strcat(Buf, "\t"); break;
4837dd7cddfSDavid du Colombier case 'n': strcat(Buf, "\n"); break;
4847dd7cddfSDavid du Colombier default: goto onechar;
485219b2ee8SDavid du Colombier }
486219b2ee8SDavid du Colombier break;
487219b2ee8SDavid du Colombier case '%':
488219b2ee8SDavid du Colombier if ((c = s[++i]) == '%')
4897dd7cddfSDavid du Colombier { strcat(Buf, "%"); /* literal */
490219b2ee8SDavid du Colombier break;
491219b2ee8SDavid du Colombier }
492219b2ee8SDavid du Colombier if (!tmp)
493219b2ee8SDavid du Colombier { non_fatal("too few print args %s", s);
494219b2ee8SDavid du Colombier break;
495219b2ee8SDavid du Colombier }
496219b2ee8SDavid du Colombier j = eval(tmp->lft);
497219b2ee8SDavid du Colombier tmp = tmp->rgt;
498219b2ee8SDavid du Colombier switch(c) {
4997dd7cddfSDavid du Colombier case 'c': sprintf(lbuf, "%c", j); break;
5007dd7cddfSDavid du Colombier case 'd': sprintf(lbuf, "%d", j); break;
5017dd7cddfSDavid du Colombier
5027dd7cddfSDavid du Colombier case 'e': strcpy(tBuf, Buf); /* event name */
5037dd7cddfSDavid du Colombier Buf[0] = '\0';
5047dd7cddfSDavid du Colombier sr_buf(j, 1);
5057dd7cddfSDavid du Colombier strcpy(lbuf, Buf);
5067dd7cddfSDavid du Colombier strcpy(Buf, tBuf);
5077dd7cddfSDavid du Colombier break;
5087dd7cddfSDavid du Colombier
5097dd7cddfSDavid du Colombier case 'o': sprintf(lbuf, "%o", j); break;
5107dd7cddfSDavid du Colombier case 'u': sprintf(lbuf, "%u", (unsigned) j); break;
5117dd7cddfSDavid du Colombier case 'x': sprintf(lbuf, "%x", j); break;
5127dd7cddfSDavid du Colombier default: non_fatal("bad print cmd: '%s'", &s[i-1]);
5137dd7cddfSDavid du Colombier lbuf[0] = '\0'; break;
5147dd7cddfSDavid du Colombier }
5157dd7cddfSDavid du Colombier goto append;
5167dd7cddfSDavid du Colombier default:
5177dd7cddfSDavid du Colombier onechar: lbuf[0] = s[i]; lbuf[1] = '\0';
5187dd7cddfSDavid du Colombier append: strcat(Buf, lbuf);
519219b2ee8SDavid du Colombier break;
520219b2ee8SDavid du Colombier }
5217dd7cddfSDavid du Colombier dotag(fd, Buf);
522219b2ee8SDavid du Colombier }
523*00d97012SDavid du Colombier if (strlen(Buf) >= 4096) fatal("printf string too long", 0);
524219b2ee8SDavid du Colombier return 1;
525219b2ee8SDavid du Colombier }
526219b2ee8SDavid du Colombier
5277dd7cddfSDavid du Colombier static int
Enabled1(Lextok * n)528219b2ee8SDavid du Colombier Enabled1(Lextok *n)
529219b2ee8SDavid du Colombier { int i; int v = verbose;
530219b2ee8SDavid du Colombier
531219b2ee8SDavid du Colombier if (n)
532219b2ee8SDavid du Colombier switch (n->ntyp) {
5337dd7cddfSDavid du Colombier case 'c':
5347dd7cddfSDavid du Colombier if (has_typ(n->lft, RUN))
5357dd7cddfSDavid du Colombier return 1; /* conservative */
5367dd7cddfSDavid du Colombier /* else fall through */
537219b2ee8SDavid du Colombier default: /* side-effect free */
538219b2ee8SDavid du Colombier verbose = 0;
5397dd7cddfSDavid du Colombier E_Check++;
540219b2ee8SDavid du Colombier i = eval(n);
5417dd7cddfSDavid du Colombier E_Check--;
542219b2ee8SDavid du Colombier verbose = v;
543219b2ee8SDavid du Colombier return i;
544219b2ee8SDavid du Colombier
545312a1df1SDavid du Colombier case C_CODE: case C_EXPR:
546312a1df1SDavid du Colombier case PRINT: case PRINTM:
547312a1df1SDavid du Colombier case ASGN: case ASSERT:
548219b2ee8SDavid du Colombier return 1;
549219b2ee8SDavid du Colombier
5507dd7cddfSDavid du Colombier case 's':
5517dd7cddfSDavid du Colombier if (q_is_sync(n))
5527dd7cddfSDavid du Colombier { if (Rvous) return 0;
5537dd7cddfSDavid du Colombier TstOnly = 1; verbose = 0;
5547dd7cddfSDavid du Colombier E_Check++;
555219b2ee8SDavid du Colombier i = eval(n);
5567dd7cddfSDavid du Colombier E_Check--;
5577dd7cddfSDavid du Colombier TstOnly = 0; verbose = v;
5587dd7cddfSDavid du Colombier return i;
5597dd7cddfSDavid du Colombier }
5607dd7cddfSDavid du Colombier return (!qfull(n));
5617dd7cddfSDavid du Colombier case 'r':
5627dd7cddfSDavid du Colombier if (q_is_sync(n))
5637dd7cddfSDavid du Colombier return 0; /* it's never a user-choice */
5647dd7cddfSDavid du Colombier n->ntyp = 'R'; verbose = 0;
5657dd7cddfSDavid du Colombier E_Check++;
5667dd7cddfSDavid du Colombier i = eval(n);
5677dd7cddfSDavid du Colombier E_Check--;
568219b2ee8SDavid du Colombier n->ntyp = 'r'; verbose = v;
569219b2ee8SDavid du Colombier return i;
570219b2ee8SDavid du Colombier }
571219b2ee8SDavid du Colombier return 0;
572219b2ee8SDavid du Colombier }
573219b2ee8SDavid du Colombier
574219b2ee8SDavid du Colombier int
Enabled0(Element * e)575219b2ee8SDavid du Colombier Enabled0(Element *e)
576219b2ee8SDavid du Colombier { SeqList *z;
577219b2ee8SDavid du Colombier
578219b2ee8SDavid du Colombier if (!e || !e->n)
579219b2ee8SDavid du Colombier return 0;
580219b2ee8SDavid du Colombier
581219b2ee8SDavid du Colombier switch (e->n->ntyp) {
5827dd7cddfSDavid du Colombier case '@':
5837dd7cddfSDavid du Colombier return X->pid == (nproc-nstop-1);
584219b2ee8SDavid du Colombier case '.':
585219b2ee8SDavid du Colombier return 1;
586219b2ee8SDavid du Colombier case GOTO:
587219b2ee8SDavid du Colombier if (Rvous) return 0;
588219b2ee8SDavid du Colombier return 1;
589219b2ee8SDavid du Colombier case UNLESS:
590219b2ee8SDavid du Colombier return Enabled0(e->sub->this->frst);
591219b2ee8SDavid du Colombier case ATOMIC:
592219b2ee8SDavid du Colombier case D_STEP:
593219b2ee8SDavid du Colombier case NON_ATOMIC:
594219b2ee8SDavid du Colombier return Enabled0(e->n->sl->this->frst);
595219b2ee8SDavid du Colombier }
596219b2ee8SDavid du Colombier if (e->sub) /* true for IF, DO, and UNLESS */
597219b2ee8SDavid du Colombier { for (z = e->sub; z; z = z->nxt)
598219b2ee8SDavid du Colombier if (Enabled0(z->this->frst))
599219b2ee8SDavid du Colombier return 1;
600219b2ee8SDavid du Colombier return 0;
601219b2ee8SDavid du Colombier }
602219b2ee8SDavid du Colombier for (z = e->esc; z; z = z->nxt)
603219b2ee8SDavid du Colombier { if (Enabled0(z->this->frst))
604219b2ee8SDavid du Colombier return 1;
605219b2ee8SDavid du Colombier }
6067dd7cddfSDavid du Colombier #if 0
6077dd7cddfSDavid du Colombier printf("enabled1 ");
6087dd7cddfSDavid du Colombier comment(stdout, e->n, 0);
6097dd7cddfSDavid du Colombier printf(" ==> %s\n", Enabled1(e->n)?"yes":"nope");
6107dd7cddfSDavid du Colombier #endif
611219b2ee8SDavid du Colombier return Enabled1(e->n);
612219b2ee8SDavid du Colombier }
6137dd7cddfSDavid du Colombier
6147dd7cddfSDavid du Colombier int
pc_enabled(Lextok * n)6157dd7cddfSDavid du Colombier pc_enabled(Lextok *n)
6167dd7cddfSDavid du Colombier { int i = nproc - nstop;
6177dd7cddfSDavid du Colombier int pid = eval(n);
6187dd7cddfSDavid du Colombier int result = 0;
6197dd7cddfSDavid du Colombier RunList *Y, *oX;
6207dd7cddfSDavid du Colombier
621312a1df1SDavid du Colombier if (pid == X->pid)
622312a1df1SDavid du Colombier fatal("used: enabled(pid=thisproc) [%s]", X->n->name);
623312a1df1SDavid du Colombier
6247dd7cddfSDavid du Colombier for (Y = run; Y; Y = Y->nxt)
6257dd7cddfSDavid du Colombier if (--i == pid)
6267dd7cddfSDavid du Colombier { oX = X; X = Y;
6277dd7cddfSDavid du Colombier result = Enabled0(Y->pc);
6287dd7cddfSDavid du Colombier X = oX;
6297dd7cddfSDavid du Colombier break;
6307dd7cddfSDavid du Colombier }
6317dd7cddfSDavid du Colombier return result;
6327dd7cddfSDavid du Colombier }
633*00d97012SDavid du Colombier
634