xref: /plan9-contrib/sys/src/cmd/spin/sched.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1*219b2ee8SDavid du Colombier /***** spin: sched.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 int	verbose, s_trail, analyze;
17*219b2ee8SDavid du Colombier extern char	*claimproc;
18*219b2ee8SDavid du Colombier extern Symbol	*Fname, *context;
19*219b2ee8SDavid du Colombier extern int	lineno, nr_errs, dumptab, xspin;
20*219b2ee8SDavid du Colombier extern int	has_enabled, u_sync, Elcnt, Interactive;
21*219b2ee8SDavid du Colombier 
22*219b2ee8SDavid du Colombier RunList		*X   = (RunList  *) 0;
23*219b2ee8SDavid du Colombier RunList		*run = (RunList  *) 0;
24*219b2ee8SDavid du Colombier RunList		*LastX  = (RunList  *) 0; /* previous executing proc */
25*219b2ee8SDavid du Colombier ProcList	*rdy = (ProcList *) 0;
26*219b2ee8SDavid du Colombier Element		*LastStep = ZE;
27*219b2ee8SDavid du Colombier int		Have_claim=0, nproc=0, nstop=0, Tval=0;
28*219b2ee8SDavid du Colombier int		Rvous=0, depth=0, nrRdy=0, SubChoice;
29*219b2ee8SDavid du Colombier 
30*219b2ee8SDavid du Colombier void
31*219b2ee8SDavid du Colombier runnable(ProcList *p)
32*219b2ee8SDavid du Colombier {	RunList *r = (RunList *) emalloc(sizeof(RunList));
33*219b2ee8SDavid du Colombier 
34*219b2ee8SDavid du Colombier 	r->n  = p->n;
35*219b2ee8SDavid du Colombier 	r->tn = p->tn;
36*219b2ee8SDavid du Colombier 	r->pid = ++nproc-nstop-1;	/* was: nproc++; */
37*219b2ee8SDavid du Colombier 	r->pc = huntele(p->s->frst, p->s->frst->status); /* was: s->frst; */
38*219b2ee8SDavid du Colombier 	r->ps = p->s;		/* was: r->maxseq = s->last->seqno */
39*219b2ee8SDavid du Colombier 	r->nxt = run;
40*219b2ee8SDavid du Colombier 	run = r;
41*219b2ee8SDavid du Colombier }
42*219b2ee8SDavid du Colombier 
43*219b2ee8SDavid du Colombier ProcList *
44*219b2ee8SDavid du Colombier ready(Symbol *n, Lextok *p, Sequence *s) /* n=name, p=formals, s=body */
45*219b2ee8SDavid du Colombier {	ProcList *r = (ProcList *) emalloc(sizeof(ProcList));
46*219b2ee8SDavid du Colombier 	Lextok *fp, *fpt; int j; extern int Npars;
47*219b2ee8SDavid du Colombier 
48*219b2ee8SDavid du Colombier 	r->n = n;
49*219b2ee8SDavid du Colombier 	r->p = p;
50*219b2ee8SDavid du Colombier 	r->s = s;
51*219b2ee8SDavid du Colombier 	r->tn = nrRdy++;
52*219b2ee8SDavid du Colombier 	r->nxt = rdy;
53*219b2ee8SDavid du Colombier 	rdy = r;
54*219b2ee8SDavid du Colombier 
55*219b2ee8SDavid du Colombier 	for (fp  = p, j = 0;  fp;  fp = fp->rgt)
56*219b2ee8SDavid du Colombier 	for (fpt = fp->lft;  fpt; fpt = fpt->rgt)
57*219b2ee8SDavid du Colombier 		j++;	/* count # of parameters */
58*219b2ee8SDavid du Colombier 	Npars = max(Npars, j);
59*219b2ee8SDavid du Colombier 
60*219b2ee8SDavid du Colombier 	return rdy;
61*219b2ee8SDavid du Colombier }
62*219b2ee8SDavid du Colombier 
63*219b2ee8SDavid du Colombier int
64*219b2ee8SDavid du Colombier find_maxel(Symbol *s)
65*219b2ee8SDavid du Colombier {	ProcList *p;
66*219b2ee8SDavid du Colombier 
67*219b2ee8SDavid du Colombier 	for (p = rdy; p; p = p->nxt)
68*219b2ee8SDavid du Colombier 		if (p->n == s)
69*219b2ee8SDavid du Colombier 			return p->s->maxel++;
70*219b2ee8SDavid du Colombier 	return Elcnt++;
71*219b2ee8SDavid du Colombier }
72*219b2ee8SDavid du Colombier 
73*219b2ee8SDavid du Colombier void
74*219b2ee8SDavid du Colombier formdump(void)
75*219b2ee8SDavid du Colombier {	ProcList *p;
76*219b2ee8SDavid du Colombier 	Lextok *f, *t;
77*219b2ee8SDavid du Colombier 	int cnt;
78*219b2ee8SDavid du Colombier 
79*219b2ee8SDavid du Colombier 	for (p = rdy; p; p = p->nxt)
80*219b2ee8SDavid du Colombier 	{	if (!p->p) continue;
81*219b2ee8SDavid du Colombier 		cnt = -1;
82*219b2ee8SDavid du Colombier 		for (f = p->p; f; f = f->rgt)	/* types */
83*219b2ee8SDavid du Colombier 		for (t = f->lft; t; t = t->rgt)	/* formals */
84*219b2ee8SDavid du Colombier 		{	if (t->ntyp != ',')
85*219b2ee8SDavid du Colombier 				t->sym->Nid = cnt--;	/* overload Nid */
86*219b2ee8SDavid du Colombier 			else
87*219b2ee8SDavid du Colombier 				t->lft->sym->Nid = cnt--;
88*219b2ee8SDavid du Colombier 		}
89*219b2ee8SDavid du Colombier 	}
90*219b2ee8SDavid du Colombier }
91*219b2ee8SDavid du Colombier 
92*219b2ee8SDavid du Colombier int
93*219b2ee8SDavid du Colombier enable(Symbol *s, Lextok *n)		/* s=name, n=actuals */
94*219b2ee8SDavid du Colombier {	ProcList *p;
95*219b2ee8SDavid du Colombier 
96*219b2ee8SDavid du Colombier 	for (p = rdy; p; p = p->nxt)
97*219b2ee8SDavid du Colombier 		if (strcmp(s->name, p->n->name) == 0)
98*219b2ee8SDavid du Colombier 		{	runnable(p);
99*219b2ee8SDavid du Colombier 			setparams(run, p, n);
100*219b2ee8SDavid du Colombier 			return (nproc-nstop-1);	/* pid */
101*219b2ee8SDavid du Colombier 		}
102*219b2ee8SDavid du Colombier 	return 0; /* process not found */
103*219b2ee8SDavid du Colombier }
104*219b2ee8SDavid du Colombier 
105*219b2ee8SDavid du Colombier void
106*219b2ee8SDavid du Colombier start_claim(int n)
107*219b2ee8SDavid du Colombier {	ProcList *p;
108*219b2ee8SDavid du Colombier 
109*219b2ee8SDavid du Colombier 	for (p = rdy; p; p = p->nxt)
110*219b2ee8SDavid du Colombier 		if (p->tn == n
111*219b2ee8SDavid du Colombier 		&&  strcmp(p->n->name, ":never:") == 0)
112*219b2ee8SDavid du Colombier 		{	runnable(p);
113*219b2ee8SDavid du Colombier 			Have_claim = run->pid;	/* was 1 */
114*219b2ee8SDavid du Colombier 			return;
115*219b2ee8SDavid du Colombier 		}
116*219b2ee8SDavid du Colombier 	fatal("couldn't find claim", (char *) 0);
117*219b2ee8SDavid du Colombier }
118*219b2ee8SDavid du Colombier 
119*219b2ee8SDavid du Colombier void
120*219b2ee8SDavid du Colombier wrapup(int fini)
121*219b2ee8SDavid du Colombier {
122*219b2ee8SDavid du Colombier 	if (nproc != nstop)
123*219b2ee8SDavid du Colombier 	{	printf("#processes: %d\n", nproc-nstop);
124*219b2ee8SDavid du Colombier 		dumpglobals();
125*219b2ee8SDavid du Colombier 		verbose &= ~1;	/* no more globals */
126*219b2ee8SDavid du Colombier 		verbose |= 32;	/* add process states */
127*219b2ee8SDavid du Colombier 		for (X = run; X; X = X->nxt)
128*219b2ee8SDavid du Colombier 			talk(X);
129*219b2ee8SDavid du Colombier 	}
130*219b2ee8SDavid du Colombier 	printf("%d processes created\n", nproc);
131*219b2ee8SDavid du Colombier 
132*219b2ee8SDavid du Colombier 	if (xspin) exit(0);	/* avoid an abort from xspin */
133*219b2ee8SDavid du Colombier 	if (fini)  exit(1);
134*219b2ee8SDavid du Colombier }
135*219b2ee8SDavid du Colombier 
136*219b2ee8SDavid du Colombier static char is_blocked[256];
137*219b2ee8SDavid du Colombier 
138*219b2ee8SDavid du Colombier int
139*219b2ee8SDavid du Colombier p_blocked(int p)
140*219b2ee8SDavid du Colombier {	register int i, j;
141*219b2ee8SDavid du Colombier 
142*219b2ee8SDavid du Colombier 	is_blocked[p%256] = 1;
143*219b2ee8SDavid du Colombier 	for (i = j = 0; i < nproc - nstop; i++)
144*219b2ee8SDavid du Colombier 		j += is_blocked[i];
145*219b2ee8SDavid du Colombier 	if (j >= nproc - nstop)
146*219b2ee8SDavid du Colombier 	{	memset(is_blocked, 0, 256);
147*219b2ee8SDavid du Colombier 		return 1;
148*219b2ee8SDavid du Colombier 	}
149*219b2ee8SDavid du Colombier 	return 0;
150*219b2ee8SDavid du Colombier }
151*219b2ee8SDavid du Colombier 
152*219b2ee8SDavid du Colombier Element *
153*219b2ee8SDavid du Colombier silent_moves(Element *e)
154*219b2ee8SDavid du Colombier {	Element *f;
155*219b2ee8SDavid du Colombier 
156*219b2ee8SDavid du Colombier 	switch (e->n->ntyp) {
157*219b2ee8SDavid du Colombier 	case GOTO:
158*219b2ee8SDavid du Colombier 		if (Rvous) break;
159*219b2ee8SDavid du Colombier 		f = get_lab(e->n, 1);
160*219b2ee8SDavid du Colombier 		cross_dsteps(e->n, f->n);
161*219b2ee8SDavid du Colombier 		return f; /* guard against goto cycles */
162*219b2ee8SDavid du Colombier 	case UNLESS:
163*219b2ee8SDavid du Colombier 		return silent_moves(e->sub->this->frst);
164*219b2ee8SDavid du Colombier 	case NON_ATOMIC:
165*219b2ee8SDavid du Colombier 	case ATOMIC:
166*219b2ee8SDavid du Colombier 	case D_STEP:
167*219b2ee8SDavid du Colombier 		e->n->sl->this->last->nxt = e->nxt;
168*219b2ee8SDavid du Colombier 		return silent_moves(e->n->sl->this->frst);
169*219b2ee8SDavid du Colombier 	case '.':
170*219b2ee8SDavid du Colombier 		return e->nxt;
171*219b2ee8SDavid du Colombier 	}
172*219b2ee8SDavid du Colombier 	return e;
173*219b2ee8SDavid du Colombier }
174*219b2ee8SDavid du Colombier 
175*219b2ee8SDavid du Colombier void
176*219b2ee8SDavid du Colombier sched(void)
177*219b2ee8SDavid du Colombier {	Element *e;
178*219b2ee8SDavid du Colombier 	RunList *Y=0;	/* previous process in run queue */
179*219b2ee8SDavid du Colombier 	RunList *oX;
180*219b2ee8SDavid du Colombier 	SeqList *z;
181*219b2ee8SDavid du Colombier 	int j, k;
182*219b2ee8SDavid du Colombier 	short Choices[256];
183*219b2ee8SDavid du Colombier 
184*219b2ee8SDavid du Colombier 	if (dumptab)
185*219b2ee8SDavid du Colombier 	{	formdump();
186*219b2ee8SDavid du Colombier 		symdump();
187*219b2ee8SDavid du Colombier 		dumplabels();
188*219b2ee8SDavid du Colombier 		return;
189*219b2ee8SDavid du Colombier 	}
190*219b2ee8SDavid du Colombier 
191*219b2ee8SDavid du Colombier 	if (has_enabled && u_sync > 0)
192*219b2ee8SDavid du Colombier 	{	printf("spin: error: >> cannot use enabled() in ");
193*219b2ee8SDavid du Colombier 		printf("models with synchronous channels <<\n");
194*219b2ee8SDavid du Colombier 		nr_errs++;
195*219b2ee8SDavid du Colombier 	}
196*219b2ee8SDavid du Colombier 	if (analyze)
197*219b2ee8SDavid du Colombier 	{	gensrc();
198*219b2ee8SDavid du Colombier 		return;
199*219b2ee8SDavid du Colombier 	} else if (s_trail)
200*219b2ee8SDavid du Colombier 	{	match_trail();
201*219b2ee8SDavid du Colombier 		return;
202*219b2ee8SDavid du Colombier 	}
203*219b2ee8SDavid du Colombier 	if (claimproc)
204*219b2ee8SDavid du Colombier 		printf("warning: claims are ignored in simulations\n");
205*219b2ee8SDavid du Colombier 
206*219b2ee8SDavid du Colombier 	if (Interactive) Tval = 1;
207*219b2ee8SDavid du Colombier 
208*219b2ee8SDavid du Colombier 	X = run;
209*219b2ee8SDavid du Colombier 	while (X)
210*219b2ee8SDavid du Colombier 	{	context = X->n;
211*219b2ee8SDavid du Colombier 		if (X->pc && X->pc->n)
212*219b2ee8SDavid du Colombier 		{	lineno = X->pc->n->ln;
213*219b2ee8SDavid du Colombier 			Fname  = X->pc->n->fn;
214*219b2ee8SDavid du Colombier 		}
215*219b2ee8SDavid du Colombier 		depth++; LastStep = ZE;
216*219b2ee8SDavid du Colombier 		oX = X;	/* a rendezvous could change it */
217*219b2ee8SDavid du Colombier 		if (e = eval_sub(X->pc))
218*219b2ee8SDavid du Colombier 		{	if (verbose&32 || verbose&4)
219*219b2ee8SDavid du Colombier 			{	if (X == oX)
220*219b2ee8SDavid du Colombier 				{	p_talk(X->pc, 1);
221*219b2ee8SDavid du Colombier 					printf("	[");
222*219b2ee8SDavid du Colombier 					if (!LastStep) LastStep = X->pc;
223*219b2ee8SDavid du Colombier 					comment(stdout, LastStep->n, 0);
224*219b2ee8SDavid du Colombier 					printf("]\n");
225*219b2ee8SDavid du Colombier 				}
226*219b2ee8SDavid du Colombier 				if (verbose&1) dumpglobals();
227*219b2ee8SDavid du Colombier 				if (verbose&2) dumplocal(X);
228*219b2ee8SDavid du Colombier 				if (xspin) printf("\n"); /* xspin looks for these */
229*219b2ee8SDavid du Colombier 			}
230*219b2ee8SDavid du Colombier 			oX->pc = e; LastX = X;
231*219b2ee8SDavid du Colombier 			if (!Interactive) Tval = 0;
232*219b2ee8SDavid du Colombier 			memset(is_blocked, 0, 256);
233*219b2ee8SDavid du Colombier 
234*219b2ee8SDavid du Colombier 			/* new implementation of atomic sequences */
235*219b2ee8SDavid du Colombier 			if (X->pc->status & (ATOM|L_ATOM))
236*219b2ee8SDavid du Colombier 				continue; /* no switch */
237*219b2ee8SDavid du Colombier 		} else
238*219b2ee8SDavid du Colombier 		{	depth--;
239*219b2ee8SDavid du Colombier 			if (X->pc->n->ntyp == '@'
240*219b2ee8SDavid du Colombier 			&&  X->pid == (nproc-nstop-1))
241*219b2ee8SDavid du Colombier 			{	if (X != run)
242*219b2ee8SDavid du Colombier 					Y->nxt = X->nxt;
243*219b2ee8SDavid du Colombier 				else
244*219b2ee8SDavid du Colombier 					run = X->nxt;
245*219b2ee8SDavid du Colombier 				nstop++;
246*219b2ee8SDavid du Colombier 				if (verbose&4)
247*219b2ee8SDavid du Colombier 				{	whoruns(1);
248*219b2ee8SDavid du Colombier 					printf("terminates\n");
249*219b2ee8SDavid du Colombier 				}
250*219b2ee8SDavid du Colombier 				LastX = X;
251*219b2ee8SDavid du Colombier 				if (!Interactive) Tval = 0;
252*219b2ee8SDavid du Colombier 				if (nproc == nstop) break;
253*219b2ee8SDavid du Colombier 				memset(is_blocked, 0, 256);
254*219b2ee8SDavid du Colombier 			} else
255*219b2ee8SDavid du Colombier 			{	if (!Interactive && p_blocked(X->pid))
256*219b2ee8SDavid du Colombier 				{	if (Tval) break;
257*219b2ee8SDavid du Colombier 					Tval = 1;
258*219b2ee8SDavid du Colombier 					printf("timeout\n");
259*219b2ee8SDavid du Colombier 		}	}	}
260*219b2ee8SDavid du Colombier 		Y = X;
261*219b2ee8SDavid du Colombier 		if (Interactive)
262*219b2ee8SDavid du Colombier 		{
263*219b2ee8SDavid du Colombier try_again:		printf("Select a statement\n");
264*219b2ee8SDavid du Colombier 			for (X = run, k = 1; X; X = X->nxt)
265*219b2ee8SDavid du Colombier 			{	if (X->pid > 255) break;
266*219b2ee8SDavid du Colombier 				Choices[X->pid] = 0;
267*219b2ee8SDavid du Colombier 				if (!X->pc)
268*219b2ee8SDavid du Colombier 					continue;
269*219b2ee8SDavid du Colombier 				Choices[X->pid] = k;
270*219b2ee8SDavid du Colombier 				X->pc = silent_moves(X->pc);
271*219b2ee8SDavid du Colombier 				if (!X->pc->sub && X->pc->n)
272*219b2ee8SDavid du Colombier 				{	if (!xspin && !Enabled0(X->pc))
273*219b2ee8SDavid du Colombier 					{	k++;
274*219b2ee8SDavid du Colombier 						continue;
275*219b2ee8SDavid du Colombier 					}
276*219b2ee8SDavid du Colombier 					printf("\tchoice %d: ", k++);
277*219b2ee8SDavid du Colombier 					p_talk(X->pc, 0);
278*219b2ee8SDavid du Colombier 					if (!Enabled0(X->pc))
279*219b2ee8SDavid du Colombier 						printf(" unexecutable,");
280*219b2ee8SDavid du Colombier 					printf(" [");
281*219b2ee8SDavid du Colombier 					comment(stdout, X->pc->n, 0);
282*219b2ee8SDavid du Colombier 					printf("]\n");
283*219b2ee8SDavid du Colombier 				} else
284*219b2ee8SDavid du Colombier 				for (z = X->pc->sub, j=0; z; z = z->nxt)
285*219b2ee8SDavid du Colombier 				{	Element *y = z->this->frst;
286*219b2ee8SDavid du Colombier 					if (!y) continue;
287*219b2ee8SDavid du Colombier 
288*219b2ee8SDavid du Colombier 					if (!xspin && !Enabled0(y))
289*219b2ee8SDavid du Colombier 					{	k++;
290*219b2ee8SDavid du Colombier 						continue;
291*219b2ee8SDavid du Colombier 					}
292*219b2ee8SDavid du Colombier 					printf("\tchoice %d: ", k++);
293*219b2ee8SDavid du Colombier 					p_talk(X->pc, 0);
294*219b2ee8SDavid du Colombier 					if (!Enabled0(y))
295*219b2ee8SDavid du Colombier 						printf(" unexecutable,");
296*219b2ee8SDavid du Colombier 					printf(" [");
297*219b2ee8SDavid du Colombier 					comment(stdout, y->n, 0);
298*219b2ee8SDavid du Colombier 					printf("]\n");
299*219b2ee8SDavid du Colombier 			}	}
300*219b2ee8SDavid du Colombier 			X = run;
301*219b2ee8SDavid du Colombier 			if (xspin)
302*219b2ee8SDavid du Colombier 				printf("Make Selection %d\n\n", k-1);
303*219b2ee8SDavid du Colombier 			else
304*219b2ee8SDavid du Colombier 				printf("Select [1-%d]: ", k-1);
305*219b2ee8SDavid du Colombier 			fflush(stdout);
306*219b2ee8SDavid du Colombier 			scanf("%d", &j);
307*219b2ee8SDavid du Colombier 			if (j < 1 || j >= k)
308*219b2ee8SDavid du Colombier 			{	printf("\tchoice is outside range\n");
309*219b2ee8SDavid du Colombier 				goto try_again;
310*219b2ee8SDavid du Colombier 			}
311*219b2ee8SDavid du Colombier 			SubChoice = 0;
312*219b2ee8SDavid du Colombier 			for (X = run; X; X = X->nxt)
313*219b2ee8SDavid du Colombier 			{	if (!X->nxt
314*219b2ee8SDavid du Colombier 				||   X->nxt->pid > 255
315*219b2ee8SDavid du Colombier 				||   j < Choices[X->nxt->pid])
316*219b2ee8SDavid du Colombier 				{
317*219b2ee8SDavid du Colombier 					SubChoice = 1+j-Choices[X->pid];
318*219b2ee8SDavid du Colombier 					break;
319*219b2ee8SDavid du Colombier 				}
320*219b2ee8SDavid du Colombier 			}
321*219b2ee8SDavid du Colombier 		} else
322*219b2ee8SDavid du Colombier 		{	j = (int) Rand()%(nproc-nstop);
323*219b2ee8SDavid du Colombier 			while (j-- >= 0)
324*219b2ee8SDavid du Colombier 			{	X = X->nxt;
325*219b2ee8SDavid du Colombier 				if (!X) X = run;
326*219b2ee8SDavid du Colombier 		}	}
327*219b2ee8SDavid du Colombier 	}
328*219b2ee8SDavid du Colombier 	context = ZS;
329*219b2ee8SDavid du Colombier 	wrapup(0);
330*219b2ee8SDavid du Colombier }
331*219b2ee8SDavid du Colombier 
332*219b2ee8SDavid du Colombier int
333*219b2ee8SDavid du Colombier complete_rendez(void)
334*219b2ee8SDavid du Colombier {	RunList *orun = X, *tmp;
335*219b2ee8SDavid du Colombier 	Element  *s_was = LastStep;
336*219b2ee8SDavid du Colombier 	Element *e;
337*219b2ee8SDavid du Colombier 
338*219b2ee8SDavid du Colombier 	if (s_trail)
339*219b2ee8SDavid du Colombier 		return 1;
340*219b2ee8SDavid du Colombier 	Rvous = 1;
341*219b2ee8SDavid du Colombier 	for (X = run; X; X = X->nxt)
342*219b2ee8SDavid du Colombier 		if (X != orun && (e = eval_sub(X->pc)))
343*219b2ee8SDavid du Colombier 		{	if (verbose&4)
344*219b2ee8SDavid du Colombier 			{	tmp = orun; orun = X; X = tmp;
345*219b2ee8SDavid du Colombier 				if (!s_was) s_was = X->pc;
346*219b2ee8SDavid du Colombier 				p_talk(s_was, 1);
347*219b2ee8SDavid du Colombier 				printf("	[");
348*219b2ee8SDavid du Colombier 				comment(stdout, s_was->n, 0);
349*219b2ee8SDavid du Colombier 				printf("]\n");
350*219b2ee8SDavid du Colombier 				tmp = orun; orun = X; X = tmp;
351*219b2ee8SDavid du Colombier 			/*	printf("\t");	*/
352*219b2ee8SDavid du Colombier 				if (!LastStep) LastStep = X->pc;
353*219b2ee8SDavid du Colombier 				p_talk(LastStep, 1);
354*219b2ee8SDavid du Colombier 				printf("	[");
355*219b2ee8SDavid du Colombier 				comment(stdout, LastStep->n, 0);
356*219b2ee8SDavid du Colombier 				printf("]\n");
357*219b2ee8SDavid du Colombier 			}
358*219b2ee8SDavid du Colombier 			X->pc = e;
359*219b2ee8SDavid du Colombier 			Rvous = 0;
360*219b2ee8SDavid du Colombier 			return 1;
361*219b2ee8SDavid du Colombier 		}
362*219b2ee8SDavid du Colombier 	Rvous = 0;
363*219b2ee8SDavid du Colombier 	X = orun;
364*219b2ee8SDavid du Colombier 	return 0;
365*219b2ee8SDavid du Colombier }
366*219b2ee8SDavid du Colombier 
367*219b2ee8SDavid du Colombier /***** Runtime - Local Variables *****/
368*219b2ee8SDavid du Colombier 
369*219b2ee8SDavid du Colombier void
370*219b2ee8SDavid du Colombier addsymbol(RunList *r, Symbol  *s)
371*219b2ee8SDavid du Colombier {	Symbol *t;
372*219b2ee8SDavid du Colombier 	int i;
373*219b2ee8SDavid du Colombier 
374*219b2ee8SDavid du Colombier 	for (t = r->symtab; t; t = t->next)
375*219b2ee8SDavid du Colombier 		if (strcmp(t->name, s->name) == 0)
376*219b2ee8SDavid du Colombier 			return;		/* it's already there */
377*219b2ee8SDavid du Colombier 
378*219b2ee8SDavid du Colombier 	t = (Symbol *) emalloc(sizeof(Symbol));
379*219b2ee8SDavid du Colombier 	t->name = s->name;
380*219b2ee8SDavid du Colombier 	t->type = s->type;
381*219b2ee8SDavid du Colombier 	t->nel  = s->nel;
382*219b2ee8SDavid du Colombier 	t->ini  = s->ini;
383*219b2ee8SDavid du Colombier 	t->setat = depth;
384*219b2ee8SDavid du Colombier 	if (s->type != STRUCT)
385*219b2ee8SDavid du Colombier 	{	if (s->val)	/* if already initialized, copy info */
386*219b2ee8SDavid du Colombier 		{	t->val = (int *) emalloc(s->nel*sizeof(int));
387*219b2ee8SDavid du Colombier 			for (i = 0; i < s->nel; i++)
388*219b2ee8SDavid du Colombier 				t->val[i] = s->val[i];
389*219b2ee8SDavid du Colombier 		} else
390*219b2ee8SDavid du Colombier 			(void) checkvar(t, 0);	/* initialize it */
391*219b2ee8SDavid du Colombier 	} else
392*219b2ee8SDavid du Colombier 	{	if (s->Sval)
393*219b2ee8SDavid du Colombier 			fatal("saw preinitialized struct %s", s->name);
394*219b2ee8SDavid du Colombier 		t->Slst = s->Slst;
395*219b2ee8SDavid du Colombier 		t->Snm  = s->Snm;
396*219b2ee8SDavid du Colombier 		t->owner = s->owner;
397*219b2ee8SDavid du Colombier 		t->context = r->n;
398*219b2ee8SDavid du Colombier 	}
399*219b2ee8SDavid du Colombier 	t->next = r->symtab;	/* add it */
400*219b2ee8SDavid du Colombier 	r->symtab = t;
401*219b2ee8SDavid du Colombier }
402*219b2ee8SDavid du Colombier 
403*219b2ee8SDavid du Colombier void
404*219b2ee8SDavid du Colombier oneparam(RunList *r, Lextok *t, Lextok *a, ProcList *p)
405*219b2ee8SDavid du Colombier {	int k; int at, ft;
406*219b2ee8SDavid du Colombier 	RunList *oX = X;
407*219b2ee8SDavid du Colombier 
408*219b2ee8SDavid du Colombier 	if (!a)
409*219b2ee8SDavid du Colombier 		fatal("missing actual parameters: '%s'", p->n->name);
410*219b2ee8SDavid du Colombier 	if (t->sym->nel != 1)
411*219b2ee8SDavid du Colombier 		fatal("array in parameter list, %s", t->sym->name);
412*219b2ee8SDavid du Colombier 	k = eval(a->lft);
413*219b2ee8SDavid du Colombier 
414*219b2ee8SDavid du Colombier 	at = Sym_typ(a->lft);
415*219b2ee8SDavid du Colombier 	X = r;	/* switch context */
416*219b2ee8SDavid du Colombier 	ft = Sym_typ(t);
417*219b2ee8SDavid du Colombier 
418*219b2ee8SDavid du Colombier 	if (at != ft && (at == CHAN || ft == CHAN))
419*219b2ee8SDavid du Colombier 	{	char buf[128], tag1[32], tag2[32];
420*219b2ee8SDavid du Colombier 		(void) sputtype(tag1, ft);
421*219b2ee8SDavid du Colombier 		(void) sputtype(tag2, at);
422*219b2ee8SDavid du Colombier 		sprintf(buf, "type-clash in param-list of %s(..), (%s<-> %s)",
423*219b2ee8SDavid du Colombier 			p->n->name, tag1, tag2);
424*219b2ee8SDavid du Colombier 		non_fatal("%s", buf);
425*219b2ee8SDavid du Colombier 	}
426*219b2ee8SDavid du Colombier 	t->ntyp = NAME;
427*219b2ee8SDavid du Colombier 	addsymbol(r, t->sym);
428*219b2ee8SDavid du Colombier 	(void) setval(t, k);
429*219b2ee8SDavid du Colombier 
430*219b2ee8SDavid du Colombier 	X = oX;
431*219b2ee8SDavid du Colombier }
432*219b2ee8SDavid du Colombier 
433*219b2ee8SDavid du Colombier void
434*219b2ee8SDavid du Colombier setparams(RunList *r, ProcList *p, Lextok *q)
435*219b2ee8SDavid du Colombier {	Lextok *f, *a;	/* formal and actual pars */
436*219b2ee8SDavid du Colombier 	Lextok *t;	/* list of pars of 1 type */
437*219b2ee8SDavid du Colombier 
438*219b2ee8SDavid du Colombier 	if (q)
439*219b2ee8SDavid du Colombier 	{	lineno = q->ln;
440*219b2ee8SDavid du Colombier 		Fname  = q->fn;
441*219b2ee8SDavid du Colombier 	}
442*219b2ee8SDavid du Colombier 	for (f = p->p, a = q; f; f = f->rgt) /* one type at a time */
443*219b2ee8SDavid du Colombier 	for (t = f->lft; t; t = t->rgt, a = (a)?a->rgt:a)
444*219b2ee8SDavid du Colombier 	{	if (t->ntyp != ',')
445*219b2ee8SDavid du Colombier 			oneparam(r, t, a, p);	/* plain var */
446*219b2ee8SDavid du Colombier 		else
447*219b2ee8SDavid du Colombier 			oneparam(r, t->lft, a, p);	/* expanded structure */
448*219b2ee8SDavid du Colombier 	}
449*219b2ee8SDavid du Colombier }
450*219b2ee8SDavid du Colombier 
451*219b2ee8SDavid du Colombier Symbol *
452*219b2ee8SDavid du Colombier findloc(Symbol *s)
453*219b2ee8SDavid du Colombier {	Symbol *r;
454*219b2ee8SDavid du Colombier 
455*219b2ee8SDavid du Colombier 	if (!X)
456*219b2ee8SDavid du Colombier 	{	/* fatal("error, cannot eval '%s' (no proc)", s->name); */
457*219b2ee8SDavid du Colombier 		return ZS;
458*219b2ee8SDavid du Colombier 	}
459*219b2ee8SDavid du Colombier 	for (r = X->symtab; r; r = r->next)
460*219b2ee8SDavid du Colombier 		if (strcmp(r->name, s->name) == 0)
461*219b2ee8SDavid du Colombier 			break;
462*219b2ee8SDavid du Colombier 	if (!r)
463*219b2ee8SDavid du Colombier 	{	addsymbol(X, s);
464*219b2ee8SDavid du Colombier 		r = X->symtab;
465*219b2ee8SDavid du Colombier 	}
466*219b2ee8SDavid du Colombier 	return r;
467*219b2ee8SDavid du Colombier }
468*219b2ee8SDavid du Colombier 
469*219b2ee8SDavid du Colombier int
470*219b2ee8SDavid du Colombier getlocal(Lextok *sn)
471*219b2ee8SDavid du Colombier {	Symbol *r, *s = sn->sym;
472*219b2ee8SDavid du Colombier 	int n = eval(sn->lft);
473*219b2ee8SDavid du Colombier 
474*219b2ee8SDavid du Colombier 	r = findloc(s);
475*219b2ee8SDavid du Colombier 	if (r && r->type == STRUCT)
476*219b2ee8SDavid du Colombier 		return Rval_struct(sn, r, 1); /* 1 = check init */
477*219b2ee8SDavid du Colombier 	if (r)
478*219b2ee8SDavid du Colombier 	{	if (n >= r->nel || n < 0)
479*219b2ee8SDavid du Colombier 		{	printf("spin: indexing %s[%d] - size is %d\n",
480*219b2ee8SDavid du Colombier 				s->name, n, r->nel);
481*219b2ee8SDavid du Colombier 			non_fatal("array indexing error %s", s->name);
482*219b2ee8SDavid du Colombier 		} else
483*219b2ee8SDavid du Colombier 		{	return cast_val(r->type, r->val[n]);
484*219b2ee8SDavid du Colombier 	}	}
485*219b2ee8SDavid du Colombier 
486*219b2ee8SDavid du Colombier 	return 0;
487*219b2ee8SDavid du Colombier }
488*219b2ee8SDavid du Colombier 
489*219b2ee8SDavid du Colombier int
490*219b2ee8SDavid du Colombier setlocal(Lextok *p, int m)
491*219b2ee8SDavid du Colombier {	Symbol *r = findloc(p->sym);
492*219b2ee8SDavid du Colombier 	int n = eval(p->lft);
493*219b2ee8SDavid du Colombier 
494*219b2ee8SDavid du Colombier 	if (!r) return 1;
495*219b2ee8SDavid du Colombier 
496*219b2ee8SDavid du Colombier 	if (n >= r->nel || n < 0)
497*219b2ee8SDavid du Colombier 	{	printf("spin: indexing %s[%d] - size is %d\n",
498*219b2ee8SDavid du Colombier 			r->name, n, r->nel);
499*219b2ee8SDavid du Colombier 		non_fatal("array indexing error %s", r->name);
500*219b2ee8SDavid du Colombier 	} else
501*219b2ee8SDavid du Colombier 	{	if (r->type == STRUCT)
502*219b2ee8SDavid du Colombier 			(void) Lval_struct(p, r, 1, m); /* 1 = check init */
503*219b2ee8SDavid du Colombier 		else
504*219b2ee8SDavid du Colombier 		{	r->val[n] = m;
505*219b2ee8SDavid du Colombier 			r->setat = depth;
506*219b2ee8SDavid du Colombier 	}	}
507*219b2ee8SDavid du Colombier 
508*219b2ee8SDavid du Colombier 	return 1;
509*219b2ee8SDavid du Colombier }
510*219b2ee8SDavid du Colombier 
511*219b2ee8SDavid du Colombier void
512*219b2ee8SDavid du Colombier whoruns(int lnr)
513*219b2ee8SDavid du Colombier {	if (!X) return;
514*219b2ee8SDavid du Colombier 
515*219b2ee8SDavid du Colombier 	if (lnr) printf("%3d:	", depth);
516*219b2ee8SDavid du Colombier 	printf("proc ");
517*219b2ee8SDavid du Colombier 	if (Have_claim)
518*219b2ee8SDavid du Colombier 	{	if (X->pid == Have_claim)
519*219b2ee8SDavid du Colombier 			printf(" -");
520*219b2ee8SDavid du Colombier 		else if (X->pid > Have_claim)
521*219b2ee8SDavid du Colombier 			printf("%2d", X->pid-1);
522*219b2ee8SDavid du Colombier 		else
523*219b2ee8SDavid du Colombier 			printf("%2d", X->pid);
524*219b2ee8SDavid du Colombier 	} else
525*219b2ee8SDavid du Colombier 		printf("%2d", X->pid);
526*219b2ee8SDavid du Colombier 	printf(" (%s) ", X->n->name);
527*219b2ee8SDavid du Colombier }
528*219b2ee8SDavid du Colombier 
529*219b2ee8SDavid du Colombier void
530*219b2ee8SDavid du Colombier talk(RunList *r)
531*219b2ee8SDavid du Colombier {
532*219b2ee8SDavid du Colombier 	if (verbose&32 || verbose&4)
533*219b2ee8SDavid du Colombier 	{	p_talk(r->pc, 1);
534*219b2ee8SDavid du Colombier 		printf("\n");
535*219b2ee8SDavid du Colombier 		if (verbose&1) dumpglobals();
536*219b2ee8SDavid du Colombier 		if (verbose&2) dumplocal(r);
537*219b2ee8SDavid du Colombier 	}
538*219b2ee8SDavid du Colombier }
539*219b2ee8SDavid du Colombier 
540*219b2ee8SDavid du Colombier void
541*219b2ee8SDavid du Colombier p_talk(Element *e, int lnr)
542*219b2ee8SDavid du Colombier {
543*219b2ee8SDavid du Colombier 	whoruns(lnr);
544*219b2ee8SDavid du Colombier 	if (e)
545*219b2ee8SDavid du Colombier 	printf("line %3d %s (state %d)",
546*219b2ee8SDavid du Colombier 			e->n?e->n->ln:-1,
547*219b2ee8SDavid du Colombier 			e->n?e->n->fn->name:"-",
548*219b2ee8SDavid du Colombier 			e->seqno);
549*219b2ee8SDavid du Colombier }
550*219b2ee8SDavid du Colombier 
551*219b2ee8SDavid du Colombier int
552*219b2ee8SDavid du Colombier remotelab(Lextok *n)
553*219b2ee8SDavid du Colombier {	int i;
554*219b2ee8SDavid du Colombier 
555*219b2ee8SDavid du Colombier 	lineno = n->ln;
556*219b2ee8SDavid du Colombier 	Fname  = n->fn;
557*219b2ee8SDavid du Colombier 	if (n->sym->type)
558*219b2ee8SDavid du Colombier 		fatal("not a labelname: '%s'", n->sym->name);
559*219b2ee8SDavid du Colombier 	if ((i = find_lab(n->sym, n->lft->sym)) == 0)
560*219b2ee8SDavid du Colombier 		fatal("unknown labelname: %s", n->sym->name);
561*219b2ee8SDavid du Colombier 	return i;
562*219b2ee8SDavid du Colombier }
563*219b2ee8SDavid du Colombier 
564*219b2ee8SDavid du Colombier int
565*219b2ee8SDavid du Colombier remotevar(Lextok *n)
566*219b2ee8SDavid du Colombier {	int pno, i, trick=0;
567*219b2ee8SDavid du Colombier 	RunList *Y;
568*219b2ee8SDavid du Colombier 
569*219b2ee8SDavid du Colombier 	lineno = n->ln;
570*219b2ee8SDavid du Colombier 	Fname  = n->fn;
571*219b2ee8SDavid du Colombier 	if (!n->lft->lft)
572*219b2ee8SDavid du Colombier 	{	non_fatal("missing pid in %s", n->sym->name);
573*219b2ee8SDavid du Colombier 		return 0;
574*219b2ee8SDavid du Colombier 	}
575*219b2ee8SDavid du Colombier 
576*219b2ee8SDavid du Colombier 	pno = eval(n->lft->lft);	/* pid - can cause recursive call */
577*219b2ee8SDavid du Colombier TryAgain:
578*219b2ee8SDavid du Colombier 	i = nproc - nstop;
579*219b2ee8SDavid du Colombier 	for (Y = run; Y; Y = Y->nxt)
580*219b2ee8SDavid du Colombier 	if (--i == pno)
581*219b2ee8SDavid du Colombier 	{	if (strcmp(Y->n->name, n->lft->sym->name) != 0)
582*219b2ee8SDavid du Colombier 		{	if (!trick && Have_claim)
583*219b2ee8SDavid du Colombier 			{	trick = 1; pno++;
584*219b2ee8SDavid du Colombier 				/* assumes user guessed the pid */
585*219b2ee8SDavid du Colombier 				goto TryAgain;
586*219b2ee8SDavid du Colombier 			}
587*219b2ee8SDavid du Colombier 			printf("remote ref %s[%d] refers to %s\n",
588*219b2ee8SDavid du Colombier 				n->lft->sym->name, pno, Y->n->name);
589*219b2ee8SDavid du Colombier 			non_fatal("wrong proctype %s", Y->n->name);
590*219b2ee8SDavid du Colombier 		}
591*219b2ee8SDavid du Colombier 		if (strcmp(n->sym->name, "_p") == 0)
592*219b2ee8SDavid du Colombier 			return Y->pc->seqno;
593*219b2ee8SDavid du Colombier 		break;
594*219b2ee8SDavid du Colombier 	}
595*219b2ee8SDavid du Colombier 	printf("remote ref: %s[%d] ", n->lft->sym->name, pno);
596*219b2ee8SDavid du Colombier 	non_fatal("%s not found", n->sym->name);
597*219b2ee8SDavid du Colombier 
598*219b2ee8SDavid du Colombier 	return 0;
599*219b2ee8SDavid du Colombier }
600