xref: /plan9/sys/src/cmd/spin/pangen1.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
1 /***** spin: pangen1.c *****/
2 
3 /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
4 /* All Rights Reserved.  This software is for educational purposes only.  */
5 /* No guarantee whatsoever is expressed or implied by the distribution of */
6 /* this code.  Permission is given to distribute this code provided that  */
7 /* this introductory message is not removed and no monies are exchanged.  */
8 /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9 /*             http://spinroot.com/                                       */
10 /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
11 /* (c) 2007: small additions for V5.0 to support multi-core verifications */
12 
13 #include "spin.h"
14 #include "y.tab.h"
15 #include "pangen1.h"
16 #include "pangen3.h"
17 #include "pangen6.h"
18 #include <assert.h>
19 
20 extern FILE	*tc, *th, *tt;
21 extern Label	*labtab;
22 extern Ordered	*all_names;
23 extern ProcList	*rdy;
24 extern Queue	*qtab;
25 extern Symbol	*Fname;
26 extern int	lineno, verbose, Pid, separate, old_scope_rules, nclaims;
27 extern int	nrRdy, nqs, mst, Mpars, claimnr, eventmapnr;
28 extern short	has_sorted, has_random, has_provided;
29 extern Queue	*ltab[];
30 
31 int	Npars=0, u_sync=0, u_async=0, hastrack = 1;
32 short	has_io = 0;
33 short	has_state=0;	/* code contains c_state */
34 
35 static Symbol	*LstSet=ZS;
36 static int	acceptors=0, progressors=0, nBits=0;
37 static int	Types[] = { UNSIGNED, BIT, BYTE, CHAN, MTYPE, SHORT, INT, STRUCT };
38 
39 static int	doglobal(char *, int);
40 static void	dohidden(void);
41 static void	do_init(FILE *, Symbol *);
42 static void	end_labs(Symbol *, int);
43 static void	put_ptype(char *, int, int, int, enum btypes);
44 static void	tc_predef_np(void);
45 static void	put_pinit(ProcList *);
46 static void	multi_init(void);
47        void	walk_struct(FILE *, int, char *, Symbol *, char *, char *, char *);
48 
49 static void
reverse_names(ProcList * p)50 reverse_names(ProcList *p)
51 {
52 	if (!p) return;
53 	reverse_names(p->nxt);
54 	fprintf(th, "   \"%s\",\n", p->n->name);
55 }
56 static void
reverse_types(ProcList * p)57 reverse_types(ProcList *p)
58 {
59 	if (!p) return;
60 	reverse_types(p->nxt);
61 	fprintf(th, "   %d,	/* %s */\n", p->b, p->n->name);
62 }
63 
64 static int
blog(int n)65 blog(int n)	/* for small log2 without rounding problems */
66 {	int m=1, r=2;
67 
68 	while (r < n) { m++; r *= 2; }
69 	return 1+m;
70 }
71 
72 void
genheader(void)73 genheader(void)
74 {	ProcList *p; int i;
75 
76 	if (separate == 2)
77 	{	putunames(th);
78 		goto here;
79 	}
80 	/* 5.2.3: gcc 3 no longer seems to compute sizeof at compile time */
81 	fprintf(th, "#define WS		%d /* word size in bytes */\n", (int) sizeof(void *));
82 	fprintf(th, "#define SYNC	%d\n", u_sync);
83 	fprintf(th, "#define ASYNC	%d\n\n", u_async);
84 	fprintf(th, "#ifndef NCORE\n");
85 	fprintf(th, "	#ifdef DUAL_CORE\n");
86 	fprintf(th, "		#define NCORE	2\n");
87 	fprintf(th, "	#elif QUAD_CORE\n");
88 	fprintf(th, "		#define NCORE	4\n");
89 	fprintf(th, "	#else\n");
90 	fprintf(th, "		#define NCORE	1\n");
91 	fprintf(th, "	#endif\n");
92 	fprintf(th, "#endif\n");
93 
94 	putunames(th);
95 
96 	fprintf(tc, "short Air[] = { ");
97 	for (p = rdy, i=0; p; p = p->nxt, i++)
98 		fprintf(tc, "%s (short) Air%d", (p!=rdy)?",":"", i);
99 	fprintf(tc, ", (short) Air%d", i);	/* np_ */
100 	if (nclaims > 1)
101 	{	fprintf(tc, "\n#ifndef NOCLAIM\n");
102 		fprintf(tc, "	, (short) Air%d", i+1);	/* Multi */
103 		fprintf(tc, "\n#endif\n\t");
104 	}
105 	fprintf(tc, " };\n");
106 
107 	fprintf(th, "char *procname[] = {\n");
108 		reverse_names(rdy);
109 	fprintf(th, "   \":np_:\",\n");
110 	fprintf(th, "};\n\n");
111 
112 	fprintf(th, "enum btypes { NONE=%d, N_CLAIM=%d,", NONE, N_CLAIM);
113 	fprintf(th, " I_PROC=%d, A_PROC=%d,", I_PROC, A_PROC);
114 	fprintf(th, " P_PROC=%d, E_TRACE=%d, N_TRACE=%d };\n",
115 		P_PROC, E_TRACE, N_TRACE);
116 	fprintf(th, "int Btypes[] = {\n");
117 		reverse_types(rdy);
118 	fprintf(th, "   0	/* :np_: */\n");
119 	fprintf(th, "};\n\n");
120 
121 here:
122 	for (p = rdy; p; p = p->nxt)
123 		put_ptype(p->n->name, p->tn, mst, nrRdy+1, p->b);
124 		/* +1 for np_ */
125 	put_ptype("np_", nrRdy, mst, nrRdy+1, 0);
126 
127 	if (nclaims > 1)
128 	{	/* this is the structure that goes into the state-vector
129 		 * instead of the actual never claims
130 		 * this assumes that the claims do not have any local variables
131 		 * this claim records the types and states of all subclaims in an array
132 		 * NB: not sure if we need the first 3 fields in this structure
133 		 *     it's here for now to avoid breaking some possible dependence
134 		 * in the calculations above, we were already taking into account
135 		 * that there is one never-claim, which will now be this one
136 		 */
137 
138 		i = blog(mst);
139 		fprintf(th, "\n");
140 		fprintf(th, "#ifndef NOCLAIM\n");
141 		fprintf(th, "	#undef VERI\n");
142 		fprintf(th, "	#define VERI	%d\n", nrRdy+1);
143 		fprintf(th, "	#define Pclaim	P%d\n\n", nrRdy+1);
144 		fprintf(th, "typedef struct P%d {\n", nrRdy+1);
145 		fprintf(th, "	unsigned _pid : 8; /* always zero */\n");
146 		fprintf(th, "	unsigned _t   : %d; /* active-claim type  */\n",
147 			blog(nrRdy+1));
148 		fprintf(th, "	unsigned _p   : %d; /* active-claim state */\n",
149 			i);
150 		fprintf(th, "	unsigned _n   : %d; /* active-claim index */\n",
151 			blog(nclaims));
152 		if (i <= 255)	/* in stdint.h = UCHAR_MAX from limits.h */
153 		{	fprintf(th, "	uchar c_cur[NCLAIMS]; /* claim-states */\n");
154 		} else if (i <= 65535)	/* really USHRT_MAX from limits.h */
155 		{	fprintf(th, "	ushort c_cur[NCLAIMS]; /* claim-states */\n");
156 		} else	/* the most unlikely case */
157 		{	fprintf(th, "	uint c_cur[NCLAIMS]; /* claim-states */\n");
158 		}
159 		fprintf(th, "} P%d;\n", nrRdy+1);
160 		fprintf(th, "uchar spin_c_typ[NCLAIMS]; /* claim-types */\n");
161 		fprintf(th, "	#define Air%d	(0)\n\n", nrRdy+1);
162 		fprintf(th, "#endif\n");
163 		/*
164 		 * find special states as:
165 		 *	stopstate [ claimnr ][ curstate ] == 1
166 		 *	accpstate [ claimnr ][ curstate ]
167 		 *	progstate [ claimnr ][ curstate ]
168 		 *	reached   [ claimnr ][ curstate ]
169 		 *	visstate  [ claimnr ][ curstate ]
170 		 *	loopstate [ claimnr ][ curstate ]
171 		 *	mapstate  [ claimnr ][ curstate ]
172 		 */
173 	} else
174 	{	fprintf(th, "\n#define Pclaim	P0\n");
175 		fprintf(th, "#ifndef NCLAIMS\n");
176 		fprintf(th, "	#define NCLAIMS 1\n");
177 		fprintf(th, "#endif\n");
178 		fprintf(th, "uchar spin_c_typ[NCLAIMS]; /* claim-types */\n");
179 	}
180 
181 	ntimes(th, 0, 1, Head0);
182 
183 	if (separate != 2)
184 	{	extern void c_add_stack(FILE *);
185 		extern void c_stack_size(FILE *);
186 
187 		ntimes(th, 0, 1, Header);
188 		fprintf(th, "#define StackSize	(");
189 			c_stack_size(th);
190 		fprintf(th, ")\n");
191 
192 		c_add_stack(th);
193 		ntimes(th, 0, 1, Header0);
194 	}
195 	ntimes(th, 0, 1, Head1);
196 
197 	LstSet = ZS;
198 	(void) doglobal("", PUTV);
199 
200 	hastrack = c_add_sv(th);
201 
202 	fprintf(th, "#ifdef TRIX\n");
203 	fprintf(th, "	/* room for 512 proc+chan ptrs, + safety margin */\n");
204 	fprintf(th, "	char *_ids_[MAXPROC+MAXQ+4];\n");
205 	fprintf(th, "#else\n");
206 	fprintf(th, "	uchar sv[VECTORSZ];\n");
207 	fprintf(th, "#endif\n");
208 
209 	fprintf(th, "} State");
210 #ifdef SOLARIS
211 	fprintf(th,"\n#ifdef GCC\n");
212 	fprintf(th, "\t__attribute__ ((aligned(8)))");
213 	fprintf(th, "\n#endif\n\t");
214 #endif
215 	fprintf(th, ";\n\n");
216 
217 	fprintf(th, "#ifdef TRIX\n");
218 	fprintf(th, "typedef struct TRIX_v6 {\n");
219 	fprintf(th, "	uchar *body; /* aligned */\n");
220 	fprintf(th, "#ifndef BFS\n");
221 	fprintf(th, "	short modified;\n");
222 	fprintf(th, "#endif\n");
223 	fprintf(th, "	short psize;\n");
224 	fprintf(th, "	short parent_pid;\n");
225 	fprintf(th, "	struct TRIX_v6 *nxt;\n");
226 	fprintf(th, "} TRIX_v6;\n");
227 	fprintf(th, "TRIX_v6 *freebodies;\n");
228 	fprintf(th, "TRIX_v6 *processes[MAXPROC+1];\n");
229 	fprintf(th, "TRIX_v6 *channels[MAXQ+1]; \n");
230 	fprintf(th, "long _p_count[MAXPROC];\n");
231 	fprintf(th, "long _c_count[MAXPROC];\n");
232 	fprintf(th, "#endif\n\n");
233 
234 	fprintf(th, "#define HAS_TRACK	%d\n", hastrack);
235 
236 	if (separate != 2)
237 		dohidden();
238 }
239 
240 void
genaddproc(void)241 genaddproc(void)
242 {	ProcList *p;
243 	int i = 0, j;
244 
245 	if (separate == 2) goto shortcut;
246 
247 	fprintf(tc, "\n#ifdef TRIX\n");
248 	fprintf(tc, "int what_p_size(int);\n");
249 	fprintf(tc, "int what_q_size(int);\n\n");
250 	/* the number of processes just changed by 1 (up or down) */
251 	/* this means that the channel indices move up or down by one slot */
252 	/* not all new channels may have a valid index yet, but we move */
253 	/* all of them anyway, as if they existed */
254 	fprintf(tc, "void\nre_mark_all(int whichway)\n");
255 	fprintf(tc, "{	int j;\n");
256 	fprintf(tc, "	#ifdef V_TRIX\n");
257 	fprintf(tc, "		printf(\"%%d: re_mark_all channels %%d\\n\", depth, whichway);\n");
258 	fprintf(tc, "	#endif\n");
259 	fprintf(tc, "	#ifndef BFS\n");
260 	fprintf(tc, "	for (j = 0; j < now._nr_qs; j++)\n");
261 	fprintf(tc, "		channels[j]->modified = 1; /* channel index moved */\n");
262 	fprintf(tc, "	#endif\n");
263 	fprintf(tc, "	#ifndef TRIX_ORIG\n");
264 	fprintf(tc, "	if (whichway > 0)\n");
265 	fprintf(tc, "	{	for (j = now._nr_pr + now._nr_qs - 1; j >= now._nr_pr; j--)\n");
266 	fprintf(tc, "			now._ids_[j] = now._ids_[j-1];\n");
267 	fprintf(tc, "	} else\n");
268 	fprintf(tc, "	{	for (j = now._nr_pr; j < now._nr_pr + now._nr_qs; j++)\n");
269 	fprintf(tc, "			now._ids_[j] = now._ids_[j+1];\n");
270 	fprintf(tc, "	}\n");
271 	fprintf(tc, "	#endif\n");
272 	fprintf(tc, "}\n");
273 
274 	fprintf(tc, "#endif\n\n");
275 
276 	fprintf(tc, "int\naddproc(int calling_pid, int n");
277 	for (/* i = 0 */; i < Npars; i++)
278 		fprintf(tc, ", int par%d", i);
279 
280 	ntimes(tc, 0, 1, Addp0);
281 	ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
282 
283 	if (nclaims > 1)
284 	{	fprintf(tc, "#ifndef NOCLAIM\n");
285 		ntimes(tc, nrRdy+1, nrRdy+2, R5);
286 		fprintf(tc, "#endif\n");
287 	}
288 
289 	ntimes(tc, 0, 1, Addp1);
290 
291 	if (has_provided)
292 	{	fprintf(tt, "\nint\nprovided(int II, unsigned char ot, ");
293 		fprintf(tt, "int tt, Trans *t)\n");
294 		fprintf(tt, "{\n\tswitch(ot) {\n");
295 	}
296 shortcut:
297 	if (nclaims > 1)
298 	{	multi_init();
299 	}
300 	tc_predef_np();
301 	for (p = rdy; p; p = p->nxt)
302 	{	Pid = p->tn;
303 		put_pinit(p);
304 	}
305 	if (separate == 2) return;
306 
307 	Pid = 0;
308 	if (has_provided)
309 	{	fprintf(tt, "\tdefault: return 1; /* e.g., a claim */\n");
310 		fprintf(tt, "\t}\n\treturn 0;\n}\n");
311 	}
312 
313 	ntimes(tc, i, i+1, R6);
314 	if (separate == 0)
315 		ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
316 	else
317 		ntimes(tc, 1, nrRdy, R5);
318 	ntimes(tc, 0, 1, R8a);
319 }
320 
321 void
do_locinits(FILE * fd)322 do_locinits(FILE *fd)
323 {	ProcList *p;
324 
325 	for (p = rdy; p; p = p->nxt)
326 		c_add_locinit(fd, p->tn, p->n->name);
327 }
328 
329 void
genother(void)330 genother(void)
331 {	ProcList *p;
332 
333 	switch (separate) {
334 	case 2:
335 		if (nclaims > 0)
336 		{	for (p = rdy; p; p = p->nxt)
337 			{	if (p->b == N_CLAIM)
338 				{	ntimes(tc, p->tn, p->tn+1, R0); /* claims only */
339 		}	}	}
340 		break;
341 	case 1:
342 		ntimes(tc,     0,    1, Code0);
343 		for (p = rdy; p; p = p->nxt)
344 		{	if (p->b != N_CLAIM)
345 			{	ntimes(tc, p->tn, p->tn+1, R0); /* all except claims */
346 		}	}
347 		break;
348 	case 0:
349 		ntimes(tc,     0,    1, Code0);
350 		ntimes(tc,     0, nrRdy+1, R0); /* +1 for np_ */
351 		break;
352 	}
353 
354 	for (p = rdy; p; p = p->nxt)
355 		end_labs(p->n, p->tn);
356 
357 	switch (separate) {
358 	case 2:
359 		if (nclaims > 0)
360 		{	for (p = rdy; p; p = p->nxt)
361 			{	if (p->b == N_CLAIM)
362 				{	ntimes(tc, p->tn, p->tn+1, R0a); /* claims only */
363 		}	}	}
364 		return;
365 	case 1:
366 		for (p = rdy; p; p = p->nxt)
367 		{	if (p->b != N_CLAIM)
368 			{	ntimes(tc, p->tn, p->tn+1, R0a); /* all except claims */
369 		}	}
370 		fprintf(tc, "	if (state_tables)\n");
371 		fprintf(tc, "		ini_claim(%d, 0);\n", claimnr);	/* the default claim */
372 		if (acceptors == 0)
373 		{	acceptors = 1;	/* assume at least 1 acceptstate */
374 		}
375 		break;
376 	case 0:
377 		ntimes(tc, 0, nrRdy, R0a);	/* all */
378 		break;
379 	}
380 
381 	ntimes(th, acceptors,   acceptors+1,   Code1);
382 	ntimes(th, progressors, progressors+1, Code3);
383 	ntimes(th, nrRdy+1, nrRdy+2, R2); /* +1 for np_ */
384 
385 	ntimes(tc, 0,     1, Code2a);	/* dfs, bfs */
386 	ntimes(tc, 0,     1, Code2c);	/* multicore */
387 	ntimes(tc, 0,     1, Code2d);
388 
389 	fprintf(tc, "void\ndo_reach(void)\n{\n");
390 	ntimes(tc, 0,     nrRdy, R4);
391 	fprintf(tc, "}\n\n");
392 
393 	fprintf(tc, "void\niniglobals(int calling_pid)\n{\n");
394 	ntimes(tc, 1, u_sync+u_async+1, R3); /* because nqs is still 0 */
395 	fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);\n");
396 	fprintf(tc, "\tif ((Maxbody %% WS) != 0)\n");
397 	fprintf(tc, "\t	Maxbody += WS - (Maxbody %% WS);\n\n");
398 
399 	/* after the value of Maxbody has settled */
400 	if (doglobal("", INIV) > 0)
401 	{	fprintf(tc, "#ifdef VAR_RANGES\n");
402 		(void) doglobal("logval(\"", LOGV);
403 		fprintf(tc, "#endif\n");
404 	}
405 	fprintf(tc, "}\n\n");
406 }
407 
408 void
gensvmap(void)409 gensvmap(void)
410 {
411 	ntimes(tc, 0, 1, SvMap);
412 }
413 
414 static struct {
415 	char *s,	*t;		int n,	m,	p;
416 } ln[] = {
417 	{"end",  	"stopstate",	3,	0,	0},
418 	{"progress",	"progstate",	8,	0,	1},
419 	{"accept",	"accpstate",	6,	1,	0},
420 	{0,		0,		0,	0,	0},
421 };
422 
423 static void
end_labs(Symbol * s,int i)424 end_labs(Symbol *s, int i)
425 {	int oln = lineno;
426 	Symbol *ofn = Fname;
427 	Label *l;
428 	int j; char foo[128];
429 
430 	if ((pid_is_claim(i) && separate == 1)
431 	|| (!pid_is_claim(i) && separate == 2))
432 		return;
433 
434 	for (l = labtab; l; l = l->nxt)
435 	for (j = 0; ln[j].n; j++)
436 	{	if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0
437 		&&  strcmp(l->c->name, s->name) == 0)
438 		{	fprintf(tc, "\t%s[%d][%d] = 1;\n",
439 				ln[j].t, i, l->e->seqno);
440 			acceptors += ln[j].m;
441 			progressors += ln[j].p;
442 			if (l->e->status & D_ATOM)
443 			{	sprintf(foo, "%s label inside d_step",
444 					ln[j].s);
445 				goto complain;
446 			}
447 			if (j > 0 && (l->e->status & ATOM))
448 			{	sprintf(foo, "%s label inside atomic",
449 					ln[j].s);
450 		complain:	lineno = l->e->n->ln;
451 				Fname  = l->e->n->fn;
452 				printf("spin: %3d:%s, warning, %s - is invisible\n",
453 					lineno, Fname?Fname->name:"-", foo);
454 	}	}	}
455 	/* visible states -- through remote refs: */
456 	for (l = labtab; l; l = l->nxt)
457 		if (l->visible
458 		&&  strcmp(l->s->context->name, s->name) == 0)
459 		fprintf(tc, "\tvisstate[%d][%d] = 1;\n",
460 				i, l->e->seqno);
461 
462 	lineno = oln;
463 	Fname  = ofn;
464 }
465 
466 void
ntimes(FILE * fd,int n,int m,char * c[])467 ntimes(FILE *fd, int n, int m, char *c[])
468 {
469 	int i, j;
470 	for (j = 0; c[j]; j++)
471 	for (i = n; i < m; i++)
472 	{	fprintf(fd, c[j], i, i, i, i, i, i);
473 		fprintf(fd, "\n");
474 	}
475 }
476 
477 void
prehint(Symbol * s)478 prehint(Symbol *s)
479 {	Lextok *n;
480 
481 	printf("spin: warning, ");
482 	if (!s) return;
483 
484 	n = (s->context != ZS)?s->context->ini:s->ini;
485 	if (n)
486 	printf("line %s:%d, ", n->fn->name, n->ln);
487 }
488 
489 void
checktype(Symbol * sp,char * s)490 checktype(Symbol *sp, char *s)
491 {	char buf[128]; int i;
492 
493 	if (!s
494 	|| (sp->type != BYTE
495 	&&  sp->type != SHORT
496 	&&  sp->type != INT))
497 		return;
498 
499 	if (sp->hidden&16)	/* formal parameter */
500 	{	ProcList *p; Lextok *f, *t;
501 		int posnr = 0;
502 		for (p = rdy; p; p = p->nxt)
503 			if (p->n->name
504 			&&  strcmp(s, p->n->name) == 0)
505 				break;
506 		if (p)
507 		for (f = p->p; f; f = f->rgt) /* list of types */
508 		for (t = f->lft; t; t = t->rgt, posnr++)
509 			if (t->sym
510 			&&  strcmp(t->sym->name, sp->name) == 0)
511 			{	checkrun(sp, posnr);
512 				return;
513 			}
514 
515 	} else if (!(sp->hidden&4))
516 	{	if (!(verbose&32)) return;
517 		sputtype(buf, sp->type);
518 		i = (int) strlen(buf);
519 		while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
520 		prehint(sp);
521 		if (sp->context)
522 			printf("proctype %s:", s);
523 		else
524 			printf("global");
525 		printf(" '%s %s' could be declared 'bit %s'\n",
526 			buf, sp->name, sp->name);
527 	} else if (sp->type != BYTE && !(sp->hidden&8))
528 	{	if (!(verbose&32)) return;
529 		sputtype(buf, sp->type);
530 		i = (int) strlen(buf);
531 		while (buf[--i] == ' ') buf[i] = '\0';
532 		prehint(sp);
533 		if (sp->context)
534 			printf("proctype %s:", s);
535 		else
536 			printf("global");
537 		printf(" '%s %s' could be declared 'byte %s'\n",
538 			buf, sp->name, sp->name);
539 	}
540 }
541 
542 static int
dolocal(FILE * ofd,char * pre,int dowhat,int p,char * s,enum btypes b)543 dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s, enum btypes b)
544 {	int h, j, k=0; extern int nr_errs;
545 	Ordered *walk;
546 	Symbol *sp;
547 	char buf[128], buf2[128], buf3[128];
548 
549 	if (dowhat == INIV)
550 	{	/* initialize in order of declaration */
551 		for (walk = all_names; walk; walk = walk->next)
552 		{	sp = walk->entry;
553 			if (sp->context
554 			&& !sp->owner
555 			&&  strcmp(s, sp->context->name) == 0)
556 			{	checktype(sp, s); /* fall through */
557 				if (!(sp->hidden&16))
558 				{	sprintf(buf, "((P%d *)pptr(h))->", p);
559 					do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
560 				}
561 				k++;
562 		}	}
563 	} else
564 	{	for (j = 0; j < 8; j++)
565 		for (h = 0; h <= 1; h++)
566 		for (walk = all_names; walk; walk = walk->next)
567 		{	sp = walk->entry;
568 			if (sp->context
569 			&& !sp->owner
570 			&&  sp->type == Types[j]
571 			&&  ((h == 0 && (sp->nel == 1 && sp->isarray == 0))
572 			||   (h == 1 && (sp->nel  > 1 || sp->isarray == 1)))
573 			&&  strcmp(s, sp->context->name) == 0)
574 			{	switch (dowhat) {
575 				case LOGV:
576 					if (sp->type == CHAN
577 					&&  verbose == 0)
578 						break;
579 					sprintf(buf, "%s%s:", pre, s);
580 					{ sprintf(buf2, "\", ((P%d *)pptr(h))->", p);
581 					  sprintf(buf3, ");\n");
582 					}
583 					do_var(ofd, dowhat, "", sp, buf, buf2, buf3);
584 					break;
585 				case PUTV:
586 					sprintf(buf, "((P%d *)pptr(h))->", p);
587 					do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
588 					k++;
589 					break;
590 				}
591 				if (b == N_CLAIM)
592 				{	printf("error: %s defines local %s\n",
593 						s, sp->name);
594 					nr_errs++;
595 	}	}	}	}
596 
597 	return k;
598 }
599 
600 void
c_chandump(FILE * fd)601 c_chandump(FILE *fd)
602 {	Queue *q;
603 	char buf[256];
604 	int i;
605 
606 	if (!qtab)
607 	{	fprintf(fd, "void\nc_chandump(int unused) ");
608 		fprintf(fd, "{ unused++; /* avoid complaints */ }\n");
609 		return;
610 	}
611 
612 	fprintf(fd, "void\nc_chandump(int from)\n");
613 	fprintf(fd, "{	uchar *z; int slot;\n");
614 
615 	fprintf(fd, "	from--;\n");
616 	fprintf(fd, "	if (from >= (int) now._nr_qs || from < 0)\n");
617 	fprintf(fd, "	{	printf(\"pan: bad qid %%d\\n\", from+1);\n");
618 	fprintf(fd, "		return;\n");
619 	fprintf(fd, "	}\n");
620 	fprintf(fd, "	z = qptr(from);\n");
621 	fprintf(fd, "	switch (((Q0 *)z)->_t) {\n");
622 
623 	for (q = qtab; q; q = q->nxt)
624 	{	fprintf(fd, "	case %d:\n\t\t", q->qid);
625 		sprintf(buf, "((Q%d *)z)->", q->qid);
626 
627 		fprintf(fd, "for (slot = 0; slot < %sQlen; slot++)\n\t\t", buf);
628 		fprintf(fd, "{	printf(\" [\");\n\t\t");
629 		for (i = 0; i < q->nflds; i++)
630 		{	if (q->fld_width[i] == MTYPE)
631 			{	fprintf(fd, "\tprintm(%scontents[slot].fld%d);\n\t\t",
632 				buf, i);
633 			} else
634 			fprintf(fd, "\tprintf(\"%%d,\", %scontents[slot].fld%d);\n\t\t",
635 				buf, i);
636 		}
637 		fprintf(fd, "	printf(\"],\");\n\t\t");
638 		fprintf(fd, "}\n\t\t");
639 		fprintf(fd, "break;\n");
640 	}
641 	fprintf(fd, "	}\n");
642 	fprintf(fd, "	printf(\"\\n\");\n}\n");
643 }
644 
645 void
c_var(FILE * fd,char * pref,Symbol * sp)646 c_var(FILE *fd, char *pref, Symbol *sp)
647 {	char *ptr, buf[256];
648 	int i;
649 
650 	if (!sp)
651 	{	fatal("cannot happen - c_var", 0);
652 	}
653 
654 	ptr = sp?sp->name:"";
655 	if (!old_scope_rules)
656 	{	while (*ptr == '_' || isdigit((int)*ptr))
657 		{	ptr++;
658 	}	}
659 
660 	switch (sp->type) {
661 	case STRUCT:
662 		/* c_struct(fd, pref, sp); */
663 		fprintf(fd, "\t\tprintf(\"\t(struct %s)\\n\");\n",
664 			sp->name);
665 		sprintf(buf, "%s%s.", pref, sp->name);
666 		c_struct(fd, buf, sp);
667 		break;
668 	case BIT:   case BYTE:
669 	case SHORT: case INT:
670 	case UNSIGNED:
671 		sputtype(buf, sp->type);
672 		if (sp->nel == 1 && sp->isarray == 0)
673 		{	fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n",
674 				buf, ptr, pref, sp->name);
675 		} else
676 		{	fprintf(fd, "\t{\tint l_in;\n");
677 			fprintf(fd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
678 			fprintf(fd, "\t\t{\n");
679 			fprintf(fd, "\t\t\tprintf(\"\t%s %s[%%d]:\t%%d\\n\", l_in, %s%s[l_in]);\n",
680 						buf, ptr, pref, sp->name);
681 			fprintf(fd, "\t\t}\n");
682 			fprintf(fd, "\t}\n");
683 		}
684 		break;
685 	case CHAN:
686 		if (sp->nel == 1 && sp->isarray == 0)
687 		{  fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ", ptr);
688 		   fprintf(fd, "%s%s, q_len(%s%s));\n",
689 			pref, sp->name, pref, sp->name);
690 		   fprintf(fd, "\tc_chandump(%s%s);\n", pref, sp->name);
691 		} else
692 		for (i = 0; i < sp->nel; i++)
693 		{  fprintf(fd, "\tprintf(\"\tchan %s[%d] (=%%d):\tlen %%d:\\t\", ",
694 			ptr, i);
695 		   fprintf(fd, "%s%s[%d], q_len(%s%s[%d]));\n",
696 			pref, sp->name, i, pref, sp->name, i);
697 		   fprintf(fd, "\tc_chandump(%s%s[%d]);\n",
698 			pref, sp->name, i);
699 		}
700 		break;
701 	}
702 }
703 
704 int
c_splurge_any(ProcList * p)705 c_splurge_any(ProcList *p)
706 {	Ordered *walk;
707 	Symbol *sp;
708 
709 	if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE)
710 	for (walk = all_names; walk; walk = walk->next)
711 	{	sp = walk->entry;
712 		if (!sp->context
713 		||  sp->type == 0
714 		||  strcmp(sp->context->name, p->n->name) != 0
715 		||  sp->owner || (sp->hidden&1)
716 		|| (sp->type == MTYPE && ismtype(sp->name)))
717 			continue;
718 
719 		return 1;
720 	}
721 	return 0;
722 }
723 
724 void
c_splurge(FILE * fd,ProcList * p)725 c_splurge(FILE *fd, ProcList *p)
726 {	Ordered *walk;
727 	Symbol *sp;
728 	char pref[64];
729 
730 	if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE)
731 	for (walk = all_names; walk; walk = walk->next)
732 	{	sp = walk->entry;
733 		if (!sp->context
734 		||  sp->type == 0
735 		||  strcmp(sp->context->name, p->n->name) != 0
736 		||  sp->owner || (sp->hidden&1)
737 		|| (sp->type == MTYPE && ismtype(sp->name)))
738 			continue;
739 
740 		sprintf(pref, "((P%d *)pptr(pid))->", p->tn);
741 		c_var(fd, pref, sp);
742 	}
743 }
744 
745 void
c_wrapper(FILE * fd)746 c_wrapper(FILE *fd)	/* allow pan.c to print out global sv entries */
747 {	Ordered *walk;
748 	ProcList *p;
749 	Symbol *sp;
750 	Lextok *n;
751 	extern Lextok *Mtype;
752 	int j;
753 
754 	fprintf(fd, "void\nc_globals(void)\n{\t/* int i; */\n");
755 	fprintf(fd, "	printf(\"global vars:\\n\");\n");
756 	for (walk = all_names; walk; walk = walk->next)
757 	{	sp = walk->entry;
758 		if (sp->context || sp->owner || (sp->hidden&1)
759 		|| (sp->type == MTYPE && ismtype(sp->name)))
760 			continue;
761 
762 		c_var(fd, "now.", sp);
763 	}
764 	fprintf(fd, "}\n");
765 
766 	fprintf(fd, "void\nc_locals(int pid, int tp)\n{\t/* int i; */\n");
767 	fprintf(fd, "	switch(tp) {\n");
768 	for (p = rdy; p; p = p->nxt)
769 	{	fprintf(fd, "	case %d:\n", p->tn);
770 		if (c_splurge_any(p))
771 		{	fprintf(fd, "	\tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
772 				p->n->name);
773 			c_splurge(fd, p);
774 		} else
775 		{	fprintf(fd, "	\t/* none */\n");
776 		}
777 		fprintf(fd, "	\tbreak;\n");
778 	}
779 	fprintf(fd, "	}\n}\n");
780 
781 	fprintf(fd, "void\nprintm(int x)\n{\n");
782 	fprintf(fd, "	switch (x) {\n");
783         for (n = Mtype, j = 1; n && j; n = n->rgt, j++)
784                 fprintf(fd, "\tcase %d: Printf(\"%s\"); break;\n",
785 			j, n->lft->sym->name);
786 	fprintf(fd, "	default: Printf(\"%%d\", x);\n");
787 	fprintf(fd, "	}\n");
788 	fprintf(fd, "}\n");
789 }
790 
791 static int
doglobal(char * pre,int dowhat)792 doglobal(char *pre, int dowhat)
793 {	Ordered *walk;
794 	Symbol *sp;
795 	int j, cnt = 0;
796 
797 	for (j = 0; j < 8; j++)
798 	for (walk = all_names; walk; walk = walk->next)
799 	{	sp = walk->entry;
800 		if (!sp->context
801 		&&  !sp->owner
802 		&&  sp->type == Types[j])
803 		{	if (Types[j] != MTYPE || !ismtype(sp->name))
804 			switch (dowhat) {
805 			case LOGV:
806 				if (sp->type == CHAN
807 				&&  verbose == 0)
808 					break;
809 				if (sp->hidden&1)
810 					break;
811 				do_var(tc, dowhat, "", sp,
812 					pre, "\", now.", ");\n");
813 				break;
814 			case INIV:
815 				checktype(sp, (char *) 0);
816 				cnt++; /* fall through */
817 			case PUTV:
818 				do_var(tc, dowhat,
819 					(sp->hidden&1)?"":"now.", sp,
820 					"", " = ", ";\n");
821 				break;
822 	}	}	}
823 	return cnt;
824 }
825 
826 static void
dohidden(void)827 dohidden(void)
828 {	Ordered *walk;
829 	Symbol *sp;
830 	int j;
831 
832 	for (j = 0; j < 8; j++)
833 	for (walk = all_names; walk; walk = walk->next)
834 	{	sp = walk->entry;
835 		if ((sp->hidden&1)
836 		&&  sp->type == Types[j])
837 		{	if (sp->context || sp->owner)
838 			fatal("cannot hide non-globals (%s)", sp->name);
839 			if (sp->type == CHAN)
840 			fatal("cannot hide channels (%s)", sp->name);
841 			fprintf(th, "/* hidden variable: */");
842 			typ2c(sp);
843 	}	}
844 	fprintf(th, "int _; /* a predefined write-only variable */\n\n");
845 }
846 
847 void
do_var(FILE * ofd,int dowhat,char * s,Symbol * sp,char * pre,char * sep,char * ter)848 do_var(FILE *ofd, int dowhat, char *s, Symbol *sp,
849 	char *pre, char *sep, char *ter)
850 {	int i;
851 	char *ptr = sp?sp->name:"";
852 
853 	if (!sp)
854 	{	fatal("cannot happen - do_var", 0);
855 	}
856 
857 	switch(dowhat) {
858 	case PUTV:
859 		if (sp->hidden&1) break;
860 
861 		typ2c(sp);
862 		break;
863 
864 	case LOGV:
865 		if (!old_scope_rules)
866 		{	while (*ptr == '_' || isdigit((int)*ptr))
867 			{	ptr++;
868 		}	}
869 		/* fall thru */
870 	case INIV:
871 		if (sp->type == STRUCT)
872 		{	/* struct may contain a chan */
873 			walk_struct(ofd, dowhat, s, sp, pre, sep, ter);
874 			break;
875 		}
876 		if (!sp->ini && dowhat != LOGV)	/* it defaults to 0 */
877 			break;
878 		if (sp->nel == 1 && sp->isarray == 0)
879 		{	if (dowhat == LOGV)
880 			{	fprintf(ofd, "\t\t%s%s%s%s",
881 					pre, s, ptr, sep);
882 				fprintf(ofd, "%s%s", s, sp->name);
883 			} else
884 			{	fprintf(ofd, "\t\t%s%s%s%s",
885 					pre, s, sp->name, sep);
886 				do_init(ofd, sp);
887 			}
888 			fprintf(ofd, "%s", ter);
889 		} else
890 		{	if (sp->ini && sp->ini->ntyp == CHAN)
891 			{	for (i = 0; i < sp->nel; i++)
892 				{	fprintf(ofd, "\t\t%s%s%s[%d]%s",
893 						pre, s, sp->name, i, sep);
894 					if (dowhat == LOGV)
895 						fprintf(ofd, "%s%s[%d]",
896 							s, sp->name, i);
897 					else
898 						do_init(ofd, sp);
899 					fprintf(ofd, "%s", ter);
900 				}
901 			} else
902 			{	fprintf(ofd, "\t{\tint l_in;\n");
903 				fprintf(ofd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
904 				fprintf(ofd, "\t\t{\n");
905 				fprintf(ofd, "\t\t\t%s%s%s[l_in]%s",
906 						pre, s, sp->name, sep);
907 				if (dowhat == LOGV)
908 					fprintf(ofd, "%s%s[l_in]", s, sp->name);
909 				else
910 					putstmnt(ofd, sp->ini, 0);
911 				fprintf(ofd, "%s", ter);
912 				fprintf(ofd, "\t\t}\n");
913 				fprintf(ofd, "\t}\n");
914 		}	}
915 		break;
916 	}
917 }
918 
919 static void
do_init(FILE * ofd,Symbol * sp)920 do_init(FILE *ofd, Symbol *sp)
921 {	int i;
922 
923 	if (sp->ini
924 	&&  sp->type == CHAN
925 	&& ((i = qmake(sp)) > 0))
926 	{	if (sp->ini->ntyp == CHAN)
927 		{	fprintf(ofd, "addqueue(calling_pid, %d, %d)",
928 				i, ltab[i-1]->nslots == 0);
929 		} else
930 		{	fprintf(ofd, "%d", i);
931 		}
932 	} else
933 	{	putstmnt(ofd, sp->ini, 0);
934 	}
935 }
936 
937 static void
put_ptype(char * s,int i,int m0,int m1,enum btypes b)938 put_ptype(char *s, int i, int m0, int m1, enum btypes b)
939 {	int k;
940 
941 	if (b == I_PROC)
942 	{	fprintf(th, "#define Pinit	((P%d *)this)\n", i);
943 	} else if (b == P_PROC || b == A_PROC)
944 	{	fprintf(th, "#define P%s	((P%d *)this)\n", s, i);
945 	}
946 
947 	fprintf(th, "typedef struct P%d { /* %s */\n", i, s);
948 	fprintf(th, "	unsigned _pid : 8;  /* 0..255 */\n");
949 	fprintf(th, "	unsigned _t   : %d; /* proctype */\n", blog(m1));
950 	fprintf(th, "	unsigned _p   : %d; /* state    */\n", blog(m0));
951 	LstSet = ZS;
952 	nBits = 8 + blog(m1) + blog(m0);
953 	k = dolocal(tc, "", PUTV, i, s, b);	/* includes pars */
954 
955 	c_add_loc(th, s);
956 
957 	fprintf(th, "} P%d;\n", i);
958 	if ((!LstSet && k > 0) || has_state)
959 		fprintf(th, "#define Air%d	0\n", i);
960 	else if (LstSet || k == 0)			/* 5.0, added condition */
961 	{	fprintf(th, "#define Air%d	(sizeof(P%d) - ", i, i);
962 		if (k == 0)
963 		{	fprintf(th, "%d", (nBits+7)/8);
964 			goto done;
965 		}
966 		if ((LstSet->type != BIT && LstSet->type != UNSIGNED)
967 		||   LstSet->nel != 1)
968 		{	fprintf(th, "Offsetof(P%d, %s) - %d*sizeof(",
969 				i, LstSet->name, LstSet->nel);
970 		}
971 		switch(LstSet->type) {
972 		case UNSIGNED:
973 			fprintf(th, "%d", (nBits+7)/8);
974 			break;
975 		case BIT:
976 			if (LstSet->nel == 1)
977 			{	fprintf(th, "%d", (nBits+7)/8);
978 				break;
979 			}	/* else fall through */
980 		case MTYPE: case BYTE: case CHAN:
981 			fprintf(th, "uchar)"); break;
982 		case SHORT:
983 			fprintf(th, "short)"); break;
984 		case INT:
985 			fprintf(th, "int)"); break;
986 		default:
987 			fatal("cannot happen Air %s",
988 				LstSet->name);
989 		}
990 done:		fprintf(th, ")\n");
991 	}
992 }
993 
994 static void
tc_predef_np(void)995 tc_predef_np(void)
996 {	int i = nrRdy;	/* 1+ highest proctype nr */
997 
998 	fprintf(th, "#define _NP_	%d\n", i);
999 /*	if (separate == 2) fprintf(th, "extern ");	*/
1000 	fprintf(th, "uchar reached%d[3];  /* np_ */\n", i);
1001 	fprintf(th, "uchar *loopstate%d;  /* np_ */\n", i);
1002 
1003 	fprintf(th, "#define nstates%d	3 /* np_ */\n", i);
1004 	fprintf(th, "#define endstate%d	2 /* np_ */\n\n", i);
1005 	fprintf(th, "#define start%d	0 /* np_ */\n", i);
1006 
1007 	fprintf(tc, "\tcase %d:	/* np_ */\n", i);
1008 	if (separate == 1)
1009 	{	fprintf(tc, "\t\tini_claim(%d, h);\n", i);
1010 	} else
1011 	{	fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
1012 		fprintf(tc, "\t\t((P%d *)pptr(h))->_p = 0;\n", i);
1013 		fprintf(tc, "\t\treached%d[0] = 1;\n", i);
1014 		fprintf(tc, "\t\taccpstate[%d][1] = 1;\n", i);
1015 	}
1016 	fprintf(tc, "\t\tbreak;\n");
1017 }
1018 
1019 static void
multi_init(void)1020 multi_init(void)
1021 {	ProcList *p;
1022 	Element	*e;
1023 	int i = nrRdy+1;
1024 	int ini, j;
1025 	int nrc = nclaims;
1026 
1027 	fprintf(tc, "#ifndef NOCLAIM\n");
1028 	fprintf(tc, "\tcase %d:	/* claim select */\n", i);
1029 	for (p = rdy, j = 0; p; p = p->nxt, j++)
1030 	{	if (p->b == N_CLAIM)
1031 		{	e = p->s->frst;
1032 			ini = huntele(e, e->status, -1)->seqno;
1033 
1034 			fprintf(tc, "\t\tspin_c_typ[%d] = %d; /* %s */\n",
1035 				j, p->tn, p->n->name);
1036 			fprintf(tc, "\t\t((P%d *)pptr(h))->c_cur[%d] = %d;\n",
1037 				i, j, ini);
1038 			fprintf(tc, "\t\treached%d[%d]=1;\n", p->tn, ini);
1039 
1040 			/* the default initial claim is first one in model */
1041 			if (--nrc == 0)
1042 			{ fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, p->tn);
1043 			  fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;\n", i, ini);
1044 			  fprintf(tc, "\t\t((P%d *)pptr(h))->_n = %d; /* %s */\n",
1045 				i, j, p->n->name);
1046 			  fprintf(tc, "\t\tsrc_claim = src_ln%d;\n", p->tn);
1047 			  fprintf(tc, "#ifndef BFS\n");
1048 			  fprintf(tc, "\t\tif (whichclaim == -1 && claimname == NULL)\n");
1049 			  fprintf(tc, "\t\t\tprintf(\"0: Claim %s (%d), from state %d\\n\");\n",
1050 				p->n->name, p->tn, ini);
1051 			  fprintf(tc, "#endif\n");
1052 			}
1053 	}	}
1054 	fprintf(tc, "\t\tif (whichclaim != -1)\n");
1055 	fprintf(tc, "\t\t{	select_claim(whichclaim);\n");
1056 	fprintf(tc, "\t\t}\n");
1057 	fprintf(tc, "\t\tbreak;\n\n");
1058 	fprintf(tc, "#endif\n");
1059 }
1060 
1061 static void
put_pinit(ProcList * P)1062 put_pinit(ProcList *P)
1063 {	Lextok	*fp, *fpt, *t;
1064 	Element	*e = P->s->frst;
1065 	Symbol	*s = P->n;
1066 	Lextok	*p = P->p;
1067 	int	 i = P->tn;
1068 	int	ini, j, k;
1069 
1070 	if (pid_is_claim(i)
1071 	&&  separate == 1)
1072 	{	fprintf(tc, "\tcase %d:	/* %s */\n", i, s->name);
1073 		fprintf(tc, "\t\tini_claim(%d, h);\n", i);
1074 		fprintf(tc, "\t\tbreak;\n");
1075 		return;
1076 	}
1077 	if (!pid_is_claim(i)
1078 	&&  separate == 2)
1079 		return;
1080 
1081 	ini = huntele(e, e->status, -1)->seqno;
1082 	fprintf(th, "#define start%d	%d\n", i, ini);
1083 	if (i == eventmapnr)
1084 	fprintf(th, "#define start_event	%d\n", ini);
1085 
1086 	fprintf(tc, "\tcase %d:	/* %s */\n", i, s->name);
1087 
1088 	fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
1089 	fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;\n", i, ini);
1090 	fprintf(tc, "\t\treached%d[%d]=1;\n", i, ini);
1091 	if (P->b == N_CLAIM)
1092 	{	fprintf(tc, "\t\tsrc_claim = src_ln%d;\n", i);
1093 	}
1094 
1095 	if (has_provided)
1096 	{	fprintf(tt, "\tcase %d: /* %s */\n\t\t", i, s->name);
1097 		if (P->prov)
1098 		{	fprintf(tt, "if (");
1099 			putstmnt(tt, P->prov, 0);
1100 			fprintf(tt, ")\n\t\t\t");
1101 		}
1102 		fprintf(tt, "return 1;\n");
1103 		if (P->prov)
1104 			fprintf(tt, "\t\tbreak;\n");
1105 	}
1106 
1107 	fprintf(tc, "\t\t/* params: */\n");
1108 	for (fp  = p, j=0; fp; fp = fp->rgt)
1109 	for (fpt = fp->lft; fpt; fpt = fpt->rgt, j++)
1110 	{	t = (fpt->ntyp == ',') ? fpt->lft : fpt;
1111 		if (t->sym->nel > 1 || t->sym->isarray)
1112 		{	lineno = t->ln;
1113 			Fname  = t->fn;
1114 			fatal("array in parameter list, %s",
1115 			t->sym->name);
1116 		}
1117 		fprintf(tc, "\t\t((P%d *)pptr(h))->", i);
1118 		if (t->sym->type == STRUCT)
1119 		{	if (full_name(tc, t, t->sym, 1))
1120 			{	lineno = t->ln;
1121 				Fname  = t->fn;
1122 				fatal("hidden array in parameter %s",
1123 				t->sym->name);
1124 			}
1125 		} else
1126 			fprintf(tc, "%s", t->sym->name);
1127 		fprintf(tc, " = par%d;\n", j);
1128 	}
1129 	fprintf(tc, "\t\t/* locals: */\n");
1130 	k = dolocal(tc, "", INIV, i, s->name, P->b);
1131 	if (k > 0)
1132 	{	fprintf(tc, "#ifdef VAR_RANGES\n");
1133 		(void) dolocal(tc, "logval(\"", LOGV, i, s->name, P->b);
1134 		fprintf(tc, "#endif\n");
1135 	}
1136 
1137 	fprintf(tc, "#ifdef HAS_CODE\n");
1138 	fprintf(tc, "\t\tlocinit%d(h);\n", i);
1139 	fprintf(tc, "#endif\n");
1140 
1141 	dumpclaims(tc, i, s->name);
1142 	fprintf(tc, "\t	break;\n");
1143 }
1144 
1145 Element *
huntstart(Element * f)1146 huntstart(Element *f)
1147 {	Element *e = f;
1148 	Element *elast = (Element *) 0;
1149 	int cnt = 0;
1150 
1151 	while (elast != e && cnt++ < 200)	/* new 4.0.8 */
1152 	{	elast = e;
1153 		if (e->n)
1154 		{	if (e->n->ntyp == '.' && e->nxt)
1155 				e = e->nxt;
1156 			else if (e->n->ntyp == UNLESS)
1157 				e = e->sub->this->frst;
1158 	}	}
1159 
1160 	if (cnt >= 200 || !e)
1161 		fatal("confusing control structure", (char *) 0);
1162 	return e;
1163 }
1164 
1165 Element *
huntele(Element * f,int o,int stopat)1166 huntele(Element *f, int o, int stopat)
1167 {	Element *g, *e = f;
1168 	int cnt=0; /* a precaution against loops */
1169 
1170 	if (e)
1171 	for ( ; cnt < 200 && e->n; cnt++)
1172 	{
1173 		if (e->seqno == stopat)
1174 			break;
1175 
1176 		switch (e->n->ntyp) {
1177 		case GOTO:
1178 			g = get_lab(e->n,1);
1179 			cross_dsteps(e->n, g->n);
1180 			break;
1181 		case '.':
1182 		case BREAK:
1183 			if (!e->nxt)
1184 				return e;
1185 			g = e->nxt;
1186 			break;
1187 		case UNLESS:
1188 			g = huntele(e->sub->this->frst, o, stopat);
1189 			break;
1190 		case D_STEP:
1191 		case ATOMIC:
1192 		case NON_ATOMIC:
1193 		default:
1194 			return e;
1195 		}
1196 		if ((o & ATOM) && !(g->status & ATOM))
1197 			return e;
1198 		e = g;
1199 	}
1200 	if (cnt >= 200 || !e)
1201 		fatal("confusing control structure", (char *) 0);
1202 	return e;
1203 }
1204 
1205 void
typ2c(Symbol * sp)1206 typ2c(Symbol *sp)
1207 {	int wsbits = sizeof(long)*8; /* wordsize in bits */
1208 	switch (sp->type) {
1209 	case UNSIGNED:
1210 		if (sp->hidden&1)
1211 			fprintf(th, "\tuchar %s;", sp->name);
1212 		else
1213 			fprintf(th, "\tunsigned %s : %d",
1214 				sp->name, sp->nbits);
1215 		LstSet = sp;
1216 		if (nBits%wsbits > 0
1217 		&&  wsbits - nBits%wsbits < sp->nbits)
1218 		{	/* must padd to a word-boundary */
1219 			nBits += wsbits - nBits%wsbits;
1220 		}
1221 		nBits += sp->nbits;
1222 		break;
1223 	case BIT:
1224 		if (sp->nel == 1 && sp->isarray == 0 && !(sp->hidden&1))
1225 		{	fprintf(th, "\tunsigned %s : 1", sp->name);
1226 			LstSet = sp;
1227 			nBits++;
1228 			break;
1229 		} /* else fall through */
1230 		if (!(sp->hidden&1) && (verbose&32))
1231 		printf("spin: warning: bit-array %s[%d] mapped to byte-array\n",
1232 			sp->name, sp->nel);
1233 		nBits += 8*sp->nel; /* mapped onto array of uchars */
1234 	case MTYPE:
1235 	case BYTE:
1236 	case CHAN:	/* good for up to 255 channels */
1237 		fprintf(th, "\tuchar %s", sp->name);
1238 		LstSet = sp;
1239 		break;
1240 	case SHORT:
1241 		fprintf(th, "\tshort %s", sp->name);
1242 		LstSet = sp;
1243 		break;
1244 	case INT:
1245 		fprintf(th, "\tint %s", sp->name);
1246 		LstSet = sp;
1247 		break;
1248 	case STRUCT:
1249 		if (!sp->Snm)
1250 			fatal("undeclared structure element %s", sp->name);
1251 		fprintf(th, "\tstruct %s %s",
1252 			sp->Snm->name,
1253 			sp->name);
1254 		LstSet = ZS;
1255 		break;
1256 	case CODE_FRAG:
1257 	case PREDEF:
1258 		return;
1259 	default:
1260 		fatal("variable %s undeclared", sp->name);
1261 	}
1262 
1263 	if (sp->nel > 1 || sp->isarray)
1264 		fprintf(th, "[%d]", sp->nel);
1265 	fprintf(th, ";\n");
1266 }
1267 
1268 static void
ncases(FILE * fd,int p,int n,int m,char * c[])1269 ncases(FILE *fd, int p, int n, int m, char *c[])
1270 {	int i, j;
1271 
1272 	for (j = 0; c[j]; j++)
1273 	for (i = n; i < m; i++)
1274 	{	fprintf(fd, c[j], i, p, i);
1275 		fprintf(fd, "\n");
1276 	}
1277 }
1278 
1279 void
qlen_type(int qmax)1280 qlen_type(int qmax)
1281 {
1282 	fprintf(th, "\t");
1283 	if (qmax < 256)
1284 		fprintf(th, "uchar");
1285 	else if (qmax < 65535)
1286 		fprintf(th, "ushort");
1287 	else
1288 		fprintf(th, "uint");
1289 	fprintf(th, " Qlen;	/* q_size */\n");
1290 }
1291 
1292 void
genaddqueue(void)1293 genaddqueue(void)
1294 {	char buf0[256];
1295 	int j, qmax = 0;
1296 	Queue *q;
1297 
1298 	ntimes(tc, 0, 1, Addq0);
1299 	if (has_io && !nqs)
1300 		fprintf(th, "#define NQS	1 /* nqs=%d, but has_io */\n", nqs);
1301 	else
1302 		fprintf(th, "#define NQS	%d\n", nqs);
1303 	fprintf(th, "short q_flds[%d];\n", nqs+1);
1304 	fprintf(th, "short q_max[%d];\n", nqs+1);
1305 
1306 	for (q = qtab; q; q = q->nxt)
1307 		if (q->nslots > qmax)
1308 			qmax = q->nslots;
1309 
1310 	for (q = qtab; q; q = q->nxt)
1311 	{	j = q->qid;
1312 		fprintf(tc, "\tcase %d: j = sizeof(Q%d);", j, j);
1313 		fprintf(tc, " q_flds[%d] = %d;", j, q->nflds);
1314 		fprintf(tc, " q_max[%d] = %d;", j, max(1,q->nslots));
1315 		fprintf(tc, " break;\n");
1316 
1317 		fprintf(th, "typedef struct Q%d {\n", j);
1318 		qlen_type(qmax);	/* 4.2.2 */
1319 		fprintf(th, "	uchar _t;	/* q_type */\n");
1320 		fprintf(th, "	struct {\n");
1321 
1322 		for (j = 0; j < q->nflds; j++)
1323 		{	switch (q->fld_width[j]) {
1324 			case BIT:
1325 				if (q->nflds != 1)
1326 				{	fprintf(th, "\t\tunsigned");
1327 					fprintf(th, " fld%d : 1;\n", j);
1328 					break;
1329 				} /* else fall through: smaller struct */
1330 			case MTYPE:
1331 			case CHAN:
1332 			case BYTE:
1333 				fprintf(th, "\t\tuchar fld%d;\n", j);
1334 				break;
1335 			case SHORT:
1336 				fprintf(th, "\t\tshort fld%d;\n", j);
1337 				break;
1338 			case INT:
1339 				fprintf(th, "\t\tint fld%d;\n", j);
1340 				break;
1341 			default:
1342 				fatal("bad channel spec", "");
1343 			}
1344 		}
1345 		fprintf(th, "	} contents[%d];\n", max(1, q->nslots));
1346 		fprintf(th, "} Q%d;\n", q->qid);
1347 	}
1348 
1349 	fprintf(th, "typedef struct Q0 {\t/* generic q */\n");
1350 	qlen_type(qmax);	/* 4.2.2 */
1351 	fprintf(th, "	uchar _t;\n");
1352 	fprintf(th, "} Q0;\n");
1353 
1354 	ntimes(tc, 0, 1, Addq1);
1355 
1356 	fprintf(tc, "#ifdef TRIX\n");
1357 	fprintf(tc, "int\nwhat_p_size(int t)\n{\tint j;\n");
1358 	fprintf(tc, "	switch (t) {\n");
1359 	ntimes(tc, 0, nrRdy+1, R5); /* +1 for np_ */
1360 	fprintf(tc, "	default: Uerror(\"bad proctype\");\n");
1361 	fprintf(tc, "	}\n	return j;\n}\n\n");
1362 
1363 	fprintf(tc, "int\nwhat_q_size(int t)\n{\tint j;\n");
1364 	fprintf(tc, "	switch (t) {\n");
1365 	for (j = 0; j < nqs+1; j++)
1366 	{	fprintf(tc, "	case %d: j = sizeof(Q%d); break;\n", j, j);
1367 	}
1368 	fprintf(tc, "	default: Uerror(\"bad qtype\");\n");
1369 	fprintf(tc, "	}\n	return j;\n}\n");
1370 	fprintf(tc, "#endif\n\n");
1371 
1372 	if (has_random)
1373 	{	fprintf(th, "int Q_has(int");
1374 		for (j = 0; j < Mpars; j++)
1375 			fprintf(th, ", int, int");
1376 		fprintf(th, ");\n");
1377 
1378 		fprintf(tc, "int\nQ_has(int into");
1379 		for (j = 0; j < Mpars; j++)
1380 			fprintf(tc, ", int want%d, int fld%d", j, j);
1381 		fprintf(tc, ")\n");
1382 		fprintf(tc, "{	int i;\n\n");
1383 		fprintf(tc, "	if (!into--)\n");
1384 		fprintf(tc, "	uerror(\"ref to unknown chan ");
1385 		fprintf(tc, "(recv-poll)\");\n\n");
1386 		fprintf(tc, "	if (into >= now._nr_qs || into < 0)\n");
1387 		fprintf(tc, "		Uerror(\"qrecv bad queue#\");\n\n");
1388 		fprintf(tc, "	for (i = 0; i < ((Q0 *)qptr(into))->Qlen;");
1389 		fprintf(tc, " i++)\n");
1390 		fprintf(tc, "	{\n");
1391 		for (j = 0; j < Mpars; j++)
1392 		{	fprintf(tc, "		if (want%d && ", j);
1393 			fprintf(tc, "qrecv(into+1, i, %d, 0) != fld%d)\n",
1394 				j, j);
1395 			fprintf(tc, "			continue;\n");
1396 		}
1397 		fprintf(tc, "		return i+1;\n");
1398 		fprintf(tc, "	}\n");
1399 		fprintf(tc, "	return 0;\n");
1400 		fprintf(tc, "}\n");
1401 	}
1402 
1403 	fprintf(tc, "#if NQS>0\n");
1404 	fprintf(tc, "void\nqsend(int into, int sorted");
1405 	for (j = 0; j < Mpars; j++)
1406 		fprintf(tc, ", int fld%d", j);
1407 	fprintf(tc, ", int args_given)\n");
1408 	ntimes(tc, 0, 1, Addq11);
1409 
1410 	for (q = qtab; q; q = q->nxt)
1411 	{	sprintf(buf0, "((Q%d *)z)->", q->qid);
1412 		fprintf(tc, "\tcase %d:%s\n", q->qid,
1413 			(q->nslots)?"":" /* =rv= */");
1414 		if (q->nslots == 0)	/* reset handshake point */
1415 			fprintf(tc, "\t\t(trpt+2)->o_m = 0;\n");
1416 
1417 		if (has_sorted)
1418 		{	fprintf(tc, "\t\tif (!sorted) goto append%d;\n", q->qid);
1419 			fprintf(tc, "\t\tfor (j = 0; j < %sQlen; j++)\n", buf0);
1420 			fprintf(tc, "\t\t{\t/* find insertion point */\n");
1421 			sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
1422 			for (j = 0; j < q->nflds; j++)
1423 			{	fprintf(tc, "\t\t\tif (fld%d > %s%d) continue;\n",
1424 						j, buf0, j);
1425 				fprintf(tc, "\t\t\tif (fld%d < %s%d) ", j, buf0, j);
1426 				fprintf(tc, "goto found%d;\n\n", q->qid);
1427 			}
1428 			fprintf(tc, "\t\t}\n");
1429 			fprintf(tc, "\tfound%d:\n", q->qid);
1430 			sprintf(buf0, "((Q%d *)z)->", q->qid);
1431 			fprintf(tc, "\t\tfor (k = %sQlen - 1; k >= j; k--)\n", buf0);
1432 			fprintf(tc, "\t\t{\t/* shift up */\n");
1433 			for (j = 0; j < q->nflds; j++)
1434 			{	fprintf(tc, "\t\t\t%scontents[k+1].fld%d = ",
1435 					buf0, j);
1436 				fprintf(tc, "%scontents[k].fld%d;\n",
1437 					buf0, j);
1438 			}
1439 			fprintf(tc, "\t\t}\n");
1440 			fprintf(tc, "\tappend%d:\t/* insert in slot j */\n", q->qid);
1441 		}
1442 
1443 		fprintf(tc, "#ifdef HAS_SORTED\n");
1444 		fprintf(tc, "\t\t(trpt+1)->ipt = j;\n");	/* ipt was bup.oval */
1445 		fprintf(tc, "#endif\n");
1446 		fprintf(tc, "\t\t%sQlen = %sQlen + 1;\n", buf0, buf0);
1447 		sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
1448 		for (j = 0; j < q->nflds; j++)
1449 			fprintf(tc, "\t\t%s%d = fld%d;\n", buf0, j, j);
1450 		fprintf(tc, "\t\tif (args_given != %d)\n", q->nflds);
1451 		fprintf(tc, "\t\t{	if (args_given > %d)\n", q->nflds);
1452 		fprintf(tc, "\t\t		uerror(\"too many parameters in send stmnt\");\n");
1453 		fprintf(tc, "\t\t	else\n");
1454 		fprintf(tc, "\t\t		uerror(\"too few parameters in send stmnt\");\n");
1455 		fprintf(tc, "\t\t}\n");
1456 		fprintf(tc, "\t\tbreak;\n");
1457 	}
1458 	ntimes(tc, 0, 1, Addq2);
1459 
1460 	for (q = qtab; q; q = q->nxt)
1461 	fprintf(tc, "\tcase %d: return %d;\n", q->qid, (!q->nslots));
1462 
1463 	ntimes(tc, 0, 1, Addq3);
1464 
1465 	for (q = qtab; q; q = q->nxt)
1466 	fprintf(tc, "\tcase %d: return (q_sz(from) == %d);\n",
1467 			q->qid, max(1, q->nslots));
1468 
1469 	ntimes(tc, 0, 1, Addq4);
1470 	for (q = qtab; q; q = q->nxt)
1471 	{	sprintf(buf0, "((Q%d *)z)->", q->qid);
1472 		fprintf(tc, "	case %d:%s\n\t\t",
1473 			q->qid, (q->nslots)?"":" /* =rv= */");
1474 		if (q->nflds == 1)
1475 		{	fprintf(tc, "if (fld == 0) r = %s", buf0);
1476 			fprintf(tc, "contents[slot].fld0;\n");
1477 		} else
1478 		{	fprintf(tc, "switch (fld) {\n");
1479 			ncases(tc, q->qid, 0, q->nflds, R12);
1480 			fprintf(tc, "\t\tdefault: Uerror");
1481 			fprintf(tc, "(\"too many fields in recv\");\n");
1482 			fprintf(tc, "\t\t}\n");
1483 		}
1484 		fprintf(tc, "\t\tif (done)\n");
1485 		if (q->nslots == 0)
1486 		{	fprintf(tc, "\t\t{	j = %sQlen - 1;\n",  buf0);
1487 			fprintf(tc, "\t\t	%sQlen = 0;\n", buf0);
1488 			sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
1489 		} else
1490 	 	{	fprintf(tc, "\t\t{	j = %sQlen;\n",  buf0);
1491 			fprintf(tc, "\t\t	%sQlen = --j;\n", buf0);
1492 			fprintf(tc, "\t\t	for (k=slot; k<j; k++)\n");
1493 			fprintf(tc, "\t\t	{\n");
1494 			sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
1495 			for (j = 0; j < q->nflds; j++)
1496 			{	fprintf(tc, "\t%s[k].fld%d = \n", buf0, j);
1497 				fprintf(tc, "\t\t%s[k+1].fld%d;\n", buf0, j);
1498 			}
1499 			fprintf(tc, "\t\t	}\n");
1500 	 	}
1501 
1502 		for (j = 0; j < q->nflds; j++)
1503 			fprintf(tc, "%s[j].fld%d = 0;\n", buf0, j);
1504 		fprintf(tc, "\t\t\tif (fld+1 != %d)\n\t\t\t", q->nflds);
1505 		fprintf(tc, "\tuerror(\"missing pars in receive\");\n");
1506 		/* incompletely received msgs cannot be unrecv'ed */
1507 		fprintf(tc, "\t\t}\n");
1508 		fprintf(tc, "\t\tbreak;\n");
1509 	}
1510 	ntimes(tc, 0, 1, Addq5);
1511 	for (q = qtab; q; q = q->nxt)
1512 	fprintf(tc, "	case %d: j = sizeof(Q%d); break;\n",
1513 		q->qid, q->qid);
1514 	ntimes(tc, 0, 1, R8b);
1515 
1516 	ntimes(th, 0, 1, Proto);	/* tag on function prototypes */
1517 	fprintf(th, "void qsend(int, int");
1518 	for (j = 0; j < Mpars; j++)
1519 		fprintf(th, ", int");
1520 	fprintf(th, ", int);\n");
1521 
1522 	fprintf(th, "#define Addproc(x)	addproc(256, x");
1523 	/* 256 is param outside the range of valid pids */
1524 	for (j = 0; j < Npars; j++)
1525 		fprintf(th, ", 0");
1526 	fprintf(th, ")\n");
1527 }
1528