Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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
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
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
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
}