xref: /plan9-contrib/sys/src/cmd/spin/run.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier /***** spin: run.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 "y.tab.h"
15*219b2ee8SDavid du Colombier 
16*219b2ee8SDavid du Colombier extern Symbol	*Fname;
17*219b2ee8SDavid du Colombier extern Element	*LastStep;
18*219b2ee8SDavid du Colombier extern int	Rvous, lineno, Tval, Interactive, SubChoice;
19*219b2ee8SDavid du Colombier extern int	TstOnly, verbose, s_trail, xspin;
20*219b2ee8SDavid du Colombier 
21*219b2ee8SDavid du Colombier static long Seed=1;
22*219b2ee8SDavid du Colombier 
23*219b2ee8SDavid du Colombier void
24*219b2ee8SDavid du Colombier Srand(unsigned int s)
25*219b2ee8SDavid du Colombier {	Seed = s;
26*219b2ee8SDavid du Colombier }
27*219b2ee8SDavid du Colombier 
28*219b2ee8SDavid du Colombier long
29*219b2ee8SDavid du Colombier Rand(void)
30*219b2ee8SDavid du Colombier {	/* CACM 31(10), Oct 1988 */
31*219b2ee8SDavid du Colombier 	Seed = 16807*(Seed%127773) - 2836*(Seed/127773);
32*219b2ee8SDavid du Colombier 	if (Seed <= 0) Seed += 2147483647;
33*219b2ee8SDavid du Colombier 	return Seed;
34*219b2ee8SDavid du Colombier }
35*219b2ee8SDavid du Colombier 
36*219b2ee8SDavid du Colombier Element *
37*219b2ee8SDavid du Colombier eval_sub(Element *e)
38*219b2ee8SDavid du Colombier {	Element *f, *g;
39*219b2ee8SDavid du Colombier 	SeqList *z;
40*219b2ee8SDavid du Colombier 	int i, j, k;
41*219b2ee8SDavid du Colombier 
42*219b2ee8SDavid du Colombier 	if (!e->n)
43*219b2ee8SDavid du Colombier 		return ZE;
44*219b2ee8SDavid du Colombier #ifdef DEBUG
45*219b2ee8SDavid du Colombier 	printf("eval_sub(%d) ", e->Seqno);
46*219b2ee8SDavid du Colombier 	comment(stdout, e->n, 0);
47*219b2ee8SDavid du Colombier 	printf("\n");
48*219b2ee8SDavid du Colombier #endif
49*219b2ee8SDavid du Colombier 	if (e->n->ntyp == GOTO)
50*219b2ee8SDavid du Colombier 	{	if (Rvous) return ZE;
51*219b2ee8SDavid du Colombier 		f = get_lab(e->n, 1);
52*219b2ee8SDavid du Colombier 		cross_dsteps(e->n, f->n);
53*219b2ee8SDavid du Colombier 		return f;
54*219b2ee8SDavid du Colombier 	}
55*219b2ee8SDavid du Colombier 	if (e->n->ntyp == UNLESS)
56*219b2ee8SDavid du Colombier 	{	/* escapes were distributed into sequence */
57*219b2ee8SDavid du Colombier 		return eval_sub(e->sub->this->frst);
58*219b2ee8SDavid du Colombier 	} else if (e->sub)	/* true for IF, DO, and UNLESS */
59*219b2ee8SDavid du Colombier 	{	Element *has_else = ZE;
60*219b2ee8SDavid du Colombier 
61*219b2ee8SDavid du Colombier 		if (Interactive && !SubChoice)
62*219b2ee8SDavid du Colombier 		{	printf("Select stmnt (");
63*219b2ee8SDavid du Colombier 			whoruns(0); printf(")\n");
64*219b2ee8SDavid du Colombier 			printf("\tchoice 0: other process\n");
65*219b2ee8SDavid du Colombier 		}
66*219b2ee8SDavid du Colombier 		for (z = e->sub, j=0; z; z = z->nxt)
67*219b2ee8SDavid du Colombier 		{	j++;
68*219b2ee8SDavid du Colombier 			if (Interactive
69*219b2ee8SDavid du Colombier 			&& !SubChoice
70*219b2ee8SDavid du Colombier 			&& z->this->frst
71*219b2ee8SDavid du Colombier 			&& (xspin || Enabled0(z->this->frst)))
72*219b2ee8SDavid du Colombier 			{	printf("\tchoice %d: ", j);
73*219b2ee8SDavid du Colombier 				if (!Enabled0(z->this->frst))
74*219b2ee8SDavid du Colombier 					printf("unexecutable, ");
75*219b2ee8SDavid du Colombier 				comment(stdout, z->this->frst->n, 0);
76*219b2ee8SDavid du Colombier 				printf("\n");
77*219b2ee8SDavid du Colombier 		}	}
78*219b2ee8SDavid du Colombier 		if (Interactive)
79*219b2ee8SDavid du Colombier 		{	if (!SubChoice)
80*219b2ee8SDavid du Colombier 			{	if (xspin)
81*219b2ee8SDavid du Colombier 					printf("Make Selection %d\n\n", j);
82*219b2ee8SDavid du Colombier 				else
83*219b2ee8SDavid du Colombier 					printf("Select [0-%d]: ", j);
84*219b2ee8SDavid du Colombier 				fflush(stdout);
85*219b2ee8SDavid du Colombier 				scanf("%d", &k);
86*219b2ee8SDavid du Colombier 			} else
87*219b2ee8SDavid du Colombier 			{	k = SubChoice;
88*219b2ee8SDavid du Colombier 				SubChoice = 0;
89*219b2ee8SDavid du Colombier 			}
90*219b2ee8SDavid du Colombier 			if (k < 1 || k > j)
91*219b2ee8SDavid du Colombier 			{	printf("\tchoice outside range\n");
92*219b2ee8SDavid du Colombier 				return ZE;
93*219b2ee8SDavid du Colombier 			}
94*219b2ee8SDavid du Colombier 			k--;
95*219b2ee8SDavid du Colombier 		} else
96*219b2ee8SDavid du Colombier 			k = Rand()%j;	/* nondeterminism */
97*219b2ee8SDavid du Colombier 		for (i = 0, z = e->sub; i < j+k; i++)
98*219b2ee8SDavid du Colombier 		{	if (z->this->frst
99*219b2ee8SDavid du Colombier 			&&  z->this->frst->n->ntyp == ELSE)
100*219b2ee8SDavid du Colombier 			{	has_else = z->this->frst->nxt;
101*219b2ee8SDavid du Colombier 				if (!Interactive)
102*219b2ee8SDavid du Colombier 				{	z = (z->nxt)?z->nxt:e->sub;
103*219b2ee8SDavid du Colombier 					continue;
104*219b2ee8SDavid du Colombier 			}	}
105*219b2ee8SDavid du Colombier 			if (i >= k)
106*219b2ee8SDavid du Colombier 			{	if (f = eval_sub(z->this->frst))
107*219b2ee8SDavid du Colombier 					return f;
108*219b2ee8SDavid du Colombier 				else if (Interactive)
109*219b2ee8SDavid du Colombier 				{	printf("\tunexecutable\n");
110*219b2ee8SDavid du Colombier 					return ZE;
111*219b2ee8SDavid du Colombier 			}	}
112*219b2ee8SDavid du Colombier 			z = (z->nxt)?z->nxt:e->sub;
113*219b2ee8SDavid du Colombier 		}
114*219b2ee8SDavid du Colombier 		LastStep = z->this->frst;
115*219b2ee8SDavid du Colombier 		return has_else;
116*219b2ee8SDavid du Colombier 	} else
117*219b2ee8SDavid du Colombier 	{	if (e->n->ntyp == ATOMIC
118*219b2ee8SDavid du Colombier 		||  e->n->ntyp == D_STEP)
119*219b2ee8SDavid du Colombier 		{	f = e->n->sl->this->frst;
120*219b2ee8SDavid du Colombier 			g = e->n->sl->this->last;
121*219b2ee8SDavid du Colombier 			g->nxt = e->nxt;
122*219b2ee8SDavid du Colombier 			if (!(g = eval_sub(f)))	/* atomic guard */
123*219b2ee8SDavid du Colombier 				return ZE;
124*219b2ee8SDavid du Colombier 			/* new implementation of atomic sequences */
125*219b2ee8SDavid du Colombier 			return g;
126*219b2ee8SDavid du Colombier 		} else if (e->n->ntyp == NON_ATOMIC)
127*219b2ee8SDavid du Colombier 		{	f = e->n->sl->this->frst;
128*219b2ee8SDavid du Colombier 			g = e->n->sl->this->last;
129*219b2ee8SDavid du Colombier 			g->nxt = e->nxt;		/* close it */
130*219b2ee8SDavid du Colombier 			return eval_sub(f);
131*219b2ee8SDavid du Colombier 		} else if (Rvous)
132*219b2ee8SDavid du Colombier 		{	if (eval_sync(e))
133*219b2ee8SDavid du Colombier 				return e->nxt;
134*219b2ee8SDavid du Colombier 		} else if (e->n->ntyp == '.')
135*219b2ee8SDavid du Colombier 		{	return e->nxt;
136*219b2ee8SDavid du Colombier 		} else
137*219b2ee8SDavid du Colombier 		{	SeqList *x;
138*219b2ee8SDavid du Colombier 			if (e->esc && verbose&32)
139*219b2ee8SDavid du Colombier 			{	printf("Statement [");
140*219b2ee8SDavid du Colombier 				comment(stdout, e->n, 0);
141*219b2ee8SDavid du Colombier 				printf("] - can be escaped by\n");
142*219b2ee8SDavid du Colombier 				for (x = e->esc; x; x = x->nxt)
143*219b2ee8SDavid du Colombier 				{	printf("\t[");
144*219b2ee8SDavid du Colombier 					comment(stdout, x->this->frst->n, 0);
145*219b2ee8SDavid du Colombier 					printf("]\n");
146*219b2ee8SDavid du Colombier 			}	}
147*219b2ee8SDavid du Colombier 			for (x = e->esc; x; x = x->nxt)
148*219b2ee8SDavid du Colombier 			{	if (g = eval_sub(x->this->frst))
149*219b2ee8SDavid du Colombier 				{	if (verbose&4)
150*219b2ee8SDavid du Colombier 						printf("\tEscape taken\n");
151*219b2ee8SDavid du Colombier 					return g;
152*219b2ee8SDavid du Colombier 			}	}
153*219b2ee8SDavid du Colombier 			switch (e->n->ntyp) {
154*219b2ee8SDavid du Colombier 			case TIMEOUT: case RUN:
155*219b2ee8SDavid du Colombier 			case PRINT: case ASGN: case ASSERT:
156*219b2ee8SDavid du Colombier 			case 's': case 'r': case 'c':
157*219b2ee8SDavid du Colombier 				/* toplevel statements only */
158*219b2ee8SDavid du Colombier 				LastStep = e;
159*219b2ee8SDavid du Colombier 			default:
160*219b2ee8SDavid du Colombier 				break;
161*219b2ee8SDavid du Colombier 			}
162*219b2ee8SDavid du Colombier 			return (eval(e->n))?e->nxt:ZE;
163*219b2ee8SDavid du Colombier 		}
164*219b2ee8SDavid du Colombier 	}
165*219b2ee8SDavid du Colombier 	return ZE;
166*219b2ee8SDavid du Colombier }
167*219b2ee8SDavid du Colombier 
168*219b2ee8SDavid du Colombier int
169*219b2ee8SDavid du Colombier eval_sync(Element *e)
170*219b2ee8SDavid du Colombier {	/* allow only synchronous receives
171*219b2ee8SDavid du Colombier 	/* and related node types    */
172*219b2ee8SDavid du Colombier 	Lextok *now = (e)?e->n:ZN;
173*219b2ee8SDavid du Colombier 
174*219b2ee8SDavid du Colombier 	if (!now
175*219b2ee8SDavid du Colombier 	||  now->ntyp != 'r'
176*219b2ee8SDavid du Colombier 	||  !q_is_sync(now))
177*219b2ee8SDavid du Colombier 		return 0;
178*219b2ee8SDavid du Colombier 
179*219b2ee8SDavid du Colombier 	LastStep = e;
180*219b2ee8SDavid du Colombier 	return eval(now);
181*219b2ee8SDavid du Colombier }
182*219b2ee8SDavid du Colombier 
183*219b2ee8SDavid du Colombier int
184*219b2ee8SDavid du Colombier assign(Lextok *now)
185*219b2ee8SDavid du Colombier {	int t;
186*219b2ee8SDavid du Colombier 
187*219b2ee8SDavid du Colombier 	if (TstOnly) return 1;
188*219b2ee8SDavid du Colombier 
189*219b2ee8SDavid du Colombier 	switch (now->rgt->ntyp) {
190*219b2ee8SDavid du Colombier 	case FULL:	case NFULL:
191*219b2ee8SDavid du Colombier 	case EMPTY:	case NEMPTY:
192*219b2ee8SDavid du Colombier 	case RUN:	case LEN:
193*219b2ee8SDavid du Colombier 		t = BYTE;
194*219b2ee8SDavid du Colombier 		break;
195*219b2ee8SDavid du Colombier 	default:
196*219b2ee8SDavid du Colombier 		t = Sym_typ(now->rgt);
197*219b2ee8SDavid du Colombier 		break;
198*219b2ee8SDavid du Colombier 	}
199*219b2ee8SDavid du Colombier 	typ_ck(Sym_typ(now->lft), t, "assignment");
200*219b2ee8SDavid du Colombier 	return setval(now->lft, eval(now->rgt));
201*219b2ee8SDavid du Colombier }
202*219b2ee8SDavid du Colombier 
203*219b2ee8SDavid du Colombier int
204*219b2ee8SDavid du Colombier eval(Lextok *now)
205*219b2ee8SDavid du Colombier {
206*219b2ee8SDavid du Colombier 	if (now) {
207*219b2ee8SDavid du Colombier 	lineno = now->ln;
208*219b2ee8SDavid du Colombier 	Fname  = now->fn;
209*219b2ee8SDavid du Colombier #ifdef DEBUG
210*219b2ee8SDavid du Colombier 	printf("eval ");
211*219b2ee8SDavid du Colombier 	comment(stdout, now, 0);
212*219b2ee8SDavid du Colombier 	printf("\n");
213*219b2ee8SDavid du Colombier #endif
214*219b2ee8SDavid du Colombier 	switch (now->ntyp) {
215*219b2ee8SDavid du Colombier 	case CONST: return now->val;
216*219b2ee8SDavid du Colombier 	case   '!': return !eval(now->lft);
217*219b2ee8SDavid du Colombier 	case  UMIN: return -eval(now->lft);
218*219b2ee8SDavid du Colombier 	case   '~': return ~eval(now->lft);
219*219b2ee8SDavid du Colombier 
220*219b2ee8SDavid du Colombier 	case   '/': return (eval(now->lft) / eval(now->rgt));
221*219b2ee8SDavid du Colombier 	case   '*': return (eval(now->lft) * eval(now->rgt));
222*219b2ee8SDavid du Colombier 	case   '-': return (eval(now->lft) - eval(now->rgt));
223*219b2ee8SDavid du Colombier 	case   '+': return (eval(now->lft) + eval(now->rgt));
224*219b2ee8SDavid du Colombier 	case   '%': return (eval(now->lft) % eval(now->rgt));
225*219b2ee8SDavid du Colombier 	case    LT: return (eval(now->lft) <  eval(now->rgt));
226*219b2ee8SDavid du Colombier 	case    GT: return (eval(now->lft) >  eval(now->rgt));
227*219b2ee8SDavid du Colombier 	case   '&': return (eval(now->lft) &  eval(now->rgt));
228*219b2ee8SDavid du Colombier 	case   '|': return (eval(now->lft) |  eval(now->rgt));
229*219b2ee8SDavid du Colombier 	case    LE: return (eval(now->lft) <= eval(now->rgt));
230*219b2ee8SDavid du Colombier 	case    GE: return (eval(now->lft) >= eval(now->rgt));
231*219b2ee8SDavid du Colombier 	case    NE: return (eval(now->lft) != eval(now->rgt));
232*219b2ee8SDavid du Colombier 	case    EQ: return (eval(now->lft) == eval(now->rgt));
233*219b2ee8SDavid du Colombier 	case    OR: return (eval(now->lft) || eval(now->rgt));
234*219b2ee8SDavid du Colombier 	case   AND: return (eval(now->lft) && eval(now->rgt));
235*219b2ee8SDavid du Colombier 	case LSHIFT: return (eval(now->lft) << eval(now->rgt));
236*219b2ee8SDavid du Colombier 	case RSHIFT: return (eval(now->lft) >> eval(now->rgt));
237*219b2ee8SDavid du Colombier 	case   '?': return (eval(now->lft) ? eval(now->rgt->lft)
238*219b2ee8SDavid du Colombier 					   : eval(now->rgt->rgt));
239*219b2ee8SDavid du Colombier 
240*219b2ee8SDavid du Colombier 	case     'p': return remotevar(now);	/* only _p allowed */
241*219b2ee8SDavid du Colombier 	case     'q': return remotelab(now);
242*219b2ee8SDavid du Colombier 	case     'R': return qrecv(now, 0);	/* test only    */
243*219b2ee8SDavid du Colombier 	case     LEN: return qlen(now);
244*219b2ee8SDavid du Colombier 	case    FULL: return (qfull(now));
245*219b2ee8SDavid du Colombier 	case   EMPTY: return (qlen(now)==0);
246*219b2ee8SDavid du Colombier 	case   NFULL: return (!qfull(now));
247*219b2ee8SDavid du Colombier 	case  NEMPTY: return (qlen(now)>0);
248*219b2ee8SDavid du Colombier 	case ENABLED: return 1;	/* can only be hit with -t option*/
249*219b2ee8SDavid du Colombier 	case  PC_VAL: return pc_value(now->lft);
250*219b2ee8SDavid du Colombier 	case    NAME: return getval(now);
251*219b2ee8SDavid du Colombier 
252*219b2ee8SDavid du Colombier 	case TIMEOUT: return Tval;
253*219b2ee8SDavid du Colombier 	case     RUN: return TstOnly?1:enable(now->sym, now->lft);
254*219b2ee8SDavid du Colombier 
255*219b2ee8SDavid du Colombier 	case   's': return qsend(now);		/* send         */
256*219b2ee8SDavid du Colombier 	case   'r': return qrecv(now, 1);	/* full-receive */
257*219b2ee8SDavid du Colombier 	case   'c': return eval(now->lft);	/* condition    */
258*219b2ee8SDavid du Colombier 	case PRINT: return TstOnly?1:interprint(now);
259*219b2ee8SDavid du Colombier 	case  ASGN: return assign(now);
260*219b2ee8SDavid du Colombier 	case ASSERT: if (TstOnly || eval(now->lft)) return 1;
261*219b2ee8SDavid du Colombier 		     non_fatal("assertion violated", (char *) 0);
262*219b2ee8SDavid du Colombier 		     if (s_trail) return 1; /* else */
263*219b2ee8SDavid du Colombier 		     wrapup(1); /* doesn't return */
264*219b2ee8SDavid du Colombier 
265*219b2ee8SDavid du Colombier 	case  IF: case DO: case BREAK: case UNLESS:	/* compound structure */
266*219b2ee8SDavid du Colombier 	case   '.': return 1;	/* return label for compound */
267*219b2ee8SDavid du Colombier 	case   '@': return 0;	/* stop state */
268*219b2ee8SDavid du Colombier 	case  ELSE: return 1;	/* only hit here in guided trails */
269*219b2ee8SDavid du Colombier 	default   : printf("spin: bad node type %d (run)\n", now->ntyp);
270*219b2ee8SDavid du Colombier 		    fatal("aborting", 0);
271*219b2ee8SDavid du Colombier 	}}
272*219b2ee8SDavid du Colombier 	return 0;
273*219b2ee8SDavid du Colombier }
274*219b2ee8SDavid du Colombier 
275*219b2ee8SDavid du Colombier int
276*219b2ee8SDavid du Colombier interprint(Lextok *n)
277*219b2ee8SDavid du Colombier {	Lextok *tmp = n->lft;
278*219b2ee8SDavid du Colombier 	char c, *s = n->sym->name;
279*219b2ee8SDavid du Colombier 	int i, j;
280*219b2ee8SDavid du Colombier 
281*219b2ee8SDavid du Colombier 	for (i = 0; i < strlen(s); i++)
282*219b2ee8SDavid du Colombier 		switch (s[i]) {
283*219b2ee8SDavid du Colombier 		default:   putchar(s[i]); break;
284*219b2ee8SDavid du Colombier 		case '\"': break; /* ignore */
285*219b2ee8SDavid du Colombier 		case '\\':
286*219b2ee8SDavid du Colombier 			 switch(s[++i]) {
287*219b2ee8SDavid du Colombier 			 case 't': putchar('\t'); break;
288*219b2ee8SDavid du Colombier 			 case 'n': putchar('\n'); break;
289*219b2ee8SDavid du Colombier 			 default:  putchar(s[i]); break;
290*219b2ee8SDavid du Colombier 			 }
291*219b2ee8SDavid du Colombier 			 break;
292*219b2ee8SDavid du Colombier 		case  '%':
293*219b2ee8SDavid du Colombier 			 if ((c = s[++i]) == '%')
294*219b2ee8SDavid du Colombier 			 {	putchar('%'); /* literal */
295*219b2ee8SDavid du Colombier 				break;
296*219b2ee8SDavid du Colombier 			 }
297*219b2ee8SDavid du Colombier 			 if (!tmp)
298*219b2ee8SDavid du Colombier 			 {	non_fatal("too few print args %s", s);
299*219b2ee8SDavid du Colombier 				break;
300*219b2ee8SDavid du Colombier 			 }
301*219b2ee8SDavid du Colombier 			 j = eval(tmp->lft);
302*219b2ee8SDavid du Colombier 			 tmp = tmp->rgt;
303*219b2ee8SDavid du Colombier 			 switch(c) {
304*219b2ee8SDavid du Colombier 			 case 'c': printf("%c", j); break;
305*219b2ee8SDavid du Colombier 			 case 'd': printf("%d", j); break;
306*219b2ee8SDavid du Colombier 			 case 'o': printf("%o", j); break;
307*219b2ee8SDavid du Colombier 			 case 'u': printf("%u", (unsigned) j); break;
308*219b2ee8SDavid du Colombier 			 case 'x': printf("%x", j); break;
309*219b2ee8SDavid du Colombier 			 default:  non_fatal("unrecognized print cmd: '%s'", &s[i-1]);
310*219b2ee8SDavid du Colombier 				   break;
311*219b2ee8SDavid du Colombier 			 }
312*219b2ee8SDavid du Colombier 			 break;
313*219b2ee8SDavid du Colombier 		}
314*219b2ee8SDavid du Colombier 	fflush(stdout);
315*219b2ee8SDavid du Colombier 	return 1;
316*219b2ee8SDavid du Colombier }
317*219b2ee8SDavid du Colombier 
318*219b2ee8SDavid du Colombier /* new */
319*219b2ee8SDavid du Colombier 
320*219b2ee8SDavid du Colombier int
321*219b2ee8SDavid du Colombier Enabled1(Lextok *n)
322*219b2ee8SDavid du Colombier {	int i; int v = verbose;
323*219b2ee8SDavid du Colombier 
324*219b2ee8SDavid du Colombier 	if (n)
325*219b2ee8SDavid du Colombier 	switch (n->ntyp) {
326*219b2ee8SDavid du Colombier 	default:	/* side-effect free */
327*219b2ee8SDavid du Colombier 		verbose = 0;
328*219b2ee8SDavid du Colombier 		i = eval(n);
329*219b2ee8SDavid du Colombier 		verbose = v;
330*219b2ee8SDavid du Colombier 		return i;
331*219b2ee8SDavid du Colombier 
332*219b2ee8SDavid du Colombier 	case PRINT:  case  ASGN:
333*219b2ee8SDavid du Colombier 	case ASSERT: case   RUN:
334*219b2ee8SDavid du Colombier 		return 1;
335*219b2ee8SDavid du Colombier 
336*219b2ee8SDavid du Colombier 	case 's':	/* guesses for rv */
337*219b2ee8SDavid du Colombier 		if (q_is_sync(n)) return !Rvous;
338*219b2ee8SDavid du Colombier 		return (!qfull(n));
339*219b2ee8SDavid du Colombier 	case 'r':	/* guesses for rv */
340*219b2ee8SDavid du Colombier 		if (q_is_sync(n)) return Rvous;
341*219b2ee8SDavid du Colombier 		n->ntyp = 'R'; verbose = 0;
342*219b2ee8SDavid du Colombier 		i = eval(n);
343*219b2ee8SDavid du Colombier 		n->ntyp = 'r'; verbose = v;
344*219b2ee8SDavid du Colombier 		return i;
345*219b2ee8SDavid du Colombier 	}
346*219b2ee8SDavid du Colombier 	return 0;
347*219b2ee8SDavid du Colombier }
348*219b2ee8SDavid du Colombier 
349*219b2ee8SDavid du Colombier int
350*219b2ee8SDavid du Colombier Enabled0(Element *e)
351*219b2ee8SDavid du Colombier {	SeqList *z;
352*219b2ee8SDavid du Colombier 
353*219b2ee8SDavid du Colombier 	if (!e || !e->n)
354*219b2ee8SDavid du Colombier 		return 0;
355*219b2ee8SDavid du Colombier 
356*219b2ee8SDavid du Colombier 	switch (e->n->ntyp) {
357*219b2ee8SDavid du Colombier 	case '.':
358*219b2ee8SDavid du Colombier 		return 1;
359*219b2ee8SDavid du Colombier 	case GOTO:
360*219b2ee8SDavid du Colombier 		if (Rvous) return 0;
361*219b2ee8SDavid du Colombier 		return 1;
362*219b2ee8SDavid du Colombier 	case UNLESS:
363*219b2ee8SDavid du Colombier 		return Enabled0(e->sub->this->frst);
364*219b2ee8SDavid du Colombier 	case ATOMIC:
365*219b2ee8SDavid du Colombier 	case D_STEP:
366*219b2ee8SDavid du Colombier 	case NON_ATOMIC:
367*219b2ee8SDavid du Colombier 		return Enabled0(e->n->sl->this->frst);
368*219b2ee8SDavid du Colombier 	}
369*219b2ee8SDavid du Colombier 	if (e->sub)	/* true for IF, DO, and UNLESS */
370*219b2ee8SDavid du Colombier 	{	for (z = e->sub; z; z = z->nxt)
371*219b2ee8SDavid du Colombier 			if (Enabled0(z->this->frst))
372*219b2ee8SDavid du Colombier 				return 1;
373*219b2ee8SDavid du Colombier 		return 0;
374*219b2ee8SDavid du Colombier 	}
375*219b2ee8SDavid du Colombier 	for (z = e->esc; z; z = z->nxt)
376*219b2ee8SDavid du Colombier 	{	if (Enabled0(z->this->frst))
377*219b2ee8SDavid du Colombier 			return 1;
378*219b2ee8SDavid du Colombier 	}
379*219b2ee8SDavid du Colombier 	return Enabled1(e->n);
380*219b2ee8SDavid du Colombier }
381