1 /***** spin: pangen2.c *****/
2 
3 /*
4  * This file is part of the public release of Spin. It is subject to the
5  * terms in the LICENSE file that is included in this source directory.
6  * Tool documentation is available at http://spinroot.com
7  */
8 
9 #include "spin.h"
10 #include "version.h"
11 #include "y.tab.h"
12 #include "pangen2.h"
13 #include "pangen4.h"
14 #include "pangen5.h"
15 #include "pangen7.h"
16 
17 #define DELTA	500	/* sets an upperbound on nr of chan names */
18 
19 #define blurb(fd, e)	{ fprintf(fd, "\n"); if (!merger) fprintf(fd, "\t\t/* %s:%d */\n", \
20 				e->n->fn->name, e->n->ln); }
21 #define tr_map(m, e)	{ if (!merger) fprintf(fd_tt, "\t\ttr_2_src(%d, \"%s\", %d);\n", \
22 				m, e->n->fn->name, e->n->ln); }
23 
24 extern ProcList	*ready;
25 extern RunList	*run_lst;
26 extern Lextok	*runstmnts;
27 extern Symbol	*Fname, *oFname, *context;
28 extern char	*claimproc, *eventmap;
29 extern int	lineno, verbose, Npars, Mpars, nclaims;
30 extern int	m_loss, has_remote, has_remvar, merger, rvopt, separate;
31 extern int	Ntimeouts, Etimeouts, deadvar, old_scope_rules, old_priority_rules;
32 extern int	u_sync, u_async, nrRdy, Unique;
33 extern int	GenCode, IsGuard, Level, TestOnly;
34 extern int	globmin, globmax, ltl_mode, dont_simplify;
35 
36 extern short	has_stack;
37 extern char	*NextLab[64];	/* must match value in dstep.c:18 */
38 
39 int	 	 buzzed;
40 FILE		*fd_tc, *fd_th, *fd_tt, *fd_tb;
41 static FILE	*fd_tm;
42 
43 int	OkBreak = -1, has_hidden = 0; /* has_hidden set in sym.c and structs.c */
44 short	nocast=0;	/* to turn off casts in lvalues */
45 short	terse=0;	/* terse printing of varnames */
46 short	no_arrays=0;
47 short	has_last=0;	/* spec refers to _last */
48 short	has_priority=0;	/* spec refers to _priority */
49 short	has_badelse=0;	/* spec contains else combined with chan refs */
50 short	has_enabled=0;	/* spec contains enabled() */
51 short	has_pcvalue=0;	/* spec contains pc_value() */
52 short	has_np=0;	/* spec contains np_ */
53 short	has_sorted=0;	/* spec contains `!!' (sorted-send) operator */
54 short	has_random=0;	/* spec contains `??' (random-recv) operator */
55 short	has_xu=0;	/* spec contains xr or xs assertions */
56 short	has_unless=0;	/* spec contains unless statements */
57 short	has_provided=0;	/* spec contains PROVIDED clauses on procs */
58 short	has_code=0;	/* spec contains c_code, c_expr, c_state */
59 short	has_ltl=0;	/* has inline ltl formulae */
60 int	mstp=0;		/* max nr of state/process */
61 int	claimnr = -1;	/* claim process, if any */
62 int	eventmapnr = -1; /* event trace, if any */
63 int	Pid_nr;		/* proc currently processed */
64 int	multi_oval;	/* set in merges, used also in pangen4.c */
65 int	in_settr;	/* avoid quotes inside quotes */
66 
67 #define MAXMERGE	256	/* max nr of bups per merge sequence */
68 
69 static short	CnT[MAXMERGE];
70 static Lextok	XZ, YZ[MAXMERGE];
71 static int	didcase, YZmax, YZcnt;
72 
73 static Lextok	*Nn[2];
74 static int	Det;	/* set if deterministic */
75 static int	T_sum, T_mus, t_cyc;
76 static int	TPE[2], EPT[2];
77 static int	uniq=1;
78 static int	multi_needed, multi_undo;
79 static short	AllGlobal=0;	/* set if process has provided clause */
80 static short	withprocname=0;	/* prefix local varnames with procname */
81 static short	_isok=0;	/* checks usage of predefined variable _ */
82 static short	evalindex=0;	/* evaluate index of var names */
83 
84 extern int	has_global(Lextok *);
85 extern void	check_mtypes(Lextok *, Lextok *);
86 extern void	walk2_struct(char *, Symbol *);
87 extern int	find_min(Sequence *);
88 extern int	find_max(Sequence *);
89 
90 static int	getweight(Lextok *);
91 static int	scan_seq(Sequence *);
92 static void	genconditionals(void);
93 static void	mark_seq(Sequence *);
94 static void	patch_atomic(Sequence *);
95 static void	put_seq(Sequence *, int, int);
96 static void	putproc(ProcList *);
97 static void	Tpe(Lextok *);
98 extern void	spit_recvs(FILE *, FILE*);
99 
100 static L_List *keep_track;
101 
102 void
keep_track_off(Lextok * n)103 keep_track_off(Lextok *n)
104 {	L_List *p;
105 
106 	p = (L_List *) emalloc(sizeof(L_List));
107 	p->n = n;
108 	p->nxt = keep_track;
109 	keep_track = p;
110 }
111 
112 int
check_track(Lextok * n)113 check_track(Lextok *n)
114 {	L_List *p;
115 
116 	for (p = keep_track; p; p = p->nxt)
117 	{	if (p->n == n)
118 		{	return n->sym?n->sym->type:0;
119 	}	}
120 	return 0;
121 }
122 
123 static int
fproc(char * s)124 fproc(char *s)
125 {	ProcList *p;
126 
127 	for (p = ready; p; p = p->nxt)
128 		if (strcmp(p->n->name, s) == 0)
129 			return p->tn;
130 
131 	fatal("proctype %s not found", s);
132 	return -1;
133 }
134 
135 int
pid_is_claim(int p)136 pid_is_claim(int p)	/* Pid_nr (p->tn) to type (p->b) */
137 {	ProcList *r;
138 
139 	for (r = ready; r; r = r->nxt)
140 	{	if (r->tn == p) return (r->b == N_CLAIM);
141 	}
142 	printf("spin: error, cannot find pid %d\n", p);
143 	return 0;
144 }
145 
146 static void
reverse_procs(RunList * q)147 reverse_procs(RunList *q)
148 {
149 	if (!q) return;
150 	reverse_procs(q->nxt);
151 	fprintf(fd_tc, "		Addproc(%d, %d);\n",
152 		q->tn, q->priority < 1 ? 1 : q->priority);
153 }
154 
155 static void
forward_procs(RunList * q)156 forward_procs(RunList *q)
157 {
158 	if (!q) return;
159 	fprintf(fd_tc, "		Addproc(%d, %d);\n",
160 		q->tn, q->priority < 1 ? 1 : q->priority);
161 	forward_procs(q->nxt);
162 }
163 
164 static void
tm_predef_np(void)165 tm_predef_np(void)
166 {
167 	fprintf(fd_th, "#define _T5	%d\n", uniq++);
168 	fprintf(fd_th, "#define _T2	%d\n", uniq++);
169 
170 	fprintf(fd_tm, "\tcase  _T5:\t/* np_ */\n");
171 
172 	if (separate == 2)
173 	{	fprintf(fd_tm, "\t\tif (!((!(o_pm&4) && !(tau&128))))\n");
174 	} else
175 	{	fprintf(fd_tm, "\t\tif (!((!(trpt->o_pm&4) && !(trpt->tau&128))))\n");
176 	}
177 	fprintf(fd_tm, "\t\t\tcontinue;\n");
178 	fprintf(fd_tm, "\t\t/* else fall through */\n");
179 	fprintf(fd_tm, "\tcase  _T2:\t/* true */\n");
180 	fprintf(fd_tm, "\t\t_m = 3; goto P999;\n");
181 }
182 
183 static void
tt_predef_np(void)184 tt_predef_np(void)
185 {
186 	fprintf(fd_tt, "\t/* np_ demon: */\n");
187 	fprintf(fd_tt, "\ttrans[_NP_] = ");
188 	fprintf(fd_tt, "(Trans **) emalloc(3*sizeof(Trans *));\n");
189 	fprintf(fd_tt, "\tT = trans[_NP_][0] = ");
190 	fprintf(fd_tt, "settr(9997,0,1,_T5,0,\"(np_)\", 1,2,0);\n");
191 	fprintf(fd_tt, "\t    T->nxt	  = ");
192 	fprintf(fd_tt, "settr(9998,0,0,_T2,0,\"(1)\",   0,2,0);\n");
193 	fprintf(fd_tt, "\tT = trans[_NP_][1] = ");
194 	fprintf(fd_tt, "settr(9999,0,1,_T5,0,\"(np_)\", 1,2,0);\n");
195 }
196 
197 static struct {
198 	char *nm[3];
199 } Cfile[] = {
200 	{ { "pan.c", "pan_s.c", "pan_t.c" } },
201 	{ { "pan.h", "pan_s.h", "pan_t.h" } },
202 	{ { "pan.t", "pan_s.t", "pan_t.t" } },
203 	{ { "pan.m", "pan_s.m", "pan_t.m" } },
204 	{ { "pan.b", "pan_s.b", "pan_t.b" } }
205 };
206 
207 void
gensrc(void)208 gensrc(void)
209 {	ProcList *p;
210 	int i;
211 
212 	disambiguate();		/* avoid name-clashes between scopes */
213 
214 	if (!(fd_tc = fopen(Cfile[0].nm[separate], MFLAGS))		/* main routines */
215 	||  !(fd_th = fopen(Cfile[1].nm[separate], MFLAGS))		/* header file   */
216 	||  !(fd_tt = fopen(Cfile[2].nm[separate], MFLAGS))		/* transition matrix */
217 	||  !(fd_tm = fopen(Cfile[3].nm[separate], MFLAGS))		/* forward  moves */
218 	||  !(fd_tb = fopen(Cfile[4].nm[separate], MFLAGS)))	/* backward moves */
219 	{	printf("spin: cannot create pan.[chtmfb]\n");
220 		alldone(1);
221 	}
222 
223 	fprintf(fd_th, "#ifndef PAN_H\n");
224 	fprintf(fd_th, "#define PAN_H\n\n");
225 
226 	fprintf(fd_th, "#define SpinVersion	\"%s\"\n", SpinVersion);
227 	fprintf(fd_th, "#define PanSource	\"");
228 	for (i = 0; oFname->name[i] != '\0'; i++)
229 	{	char c = oFname->name[i];
230 		if (c == '\\') /* Windows path */
231 		{	fprintf(fd_th, "\\");
232 		}
233 		fprintf(fd_th, "%c", c);
234 	}
235 	fprintf(fd_th, "\"\n\n");
236 
237 	fprintf(fd_th, "#define G_long	%d\n", (int) sizeof(long));
238 	fprintf(fd_th, "#define G_int	%d\n\n", (int) sizeof(int));
239 	fprintf(fd_th, "#define ulong	unsigned long\n");
240 	fprintf(fd_th, "#define ushort	unsigned short\n");
241 
242 	fprintf(fd_th, "#ifdef WIN64\n");
243 	fprintf(fd_th, "	#define ONE_L	(1L)\n");
244 	fprintf(fd_th, "/*	#define long	long long */\n");
245 	fprintf(fd_th, "#else\n");
246 	fprintf(fd_th, "	#define ONE_L	(1L)\n");
247 	fprintf(fd_th, "#endif\n\n");
248 
249 	fprintf(fd_th, "#ifdef BFS_PAR\n");
250 	fprintf(fd_th, "	#define NRUNS	%d\n", (runstmnts)?1:0);
251 	fprintf(fd_th, "	#ifndef BFS\n");
252 	fprintf(fd_th, "		#define BFS\n");
253 	fprintf(fd_th, "	#endif\n");
254 	fprintf(fd_th, "	#ifndef PUTPID\n");
255 	fprintf(fd_th, "		#define PUTPID\n");
256 	fprintf(fd_th, "	#endif\n\n");
257 	fprintf(fd_th, "	#if !defined(USE_TDH) && !defined(NO_TDH)\n");
258 	fprintf(fd_th, "		#define USE_TDH\n");
259 	fprintf(fd_th, "	#endif\n");
260 	fprintf(fd_th, "	#if defined(USE_TDH) && !defined(NO_HC)\n");
261 	fprintf(fd_th, "		#define HC /* default for USE_TDH */\n");
262 	fprintf(fd_th, "	#endif\n");
263 	fprintf(fd_th, "	#ifndef BFS_MAXPROCS\n");
264 	fprintf(fd_th, "		#define BFS_MAXPROCS	64	/* max nr of cores to use */\n");
265 	fprintf(fd_th, "	#endif\n");
266 
267 	fprintf(fd_th, "	#define BFS_GLOB	0	/* global lock */\n");
268 	fprintf(fd_th, "	#define BFS_ORD		1	/* used with -DCOLLAPSE */\n");
269 	fprintf(fd_th, "	#define BFS_MEM		2	/* malloc from shared heap */\n");
270 	fprintf(fd_th, "	#define BFS_PRINT	3	/* protect printfs */\n");
271 	fprintf(fd_th, "	#define BFS_STATE	4	/* hashtable */\n\n");
272 	fprintf(fd_th, "	#define BFS_INQ 	2	/* state is in q */\n\n");
273 
274 	fprintf(fd_th, "	#ifdef BFS_FIFO\n");	/* queue access */
275 	fprintf(fd_th, "	  #define BFS_ID(a,b)	(BFS_STATE + (int) ((a)*BFS_MAXPROCS+(b)))\n");
276 	fprintf(fd_th, "	  #define BFS_MAXLOCKS	(BFS_STATE + (BFS_MAXPROCS*BFS_MAXPROCS))\n");
277 	fprintf(fd_th, "	#else\n");		/* h_store access (not needed for o_store) */
278 	fprintf(fd_th, "	  #ifndef BFS_W\n");
279 	fprintf(fd_th, "		#define BFS_W	10\n");	/* 1<<BFS_W locks */
280 	fprintf(fd_th, "	  #endif\n");
281 	fprintf(fd_th, "	  #define BFS_MASK	((1<<BFS_W) - 1)\n");
282 	fprintf(fd_th, "	  #define BFS_ID	(BFS_STATE + (int) (j1_spin & (BFS_MASK)))\n");
283 	fprintf(fd_th, "	  #define BFS_MAXLOCKS	(BFS_STATE + (1<<BFS_W))\n"); /* 4+1024 */
284 	fprintf(fd_th, "	#endif\n");
285 
286 	fprintf(fd_th, "	#undef NCORE\n");
287 	fprintf(fd_th, "	extern int Cores, who_am_i;\n");
288 	fprintf(fd_th, "	#ifndef SAFETY\n");
289 	fprintf(fd_th, "	  #if !defined(BFS_STAGGER) && !defined(BFS_DISK)\n");
290 	fprintf(fd_th, "		#define BFS_STAGGER	64 /* randomizer, was 16 */\n");
291 	fprintf(fd_th, "	  #endif\n");
292 	fprintf(fd_th, "	  #ifndef L_BOUND\n");
293 	fprintf(fd_th, "		#define L_BOUND 	10 /* default */\n");
294 	fprintf(fd_th, "	  #endif\n");
295 	fprintf(fd_th, "	  extern int L_bound;\n");
296 	fprintf(fd_th, "	#endif\n");
297 	fprintf(fd_th, "	#if defined(BFS_DISK) && defined(BFS_STAGGER)\n");
298 	fprintf(fd_th, "		#error BFS_DISK and BFS_STAGGER are not compatible\n");
299 	fprintf(fd_th, "	#endif\n");
300 	fprintf(fd_th, "#endif\n\n");
301 
302 	fprintf(fd_th, "#if defined(BFS)\n");
303 	fprintf(fd_th, "	#ifndef SAFETY\n");
304 	fprintf(fd_th, "		#define SAFETY\n");
305 	fprintf(fd_th, "	#endif\n");
306 	fprintf(fd_th, "	#ifndef XUSAFE\n");
307 	fprintf(fd_th, "		#define XUSAFE\n");
308 	fprintf(fd_th, "	#endif\n");
309 	fprintf(fd_th, "#endif\n");
310 
311 	fprintf(fd_th, "#ifndef uchar\n");
312 	fprintf(fd_th, "	#define uchar	unsigned char\n");
313 	fprintf(fd_th, "#endif\n");
314 	fprintf(fd_th, "#ifndef uint\n");
315 	fprintf(fd_th, "	#define uint	unsigned int\n");
316 	fprintf(fd_th, "#endif\n");
317 
318 	if (separate == 1 && !claimproc)
319 	{	Symbol *n = (Symbol *) emalloc(sizeof(Symbol));
320 		Sequence *s = (Sequence *) emalloc(sizeof(Sequence));
321 		s->minel = -1;
322 		claimproc = n->name = "_:never_template:_";
323 		mk_rdy(n, ZN, s, 0, ZN, N_CLAIM);
324 	}
325 	if (separate == 2)
326 	{	if (has_remote)
327 		{	printf("spin: warning, make sure that the S1 model\n");
328 			printf("      includes the same remote references\n");
329 		}
330 		fprintf(fd_th, "#ifndef NFAIR\n");
331 		fprintf(fd_th, "#define NFAIR	2	/* must be >= 2 */\n");
332 		fprintf(fd_th, "#endif\n");
333 		if (has_last)
334 		fprintf(fd_th, "#define HAS_LAST	%d\n", has_last);
335 		if (has_priority && !old_priority_rules)
336 		fprintf(fd_th, "#define HAS_PRIORITY	%d\n", has_priority);
337 		goto doless;
338 	}
339 
340 	fprintf(fd_th, "#define DELTA	%d\n", DELTA);
341 	fprintf(fd_th, "#ifdef MA\n");
342 	fprintf(fd_th, "	#if NCORE>1 && !defined(SEP_STATE)\n");
343 	fprintf(fd_th, "		#define SEP_STATE\n");
344 	fprintf(fd_th, "	#endif\n");
345 	fprintf(fd_th, "	#if MA==1\n"); /* user typed -DMA without size */
346 	fprintf(fd_th, "		#undef MA\n");
347 	fprintf(fd_th, "		#define MA	100\n");
348 	fprintf(fd_th, "	#endif\n");
349 	fprintf(fd_th, "#endif\n");
350 	fprintf(fd_th, "#ifdef W_XPT\n");
351 	fprintf(fd_th, "	#if W_XPT==1\n"); /* user typed -DW_XPT without size */
352 	fprintf(fd_th, "		#undef W_XPT\n");
353 	fprintf(fd_th, "		#define W_XPT 1000000\n");
354 	fprintf(fd_th, "	#endif\n");
355 	fprintf(fd_th, "#endif\n");
356 	fprintf(fd_th, "#ifndef NFAIR\n");
357 	fprintf(fd_th, "	#define NFAIR	2	/* must be >= 2 */\n");
358 	fprintf(fd_th, "#endif\n");
359 	if (Ntimeouts)
360 	fprintf(fd_th, "#define NTIM	%d\n", Ntimeouts);
361 	if (Etimeouts)
362 	fprintf(fd_th, "#define ETIM	%d\n", Etimeouts);
363 	if (has_remvar)
364 	fprintf(fd_th, "#define REM_VARS	1\n");
365 	if (has_remote)
366 	fprintf(fd_th, "#define REM_REFS	%d\n", has_remote); /* not yet used */
367 	if (has_hidden)
368 	{	fprintf(fd_th, "#define HAS_HIDDEN	%d\n", has_hidden);
369 		fprintf(fd_th, "#if defined(BFS_PAR) || defined(BFS)\n");
370 		fprintf(fd_th, "	#error cannot use BFS on models with variables declared hidden\n");
371 		fprintf(fd_th, "#endif\n");
372 	}
373 	if (has_last)
374 	fprintf(fd_th, "#define HAS_LAST	%d\n", has_last);
375 	if (has_priority && !old_priority_rules)
376 	fprintf(fd_th, "#define HAS_PRIORITY	%d\n", has_priority);
377 	if (has_sorted)
378 	fprintf(fd_th, "#define HAS_SORTED	%d\n", has_sorted);
379 	if (m_loss)
380 	fprintf(fd_th, "#define M_LOSS\n");
381 	if (has_random)
382 	fprintf(fd_th, "#define HAS_RANDOM	%d\n", has_random);
383 	if (has_ltl)
384 	fprintf(fd_th, "#define HAS_LTL	1\n");
385 	fprintf(fd_th, "#define HAS_CODE	1\n");	/* could also be set to has_code */
386 		/* always defining it doesn't seem to cause measurable overhead though */
387 		/* and allows for pan -r etc to work for non-embedded code as well */
388 	fprintf(fd_th, "#if defined(RANDSTORE) && !defined(RANDSTOR)\n");
389 	fprintf(fd_th, "	#define RANDSTOR	RANDSTORE\n"); /* xspin uses RANDSTORE... */
390 	fprintf(fd_th, "#endif\n");
391 	if (has_stack)
392 	fprintf(fd_th, "#define HAS_STACK	%d\n", has_stack);
393 	if (has_enabled || (has_priority && !old_priority_rules))
394 	fprintf(fd_th, "#define HAS_ENABLED	1\n");
395 	if (has_unless)
396 	fprintf(fd_th, "#define HAS_UNLESS	%d\n", has_unless);
397 	if (has_provided)
398 	fprintf(fd_th, "#define HAS_PROVIDED	%d\n", has_provided);
399 	if (has_pcvalue)
400 	fprintf(fd_th, "#define HAS_PCVALUE	%d\n", has_pcvalue);
401 	if (has_badelse)
402 	fprintf(fd_th, "#define HAS_BADELSE	%d\n", has_badelse);
403 	if (has_enabled
404 	|| (has_priority && !old_priority_rules)
405 	||  has_pcvalue
406 	||  has_badelse
407 	||  has_last)
408 	{	fprintf(fd_th, "#ifndef NOREDUCE\n");
409 		fprintf(fd_th, "	#define NOREDUCE	1\n");
410 		fprintf(fd_th, "#endif\n");
411 	}
412 	if (has_np)
413 	fprintf(fd_th, "#define HAS_NP	%d\n", has_np);
414 	if (merger)
415 	fprintf(fd_th, "#define MERGED	1\n");
416 
417 doless:
418 	fprintf(fd_th, "#if !defined(HAS_LAST) && defined(BCS)\n");
419 	fprintf(fd_th, "	#define HAS_LAST	1 /* use it, but */\n");
420 	fprintf(fd_th, "	#ifndef STORE_LAST\n"); /* unless the user insists */
421 	fprintf(fd_th, "		#define NO_LAST	1 /* dont store it */\n");
422 	fprintf(fd_th, "	#endif\n");
423 	fprintf(fd_th, "#endif\n");
424 
425 	fprintf(fd_th, "#if defined(BCS) && defined(BITSTATE)\n");
426 	fprintf(fd_th, "	#ifndef NO_CTX\n");
427 	fprintf(fd_th, "		#define STORE_CTX	1\n");
428 	fprintf(fd_th, "	#endif\n");
429 	fprintf(fd_th, "#endif\n");
430 
431 	fprintf(fd_th, "#ifdef NP\n");
432 	if (!has_np)
433 	fprintf(fd_th, "	#define HAS_NP	2\n");
434 	fprintf(fd_th, "	#define VERI	%d	/* np_ */\n",	nrRdy);
435 	fprintf(fd_th, "#endif\n");
436 
437 	fprintf(fd_th, "#if defined(NOCLAIM) && defined(NP)\n");
438 	fprintf(fd_th, "	#undef NOCLAIM\n");
439 	fprintf(fd_th, "#endif\n");
440 	if (claimproc)
441 	{	claimnr = fproc(claimproc);	/* the default claim */
442 		fprintf(fd_th, "#ifndef NOCLAIM\n");
443 		fprintf(fd_th, "	#define NCLAIMS	%d\n", nclaims);
444 		fprintf(fd_th, "	#ifndef NP\n");
445 		fprintf(fd_th, "		#define VERI	%d\n", claimnr);
446 		fprintf(fd_th, "	#endif\n");
447 		fprintf(fd_th, "#endif\n");
448 	}
449 	if (eventmap)
450 	{	eventmapnr = fproc(eventmap);
451 		fprintf(fd_th, "#define EVENT_TRACE	%d\n",	eventmapnr);
452 		fprintf(fd_th, "#define endevent	_endstate%d\n",	eventmapnr);
453 		if (eventmap[2] == 'o')	/* ":notrace:" */
454 		fprintf(fd_th, "#define NEGATED_TRACE	1\n");
455 	}
456 
457 	fprintf(fd_th, "\ntypedef struct S_F_MAP {\n");
458 	fprintf(fd_th, "	char *fnm;\n\tint from;\n\tint upto;\n");
459 	fprintf(fd_th, "} S_F_MAP;\n");
460 
461 	fprintf(fd_tc, "/*** Generated by %s ***/\n", SpinVersion);
462 	fprintf(fd_tc, "/*** From source: %s ***/\n\n", oFname->name);
463 
464 	ntimes(fd_tc, 0, 1, Pre0);
465 
466 	plunk_c_decls(fd_tc);	/* types can be refered to in State */
467 
468 	switch (separate) {
469 	case 0:	fprintf(fd_tc, "#include \"pan.h\"\n"); break;
470 	case 1:	fprintf(fd_tc, "#include \"pan_s.h\"\n"); break;
471 	case 2:	fprintf(fd_tc, "#include \"pan_t.h\"\n"); break;
472 	}
473 
474 	if (separate != 2)
475 	{	fprintf(fd_tc, "char *TrailFile = PanSource; /* default */\n");
476 		fprintf(fd_tc, "char *trailfilename;\n");
477 	}
478 
479 	fprintf(fd_tc, "#ifdef LOOPSTATE\n");
480 	fprintf(fd_tc, "double cnt_loops;\n");
481 	fprintf(fd_tc, "#endif\n");
482 
483 	fprintf(fd_tc, "State	A_Root;	/* seed-state for cycles */\n");
484 	fprintf(fd_tc, "State	now;	/* the full state-vector */\n");
485 	fprintf(fd_tc, "#if NQS > 0\n");
486 	fprintf(fd_tc, "short q_flds[NQS+1];\n");
487 	fprintf(fd_tc, "short q_max[NQS+1];\n");
488 	fprintf(fd_tc, "#endif\n");
489 
490 	plunk_c_fcts(fd_tc);	/* State can be used in fcts */
491 
492 	if (separate != 2)
493 	{	ntimes(fd_tc, 0, 1, Preamble);
494 		ntimes(fd_tc, 0, 1, Separate); /* things that moved out of pan.h */
495 	} else
496 	{	fprintf(fd_tc, "extern int verbose;\n");
497 		fprintf(fd_tc, "extern long depth, depthfound;\n");
498 	}
499 
500 	fprintf(fd_tc, "#ifndef NOBOUNDCHECK\n");
501 	fprintf(fd_tc, "	#define Index(x, y)\tBoundcheck(x, y, II, tt, t)\n");
502 	fprintf(fd_tc, "#else\n");
503 	fprintf(fd_tc, "	#define Index(x, y)\tx\n");
504 	fprintf(fd_tc, "#endif\n");
505 
506 	c_preview();	/* sets hastrack */
507 
508 	for (p = ready; p; p = p->nxt)
509 		mstp = max(p->s->maxel, mstp);
510 
511 	if (separate != 2)
512 	{	fprintf(fd_tt, "#ifdef PEG\n");
513 		fprintf(fd_tt, "struct T_SRC {\n");
514 		fprintf(fd_tt, "	char *fl; int ln;\n");
515 		fprintf(fd_tt, "} T_SRC[NTRANS];\n\n");
516 		fprintf(fd_tt, "void\ntr_2_src(int m, char *file, int ln)\n");
517 		fprintf(fd_tt, "{	T_SRC[m].fl = file;\n");
518 		fprintf(fd_tt, "	T_SRC[m].ln = ln;\n");
519 		fprintf(fd_tt, "}\n\n");
520 		fprintf(fd_tt, "void\nputpeg(int n, int m)\n");
521 		fprintf(fd_tt, "{	printf(\"%%5d\ttrans %%4d \", m, n);\n");
522 		fprintf(fd_tt, "	printf(\"%%s:%%d\\n\",\n");
523 		fprintf(fd_tt, "		T_SRC[n].fl, T_SRC[n].ln);\n");
524 		fprintf(fd_tt, "}\n");
525 		if (!merger)
526 		{	fprintf(fd_tt, "#else\n");
527 			fprintf(fd_tt, "#define tr_2_src(m,f,l)\n");
528 		}
529 		fprintf(fd_tt, "#endif\n\n");
530 		fprintf(fd_tt, "void\nsettable(void)\n{\tTrans *T;\n");
531 		fprintf(fd_tt, "\tTrans *settr(int, int, int, int, int,");
532 		fprintf(fd_tt, " char *, int, int, int);\n\n");
533 		fprintf(fd_tt, "\ttrans = (Trans ***) ");
534 		fprintf(fd_tt, "emalloc(%d*sizeof(Trans **));\n", nrRdy+1);
535 				/* +1 for np_ automaton */
536 
537 		if (separate == 1)
538 		{
539 		fprintf(fd_tm, "	if (II == 0)\n");
540 		fprintf(fd_tm, "	{ _m = step_claim(trpt->o_pm, trpt->tau, tt, ot, t);\n");
541 		fprintf(fd_tm, "	  if (_m) goto P999; else continue;\n");
542 		fprintf(fd_tm, "	} else\n");
543 		}
544 
545 		fprintf(fd_tm, "#define rand	pan_rand\n");
546 		fprintf(fd_tm, "#define pthread_equal(a,b)	((a)==(b))\n");
547 		fprintf(fd_tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n");
548 		fprintf(fd_tm, "	#ifdef BFS_PAR\n");
549 		fprintf(fd_tm, "		bfs_printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n");
550 		fprintf(fd_tm, "	#else\n");
551 		fprintf(fd_tm, "		cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\n");
552 		fprintf(fd_tm, "	#endif\n");
553 		fprintf(fd_tm, "#endif\n");
554 		fprintf(fd_tm, "	switch (t->forw) {\n");
555 	} else
556 	{	fprintf(fd_tt, "#ifndef PEG\n");
557 		fprintf(fd_tt, "	#define tr_2_src(m,f,l)\n");
558 		fprintf(fd_tt, "#endif\n");
559 		fprintf(fd_tt, "void\nset_claim(void)\n{\tTrans *T;\n");
560 		fprintf(fd_tt, "\textern Trans ***trans;\n");
561 		fprintf(fd_tt, "\textern Trans *settr(int, int, int, int, int,");
562 		fprintf(fd_tt, " char *, int, int, int);\n\n");
563 
564 		fprintf(fd_tm, "#define rand	pan_rand\n");
565 		fprintf(fd_tm, "#define pthread_equal(a,b)	((a)==(b))\n");
566 		fprintf(fd_tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n");
567 		fprintf(fd_tm, "	cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, forw);\n");
568 		fprintf(fd_tm, "#endif\n");
569 		fprintf(fd_tm, "	switch (forw) {\n");
570 	}
571 
572 	fprintf(fd_tm, "	default: Uerror(\"bad forward move\");\n");
573 	fprintf(fd_tm, "	case 0:	/* if without executable clauses */\n");
574 	fprintf(fd_tm, "		continue;\n");
575 	fprintf(fd_tm, "	case 1: /* generic 'goto' or 'skip' */\n");
576 	if (separate != 2)
577 		fprintf(fd_tm, "		IfNotBlocked\n");
578 	fprintf(fd_tm, "		_m = 3; goto P999;\n");
579 	fprintf(fd_tm, "	case 2: /* generic 'else' */\n");
580 	if (separate == 2)
581 		fprintf(fd_tm, "		if (o_pm&1) continue;\n");
582 	else
583 	{	fprintf(fd_tm, "		IfNotBlocked\n");
584 		fprintf(fd_tm, "		if (trpt->o_pm&1) continue;\n");
585 	}
586 	fprintf(fd_tm, "		_m = 3; goto P999;\n");
587 	uniq = 3;
588 
589 	if (separate == 1)
590 		fprintf(fd_tb, "	if (II == 0) goto R999;\n");
591 
592 	fprintf(fd_tb, "	switch (t->back) {\n");
593 	fprintf(fd_tb, "	default: Uerror(\"bad return move\");\n");
594 	fprintf(fd_tb, "	case  0: goto R999; /* nothing to undo */\n");
595 
596 	for (p = ready; p; p = p->nxt)
597 	{	putproc(p);
598 	}
599 
600 	if (separate != 2)
601 	{	fprintf(fd_th, "\n");
602 		for (p = ready; p; p = p->nxt)
603 			fprintf(fd_th, "extern short src_ln%d[];\n", p->tn);
604 		for (p = ready; p; p = p->nxt)
605 			fprintf(fd_th, "extern S_F_MAP src_file%d[];\n", p->tn);
606 		fprintf(fd_th, "\n");
607 
608 		fprintf(fd_tc, "uchar reached%d[3];  /* np_ */\n", nrRdy);
609 		fprintf(fd_tc, "uchar *loopstate%d;  /* np_ */\n", nrRdy);
610 
611 		fprintf(fd_tc, "struct {\n");
612 		fprintf(fd_tc, "	int tp; short *src;\n");
613 		fprintf(fd_tc, "} src_all[] = {\n");
614 		for (p = ready; p; p = p->nxt)
615 			fprintf(fd_tc, "	{ %d, &src_ln%d[0] },\n",
616 				p->tn, p->tn);
617 		fprintf(fd_tc, "	{ 0, (short *) 0 }\n");
618 		fprintf(fd_tc, "};\n");
619 
620 		fprintf(fd_tc, "S_F_MAP *flref[] = {\n");	/* 5.3.0 */
621 		for (p = ready; p; p = p->nxt)
622 		{	fprintf(fd_tc, "	src_file%d%c\n", p->tn, p->nxt?',':' ');
623 		}
624 		fprintf(fd_tc, "};\n\n");
625 	} else
626 	{	fprintf(fd_tc, "extern uchar reached%d[3];  /* np_ */\n", nrRdy);
627 	}
628 
629 	gencodetable(fd_tc);	/* was th */
630 
631 	if (Unique < (1 << (8*sizeof(unsigned char)) ))	/* was uniq before */
632 	{	fprintf(fd_th, "#define T_ID	unsigned char\n");
633 	} else if (Unique < (1 << (8*sizeof(unsigned short)) ))
634 	{	fprintf(fd_th, "#define T_ID	unsigned short\n");
635 	} else
636 	{	fprintf(fd_th, "#define T_ID	unsigned int\n");
637 	}
638 
639 	if (separate != 1)
640 	{	tm_predef_np();
641 		tt_predef_np();
642 	}
643 	fprintf(fd_tt, "}\n\n");	/* end of settable() */
644 
645 	fprintf(fd_tm, "#undef rand\n");
646 	fprintf(fd_tm, "	}\n\n");
647 	fprintf(fd_tb, "	}\n\n");
648 
649 	if (separate != 2)
650 	{	ntimes(fd_tt, 0, 1, Tail);
651 		genheader();
652 		if (separate == 1)
653 		{	fprintf(fd_th, "#define FORWARD_MOVES\t\"pan_s.m\"\n");
654 			fprintf(fd_th, "#define BACKWARD_MOVES\t\"pan_s.b\"\n");
655 			fprintf(fd_th, "#define SEPARATE\n");
656 			fprintf(fd_th, "#define TRANSITIONS\t\"pan_s.t\"\n");
657 			fprintf(fd_th, "extern void ini_claim(int, int);\n");
658 		} else
659 		{	fprintf(fd_th, "#define FORWARD_MOVES\t\"pan.m\"\n");
660 			fprintf(fd_th, "#define BACKWARD_MOVES\t\"pan.b\"\n");
661 			fprintf(fd_th, "#define TRANSITIONS\t\"pan.t\"\n");
662 		}
663 		genaddproc();
664 		genother();
665 		genaddqueue();
666 		genunio();
667 		genconditionals();
668 		gensvmap();
669 		if (!run_lst) fatal("no runable process", (char *)0);
670 		fprintf(fd_tc, "void\n");
671 		fprintf(fd_tc, "active_procs(void)\n{\n");
672 
673 		fprintf(fd_tc, "	if (reversing == 0) {\n");
674 			reverse_procs(run_lst);
675 		fprintf(fd_tc, "	} else {\n");
676 			forward_procs(run_lst);
677 		fprintf(fd_tc, "	}\n");
678 
679 		fprintf(fd_tc, "}\n");
680 		ntimes(fd_tc, 0, 1, Dfa);
681 		ntimes(fd_tc, 0, 1, Xpt);
682 
683 		fprintf(fd_th, "#define NTRANS	%d\n", uniq);
684 		if (u_sync && !u_async)
685 		{	spit_recvs(fd_th, fd_tc);
686 		}
687 	} else
688 	{	genheader();
689 		fprintf(fd_th, "#define FORWARD_MOVES\t\"pan_t.m\"\n");
690 		fprintf(fd_th, "#define BACKWARD_MOVES\t\"pan_t.b\"\n");
691 		fprintf(fd_th, "#define TRANSITIONS\t\"pan_t.t\"\n");
692 		fprintf(fd_tc, "extern int Maxbody;\n");
693 		fprintf(fd_tc, "#if VECTORSZ>32000\n");
694 		fprintf(fd_tc, "	extern int *proc_offset;\n");
695 		fprintf(fd_tc, "#else\n");
696 		fprintf(fd_tc, "	extern short *proc_offset;\n");
697 		fprintf(fd_tc, "#endif\n");
698 		fprintf(fd_tc, "extern uchar *proc_skip;\n");
699 		fprintf(fd_tc, "extern uchar *reached[];\n");
700 		fprintf(fd_tc, "extern uchar *accpstate[];\n");
701 		fprintf(fd_tc, "extern uchar *progstate[];\n");
702 		fprintf(fd_tc, "extern uchar *loopstate[];\n");
703 		fprintf(fd_tc, "extern uchar *stopstate[];\n");
704 		fprintf(fd_tc, "extern uchar *visstate[];\n\n");
705 		fprintf(fd_tc, "extern short *mapstate[];\n");
706 
707 		fprintf(fd_tc, "void\nini_claim(int n, int h)\n{");
708 		fprintf(fd_tc, "\textern State now;\n");
709 		fprintf(fd_tc, "\textern void set_claim(void);\n\n");
710 		fprintf(fd_tc, "#ifdef PROV\n");
711 		fprintf(fd_tc, "	#include PROV\n");
712 		fprintf(fd_tc, "#endif\n");
713 		fprintf(fd_tc, "\tset_claim();\n");
714 		genother();
715 		fprintf(fd_tc, "\n\tswitch (n) {\n");
716 		genaddproc();
717 		fprintf(fd_tc, "\t}\n");
718 		fprintf(fd_tc, "\n}\n");
719 		fprintf(fd_tc, "int\nstep_claim(int o_pm, int tau, int tt, int ot, Trans *t)\n");
720 		fprintf(fd_tc, "{	int forw = t->forw; int _m = 0; extern char *noptr; int II=0;\n");
721 		fprintf(fd_tc, "	extern State now;\n");
722 		fprintf(fd_tc, "#define continue	return 0\n");
723 		fprintf(fd_tc, "#include \"pan_t.m\"\n");
724 		fprintf(fd_tc, "P999:\n\treturn _m;\n}\n");
725 		fprintf(fd_tc, "#undef continue\n");
726 		fprintf(fd_tc, "int\nrev_claim(int backw)\n{ return 0; }\n");
727 		fprintf(fd_tc, "#include TRANSITIONS\n");
728 	}
729 
730 	if (separate != 2)
731 	{	c_wrapper(fd_tc);
732 		c_chandump(fd_tc);
733 	}
734 
735 	fprintf(fd_th, "#if defined(BFS_PAR) || NCORE>1\n");
736 	fprintf(fd_th, "	void e_critical(int);\n");
737 	fprintf(fd_th, "	void x_critical(int);\n");
738 	fprintf(fd_th, "	#ifdef BFS_PAR\n");
739 	fprintf(fd_th, "		void bfs_main(int, int);\n");
740 	fprintf(fd_th, "		void bfs_report_mem(void);\n");
741 	fprintf(fd_th, "	#endif\n");
742 	fprintf(fd_th, "#endif\n");
743 
744 	fprintf(fd_th, "\n\n/* end of PAN_H */\n#endif\n");
745 	fclose(fd_th);
746 	fclose(fd_tt);
747 	fclose(fd_tm);
748 	fclose(fd_tb);
749 
750 	if (!(fd_th = fopen("pan.p", MFLAGS)))
751 	{	printf("spin: cannot create pan.p for -DBFS_PAR\n");
752 		return; 	/* we're done anyway */
753 	}
754 
755 	ntimes(fd_th, 0, 1, pan_par);	/* BFS_PAR */
756 	fclose(fd_th);
757 
758 	fprintf(fd_tc, "\nTrans *t_id_lkup[%d];\n\n", globmax+1);
759 
760 	if (separate != 2)
761 	{	fprintf(fd_tc, "\n#ifdef BFS_PAR\n\t#include \"pan.p\"\n#endif\n");
762 	}
763 	fprintf(fd_tc, "\n/* end of pan.c */\n");
764 	fclose(fd_tc);
765 }
766 
767 static int
find_id(Symbol * s)768 find_id(Symbol *s)
769 {	ProcList *p;
770 
771 	if (s)
772 	for (p = ready; p; p = p->nxt)
773 		if (s == p->n)
774 			return p->tn;
775 	return 0;
776 }
777 
778 static void
dolen(Symbol * s,char * pre,int pid,int ai,int qln)779 dolen(Symbol *s, char *pre, int pid, int ai, int qln)
780 {
781 	if (ai > 0)
782 		fprintf(fd_tc, "\n\t\t\t ||    ");
783 	fprintf(fd_tc, "%s(", pre);
784 	if (!(s->hidden&1))
785 	{	if (s->context)
786 			fprintf(fd_tc, "(int) ( ((P%d *)_this)->", pid);
787 		else
788 			fprintf(fd_tc, "(int) ( now.");
789 	}
790 	fprintf(fd_tc, "%s", s->name);
791 	if (qln > 1 || s->isarray) fprintf(fd_tc, "[%d]", ai);
792 	fprintf(fd_tc, ") )");
793 }
794 
795 struct AA {	char TT[9];	char CC[8]; };
796 
797 static struct AA BB[4] = {
798 	{ "Q_FULL_F",	" q_full" },
799 	{ "Q_FULL_T",	"!q_full" },
800 	{ "Q_EMPT_F",	" !q_len" },
801 	{ "Q_EMPT_T",	"  q_len" }
802 	};
803 
804 static struct AA DD[4] = {
805 	{ "Q_FULL_F",	" q_e_f" },	/* empty or full */
806 	{ "Q_FULL_T",	"!q_full" },
807 	{ "Q_EMPT_F",	" q_e_f" },
808 	{ "Q_EMPT_T",	" q_len" }
809 	};
810 	/* this reduces the number of cases where 's' and 'r'
811 	   are considered conditionally safe under the
812 	   partial order reduction rules;  as a price for
813 	   this simple implementation, it also affects the
814 	   cases where nfull and nempty can be considered
815 	   safe -- since these are labeled the same way as
816 	   's' and 'r' respectively
817 	   it only affects reduction, not functionality
818 	 */
819 
820 void
bb_or_dd(int j,int which)821 bb_or_dd(int j, int which)
822 {
823 	if (which)
824 	{	if (has_unless)
825 			fprintf(fd_tc, "%s", DD[j].CC);
826 		else
827 			fprintf(fd_tc, "%s", BB[j].CC);
828 	} else
829 	{	if (has_unless)
830 			fprintf(fd_tc, "%s", DD[j].TT);
831 		else
832 			fprintf(fd_tc, "%s", BB[j].TT);
833 	}
834 }
835 
836 void
Done_case(char * nm,Symbol * z)837 Done_case(char *nm, Symbol *z)
838 {	int j, k;
839 	int nid = z->Nid;
840 	int qln = z->nel;
841 
842 	fprintf(fd_tc, "\t\tcase %d: if (", nid);
843 	for (j = 0; j < 4; j++)
844 	{	fprintf(fd_tc, "\t(t->ty[i] == ");
845 		bb_or_dd(j, 0);
846 		fprintf(fd_tc, " && (");
847 		for (k = 0; k < qln; k++)
848 		{	if (k > 0)
849 				fprintf(fd_tc, "\n\t\t\t ||    ");
850 			bb_or_dd(j, 1);
851 			fprintf(fd_tc, "(%s%s", nm, z->name);
852 			if (qln > 1)
853 				fprintf(fd_tc, "[%d]", k);
854 			fprintf(fd_tc, ")");
855 		}
856 		fprintf(fd_tc, "))\n\t\t\t ");
857 		if (j < 3)
858 			fprintf(fd_tc, "|| ");
859 		else
860 			fprintf(fd_tc, "   ");
861 	}
862 	fprintf(fd_tc, ") return 0; break;\n");
863 }
864 
865 static void
Docase(Symbol * s,int pid,int nid)866 Docase(Symbol *s, int pid, int nid)
867 {	int i, j;
868 
869 	fprintf(fd_tc, "\t\tcase %d: if (", nid);
870 	for (j = 0; j < 4; j++)
871 	{	fprintf(fd_tc, "\t(t->ty[i] == ");
872 		bb_or_dd(j, 0);
873 		fprintf(fd_tc, " && (");
874 		if (has_unless)
875 		{	for (i = 0; i < s->nel; i++)
876 				dolen(s, DD[j].CC, pid, i, s->nel);
877 		} else
878 		{	for (i = 0; i < s->nel; i++)
879 				dolen(s, BB[j].CC, pid, i, s->nel);
880 		}
881 		fprintf(fd_tc, "))\n\t\t\t ");
882 		if (j < 3)
883 			fprintf(fd_tc, "|| ");
884 		else
885 			fprintf(fd_tc, "   ");
886 	}
887 	fprintf(fd_tc, ") return 0; break;\n");
888 }
889 
890 static void
genconditionals(void)891 genconditionals(void)
892 {	Symbol *s;
893 	int last=0, j;
894 	extern Ordered	*all_names;
895 	Ordered *walk;
896 
897 	fprintf(fd_th, "#define LOCAL	1\n");
898 	fprintf(fd_th, "#define Q_FULL_F	2\n");
899 	fprintf(fd_th, "#define Q_EMPT_F	3\n");
900 	fprintf(fd_th, "#define Q_EMPT_T	4\n");
901 	fprintf(fd_th, "#define Q_FULL_T	5\n");
902 	fprintf(fd_th, "#define TIMEOUT_F	6\n");
903 	fprintf(fd_th, "#define GLOBAL	7\n");
904 	fprintf(fd_th, "#define BAD	8\n");
905 	fprintf(fd_th, "#define ALPHA_F	9\n");
906 
907 	fprintf(fd_tc, "int\n");
908 	fprintf(fd_tc, "q_cond(short II, Trans *t)\n");
909 	fprintf(fd_tc, "{	int i = 0;\n");
910 	fprintf(fd_tc, "	for (i = 0; i < 6; i++)\n");
911 	fprintf(fd_tc, "	{	if (t->ty[i] == TIMEOUT_F) return %s;\n",
912 					(Etimeouts)?"(!(trpt->tau&1))":"1");
913 	fprintf(fd_tc, "		if (t->ty[i] == ALPHA_F)\n");
914 	fprintf(fd_tc, "#ifdef GLOB_ALPHA\n");
915 	fprintf(fd_tc, "			return 0;\n");
916 	fprintf(fd_tc, "#else\n\t\t\treturn ");
917 	fprintf(fd_tc, "(II+1 == (short) now._nr_pr && II+1 < MAXPROC);\n");
918 	fprintf(fd_tc, "#endif\n");
919 
920 	/* we switch on the chan name from the spec (as identified by
921 	 * the corresponding Nid number) rather than the actual qid
922 	 * because we cannot predict at compile time which specific qid
923 	 * will be accessed by the statement at runtime.  that is:
924 	 * we do not know which qid to pass to q_cond at runtime
925 	 * but we do know which name is used.  if it's a chan array, we
926 	 * must check all elements of the array for compliance (bummer)
927 	 */
928 	fprintf(fd_tc, "		switch (t->qu[i]) {\n");
929 	fprintf(fd_tc, "		case 0: break;\n");
930 
931 	for (walk = all_names; walk; walk = walk->next)
932 	{	s = walk->entry;
933 		if (s->owner) continue;
934 		j = find_id(s->context);
935 		if (s->type == CHAN)
936 		{	if (last == s->Nid) continue;	/* chan array */
937 			last = s->Nid;
938 			Docase(s, j, last);
939 		} else if (s->type == STRUCT)
940 		{	/* struct may contain a chan */
941 			char pregat[128];
942 			strcpy(pregat, "");
943 			if (!(s->hidden&1))
944 			{	if (s->context)
945 					sprintf(pregat, "((P%d *)_this)->",j);
946 				else
947 					sprintf(pregat, "now.");
948 			}
949 			walk2_struct(pregat, s);
950 		}
951 	}
952 	fprintf(fd_tc, "	\tdefault: Uerror(\"unknown qid - q_cond\");\n");
953 	fprintf(fd_tc, "	\t\t\treturn 0;\n");
954 	fprintf(fd_tc, "	\t}\n");
955 	fprintf(fd_tc, "	}\n");
956 	fprintf(fd_tc, "	return 1;\n");
957 	fprintf(fd_tc, "}\n");
958 }
959 
960 static void
putproc(ProcList * p)961 putproc(ProcList *p)
962 {	Pid_nr = p->tn;
963 	Det = p->det;
964 
965 	if (pid_is_claim(Pid_nr)
966 	&&  separate == 1)
967 	{	fprintf(fd_th, "extern uchar reached%d[];\n", Pid_nr);
968 #if 0
969 		fprintf(fd_th, "extern short _nstates%d;\n", Pid_nr);
970 #else
971 		fprintf(fd_th, "\n#define _nstates%d	%d\t/* %s */\n",
972 			Pid_nr, p->s->maxel, p->n->name);
973 #endif
974 		fprintf(fd_th, "extern short src_ln%d[];\n", Pid_nr);
975 		fprintf(fd_th, "extern uchar *loopstate%d;\n", Pid_nr);
976 		fprintf(fd_th, "extern S_F_MAP src_file%d[];\n", Pid_nr);
977 		fprintf(fd_th, "#define _endstate%d	%d\n",
978 			Pid_nr, p->s->last?p->s->last->seqno:0);
979 		return;
980 	}
981 	if (!pid_is_claim(Pid_nr)
982 	&&  separate == 2)
983 	{	fprintf(fd_th, "extern short src_ln%d[];\n", Pid_nr);
984 		fprintf(fd_th, "extern uchar *loopstate%d;\n", Pid_nr);
985 		return;
986 	}
987 
988 	AllGlobal = (p->prov)?1:0;	/* process has provided clause */
989 
990 	fprintf(fd_th, "\n#define _nstates%d	%d\t/* %s */\n",
991 		Pid_nr, p->s->maxel, p->n->name);
992 /* new */
993 	fprintf(fd_th, "#define minseq%d	%d\n", Pid_nr, find_min(p->s));
994 	fprintf(fd_th, "#define maxseq%d	%d\n", Pid_nr, find_max(p->s));
995 
996 /* end */
997 
998 	if (Pid_nr == eventmapnr)
999 	fprintf(fd_th, "#define nstates_event	_nstates%d\n", Pid_nr);
1000 
1001 	fprintf(fd_th, "#define _endstate%d	%d\n", Pid_nr, p->s->last?p->s->last->seqno:0);
1002 
1003 	if (p->b == N_CLAIM || p->b == E_TRACE || p->b == N_TRACE)
1004 	{	fprintf(fd_tm, "\n		 /* CLAIM %s */\n", p->n->name);
1005 		fprintf(fd_tb, "\n		 /* CLAIM %s */\n", p->n->name);
1006 	}
1007 	else
1008 	{	fprintf(fd_tm, "\n		 /* PROC %s */\n", p->n->name);
1009 		fprintf(fd_tb, "\n		 /* PROC %s */\n", p->n->name);
1010 	}
1011 	fprintf(fd_tt, "\n	/* proctype %d: %s */\n", Pid_nr, p->n->name);
1012 	fprintf(fd_tt, "\n	trans[%d] = (Trans **)", Pid_nr);
1013 	fprintf(fd_tt, " emalloc(%d*sizeof(Trans *));\n\n", p->s->maxel);
1014 
1015 	if (Pid_nr == eventmapnr)
1016 	{	fprintf(fd_th, "\n#define in_s_scope(x_y3_)	0");
1017 		fprintf(fd_tc, "\n#define in_r_scope(x_y3_)	0");
1018 	}
1019 	put_seq(p->s, 2, 0);
1020 	if (Pid_nr == eventmapnr)
1021 	{	fprintf(fd_th, "\n\n");
1022 		fprintf(fd_tc, "\n\n");
1023 	}
1024 	dumpsrc(p->s->maxel, Pid_nr);
1025 }
1026 
1027 static void
addTpe(int x)1028 addTpe(int x)
1029 {	int i;
1030 
1031 	if (x <= 2) return;
1032 
1033 	for (i = 0; i < T_sum; i++)
1034 		if (TPE[i] == x)
1035 			return;
1036 	TPE[(T_sum++)%2] = x;
1037 }
1038 
1039 static void
cnt_seq(Sequence * s)1040 cnt_seq(Sequence *s)
1041 {	Element *f;
1042 	SeqList *h;
1043 
1044 	if (s)
1045 	for (f = s->frst; f; f = f->nxt)
1046 	{	Tpe(f->n);	/* sets EPT */
1047 		addTpe(EPT[0]);
1048 		addTpe(EPT[1]);
1049 		for (h = f->sub; h; h = h->nxt)
1050 			cnt_seq(h->this);
1051 		if (f == s->last)
1052 			break;
1053 	}
1054 }
1055 
1056 static void
typ_seq(Sequence * s)1057 typ_seq(Sequence *s)
1058 {
1059 	T_sum = 0;
1060 	TPE[0] = 2; TPE[1] = 0;
1061 	cnt_seq(s);
1062 	if (T_sum > 2)		/* more than one type */
1063 	{	TPE[0] = 5*DELTA;	/* non-mixing */
1064 		TPE[1] = 0;
1065 	}
1066 }
1067 
1068 static int
hidden(Lextok * n)1069 hidden(Lextok *n)
1070 {
1071 	if (n)
1072 	switch (n->ntyp) {
1073 	case  FULL: case  EMPTY:
1074 	case NFULL: case NEMPTY: case TIMEOUT:
1075 		Nn[(T_mus++)%2] = n;
1076 		break;
1077 	case '!': case UMIN: case '~': case ASSERT: case 'c':
1078 		(void) hidden(n->lft);
1079 		break;
1080 	case '/': case '*': case '-': case '+':
1081 	case '%': case LT:  case GT: case '&': case '^':
1082 	case '|': case LE:  case GE:  case NE: case '?':
1083 	case EQ:  case OR:  case AND: case LSHIFT: case RSHIFT:
1084 		(void) hidden(n->lft);
1085 		(void) hidden(n->rgt);
1086 		break;
1087 	}
1088 	return T_mus;
1089 }
1090 
1091 static int
getNid(Lextok * n)1092 getNid(Lextok *n)
1093 {
1094 	if (n->sym
1095 	&&  n->sym->type == STRUCT
1096 	&&  n->rgt && n->rgt->lft)
1097 		return getNid(n->rgt->lft);
1098 
1099 	if (!n->sym || n->sym->Nid == 0)
1100 	{	fatal("bad channel name '%s'",
1101 		(n->sym)?n->sym->name:"no name");
1102 	}
1103 	return n->sym->Nid;
1104 }
1105 
1106 static int
valTpe(Lextok * n)1107 valTpe(Lextok *n)
1108 {	int res = 2;
1109 	/*
1110 	2 = local
1111 	2+1	    .. 2+1*DELTA = nfull,  's'	- require q_full==false
1112 	2+1+1*DELTA .. 2+2*DELTA = nempty, 'r'	- require q_len!=0
1113 	2+1+2*DELTA .. 2+3*DELTA = empty	- require q_len==0
1114 	2+1+3*DELTA .. 2+4*DELTA = full		- require q_full==true
1115 	5*DELTA = non-mixing (i.e., always makes the selection global)
1116 	6*DELTA = timeout (conditionally safe)
1117 	7*DELTA = @, process deletion (conditionally safe)
1118 	 */
1119 	switch (n->ntyp) { /* a series of fall-thru cases: */
1120 	case   FULL:	res += DELTA;		/* add 3*DELTA + chan nr */
1121 	case  EMPTY:	res += DELTA;		/* add 2*DELTA + chan nr */
1122 	case    'r':
1123 	case NEMPTY:	res += DELTA;		/* add 1*DELTA + chan nr */
1124 	case    's':
1125 	case  NFULL:	res += getNid(n->lft);	/* add channel nr */
1126 			break;
1127 
1128 	case TIMEOUT:	res = 6*DELTA; break;
1129 	case '@':	res = 7*DELTA; break;
1130 	default:	break;
1131 	}
1132 	return res;
1133 }
1134 
1135 static void
Tpe(Lextok * n)1136 Tpe(Lextok *n)	/* mixing in selections */
1137 {
1138 	EPT[0] = 2; EPT[1] = 0;
1139 
1140 	if (!n) return;
1141 
1142 	T_mus = 0;
1143 	Nn[0] = Nn[1] = ZN;
1144 
1145 	if (n->ntyp == 'c')
1146 	{	if (hidden(n->lft) > 2)
1147 		{	EPT[0] = 5*DELTA; /* non-mixing */
1148 			EPT[1] = 0;
1149 			return;
1150 		}
1151 	} else
1152 		Nn[0] = n;
1153 
1154 	if (Nn[0]) EPT[0] = valTpe(Nn[0]);
1155 	if (Nn[1]) EPT[1] = valTpe(Nn[1]);
1156 }
1157 
1158 static void
put_escp(Element * e)1159 put_escp(Element *e)
1160 {	int n;
1161 	SeqList *x;
1162 
1163 	if (e->esc /* && e->n->ntyp != GOTO */ && e->n->ntyp != '.')
1164 	{	for (x = e->esc, n = 0; x; x = x->nxt, n++)
1165 		{	int i = huntele(x->this->frst, e->status, -1)->seqno;
1166 			fprintf(fd_tt, "\ttrans[%d][%d]->escp[%d] = %d;\n",
1167 				Pid_nr, e->seqno, n, i);
1168 			fprintf(fd_tt, "\treached%d[%d] = 1;\n",
1169 				Pid_nr, i);
1170 		}
1171 		for (x = e->esc, n=0; x; x = x->nxt, n++)
1172 		{	fprintf(fd_tt, "	/* escape #%d: %d */\n", n,
1173 				huntele(x->this->frst, e->status, -1)->seqno);
1174 			put_seq(x->this, 2, 0);	/* args?? */
1175 		}
1176 		fprintf(fd_tt, "	/* end-escapes */\n");
1177 	}
1178 }
1179 
1180 static void
put_sub(Element * e,int Tt0,int Tt1)1181 put_sub(Element *e, int Tt0, int Tt1)
1182 {	Sequence *s = e->n->sl->this;
1183 	Element *g = ZE;
1184 	int a;
1185 
1186 	patch_atomic(s);
1187 	putskip(s->frst->seqno);
1188 	g = huntstart(s->frst);
1189 	a = g->seqno;
1190 
1191 	if (0) printf("put_sub %d -> %d -> %d\n", e->seqno, s->frst->seqno, a);
1192 
1193 	if ((e->n->ntyp == ATOMIC
1194 	||  e->n->ntyp == D_STEP)
1195 	&&  scan_seq(s))
1196 		mark_seq(s);
1197 	s->last->nxt = e->nxt;
1198 
1199 	typ_seq(s);	/* sets TPE */
1200 
1201 	if (e->n->ntyp == D_STEP)
1202 	{	int inherit = (e->status&(ATOM|L_ATOM));
1203 		fprintf(fd_tm, "\tcase %d: ", uniq++);
1204 		fprintf(fd_tm, "// STATE %d - %s:%d - [",
1205 			e->seqno, e->n->fn->name, e->n->ln);
1206 		comment(fd_tm, e->n, 0);
1207 		fprintf(fd_tm, "]\n\t\t");
1208 
1209 		if (s->last->n->ntyp == BREAK)
1210 			OkBreak = target(huntele(s->last->nxt,
1211 				s->last->status, -1))->Seqno;
1212 		else
1213 			OkBreak = -1;
1214 
1215 		if (!putcode(fd_tm, s, e->nxt, 0, e->n->ln, e->seqno))
1216 		{
1217 			fprintf(fd_tm, "\n#if defined(C_States) && (HAS_TRACK==1)\n");
1218 			fprintf(fd_tm, "\t\tc_update((uchar *) &(now.c_state[0]));\n");
1219 			fprintf(fd_tm, "#endif\n");
1220 
1221 			fprintf(fd_tm, "\t\t_m = %d", getweight(s->frst->n));
1222 			if (m_loss && s->frst->n->ntyp == 's')
1223 				fprintf(fd_tm, "+delta_m; delta_m = 0");
1224 			fprintf(fd_tm, "; goto P999;\n\n");
1225 		}
1226 
1227 		fprintf(fd_tb, "\tcase %d: ", uniq-1);
1228 		fprintf(fd_tb, "// STATE %d\n", e->seqno);
1229 		fprintf(fd_tb, "\t\tsv_restor();\n");
1230 		fprintf(fd_tb, "\t\tgoto R999;\n");
1231 		if (e->nxt)
1232 			a = huntele(e->nxt, e->status, -1)->seqno;
1233 		else
1234 			a = 0;
1235 		tr_map(uniq-1, e);
1236 		fprintf(fd_tt, "/*->*/\ttrans[%d][%d]\t= ",
1237 			Pid_nr, e->seqno);
1238 		fprintf(fd_tt, "settr(%d,%d,%d,%d,%d,\"",
1239 			e->Seqno, D_ATOM|inherit, a, uniq-1, uniq-1);
1240 in_settr++;
1241 		comment(fd_tt, e->n, e->seqno);
1242 in_settr--;
1243 		fprintf(fd_tt, "\", %d, ", (s->frst->status&I_GLOB)?1:0);
1244 		fprintf(fd_tt, "%d, %d);\n", TPE[0], TPE[1]);
1245 		put_escp(e);
1246 	} else
1247 	{	/* ATOMIC or NON_ATOMIC */
1248 		fprintf(fd_tt, "\tT = trans[ %d][%d] = ", Pid_nr, e->seqno);
1249 		fprintf(fd_tt, "settr(%d,%d,0,0,0,\"",
1250 			e->Seqno, (e->n->ntyp == ATOMIC)?ATOM:0);
1251 in_settr++;
1252 		comment(fd_tt, e->n, e->seqno);
1253 in_settr--;
1254 		if ((e->status&CHECK2)
1255 		||  (g->status&CHECK2))
1256 			s->frst->status |= I_GLOB;
1257 		fprintf(fd_tt, "\", %d, %d, %d);",
1258 			(s->frst->status&I_GLOB)?1:0, Tt0, Tt1);
1259 		blurb(fd_tt, e);
1260 		fprintf(fd_tt, "\tT->nxt\t= ");
1261 		fprintf(fd_tt, "settr(%d,%d,%d,0,0,\"",
1262 			e->Seqno, (e->n->ntyp == ATOMIC)?ATOM:0, a);
1263 in_settr++;
1264 		comment(fd_tt, e->n, e->seqno);
1265 in_settr--;
1266 		fprintf(fd_tt, "\", %d, ", (s->frst->status&I_GLOB)?1:0);
1267 		if (e->n->ntyp == NON_ATOMIC)
1268 		{	fprintf(fd_tt, "%d, %d);", Tt0, Tt1);
1269 			blurb(fd_tt, e);
1270 			put_seq(s, Tt0, Tt1);
1271 		} else
1272 		{	fprintf(fd_tt, "%d, %d);", TPE[0], TPE[1]);
1273 			blurb(fd_tt, e);
1274 			put_seq(s, TPE[0], TPE[1]);
1275 		}
1276 	}
1277 }
1278 
1279 typedef struct CaseCache {
1280 	int m, b, owner;
1281 	Element *e;
1282 	Lextok *n;
1283 	FSM_use *u;
1284 	struct CaseCache *nxt;
1285 } CaseCache;
1286 
1287 static CaseCache *casing[6];
1288 
1289 static int
identical(Lextok * p,Lextok * q)1290 identical(Lextok *p, Lextok *q)
1291 {
1292 	if ((!p && q) || (p && !q))
1293 		return 0;
1294 	if (!p)
1295 		return 1;
1296 
1297 	if (p->ntyp    != q->ntyp
1298 	||  p->ismtyp  != q->ismtyp
1299 	||  p->val     != q->val
1300 	||  p->indstep != q->indstep
1301 	||  p->sym     != q->sym
1302 	||  p->sq      != q->sq
1303 	||  p->sl      != q->sl)
1304 		return 0;
1305 
1306 	return	identical(p->lft, q->lft)
1307 	&&	identical(p->rgt, q->rgt);
1308 }
1309 
1310 static int
samedeads(FSM_use * a,FSM_use * b)1311 samedeads(FSM_use *a, FSM_use *b)
1312 {	FSM_use *p, *q;
1313 
1314 	for (p = a, q = b; p && q; p = p->nxt, q = q->nxt)
1315 		if (p->var != q->var
1316 		||  p->special != q->special)
1317 			return 0;
1318 	return (!p && !q);
1319 }
1320 
1321 static Element *
findnext(Element * f)1322 findnext(Element *f)
1323 {	Element *g;
1324 
1325 	if (f->n->ntyp == GOTO)
1326 	{	g = get_lab(f->n, 1);
1327 		return huntele(g, f->status, -1);
1328 	}
1329 	return f->nxt;
1330 }
1331 
1332 static Element *
advance(Element * e,int stopat)1333 advance(Element *e, int stopat)
1334 {	Element *f = e;
1335 
1336 	if (stopat)
1337 	while (f && f->seqno != stopat)
1338 	{	f = findnext(f);
1339 		if (!f)
1340 		{	break;
1341 		}
1342 		switch (f->n->ntyp) {
1343 		case GOTO:
1344 		case '.':
1345 		case PRINT:
1346 		case PRINTM:
1347 			break;
1348 		default:
1349 			return f;
1350 	}	}
1351 	return (Element *) 0;
1352 }
1353 
1354 static int
equiv_merges(Element * a,Element * b)1355 equiv_merges(Element *a, Element *b)
1356 {	Element *f, *g;
1357 	int stopat_a, stopat_b;
1358 
1359 	if (a->merge_start)
1360 		stopat_a = a->merge_start;
1361 	else
1362 		stopat_a = a->merge;
1363 
1364 	if (b->merge_start)
1365 		stopat_b = b->merge_start;
1366 	else
1367 		stopat_b = b->merge;
1368 
1369 	if (!stopat_a && !stopat_b)
1370 		return 1;
1371 
1372 	f = advance(a, stopat_a);
1373 	g = advance(b, stopat_b);
1374 
1375 	if (!f && !g)
1376 		return 1;
1377 
1378 	if (f && g)
1379 		return identical(f->n, g->n);
1380 
1381 	return 0;
1382 }
1383 
1384 static CaseCache *
prev_case(Element * e,int owner)1385 prev_case(Element *e, int owner)
1386 {	int j; CaseCache *nc;
1387 
1388 	switch (e->n->ntyp) {
1389 	case 'r':	j = 0; break;
1390 	case 's':	j = 1; break;
1391 	case 'c':	j = 2; break;
1392 	case ASGN:	j = 3; break;
1393 	case ASSERT:	j = 4; break;
1394 	default:	j = 5; break;
1395 	}
1396 	for (nc = casing[j]; nc; nc = nc->nxt)
1397 		if (identical(nc->n, e->n)
1398 		&&  samedeads(nc->u, e->dead)
1399 		&&  equiv_merges(nc->e, e)
1400 		&&  nc->owner == owner)
1401 			return nc;
1402 
1403 	return (CaseCache *) 0;
1404 }
1405 
1406 static void
new_case(Element * e,int m,int b,int owner)1407 new_case(Element *e, int m, int b, int owner)
1408 {	int j; CaseCache *nc;
1409 
1410 	switch (e->n->ntyp) {
1411 	case 'r':	j = 0; break;
1412 	case 's':	j = 1; break;
1413 	case 'c':	j = 2; break;
1414 	case ASGN:	j = 3; break;
1415 	case ASSERT:	j = 4; break;
1416 	default:	j = 5; break;
1417 	}
1418 	nc = (CaseCache *) emalloc(sizeof(CaseCache));
1419 	nc->owner = owner;
1420 	nc->m = m;
1421 	nc->b = b;
1422 	nc->e = e;
1423 	nc->n = e->n;
1424 	nc->u = e->dead;
1425 	nc->nxt = casing[j];
1426 	casing[j] = nc;
1427 }
1428 
1429 static int
nr_bup(Element * e)1430 nr_bup(Element *e)
1431 {	FSM_use *u;
1432 	Lextok *v;
1433 	int nr = 0;
1434 
1435 	switch (e->n->ntyp) {
1436 	case ASGN:
1437 		if (check_track(e->n) == STRUCT) { break; }
1438 		nr++;
1439 		break;
1440 	case  'r':
1441 		if (e->n->val >= 1)
1442 			nr++;	/* random recv */
1443 		for (v = e->n->rgt; v; v = v->rgt)
1444 		{	if ((v->lft->ntyp == CONST
1445 			||   v->lft->ntyp == EVAL))
1446 				continue;
1447 			nr++;
1448 		}
1449 		break;
1450 	default:
1451 		break;
1452 	}
1453 	for (u = e->dead; u; u = u->nxt)
1454 	{	switch (u->special) {
1455 		case 2:		/* dead after write */
1456 			if (e->n->ntyp == ASGN
1457 			&&  e->n->rgt->ntyp == CONST
1458 			&&  e->n->rgt->val == 0)
1459 				break;
1460 			nr++;
1461 			break;
1462 		case 1:		/* dead after read */
1463 			nr++;
1464 			break;
1465 	}	}
1466 	return nr;
1467 }
1468 
1469 static int
nrhops(Element * e)1470 nrhops(Element *e)
1471 {	Element *f = e, *g;
1472 	int cnt = 0;
1473 	int stopat;
1474 
1475 	if (e->merge_start)
1476 		stopat = e->merge_start;
1477 	else
1478 		stopat = e->merge;
1479 #if 0
1480 	printf("merge: %d merge_start %d - seqno %d\n",
1481 		e->merge, e->merge_start, e->seqno);
1482 #endif
1483 	do {
1484 		cnt += nr_bup(f);
1485 
1486 		if (f->n->ntyp == GOTO)
1487 		{	g = get_lab(f->n, 1);
1488 			if (g->seqno == stopat)
1489 				f = g;
1490 			else
1491 				f = huntele(g, f->status, stopat);
1492 		} else
1493 		{
1494 			f = f->nxt;
1495 		}
1496 
1497 		if (f && !f->merge && !f->merge_single && f->seqno != stopat)
1498 		{	fprintf(fd_tm, "\n\t\t// bad hop %s:%d -- at %d, <",
1499 				f->n->fn->name,f->n->ln, f->seqno);
1500 			comment(fd_tm, f->n, 0);
1501 			fprintf(fd_tm, "> looking for %d -- merge %d:%d:%d ",
1502 				stopat, f->merge, f->merge_start, f->merge_single);
1503 		 	break;
1504 		}
1505 	} while (f && f->seqno != stopat);
1506 
1507 	return cnt;
1508 }
1509 
1510 static void
check_needed(void)1511 check_needed(void)
1512 {
1513 	if (multi_needed)
1514 	{	fprintf(fd_tm, "(trpt+1)->bup.ovals = grab_ints(%d);\n\t\t",
1515 			multi_needed);
1516 		multi_undo = multi_needed;
1517 		multi_needed = 0;
1518 	}
1519 }
1520 
1521 static void
doforward(FILE * tm_fd,Element * e)1522 doforward(FILE *tm_fd, Element *e)
1523 {	FSM_use *u;
1524 
1525 	putstmnt(tm_fd, e->n, e->seqno);
1526 
1527 	if (e->n->ntyp != ELSE && Det)
1528 	{	fprintf(tm_fd, ";\n\t\tif (trpt->o_pm&1)\n\t\t");
1529 		fprintf(tm_fd, "\tuerror(\"non-determinism in D_proctype\")");
1530 	}
1531 	if (deadvar && !has_code)
1532 	for (u = e->dead; u; u = u->nxt)
1533 	{	fprintf(tm_fd, ";\n\t\t");
1534 		fprintf(tm_fd, "if (TstOnly) return 1; /* TT */\n");
1535 		fprintf(tm_fd, "\t\t/* dead %d: %s */  ",
1536 			u->special, u->var->name);
1537 
1538 		switch (u->special) {
1539 		case 2:		/* dead after write -- lval already bupped */
1540 			if (e->n->ntyp == ASGN)	/* could be recv or asgn */
1541 			{	if (e->n->rgt->ntyp == CONST
1542 				&&  e->n->rgt->val == 0)
1543 					continue;	/* already set to 0 */
1544 			}
1545 			if (e->n->ntyp != 'r')
1546 			{	XZ.sym = u->var;
1547 				fprintf(tm_fd, "\n#ifdef HAS_CODE\n");
1548 				fprintf(tm_fd, "\t\tif (!readtrail)\n");
1549 				fprintf(tm_fd, "#endif\n\t\t\t");
1550 				putname(tm_fd, "", &XZ, 0, " = 0");
1551 				break;
1552 			} /* else fall through */
1553 		case 1:		/* dead after read -- add asgn of rval -- needs bup */
1554 			YZ[YZmax].sym = u->var;	/* store for pan.b */
1555 			CnT[YZcnt]++;		/* this step added bups */
1556 			if (multi_oval)
1557 			{	check_needed();
1558 				fprintf(tm_fd, "(trpt+1)->bup.ovals[%d] = ",
1559 					multi_oval-1);
1560 				multi_oval++;
1561 			} else
1562 				fprintf(tm_fd, "(trpt+1)->bup.oval = ");
1563 			putname(tm_fd, "", &YZ[YZmax], 0, ";\n");
1564 			fprintf(tm_fd, "#ifdef HAS_CODE\n");
1565 			fprintf(tm_fd, "\t\tif (!readtrail)\n");
1566 			fprintf(tm_fd, "#endif\n\t\t\t");
1567 			putname(tm_fd, "", &YZ[YZmax], 0, " = 0");
1568 			YZmax++;
1569 			break;
1570 	}	}
1571 	fprintf(tm_fd, ";\n\t\t");
1572 }
1573 
1574 static int
dobackward(Element * e,int casenr)1575 dobackward(Element *e, int casenr)
1576 {
1577 	if (!any_undo(e->n) && CnT[YZcnt] == 0)
1578 	{	YZcnt--;
1579 		return 0;
1580 	}
1581 
1582 	if (!didcase)
1583 	{	fprintf(fd_tb, "\n\tcase %d: ", casenr);
1584 		fprintf(fd_tb, "// STATE %d\n\t\t", e->seqno);
1585 		didcase++;
1586 	}
1587 
1588 	_isok++;
1589 	while (CnT[YZcnt] > 0)	/* undo dead variable resets */
1590 	{	CnT[YZcnt]--;
1591 		YZmax--;
1592 		if (YZmax < 0)
1593 			fatal("cannot happen, dobackward", (char *)0);
1594 		fprintf(fd_tb, ";\n\t/* %d */\t", YZmax);
1595 		putname(fd_tb, "", &YZ[YZmax], 0, " = trpt->bup.oval");
1596 		if (multi_oval > 0)
1597 		{	multi_oval--;
1598 			fprintf(fd_tb, "s[%d]", multi_oval-1);
1599 		}
1600 	}
1601 
1602 	if (e->n->ntyp != '.')
1603 	{	fprintf(fd_tb, ";\n\t\t");
1604 		undostmnt(e->n, e->seqno);
1605 	}
1606 	_isok--;
1607 
1608 	YZcnt--;
1609 	return 1;
1610 }
1611 
1612 static void
lastfirst(int stopat,Element * fin,int casenr)1613 lastfirst(int stopat, Element *fin, int casenr)
1614 {	Element *f = fin, *g;
1615 
1616 	if (f->n->ntyp == GOTO)
1617 	{	g = get_lab(f->n, 1);
1618 		if (g->seqno == stopat)
1619 			f = g;
1620 		else
1621 			f = huntele(g, f->status, stopat);
1622 	} else
1623 		f = f->nxt;
1624 
1625 	if (!f || f->seqno == stopat
1626 	|| (!f->merge && !f->merge_single))
1627 		return;
1628 	lastfirst(stopat, f, casenr);
1629 #if 0
1630 	fprintf(fd_tb, "\n\t/* merge %d -- %d:%d %d:%d:%d (casenr %d)	",
1631 		YZcnt,
1632 		f->merge_start, f->merge,
1633 		f->seqno, f?f->seqno:-1, stopat,
1634 		casenr);
1635 	comment(fd_tb, f->n, 0);
1636 	fprintf(fd_tb, " */\n");
1637 	fflush(fd_tb);
1638 #endif
1639 	dobackward(f, casenr);
1640 }
1641 
1642 static int modifier;
1643 
1644 static void
lab_transfer(Element * to,Element * from)1645 lab_transfer(Element *to, Element *from)
1646 {	Symbol *ns, *s = has_lab(from, (1|2|4));
1647 	Symbol *oc;
1648 	int ltp, usedit=0;
1649 
1650 	if (!s) return;
1651 
1652 	/* "from" could have all three labels -- rename
1653 	 * to prevent jumps to the transfered copies
1654 	 */
1655 	oc = context;	/* remember */
1656 	for (ltp = 1; ltp < 8; ltp *= 2)	/* 1, 2, and 4 */
1657 		if ((s = has_lab(from, ltp)) != (Symbol *) 0)
1658 		{	ns = (Symbol *) emalloc(sizeof(Symbol));
1659 			ns->name = (char *) emalloc((int) strlen(s->name) + 4);
1660 			sprintf(ns->name, "%s%d", s->name, modifier);
1661 
1662 			context = s->context;
1663 			set_lab(ns, to);
1664 			usedit++;
1665 		}
1666 	context = oc;	/* restore */
1667 	if (usedit)
1668 	{	if (modifier++ > 990)
1669 			fatal("modifier overflow error", (char *) 0);
1670 	}
1671 }
1672 
1673 static int
case_cache(Element * e,int a)1674 case_cache(Element *e, int a)
1675 {	int bupcase = 0, casenr = uniq, fromcache = 0;
1676 	CaseCache *Cached = (CaseCache *) 0;
1677 	Element *f, *g;
1678 	int j, nrbups, mark, ntarget;
1679 	extern int ccache;
1680 
1681 	mark = (e->status&ATOM); /* could lose atomicity in a merge chain */
1682 
1683 	if (e->merge_mark > 0
1684 	||  (merger && e->merge_in == 0))
1685 	{	/* state nominally unreachable (part of merge chains) */
1686 		if (e->n->ntyp != '.'
1687 		&&  e->n->ntyp != GOTO)
1688 		{	fprintf(fd_tt, "\ttrans[%d][%d]\t= ", Pid_nr, e->seqno);
1689 			fprintf(fd_tt, "settr(0,0,0,0,0,\"");
1690 in_settr++;
1691 			comment(fd_tt, e->n, e->seqno);
1692 in_settr--;
1693 			fprintf(fd_tt, "\",0,0,0);\n");
1694 		} else
1695 		{	fprintf(fd_tt, "\ttrans[%d][%d]\t= ", Pid_nr, e->seqno);
1696 			casenr = 1; /* mhs example */
1697 			j = a;
1698 			goto haveit; /* pakula's example */
1699 		}
1700 
1701 		return -1;
1702 	}
1703 
1704 	fprintf(fd_tt, "\ttrans[%d][%d]\t= ", Pid_nr, e->seqno);
1705 
1706 	if (ccache
1707 	&&  !pid_is_claim(Pid_nr)
1708 	&&  Pid_nr != eventmapnr
1709 	&& (Cached = prev_case(e, Pid_nr)))
1710 	{	bupcase = Cached->b;
1711 		casenr  = Cached->m;
1712 		fromcache = 1;
1713 
1714 		fprintf(fd_tm, "// STATE %d - %s:%d - [",
1715 			e->seqno, e->n->fn->name, e->n->ln);
1716 		comment(fd_tm, e->n, 0);
1717 		fprintf(fd_tm, "] (%d:%d - %d) same as %d (%d:%d - %d)\n",
1718 			e->merge_start, e->merge, e->merge_in,
1719 			casenr,
1720 			Cached->e->merge_start, Cached->e->merge, Cached->e->merge_in);
1721 
1722 		goto gotit;
1723 	}
1724 
1725 	fprintf(fd_tm, "\tcase %d: // STATE %d - %s:%d - [",
1726 		uniq++, e->seqno, e->n->fn->name, e->n->ln);
1727 	comment(fd_tm, e->n, 0);
1728 	nrbups = (e->merge || e->merge_start) ? nrhops(e) : nr_bup(e);
1729 	fprintf(fd_tm, "] (%d:%d:%d - %d)\n\t\t",
1730 		e->merge_start, e->merge, nrbups, e->merge_in);
1731 
1732 	if (nrbups > MAXMERGE-1)
1733 		fatal("merge requires more than 256 bups", (char *)0);
1734 
1735 	if (e->n->ntyp != 'r' && !pid_is_claim(Pid_nr) && Pid_nr != eventmapnr)
1736 		fprintf(fd_tm, "IfNotBlocked\n\t\t");
1737 
1738 	if (multi_needed != 0 || multi_undo != 0)
1739 		fatal("cannot happen, case_cache", (char *) 0);
1740 
1741 	if (nrbups > 1)
1742 	{	multi_oval = 1;
1743 		multi_needed = nrbups; /* allocated after edge condition */
1744 	} else
1745 		multi_oval = 0;
1746 
1747 	memset(CnT, 0, sizeof(CnT));
1748 	YZmax = YZcnt = 0;
1749 
1750 /* new 4.2.6, revised 6.0.0 */
1751 	if (pid_is_claim(Pid_nr))
1752 	{	fprintf(fd_tm, "\n#if defined(VERI) && !defined(NP)\n");
1753 		fprintf(fd_tm, "#if NCLAIMS>1\n\t\t");
1754 		 fprintf(fd_tm, "{	static int reported%d = 0;\n\t\t", e->seqno);
1755 		 fprintf(fd_tm, "	if (verbose && !reported%d)\n\t\t", e->seqno);
1756 		 fprintf(fd_tm, "	{	int nn = (int) ((Pclaim *)pptr(0))->_n;\n\t\t");
1757 		 fprintf(fd_tm, "		printf(\"depth %%ld: Claim %%s (%%d), state %%d (line %%d)\\n\",\n\t\t");
1758 		 fprintf(fd_tm, "			depth, procname[spin_c_typ[nn]], nn, ");
1759 		 fprintf(fd_tm, "(int) ((Pclaim *)pptr(0))->_p, src_claim[ (int) ((Pclaim *)pptr(0))->_p ]);\n\t\t");
1760 		 fprintf(fd_tm, "		reported%d = 1;\n\t\t", e->seqno);
1761 		 fprintf(fd_tm, "		fflush(stdout);\n\t\t");
1762 		 fprintf(fd_tm, "}	}\n");
1763 		fprintf(fd_tm, "#else\n\t\t");
1764 		 fprintf(fd_tm, "{	static int reported%d = 0;\n\t\t", e->seqno);
1765 		 fprintf(fd_tm, "	if (verbose && !reported%d)\n\t\t", e->seqno);
1766 		 fprintf(fd_tm, "	{	printf(\"depth %%d: Claim, state %%d (line %%d)\\n\",\n\t\t");
1767 		 fprintf(fd_tm, "			(int) depth, (int) ((Pclaim *)pptr(0))->_p, ");
1768 		 fprintf(fd_tm, "src_claim[ (int) ((Pclaim *)pptr(0))->_p ]);\n\t\t");
1769 		 fprintf(fd_tm, "		reported%d = 1;\n\t\t", e->seqno);
1770 		 fprintf(fd_tm, "		fflush(stdout);\n\t\t");
1771 		 fprintf(fd_tm, "}	}\n");
1772 		fprintf(fd_tm, "#endif\n");
1773 		fprintf(fd_tm, "#endif\n\t\t");
1774 	}
1775 /* end */
1776 
1777 	/* the src xrefs have the numbers in e->seqno builtin */
1778 	fprintf(fd_tm, "reached[%d][%d] = 1;\n\t\t", Pid_nr, e->seqno);
1779 
1780 	doforward(fd_tm, e);
1781 
1782 	if (e->merge_start)
1783 		ntarget = e->merge_start;
1784 	else
1785 		ntarget = e->merge;
1786 
1787 	if (ntarget)
1788 	{	f = e;
1789 
1790 more:		if (f->n->ntyp == GOTO)
1791 		{	g = get_lab(f->n, 1);
1792 			if (g->seqno == ntarget)
1793 				f = g;
1794 			else
1795 				f = huntele(g, f->status, ntarget);
1796 		} else
1797 			f = f->nxt;
1798 
1799 
1800 		if (f && f->seqno != ntarget)
1801 		{	if (!f->merge && !f->merge_single)
1802 			{	fprintf(fd_tm, "/* stop at bad hop %d, %d */\n\t\t",
1803 					f->seqno, ntarget);
1804 				goto out;
1805 			}
1806 			fprintf(fd_tm, "/* merge: ");
1807 			comment(fd_tm, f->n, 0);
1808 			fprintf(fd_tm,  "(%d, %d, %d) */\n\t\t", f->merge, f->seqno, ntarget);
1809 			fprintf(fd_tm, "reached[%d][%d] = 1;\n\t\t", Pid_nr, f->seqno);
1810 			YZcnt++;
1811 			lab_transfer(e, f);
1812 			mark = f->status&(ATOM|L_ATOM); /* last step wins */
1813 			doforward(fd_tm, f);
1814 			if (f->merge_in == 1) f->merge_mark++;
1815 
1816 			goto more;
1817 	}	}
1818 out:
1819 	fprintf(fd_tm, "_m = %d", getweight(e->n));
1820 	if (m_loss && e->n->ntyp == 's') fprintf(fd_tm, "+delta_m; delta_m = 0");
1821 	fprintf(fd_tm, "; goto P999; /* %d */\n", YZcnt);
1822 
1823 	multi_needed = 0;
1824 	didcase = 0;
1825 
1826 	if (ntarget)
1827 		lastfirst(ntarget, e, casenr); /* mergesteps only */
1828 
1829 	dobackward(e, casenr);			/* the original step */
1830 
1831 	fprintf(fd_tb, ";\n\t\t");
1832 
1833 	if (e->merge || e->merge_start)
1834 	{	if (!didcase)
1835 		{	fprintf(fd_tb, "\n\tcase %d: ", casenr);
1836 			fprintf(fd_tb, "// STATE %d", e->seqno);
1837 			didcase++;
1838 		} else
1839 			fprintf(fd_tb, ";");
1840 	} else
1841 		fprintf(fd_tb, ";");
1842 	fprintf(fd_tb, "\n\t\t");
1843 
1844 	if (multi_undo)
1845 	{	fprintf(fd_tb, "ungrab_ints(trpt->bup.ovals, %d);\n\t\t",
1846 			multi_undo);
1847 		multi_undo = 0;
1848 	}
1849 	if (didcase)
1850 	{	fprintf(fd_tb, "goto R999;\n");
1851 		bupcase = casenr;
1852 	}
1853 
1854 	if (!e->merge && !e->merge_start)
1855 		new_case(e, casenr, bupcase, Pid_nr);
1856 
1857 gotit:
1858 	j = a;
1859 	if (e->merge_start)
1860 		j = e->merge_start;
1861 	else if (e->merge)
1862 		j = e->merge;
1863 haveit:
1864 	fprintf(fd_tt, "%ssettr(%d,%d,%d,%d,%d,\"", fromcache?"/* c */ ":"",
1865 		e->Seqno, mark, j, casenr, bupcase);
1866 
1867 	return (fromcache)?0:casenr;
1868 }
1869 
1870 static void
put_el(Element * e,int Tt0,int Tt1)1871 put_el(Element *e, int Tt0, int Tt1)
1872 {	int a, casenr, Global_ref;
1873 	Element *g = ZE;
1874 
1875 	if (e->n->ntyp == GOTO)
1876 	{	g = get_lab(e->n, 1);
1877 		g = huntele(g, e->status, -1);
1878 		cross_dsteps(e->n, g->n);
1879 		a = g->seqno;
1880 	} else if (e->nxt)
1881 	{	g = huntele(e->nxt, e->status, -1);
1882 		a = g->seqno;
1883 	} else
1884 		a = 0;
1885 	if (g
1886 	&&  ((g->status&CHECK2)		/* entering remotely ref'd state */
1887 	||   (e->status&CHECK2)))	/* leaving  remotely ref'd state */
1888 		e->status |= I_GLOB;
1889 
1890 	/* don't remove dead edges in here, to preserve structure of fsm */
1891 	if (e->merge_start || e->merge)
1892 		goto non_generic;
1893 
1894 	/*** avoid duplicate or redundant cases in pan.m ***/
1895 	switch (e->n->ntyp) {
1896 	case ELSE:
1897 		casenr = 2; /* standard else */
1898 		putskip(e->seqno);
1899 		goto generic_case;
1900 		/* break; */
1901 	case '.':
1902 	case GOTO:
1903 	case BREAK:
1904 		putskip(e->seqno);
1905 		casenr = 1; /* standard goto */
1906 generic_case:	fprintf(fd_tt, "\ttrans[%d][%d]\t= ", Pid_nr, e->seqno);
1907 		fprintf(fd_tt, "settr(%d,%d,%d,%d,0,\"",
1908 			e->Seqno, e->status&ATOM, a, casenr);
1909 		break;
1910 #ifndef PRINTF
1911 	case PRINT:
1912 		goto non_generic;
1913 	case PRINTM:
1914 		goto non_generic;
1915 #endif
1916 	case 'c':
1917 		if (e->n->lft->ntyp == CONST
1918 		&&  e->n->lft->val == 1)	/* skip or true */
1919 		{	casenr = 1;
1920 			putskip(e->seqno);
1921 			goto generic_case;
1922 		}
1923 		goto non_generic;
1924 
1925 	default:
1926 non_generic:
1927 		casenr = case_cache(e, a);
1928 		if (casenr < 0) return;	/* unreachable state */
1929 		break;
1930 	}
1931 	/* tailend of settr(...); */
1932 	Global_ref = (e->status&I_GLOB)?1:has_global(e->n);
1933 in_settr++;
1934 	comment(fd_tt, e->n, e->seqno);
1935 in_settr--;
1936 	fprintf(fd_tt, "\", %d, ", Global_ref);
1937 	if (Tt0 != 2)
1938 	{	fprintf(fd_tt, "%d, %d);", Tt0, Tt1);
1939 	} else
1940 	{	Tpe(e->n);	/* sets EPT */
1941 		fprintf(fd_tt, "%d, %d);", EPT[0], EPT[1]);
1942 	}
1943 	if ((e->merge_start && e->merge_start != a)
1944 	||  (e->merge && e->merge != a))
1945 	{	fprintf(fd_tt, " /* m: %d -> %d,%d */\n",
1946 			a, e->merge_start, e->merge);
1947 		fprintf(fd_tt, "	reached%d[%d] = 1;",
1948 			Pid_nr, a); /* Sheinman's example */
1949 	}
1950 	fprintf(fd_tt, "\n");
1951 
1952 	if (casenr > 2)
1953 		tr_map(casenr, e);
1954 	put_escp(e);
1955 }
1956 
1957 static void
nested_unless(Element * e,Element * g)1958 nested_unless(Element *e, Element *g)
1959 {	struct SeqList *y = e->esc, *z = g->esc;
1960 
1961 	for ( ; y && z; y = y->nxt, z = z->nxt)
1962 		if (z->this != y->this)
1963 			break;
1964 	if (!y && !z)
1965 		return;
1966 
1967 	if (g->n->ntyp != GOTO
1968 	&&  g->n->ntyp != '.'
1969 	&&  e->sub->nxt)
1970 	{	printf("error: (%s:%d) saw 'unless' on a guard:\n",
1971 			(e->n)?e->n->fn->name:"-",
1972 			(e->n)?e->n->ln:0);
1973 		printf("=====>instead of\n");
1974 		printf("	do (or if)\n");
1975 		printf("	:: ...\n");
1976 		printf("	:: stmnt1 unless stmnt2\n");
1977 		printf("	od (of fi)\n");
1978 		printf("=====>use\n");
1979 		printf("	do (or if)\n");
1980 		printf("	:: ...\n");
1981 		printf("	:: stmnt1\n");
1982 		printf("	od (or fi) unless stmnt2\n");
1983 		printf("=====>or rewrite\n");
1984 	}
1985 }
1986 
1987 static void
put_seq(Sequence * s,int Tt0,int Tt1)1988 put_seq(Sequence *s, int Tt0, int Tt1)
1989 {	SeqList *h;
1990 	Element *e, *g;
1991 	int a, deadlink;
1992 
1993 	if (0) printf("put_seq %d\n", s->frst->seqno);
1994 
1995 	for (e = s->frst; e; e = e->nxt)
1996 	{
1997 		if (0) printf("	step %d\n", e->seqno);
1998 		if (e->status & DONE)
1999 		{
2000 			if (0) printf("		done before\n");
2001 			goto checklast;
2002 		}
2003 		e->status |= DONE;
2004 
2005 		if (e->n->ln)
2006 			putsrc(e);
2007 
2008 		if (e->n->ntyp == UNLESS)
2009 		{
2010 			if (0) printf("		an unless\n");
2011 			put_seq(e->sub->this, Tt0, Tt1);
2012 		} else if (e->sub)
2013 		{
2014 			if (0) printf("		has sub\n");
2015 			fprintf(fd_tt, "\tT = trans[%d][%d] = ",
2016 				Pid_nr, e->seqno);
2017 			fprintf(fd_tt, "settr(%d,%d,0,0,0,\"",
2018 				e->Seqno, e->status&ATOM);
2019 in_settr++;
2020 			comment(fd_tt, e->n, e->seqno);
2021 in_settr--;
2022 			if (e->status&CHECK2)
2023 				e->status |= I_GLOB;
2024 			fprintf(fd_tt, "\", %d, %d, %d);",
2025 				(e->status&I_GLOB)?1:0, Tt0, Tt1);
2026 			blurb(fd_tt, e);
2027 			for (h = e->sub; h; h = h->nxt)
2028 			{	putskip(h->this->frst->seqno);
2029 				g = huntstart(h->this->frst);
2030 				if (g->esc)
2031 					nested_unless(e, g);
2032 				a = g->seqno;
2033 
2034 				if (g->n->ntyp == 'c'
2035 				&&  g->n->lft->ntyp == CONST
2036 				&&  g->n->lft->val == 0		/* 0 or false */
2037 				&& !g->esc)
2038 				{	fprintf(fd_tt, "#if 0\n\t/* dead link: */\n");
2039 					deadlink = 1;
2040 					if (verbose&32)
2041 					printf("spin: %s:%d, warning, condition is always false\n",
2042 						g->n->fn?g->n->fn->name:"", g->n->ln);
2043 				} else
2044 					deadlink = 0;
2045 				if (0) printf("			settr %d %d\n", a, 0);
2046 				if (h->nxt)
2047 					fprintf(fd_tt, "\tT = T->nxt\t= ");
2048 				else
2049 					fprintf(fd_tt, "\t    T->nxt\t= ");
2050 				fprintf(fd_tt, "settr(%d,%d,%d,0,0,\"",
2051 					e->Seqno, e->status&ATOM, a);
2052 in_settr++;
2053 				comment(fd_tt, e->n, e->seqno);
2054 in_settr--;
2055 				if (g->status&CHECK2)
2056 					h->this->frst->status |= I_GLOB;
2057 				fprintf(fd_tt, "\", %d, %d, %d);",
2058 					(h->this->frst->status&I_GLOB)?1:0,
2059 					Tt0, Tt1);
2060 				blurb(fd_tt, e);
2061 				if (deadlink)
2062 					fprintf(fd_tt, "#endif\n");
2063 			}
2064 			for (h = e->sub; h; h = h->nxt)
2065 				put_seq(h->this, Tt0, Tt1);
2066 		} else
2067 		{
2068 			if (0) printf("		[non]atomic %d\n", e->n->ntyp);
2069 			if (e->n->ntyp == ATOMIC
2070 			||  e->n->ntyp == D_STEP
2071 			||  e->n->ntyp == NON_ATOMIC)
2072 				put_sub(e, Tt0, Tt1);
2073 			else
2074 			{
2075 				if (0) printf("			put_el %d\n", e->seqno);
2076 				put_el(e, Tt0, Tt1);
2077 			}
2078 		}
2079 checklast:	if (e == s->last)
2080 			break;
2081 	}
2082 	if (0) printf("put_seq done\n");
2083 }
2084 
2085 static void
patch_atomic(Sequence * s)2086 patch_atomic(Sequence *s)	/* catch goto's that break the chain */
2087 {	Element *f, *g;
2088 	SeqList *h;
2089 
2090 	for (f = s->frst; f ; f = f->nxt)
2091 	{
2092 		if (f->n && f->n->ntyp == GOTO)
2093 		{	g = get_lab(f->n,1);
2094 			cross_dsteps(f->n, g->n);
2095 			if ((f->status & (ATOM|L_ATOM))
2096 			&& !(g->status & (ATOM|L_ATOM)))
2097 			{	f->status &= ~ATOM;
2098 				f->status |= L_ATOM;
2099 			}
2100 			/* bridge atomics */
2101 			if ((f->status & L_ATOM)
2102 			&&  (g->status & (ATOM|L_ATOM)))
2103 			{	f->status &= ~L_ATOM;
2104 				f->status |= ATOM;
2105 			}
2106 		} else
2107 		for (h = f->sub; h; h = h->nxt)
2108 			patch_atomic(h->this);
2109 		if (f == s->extent)
2110 			break;
2111 	}
2112 }
2113 
2114 static void
mark_seq(Sequence * s)2115 mark_seq(Sequence *s)
2116 {	Element *f;
2117 	SeqList *h;
2118 
2119 	for (f = s->frst; f; f = f->nxt)
2120 	{	f->status |= I_GLOB;
2121 
2122 		if (f->n->ntyp == ATOMIC
2123 		||  f->n->ntyp == NON_ATOMIC
2124 		||  f->n->ntyp == D_STEP)
2125 			mark_seq(f->n->sl->this);
2126 
2127 		for (h = f->sub; h; h = h->nxt)
2128 			mark_seq(h->this);
2129 		if (f == s->last)
2130 			return;
2131 	}
2132 }
2133 
2134 static Element *
find_target(Element * e)2135 find_target(Element *e)
2136 {	Element *f;
2137 
2138 	if (!e) return e;
2139 
2140 	if (t_cyc++ > 32)
2141 	{	fatal("cycle of goto jumps", (char *) 0);
2142 	}
2143 	switch (e->n->ntyp) {
2144 	case  GOTO:
2145 		f = get_lab(e->n,1);
2146 		cross_dsteps(e->n, f->n);
2147 		f = find_target(f);
2148 		break;
2149 	case BREAK:
2150 		if (e->nxt)
2151 		{	f = find_target(huntele(e->nxt, e->status, -1));
2152 			break;	/* new 5.0 -- was missing */
2153 		}
2154 		/* else fall through */
2155 	default:
2156 		f = e;
2157 		break;
2158 	}
2159 	return f;
2160 }
2161 
2162 Element *
target(Element * e)2163 target(Element *e)
2164 {
2165 	if (!e) return e;
2166 	lineno = e->n->ln;
2167 	Fname  = e->n->fn;
2168 	t_cyc = 0;
2169 	return find_target(e);
2170 }
2171 
2172 static int
seq_has_el(Sequence * s,Element * g)2173 seq_has_el(Sequence *s, Element *g)		/* new to version 5.0 */
2174 {	Element *f;
2175 	SeqList *h;
2176 
2177 	for (f = s->frst; f; f = f->nxt)	/* g in same atomic? */
2178 	{	if (f == g)
2179 		{	return 1;
2180 		}
2181 		if (f->status & CHECK3)
2182 		{	continue;
2183 		}
2184 		f->status |= CHECK3; /* protect against cycles */
2185 		for (h = f->sub; h; h = h->nxt)
2186 		{	if (h->this && seq_has_el(h->this, g))
2187 			{	return 1;
2188 	}	}	}
2189 	return 0;
2190 }
2191 
2192 static int
scan_seq(Sequence * s)2193 scan_seq(Sequence *s)
2194 {	Element *f, *g;
2195 	SeqList *h;
2196 
2197 	for (f = s->frst; f; f = f->nxt)
2198 	{	if ((f->status&CHECK2)
2199 		||  has_global(f->n))
2200 			return 1;
2201 		if  (f->n->ntyp == GOTO	/* may exit or reach other atomic */
2202 		&& !(f->status & D_ATOM))	/* cannot jump from d_step */
2203 		{	/* consider jump from an atomic without globals into
2204 			 * an atomic with globals
2205 			 * example by Claus Traulsen, 22 June 2007
2206 			 */
2207 			g = target(f);
2208 #if 1
2209 			if (g && !seq_has_el(s, g)) /* not internal to this atomic/dstep */
2210 
2211 #else
2212 			if (g
2213 			&& !(f->status & L_ATOM)
2214 			&& !(g->status & (ATOM|L_ATOM)))
2215 #endif
2216 			{	fprintf(fd_tt, "\t/* mark-down line %d status %d = %d */\n", f->n->ln, f->status, (f->status & D_ATOM));
2217 				return 1; /* assume worst case */
2218 		}	}
2219 		for (h = f->sub; h; h = h->nxt)
2220 			if (scan_seq(h->this))
2221 				return 1;
2222 		if (f == s->last)
2223 			break;
2224 	}
2225 	return 0;
2226 }
2227 
2228 static int
glob_args(Lextok * n)2229 glob_args(Lextok *n)
2230 {	int result = 0;
2231 	Lextok *v;
2232 
2233 	for (v = n->rgt; v; v = v->rgt)
2234 	{	if (v->lft->ntyp == CONST)
2235 			continue;
2236 		if (v->lft->ntyp == EVAL)
2237 			result += has_global(v->lft->lft);
2238 		else
2239 			result += has_global(v->lft);
2240 	}
2241 	return result;
2242 }
2243 
2244 static int
proc_is_safe(const Lextok * n)2245 proc_is_safe(const Lextok *n)
2246 {	ProcList *p;
2247 	/* not safe unless no local var inits are used */
2248 	/* note that a local variable init could refer to a global */
2249 
2250 	for (p = ready; p; p = p->nxt)
2251 	{	if (strcmp(n->sym->name, p->n->name) == 0)
2252 		{	/* printf("proc %s safety: %d\n", p->n->name, p->unsafe); */
2253 			return (p->unsafe != 0);
2254 	}	}
2255 /*	non_fatal("bad call to proc_is_safe", (char *) 0);	*/
2256 	/* cannot happen */
2257 	return 0;
2258 }
2259 
2260 int
has_global(Lextok * n)2261 has_global(Lextok *n)
2262 {	Lextok *v;
2263 	static Symbol *n_seen = (Symbol *) 0;
2264 
2265 	if (!n) return 0;
2266 	if (AllGlobal) return 1;	/* global provided clause */
2267 
2268 	switch (n->ntyp) {
2269 	case ATOMIC:
2270 	case D_STEP:
2271 	case NON_ATOMIC:
2272 		return scan_seq(n->sl->this);
2273 
2274 	case '.':
2275 	case BREAK:
2276 	case GOTO:
2277 	case CONST:
2278 		return 0;
2279 
2280 	case   ELSE: return n->val; /* true if combined with chan refs */
2281 
2282 	case    's': return glob_args(n)!=0 || ((n->sym->xu&(XS|XX)) != XS);
2283 	case    'r': return glob_args(n)!=0 || ((n->sym->xu&(XR|XX)) != XR);
2284 	case    'R': return glob_args(n)!=0 || (((n->sym->xu)&(XR|XS|XX)) != (XR|XS));
2285 	case NEMPTY: return ((n->sym->xu&(XR|XX)) != XR);
2286 	case  NFULL: return ((n->sym->xu&(XS|XX)) != XS);
2287 	case   FULL: return ((n->sym->xu&(XR|XX)) != XR);
2288 	case  EMPTY: return ((n->sym->xu&(XS|XX)) != XS);
2289 	case  LEN:   return (((n->sym->xu)&(XR|XS|XX)) != (XR|XS));
2290 
2291 	case   NAME:
2292 		if (strcmp(n->sym->name, "_priority") == 0)
2293 		{	if (old_priority_rules)
2294 			{	if (n_seen != n->sym)
2295 					fatal("cannot refer to _priority with -o6", (char *) 0);
2296 				n_seen = n->sym;
2297 			}
2298 			return 0;
2299 		}
2300 		if (n->sym->context
2301 		|| (n->sym->hidden&64)
2302 		||  strcmp(n->sym->name, "_pid") == 0
2303 		||  strcmp(n->sym->name, "_") == 0)
2304 			return 0;
2305 		return 1;
2306 
2307 	case RUN:
2308 		return proc_is_safe(n);
2309 
2310 	case C_CODE: case C_EXPR:
2311 		return glob_inline(n->sym->name);
2312 
2313 	case ENABLED: case PC_VAL: case NONPROGRESS:
2314 	case 'p':    case 'q':
2315 	case TIMEOUT: case SET_P:  case GET_P:
2316 		return 1;
2317 
2318 	/* 	@ was 1 (global) since 2.8.5
2319 		in 3.0 it is considered local and
2320 		conditionally safe, provided:
2321 			II is the youngest process
2322 			and nrprocs < MAXPROCS
2323 	*/
2324 	case '@': return 0;
2325 
2326 	case '!': case UMIN: case '~': case ASSERT:
2327 		return has_global(n->lft);
2328 
2329 	case '/': case '*': case '-': case '+':
2330 	case '%': case LT:  case GT: case '&': case '^':
2331 	case '|': case LE:  case GE:  case NE: case '?':
2332 	case EQ:  case OR:  case AND: case LSHIFT:
2333 	case RSHIFT: case 'c': case ASGN:
2334 		return has_global(n->lft) || has_global(n->rgt);
2335 
2336 	case PRINT:
2337 		for (v = n->lft; v; v = v->rgt)
2338 			if (has_global(v->lft)) return 1;
2339 		return 0;
2340 	case PRINTM:
2341 		return has_global(n->lft);
2342 	}
2343 	return 0;
2344 }
2345 
2346 static void
Bailout(FILE * fd,char * str)2347 Bailout(FILE *fd, char *str)
2348 {
2349 	if (!GenCode)
2350 	{	fprintf(fd, "continue%s", str);
2351 	} else if (IsGuard)
2352 	{	fprintf(fd, "%s%s", NextLab[Level], str);
2353 	} else
2354 	{	fprintf(fd, "Uerror(\"block in d_step seq\")%s", str);
2355 	}
2356 }
2357 
2358 #define cat0(x)   	putstmnt(fd,now->lft,m); fprintf(fd, x); \
2359 			putstmnt(fd,now->rgt,m)
2360 #define cat1(x)		fprintf(fd,"("); cat0(x); fprintf(fd,")")
2361 #define cat2(x,y)  	fprintf(fd,x); putstmnt(fd,y,m)
2362 #define cat3(x,y,z)	fprintf(fd,x); putstmnt(fd,y,m); fprintf(fd,z)
2363 #define cat30(x,y,z)	fprintf(fd,x,0); putstmnt(fd,y,m); fprintf(fd,z)
2364 
2365 void
putstmnt(FILE * fd,Lextok * now,int m)2366 putstmnt(FILE *fd, Lextok *now, int m)
2367 {	Lextok *v;
2368 	int i, j;
2369 
2370 	if (!now) { fprintf(fd, "0"); return; }
2371 	lineno = now->ln;
2372 	Fname  = now->fn;
2373 
2374 	switch (now->ntyp) {
2375 	case CONST:	fprintf(fd, "%d", now->val); break;
2376 	case '!':	cat3(" !(", now->lft, ")"); break;
2377 	case UMIN:	cat3(" -(", now->lft, ")"); break;
2378 	case '~':	cat3(" ~(", now->lft, ")"); break;
2379 
2380 	case '/':	cat1("/");  break;
2381 	case '*':	cat1("*");  break;
2382 	case '-':	cat1("-");  break;
2383 	case '+':	cat1("+");  break;
2384 	case '%':	cat1("%%"); break;
2385 	case '&':	cat1("&");  break;
2386 	case '^':	cat1("^");  break;
2387 	case '|':	cat1("|");  break;
2388 	case LT:	cat1("<");  break;
2389 	case GT:	cat1(">");  break;
2390 	case LE:	cat1("<="); break;
2391 	case GE:	cat1(">="); break;
2392 	case NE:	cat1("!="); break;
2393 	case EQ:	cat1("=="); break;
2394 	case OR:	cat1("||"); break;
2395 	case AND:	cat1("&&"); break;
2396 	case LSHIFT:	cat1("<<"); break;
2397 	case RSHIFT:	cat1(">>"); break;
2398 
2399 	case TIMEOUT:
2400 		if (separate == 2)
2401 			fprintf(fd, "((tau)&1)");
2402 		else
2403 			fprintf(fd, "((trpt->tau)&1)");
2404 		if (GenCode)
2405 		 printf("spin: %s:%d, warning, 'timeout' in d_step sequence\n",
2406 			Fname->name, lineno);
2407 		/* is okay as a guard */
2408 		break;
2409 
2410 	case RUN:
2411 		if (now->sym == NULL)
2412 			fatal("internal error pangen2.c", (char *) 0);
2413 		if (claimproc
2414 		&&  strcmp(now->sym->name, claimproc) == 0)
2415 			fatal("claim %s, (not runnable)", claimproc);
2416 		if (eventmap
2417 		&&  strcmp(now->sym->name, eventmap) == 0)
2418 			fatal("eventmap %s, (not runnable)", eventmap);
2419 
2420 		if (GenCode)
2421 			fatal("'run' in d_step sequence (use atomic)", (char *)0);
2422 
2423 		fprintf(fd,"addproc(II, %d, %d",
2424 			(now->val > 0 && !old_priority_rules) ? now->val : 1,
2425 			fproc(now->sym->name));
2426 		for (v = now->lft, i = 0; v; v = v->rgt, i++)
2427 		{	cat2(", ", v->lft);
2428 		}
2429 		check_param_count(i, now);
2430 
2431 		if (i > Npars)
2432 		{	/* printf("\t%d parameters used, max %d expected\n", i, Npars); */
2433 			fatal("too many parameters in run %s(...)", now->sym->name);
2434 		}
2435 		for ( ; i < Npars; i++)
2436 			fprintf(fd, ", 0");
2437 		fprintf(fd, ")");
2438 		check_mtypes(now, now->lft);
2439 #if 0
2440 		/* process now->sym->name has run priority now->val */
2441 		if (now->val > 0 && now->val < 256 && !old_priority_rules)
2442 		{	fprintf(fd, " && (((P0 *)pptr(now._nr_pr - 1))->_priority = %d)", now->val);
2443 		}
2444 #endif
2445 		if (now->val < 0 || now->val > 255)	/* 0 itself is allowed */
2446 		{	fatal("bad process in run %s, valid range: 1..255", now->sym->name);
2447 		}
2448 		break;
2449 
2450 	case ENABLED:
2451 		cat3("enabled(II, ", now->lft, ")");
2452 		break;
2453 
2454 	case GET_P:
2455 		if (old_priority_rules)
2456 		{	fprintf(fd, "1");
2457 		} else
2458 		{	cat3("get_priority(", now->lft, ")");
2459 		}
2460 		break;
2461 
2462 	case SET_P:
2463 		if (!old_priority_rules)
2464 		{	fprintf(fd, "if (TstOnly) return 1; /* T30 */\n\t\t");
2465 			fprintf(fd, "set_priority(");
2466 			putstmnt(fd, now->lft->lft, m);
2467 			fprintf(fd, ", ");
2468 			putstmnt(fd, now->lft->rgt, m);
2469 			fprintf(fd, ")");
2470 		}
2471 		break;
2472 
2473 	case NONPROGRESS:
2474 		/* o_pm&4=progress, tau&128=claim stutter */
2475 		if (separate == 2)
2476 		fprintf(fd, "(!(o_pm&4) && !(tau&128))");
2477 		else
2478 		fprintf(fd, "(!(trpt->o_pm&4) && !(trpt->tau&128))");
2479 		break;
2480 
2481 	case PC_VAL:
2482 		cat3("((P0 *) Pptr(", now->lft, "+BASE))->_p");
2483 		break;
2484 
2485 	case LEN:
2486 		if (!terse && !TestOnly && has_xu)
2487 		{	fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2488 			putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
2489 			putname(fd, "q_R_check(", now->lft, m, "");
2490 			fprintf(fd, ", II)) &&\n\t\t");
2491 			putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
2492 			putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
2493 			fprintf(fd, "\n#endif\n\t\t");
2494 		}
2495 		putname(fd, "q_len(", now->lft, m, ")");
2496 		break;
2497 
2498 	case FULL:
2499 		if (!terse && !TestOnly && has_xu)
2500 		{	fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2501 			putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
2502 			putname(fd, "q_R_check(", now->lft, m, "");
2503 			fprintf(fd, ", II)) &&\n\t\t");
2504 			putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
2505 			putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
2506 			fprintf(fd, "\n#endif\n\t\t");
2507 		}
2508 		putname(fd, "q_full(", now->lft, m, ")");
2509 		break;
2510 
2511 	case EMPTY:
2512 		if (!terse && !TestOnly && has_xu)
2513 		{	fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2514 			putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
2515 			putname(fd, "q_R_check(", now->lft, m, "");
2516 			fprintf(fd, ", II)) &&\n\t\t");
2517 			putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
2518 			putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
2519 			fprintf(fd, "\n#endif\n\t\t");
2520 		}
2521 		putname(fd, "(q_len(", now->lft, m, ")==0)");
2522 		break;
2523 
2524 	case NFULL:
2525 		if (!terse && !TestOnly && has_xu)
2526 		{	fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2527 			putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
2528 			putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
2529 			fprintf(fd, "\n#endif\n\t\t");
2530 		}
2531 		putname(fd, "(!q_full(", now->lft, m, "))");
2532 		break;
2533 
2534 	case NEMPTY:
2535 		if (!terse && !TestOnly && has_xu)
2536 		{	fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2537 			putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
2538 			putname(fd, "q_R_check(", now->lft, m, ", II)) &&");
2539 			fprintf(fd, "\n#endif\n\t\t");
2540 		}
2541 		putname(fd, "(q_len(", now->lft, m, ")>0)");
2542 		break;
2543 
2544 	case 's':
2545 		if (Pid_nr == eventmapnr)
2546 		{	fprintf(fd, "if ((II == -EVENT_TRACE && _tp != 's') ");
2547 			putname(fd, "|| _qid+1 != ", now->lft, m, "");
2548 			for (v = now->rgt, i=0; v; v = v->rgt, i++)
2549 			{	if (v->lft->ntyp != CONST
2550 				&&  v->lft->ntyp != EVAL)
2551 					continue;
2552 				fprintf(fd, " \\\n\t\t|| qrecv(");
2553 				putname(fd, "", now->lft, m, ", ");
2554 				putname(fd, "q_len(", now->lft, m, ")-1, ");
2555 				fprintf(fd, "%d, 0) != ", i);
2556 				if (v->lft->ntyp == CONST)
2557 					putstmnt(fd, v->lft, m);
2558 				else /* EVAL */
2559 					putstmnt(fd, v->lft->lft, m);
2560 			}
2561 			fprintf(fd, ")\n");
2562 			fprintf(fd, "\t\t	continue");
2563 			putname(fd_th, " || (x_y3_ == ", now->lft, m, ")");
2564 			break;
2565 		}
2566 		if (TestOnly)
2567 		{	if (m_loss)
2568 				fprintf(fd, "1");
2569 			else
2570 				putname(fd, "!q_full(", now->lft, m, ")");
2571 			break;
2572 		}
2573 		if (has_xu)
2574 		{	fprintf(fd, "\n#if !defined(XUSAFE) && !defined(NOREDUCE)\n\t\t");
2575 			putname(fd, "if (q_claim[", now->lft, m, "]&2)\n\t\t");
2576 			putname(fd, "{	q_S_check(", now->lft, m, ", II);\n\t\t");
2577 			fprintf(fd, "}\n");
2578 			if (has_sorted && now->val == 1)
2579 			{	putname(fd, "\t\tif (q_claim[", now->lft, m, "]&1)\n\t\t"); /* &1 iso &2 */
2580 				fprintf(fd, "{	uerror(\"sorted send on xr channel violates po reduction\");\n\t\t");
2581 				fprintf(fd, "}\n");
2582 			}
2583 			fprintf(fd, "#endif\n\t\t");
2584 		}
2585 		fprintf(fd, "if (q_%s",
2586 			(u_sync > 0 && u_async == 0)?"len":"full");
2587 		putname(fd, "(", now->lft, m, "))\n");
2588 
2589 		if (m_loss)
2590 		{	fprintf(fd, "\t\t{ nlost++; delta_m = 1; } else {");
2591 		} else
2592 		{	fprintf(fd, "\t\t\t");
2593 			Bailout(fd, ";");
2594 		}
2595 
2596 		if (has_enabled || has_priority)
2597 			fprintf(fd, "\n\t\tif (TstOnly) return 1; /* T1 */");
2598 
2599 		if (u_sync && !u_async && rvopt)
2600 			fprintf(fd, "\n\n\t\tif (no_recvs(II)) continue;\n");
2601 
2602 		fprintf(fd, "\n#ifdef HAS_CODE\n");
2603 		fprintf(fd, "\t\tif (readtrail && gui) {\n");
2604 		fprintf(fd, "\t\t\tchar simtmp[64];\n");
2605 		putname(fd, "\t\t\tsprintf(simvals, \"%%d!\", ", now->lft, m, ");\n");
2606 		_isok++;
2607 		for (v = now->rgt, i = 0; v; v = v->rgt, i++)
2608 		{	cat3("\t\tsprintf(simtmp, \"%%d\", ", v->lft, "); strcat(simvals, simtmp);");
2609 			if (v->rgt)
2610 			fprintf(fd, "\t\tstrcat(simvals, \",\");\n");
2611 		}
2612 		_isok--;
2613 		fprintf(fd, "\t\t}\n");
2614 		fprintf(fd, "#endif\n\t\t");
2615 
2616 		putname(fd, "\n\t\tqsend(", now->lft, m, "");
2617 		fprintf(fd, ", %d", now->val);
2618 		for (v = now->rgt, i = 0; v; v = v->rgt, i++)
2619 		{	cat2(", ", v->lft);
2620 		}
2621 		if (i > Mpars)
2622 		{	terse++;
2623 			putname(stdout, "channel name: ", now->lft, m, "\n");
2624 			terse--;
2625 			printf("	%d msg parameters sent, %d expected\n", i, Mpars);
2626 			fatal("too many pars in send", "");
2627 		}
2628 		for (j = i; i < Mpars; i++)
2629 		{	fprintf(fd, ", 0");
2630 		}
2631 		fprintf(fd, ", %d)", j);
2632 		if (u_sync)
2633 		{	fprintf(fd, ";\n\t\t");
2634 			if (u_async)
2635 			{	putname(fd, "if (q_zero(", now->lft, m, ")) ");
2636 			}
2637 			putname(fd, "{ boq = ", now->lft, m, "");
2638 			if (GenCode)
2639 			{	fprintf(fd, "; Uerror(\"rv-attempt in d_step\")");
2640 			}
2641 			fprintf(fd, "; }");
2642 		}
2643 		if (m_loss)
2644 		{	fprintf(fd, ";\n\t\t}\n\t\t"); /* end of m_loss else */
2645 		}
2646 		break;
2647 
2648 	case 'r':
2649 		if (Pid_nr == eventmapnr)
2650 		{	fprintf(fd, "if ((II == -EVENT_TRACE && _tp != 'r') ");
2651 			putname(fd, "|| _qid+1 != ", now->lft, m, "");
2652 			for (v = now->rgt, i=0; v; v = v->rgt, i++)
2653 			{	if (v->lft->ntyp != CONST
2654 				&&  v->lft->ntyp != EVAL)
2655 					continue;
2656 				fprintf(fd, " \\\n\t\t|| qrecv(");
2657 				putname(fd, "", now->lft, m, ", ");
2658 				fprintf(fd, "0, %d, 0) != ", i);
2659 				if (v->lft->ntyp == CONST)
2660 					putstmnt(fd, v->lft, m);
2661 				else /* EVAL */
2662 					putstmnt(fd, v->lft->lft, m);
2663 			}
2664 			fprintf(fd, ")\n");
2665 			fprintf(fd, "\t\t	continue");
2666 
2667 			putname(fd_tc, " || (x_y3_ == ", now->lft, m, ")");
2668 
2669 			break;
2670 		}
2671 		if (TestOnly)
2672 		{	fprintf(fd, "((");
2673 			if (u_sync) fprintf(fd, "(boq == -1 && ");
2674 
2675 			putname(fd, "q_len(", now->lft, m, ")");
2676 
2677 			if (u_sync && now->val <= 1)
2678 			{ putname(fd, ") || (boq == ",  now->lft,m," && ");
2679 			  putname(fd, "q_zero(", now->lft,m,"))");
2680 			}
2681 
2682 			fprintf(fd, ")");
2683 			if (now->val == 0 || now->val == 2)
2684 			{	for (v = now->rgt, i=j=0; v; v = v->rgt, i++)
2685 				{ if (v->lft->ntyp == CONST)
2686 				  { cat3("\n\t\t&& (", v->lft, " == ");
2687 				    putname(fd, "qrecv(", now->lft, m, ", ");
2688 				    fprintf(fd, "0, %d, 0))", i);
2689 				  } else if (v->lft->ntyp == EVAL)
2690 				  { cat3("\n\t\t&& (", v->lft->lft, " == ");
2691 				    putname(fd, "qrecv(", now->lft, m, ", ");
2692 				    fprintf(fd, "0, %d, 0))", i);
2693 				  } else
2694 				  {	j++; continue;
2695 				  }
2696 				}
2697 			} else
2698 			{	fprintf(fd, "\n\t\t&& Q_has(");
2699 				putname(fd, "", now->lft, m, "");
2700 				for (v = now->rgt, i=0; v; v = v->rgt, i++)
2701 				{	if (v->lft->ntyp == CONST)
2702 					{	fprintf(fd, ", 1, ");
2703 						putstmnt(fd, v->lft, m);
2704 					} else if (v->lft->ntyp == EVAL)
2705 					{	fprintf(fd, ", 1, ");
2706 						putstmnt(fd, v->lft->lft, m);
2707 					} else
2708 					{	fprintf(fd, ", 0, 0");
2709 				}	}
2710 				for ( ; i < Mpars; i++)
2711 					fprintf(fd, ", 0, 0");
2712 				fprintf(fd, ")");
2713 			}
2714 			fprintf(fd, ")");
2715 			break;
2716 		}
2717 		if (has_xu)
2718 		{	fprintf(fd, "\n#if !defined(XUSAFE) && !defined(NOREDUCE)\n\t\t");
2719 			putname(fd, "if (q_claim[", now->lft, m, "]&1)\n\t\t");
2720 			putname(fd, "{	q_R_check(", now->lft, m, ", II);\n\t\t");
2721 			if (has_random && now->val != 0)
2722 			fprintf(fd, "	uerror(\"rand receive on xr channel violates po reduction\");\n\t\t");
2723 			fprintf(fd, "}\n");
2724 			fprintf(fd, "#endif\n\t\t");
2725 		}
2726 		if (u_sync)
2727 		{	if (now->val >= 2)
2728 			{	if (u_async)
2729 				{ fprintf(fd, "if (");
2730 				  putname(fd, "q_zero(", now->lft,m,"))");
2731 				  fprintf(fd, "\n\t\t{\t");
2732 				}
2733 				fprintf(fd, "uerror(\"polling ");
2734 				fprintf(fd, "rv chan\");\n\t\t");
2735 				if (u_async)
2736 				  fprintf(fd, "	continue;\n\t\t}\n\t\t");
2737 				fprintf(fd, "IfNotBlocked\n\t\t");
2738 			} else
2739 			{	fprintf(fd, "if (");
2740 				if (u_async == 0)
2741 				  putname(fd, "boq != ", now->lft,m,") ");
2742 				else
2743 				{ putname(fd, "q_zero(", now->lft,m,"))");
2744 				  fprintf(fd, "\n\t\t{\tif (boq != ");
2745 				  putname(fd, "",  now->lft,m,") ");
2746 				  Bailout(fd, ";\n\t\t} else\n\t\t");
2747 				  fprintf(fd, "{\tif (boq != -1) ");
2748 				}
2749 				Bailout(fd, ";\n\t\t");
2750 				if (u_async)
2751 					fprintf(fd, "}\n\t\t");
2752 		}	}
2753 		putname(fd, "if (q_len(", now->lft, m, ") == 0) ");
2754 		Bailout(fd, "");
2755 
2756 		for (v = now->rgt, j=0; v; v = v->rgt)
2757 		{	if (v->lft->ntyp != CONST
2758 			&&  v->lft->ntyp != EVAL)
2759 				j++;	/* count settables */
2760 		}
2761 		fprintf(fd, ";\n\n\t\tXX=1");
2762 /* test */	if (now->val == 0 || now->val == 2)
2763 		{	for (v = now->rgt, i=0; v; v = v->rgt, i++)
2764 			{	if (v->lft->ntyp == CONST)
2765 				{ fprintf(fd, ";\n\t\t");
2766 				  cat3("if (", v->lft, " != ");
2767 				  putname(fd, "qrecv(", now->lft, m, ", ");
2768 				  fprintf(fd, "0, %d, 0)) ", i);
2769 				  Bailout(fd, "");
2770 				} else if (v->lft->ntyp == EVAL)
2771 				{ fprintf(fd, ";\n\t\t");
2772 				  cat3("if (", v->lft->lft, " != ");
2773 				  putname(fd, "qrecv(", now->lft, m, ", ");
2774 				  fprintf(fd, "0, %d, 0)) ", i);
2775 				  Bailout(fd, "");
2776 			}	}
2777 			if (has_enabled || has_priority)
2778 				fprintf(fd, ";\n\t\tif (TstOnly) return 1 /* T2 */");
2779 		} else	/* random receive: val 1 or 3 */
2780 		{	fprintf(fd, ";\n\t\tif (!(XX = Q_has(");
2781 			putname(fd, "", now->lft, m, "");
2782 			for (v = now->rgt, i=0; v; v = v->rgt, i++)
2783 			{	if (v->lft->ntyp == CONST)
2784 				{	fprintf(fd, ", 1, ");
2785 					putstmnt(fd, v->lft, m);
2786 				} else if (v->lft->ntyp == EVAL)
2787 				{	fprintf(fd, ", 1, ");
2788 					putstmnt(fd, v->lft->lft, m);
2789 				} else
2790 				{	fprintf(fd, ", 0, 0");
2791 			}	}
2792 			for ( ; i < Mpars; i++)
2793 				fprintf(fd, ", 0, 0");
2794 			fprintf(fd, "))) ");
2795 			Bailout(fd, "");
2796 
2797 			if (has_enabled || has_priority)
2798 				fprintf(fd, ";\n\t\tif (TstOnly) return 1 /* T2 */");
2799 			if (!GenCode) {
2800 				fprintf(fd, ";\n\t\t");
2801 				if (multi_oval)
2802 				{	check_needed();
2803 					fprintf(fd, "(trpt+1)->bup.ovals[%d] = ",
2804 						multi_oval-1);
2805 					multi_oval++;
2806 				} else
2807 				{	fprintf(fd, "(trpt+1)->bup.oval = ");
2808 				}
2809 				fprintf(fd, "XX");
2810 		}	}
2811 
2812 		if (j == 0 && now->val >= 2)
2813 		{	fprintf(fd, ";\n\t\t");
2814 			break;	/* poll without side-effect */
2815 		}
2816 
2817 		if (!GenCode)
2818 		{	int jj = 0;
2819 			fprintf(fd, ";\n\t\t");
2820 			/* no variables modified */
2821 			if (j == 0 && now->val == 0)
2822 			{	fprintf(fd, "\n#ifndef BFS_PAR\n\t\t");
2823 				/* q_flds values are not shared among cores */
2824 				fprintf(fd, "if (q_flds[((Q0 *)qptr(");
2825 				putname(fd, "", now->lft, m, "-1))->_t]");
2826 				fprintf(fd, " != %d)\n\t\t\t", i);
2827 				fprintf(fd, "Uerror(\"wrong nr of msg fields in rcv\");\n");
2828 				fprintf(fd, "#endif\n\t\t");
2829 			}
2830 
2831 			for (v = now->rgt; v; v = v->rgt)
2832 			{	if ((v->lft->ntyp != CONST
2833 				&&   v->lft->ntyp != EVAL))
2834 				{	jj++;	/* nr of vars needing bup */
2835 			}	}
2836 
2837 			if (jj)
2838 			for (v = now->rgt, i = 0; v; v = v->rgt, i++)
2839 			{	char tempbuf[64];
2840 
2841 				if ((v->lft->ntyp == CONST
2842 				||   v->lft->ntyp == EVAL))
2843 					continue;
2844 
2845 				if (multi_oval)
2846 				{	check_needed();
2847 					sprintf(tempbuf, "(trpt+1)->bup.ovals[%d] = ",
2848 						multi_oval-1);
2849 					multi_oval++;
2850 				} else
2851 					sprintf(tempbuf, "(trpt+1)->bup.oval = ");
2852 
2853 				if (v->lft->sym && !strcmp(v->lft->sym->name, "_"))
2854 				{	fprintf(fd, tempbuf, (char *) 0);
2855 					putname(fd, "qrecv(", now->lft, m, "");
2856 					fprintf(fd, ", XX-1, %d, 0);\n\t\t", i);
2857 				} else
2858 				{	_isok++;
2859 					cat30(tempbuf, v->lft, ";\n\t\t");
2860 					_isok--;
2861 				}
2862 			}
2863 
2864 			if (jj)	/* check for double entries q?x,x */
2865 			{	Lextok *w;
2866 
2867 				for (v = now->rgt; v; v = v->rgt)
2868 				{	if (v->lft->ntyp != CONST
2869 					&&  v->lft->ntyp != EVAL
2870 					&&  v->lft->sym
2871 					&&  v->lft->sym->type != STRUCT	/* not a struct */
2872 					&&  (v->lft->sym->nel == 1 && v->lft->sym->isarray == 0) /* not array */
2873 					&&  strcmp(v->lft->sym->name, "_") != 0)
2874 					for (w = v->rgt; w; w = w->rgt)
2875 						if (v->lft->sym == w->lft->sym)
2876 						{	fatal("cannot use var ('%s') in multiple msg fields",
2877 								v->lft->sym->name);
2878 			}	}		}
2879 		}
2880 /* set */	for (v = now->rgt, i = 0; v; v = v->rgt, i++)
2881 		{	if ((v->lft->ntyp == CONST
2882 			||   v->lft->ntyp == EVAL) && v->rgt)
2883 				continue;
2884 			fprintf(fd, ";\n\t\t");
2885 
2886 			if (v->lft->ntyp != CONST
2887 			&&  v->lft->ntyp != EVAL
2888 			&&  v->lft->sym != NULL
2889 			&&  strcmp(v->lft->sym->name, "_") != 0)
2890 			{	nocast=1;
2891 				_isok++;
2892 				putstmnt(fd, v->lft, m);
2893 				_isok--;
2894 				nocast=0;
2895 				fprintf(fd, " = ");
2896 			}
2897 			putname(fd, "qrecv(", now->lft, m, ", ");
2898 			fprintf(fd, "XX-1, %d, ", i);
2899 			fprintf(fd, "%d)", (v->rgt || now->val >= 2)?0:1);
2900 
2901 			if (v->lft->ntyp != CONST
2902 			&&  v->lft->ntyp != EVAL
2903 			&&  v->lft->sym != NULL
2904 			&& strcmp(v->lft->sym->name, "_") != 0
2905 			&&  (v->lft->ntyp != NAME
2906 			||   v->lft->sym->type != CHAN))
2907 			{	fprintf(fd, ";\n#ifdef VAR_RANGES");
2908 				fprintf(fd, "\n\t\tlogval(\"");
2909 				withprocname = terse = nocast = 1;
2910 				_isok++;
2911 				putstmnt(fd,v->lft,m);
2912 				withprocname = terse = nocast = 0;
2913 				fprintf(fd, "\", ");
2914 				putstmnt(fd,v->lft,m);
2915 				_isok--;
2916 				fprintf(fd, ");\n#endif\n");
2917 				fprintf(fd, "\t\t");
2918 			}
2919 		}
2920 		fprintf(fd, ";\n\t\t");
2921 
2922 		fprintf(fd, "\n#ifdef HAS_CODE\n");
2923 		fprintf(fd, "\t\tif (readtrail && gui) {\n");
2924 		fprintf(fd, "\t\t\tchar simtmp[32];\n");
2925 		putname(fd, "\t\t\tsprintf(simvals, \"%%d?\", ", now->lft, m, ");\n");
2926 		_isok++;
2927 		for (v = now->rgt, i = 0; v; v = v->rgt, i++)
2928 		{	if (v->lft->ntyp != EVAL)
2929 			{ cat3("\t\tsprintf(simtmp, \"%%d\", ", v->lft, "); strcat(simvals, simtmp);");
2930 			} else
2931 			{ cat3("\t\tsprintf(simtmp, \"%%d\", ", v->lft->lft, "); strcat(simvals, simtmp);");
2932 			}
2933 			if (v->rgt)
2934 			fprintf(fd, "\t\tstrcat(simvals, \",\");\n");
2935 		}
2936 		_isok--;
2937 		fprintf(fd, "\t\t}\n");
2938 		fprintf(fd, "#endif\n\t\t");
2939 
2940 		if (u_sync)
2941 		{	putname(fd, "if (q_zero(", now->lft, m, "))");
2942 			fprintf(fd, "\n\t\t{	boq = -1;\n");
2943 
2944 			fprintf(fd, "#ifndef NOFAIR\n"); /* NEW 3.0.8 */
2945 			fprintf(fd, "\t\t\tif (fairness\n");
2946 			fprintf(fd, "\t\t\t&& !(trpt->o_pm&32)\n");
2947 			fprintf(fd, "\t\t\t&& (now._a_t&2)\n");
2948 			fprintf(fd, "\t\t\t&&  now._cnt[now._a_t&1] == II+2)\n");
2949 			fprintf(fd, "\t\t\t{	now._cnt[now._a_t&1] -= 1;\n");
2950 			fprintf(fd, "#ifdef VERI\n");
2951 			fprintf(fd, "\t\t\t	if (II == 1)\n");
2952 			fprintf(fd, "\t\t\t		now._cnt[now._a_t&1] = 1;\n");
2953 			fprintf(fd, "#endif\n");
2954 			fprintf(fd, "#ifdef DEBUG\n");
2955 			fprintf(fd, "\t\t\tprintf(\"%%3ld: proc %%d fairness \", depth, II);\n");
2956 			fprintf(fd, "\t\t\tprintf(\"Rule 2: --cnt to %%d (%%d)\\n\",\n");
2957 			fprintf(fd, "\t\t\t	now._cnt[now._a_t&1], now._a_t);\n");
2958 			fprintf(fd, "#endif\n");
2959 			fprintf(fd, "\t\t\t	trpt->o_pm |= (32|64);\n");
2960 			fprintf(fd, "\t\t\t}\n");
2961 			fprintf(fd, "#endif\n");
2962 
2963 			fprintf(fd, "\n\t\t}");
2964 		}
2965 		break;
2966 
2967 	case 'R':
2968 		if (!terse && !TestOnly && has_xu)
2969 		{	fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
2970 			putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
2971 			fprintf(fd, "q_R_check(");
2972 			putname(fd, "", now->lft, m, ", II)) &&\n\t\t");
2973 			putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
2974 			putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
2975 			fprintf(fd, "\n#endif\n\t\t");
2976 		}
2977 		if (u_sync>0)
2978 			putname(fd, "not_RV(", now->lft, m, ") && \\\n\t\t");
2979 
2980 		for (v = now->rgt, i=j=0; v; v = v->rgt, i++)
2981 			if (v->lft->ntyp != CONST
2982 			&&  v->lft->ntyp != EVAL)
2983 			{	j++; continue;
2984 			}
2985 		if (now->val == 0 || i == j)
2986 		{	putname(fd, "(q_len(", now->lft, m, ") > 0");
2987 			for (v = now->rgt, i=0; v; v = v->rgt, i++)
2988 			{	if (v->lft->ntyp != CONST
2989 				&&  v->lft->ntyp != EVAL)
2990 					continue;
2991 				fprintf(fd, " \\\n\t\t&& qrecv(");
2992 				putname(fd, "", now->lft, m, ", ");
2993 				fprintf(fd, "0, %d, 0) == ", i);
2994 				if (v->lft->ntyp == CONST)
2995 					putstmnt(fd, v->lft, m);
2996 				else /* EVAL */
2997 					putstmnt(fd, v->lft->lft, m);
2998 			}
2999 			fprintf(fd, ")");
3000 		} else
3001 		{	putname(fd, "Q_has(", now->lft, m, "");
3002 			for (v = now->rgt, i=0; v; v = v->rgt, i++)
3003 			{	if (v->lft->ntyp == CONST)
3004 				{	fprintf(fd, ", 1, ");
3005 					putstmnt(fd, v->lft, m);
3006 				} else if (v->lft->ntyp == EVAL)
3007 				{	fprintf(fd, ", 1, ");
3008 					putstmnt(fd, v->lft->lft, m);
3009 				} else
3010 					fprintf(fd, ", 0, 0");
3011 			}
3012 			for ( ; i < Mpars; i++)
3013 				fprintf(fd, ", 0, 0");
3014 			fprintf(fd, ")");
3015 		}
3016 		break;
3017 
3018 	case 'c':
3019 		preruse(fd, now->lft);	/* preconditions */
3020 		cat3("if (!(", now->lft, "))\n\t\t\t");
3021 		Bailout(fd, "");
3022 		break;
3023 
3024 	case  ELSE:
3025 		if (!GenCode)
3026 		{	if (separate == 2)
3027 				fprintf(fd, "if (o_pm&1)\n\t\t\t");
3028 			else
3029 				fprintf(fd, "if (trpt->o_pm&1)\n\t\t\t");
3030 			Bailout(fd, "");
3031 		} else
3032 		{	fprintf(fd, "/* else */");
3033 		}
3034 		break;
3035 
3036 	case '?':
3037 		if (now->lft)
3038 		{	cat3("( (", now->lft, ") ? ");
3039 		}
3040 		if (now->rgt)
3041 		{	cat3("(", now->rgt->lft, ") : ");
3042 			cat3("(", now->rgt->rgt, ") )");
3043 		}
3044 		break;
3045 
3046 	case ASGN:
3047 		if (check_track(now) == STRUCT) { break; }
3048 
3049 		if (has_enabled || has_priority)
3050 		fprintf(fd, "if (TstOnly) return 1; /* T3 */\n\t\t");
3051 		_isok++;
3052 
3053 		if (!GenCode)
3054 		{	if (multi_oval)
3055 			{	char tempbuf[64];
3056 				check_needed();
3057 				sprintf(tempbuf, "(trpt+1)->bup.ovals[%d] = ",
3058 					multi_oval-1);
3059 				multi_oval++;
3060 				cat30(tempbuf, now->lft, ";\n\t\t");
3061 			} else
3062 			{	cat3("(trpt+1)->bup.oval = ", now->lft, ";\n\t\t");
3063 		}	}
3064 		if (now->lft->sym
3065 		&&  now->lft->sym->type == PREDEF
3066 		&&  strcmp(now->lft->sym->name, "_") != 0
3067 		&&  strcmp(now->lft->sym->name, "_priority") != 0)
3068 		{	fatal("invalid assignment to %s", now->lft->sym->name);
3069 		}
3070 
3071 		nocast = 1; putstmnt(fd,now->lft,m); nocast = 0;
3072 		fprintf(fd," = ");
3073 		_isok--;
3074 		if (now->lft->sym->isarray
3075 		&&  now->rgt->ntyp == ',')	/* array initializer */
3076 		{	putstmnt(fd, now->rgt->lft, m);
3077 			non_fatal("cannot use an array list initializer here", (char *) 0);
3078 		} else
3079 		{	putstmnt(fd, now->rgt, m);
3080 		}
3081 
3082 		if (now->sym->type != CHAN
3083 		||  verbose > 0)
3084 		{	fprintf(fd, ";\n#ifdef VAR_RANGES");
3085 			fprintf(fd, "\n\t\tlogval(\"");
3086 			withprocname = terse = nocast = 1;
3087 			_isok++;
3088 			putstmnt(fd,now->lft,m);
3089 			withprocname = terse = nocast = 0;
3090 			fprintf(fd, "\", ");
3091 			putstmnt(fd,now->lft,m);
3092 			_isok--;
3093 			fprintf(fd, ");\n#endif\n");
3094 			fprintf(fd, "\t\t");
3095 		}
3096 		break;
3097 
3098 	case PRINT:
3099 		if (has_enabled || has_priority)
3100 			fprintf(fd, "if (TstOnly) return 1; /* T4 */\n\t\t");
3101 #ifdef PRINTF
3102 		fprintf(fd, "printf(%s", now->sym->name);
3103 #else
3104 		fprintf(fd, "Printf(%s", now->sym->name);
3105 #endif
3106 		for (v = now->lft; v; v = v->rgt)
3107 		{	cat2(", ", v->lft);
3108 		}
3109 		fprintf(fd, ")");
3110 		break;
3111 
3112 	case PRINTM:
3113 		{ char *s = 0;
3114 		  if (now->lft->sym
3115 		  &&  now->lft->sym->mtype_name)
3116 		  {	s = now->lft->sym->mtype_name->name;
3117 		  }
3118 
3119 		  if (has_enabled || has_priority)
3120 		  {	fprintf(fd, "if (TstOnly) return 1; /* T5 */\n\t\t");
3121 		  }
3122 		  fprintf(fd, "/* YY */ printm(");
3123 		  if (now->lft
3124 		  &&  now->lft->ismtyp)
3125 		  {	fprintf(fd, "%d", now->lft->val);
3126 		  } else
3127 		  {	putstmnt(fd, now->lft, m);
3128 		  }
3129 		  if (s)
3130 		  {	fprintf(fd, ", \"%s\"", s);
3131 		  } else
3132 		  {	fprintf(fd, ", 0");
3133 		  }
3134 		  fprintf(fd, ")");
3135 		}
3136 		break;
3137 
3138 	case NAME:
3139 		if (!nocast && now->sym && Sym_typ(now) < SHORT)
3140 			putname(fd, "((int)", now, m, ")");
3141 		else
3142 			putname(fd, "", now, m, "");
3143 		break;
3144 
3145 	case   'p':
3146 		putremote(fd, now, m);
3147 		break;
3148 
3149 	case   'q':
3150 		if (terse)
3151 			fprintf(fd, "%s", now->sym?now->sym->name:"?");
3152 		else
3153 			fprintf(fd, "%d", remotelab(now));
3154 		break;
3155 
3156 	case C_EXPR:
3157 		fprintf(fd, "(");
3158 		plunk_expr(fd, now->sym->name);
3159 #if 1
3160 		fprintf(fd, ")");
3161 #else
3162 		fprintf(fd, ") /* %s */ ", now->sym->name);
3163 #endif
3164 		break;
3165 
3166 	case C_CODE:
3167 		if (now->sym)
3168 			fprintf(fd, "/* %s */\n\t\t", now->sym->name);
3169 		if (has_enabled || has_priority)
3170 			fprintf(fd, "if (TstOnly) return 1; /* T6 */\n\t\t");
3171 
3172 		if (now->sym)
3173 			plunk_inline(fd, now->sym->name, 1, GenCode);
3174 		else
3175 			fatal("internal error pangen2.c", (char *) 0);
3176 
3177 		if (!GenCode)
3178 		{	fprintf(fd, "\n");	/* state changed, capture it */
3179 			fprintf(fd, "#if defined(C_States) && (HAS_TRACK==1)\n");
3180 			fprintf(fd, "\t\tc_update((uchar *) &(now.c_state[0]));\n");
3181 			fprintf(fd, "#endif\n");
3182 		}
3183 		break;
3184 
3185 	case ASSERT:
3186 		if (has_enabled || has_priority)
3187 			fprintf(fd, "if (TstOnly) return 1; /* T7 */\n\t\t");
3188 
3189 		cat3("spin_assert(", now->lft, ", ");
3190 		terse = nocast = 1;
3191 		cat3("\"", now->lft, "\", II, tt, t)");
3192 		terse = nocast = 0;
3193 		break;
3194 
3195 	case '.':
3196 	case BREAK:
3197 	case GOTO:
3198 		if (Pid_nr == eventmapnr)
3199 			fprintf(fd, "Uerror(\"cannot get here\")");
3200 		putskip(m);
3201 		break;
3202 
3203 	case '@':
3204 		if (Pid_nr == eventmapnr)
3205 		{	fprintf(fd, "return 0");
3206 			break;
3207 		}
3208 
3209 		if (has_enabled || has_priority)
3210 		{	fprintf(fd, "if (TstOnly)\n\t\t\t");
3211 			fprintf(fd, "return (II+1 == now._nr_pr);\n\t\t");
3212 		}
3213 		fprintf(fd, "if (!delproc(1, II)) ");
3214 		Bailout(fd, "");
3215 		break;
3216 
3217 	default:
3218 		printf("spin: error, %s:%d, bad node type %d (.m)\n",
3219 			now->fn->name, now->ln, now->ntyp);
3220 		fflush(fd);
3221 		alldone(1);
3222 	}
3223 }
3224 
3225 char *
simplify_name(char * s)3226 simplify_name(char *s)
3227 {	char *t = s;
3228 
3229 	if (!old_scope_rules)
3230 	{	while (*t == '_' || isdigit((int)*t))
3231 		{	t++;
3232 	}	}
3233 
3234 	return t;
3235 }
3236 
3237 void
putname(FILE * fd,char * pre,Lextok * n,int m,char * suff)3238 putname(FILE *fd, char *pre, Lextok *n, int m, char *suff) /* varref */
3239 {	Symbol *s = n->sym;
3240 	char *ptr;
3241 
3242 	lineno = n->ln; Fname = n->fn;
3243 
3244 	if (!s)
3245 		fatal("no name - putname", (char *) 0);
3246 
3247 	if (s->context && context && s->type)
3248 		s = findloc(s);		/* it's a local var */
3249 
3250 	if (!s)
3251 	{	fprintf(fd, "%s%s%s", pre, n->sym->name, suff);
3252 		return;
3253 	}
3254 
3255 	if (!s->type)	/* not a local name */
3256 		s = lookup(s->name);	/* must be a global */
3257 
3258 	if (!s->type)
3259 	{	if (strcmp(pre, ".") != 0)
3260 			fatal("undeclared variable '%s'", s->name);
3261 		s->type = INT;
3262 	}
3263 
3264 	if (s->type == PROCTYPE)
3265 		fatal("proctype-name '%s' used as array-name", s->name);
3266 
3267 	fprintf(fd, pre, 0);
3268 	if (!terse && !s->owner && evalindex != 1)
3269 	{	if (old_priority_rules
3270 		&&  strcmp(s->name, "_priority") == 0)
3271 		{	fprintf(fd, "1");
3272 			goto shortcut;
3273 		} else
3274 		{	if (s->context
3275 			||  strcmp(s->name, "_p") == 0
3276 			||  strcmp(s->name, "_pid") == 0
3277 			||  strcmp(s->name, "_priority") == 0)
3278 			{	fprintf(fd, "((P%d *)_this)->", Pid_nr);
3279 			} else
3280 			{	int x = strcmp(s->name, "_");
3281 				if (!(s->hidden&1) && x != 0)
3282 					fprintf(fd, "now.");
3283 				if (x == 0 && _isok == 0)
3284 					fatal("attempt to read value of '_'", 0);
3285 	}	}	}
3286 
3287 	if (terse && buzzed == 1)
3288 	{	fprintf(fd, "B_state.%s", (s->context)?"local[B_pid].":"");
3289 	}
3290 
3291 	ptr = s->name;
3292 
3293 	if (!dont_simplify	/* new 6.4.3 */
3294 	&&  s->type != PREDEF)	/* new 6.0.2 */
3295 	{	if (withprocname
3296 		&&  s->context
3297 		&&  strcmp(pre, "."))
3298 		{	fprintf(fd, "%s:", s->context->name);
3299 			ptr = simplify_name(ptr);
3300 		} else
3301 		{	if (terse)
3302 			{	ptr = simplify_name(ptr);
3303 	}	}	}
3304 
3305 	if (evalindex != 1)
3306 		fprintf(fd, "%s", ptr);
3307 
3308 	if (s->nel > 1 || s->isarray == 1)
3309 	{	if (no_arrays)
3310 		{	non_fatal("ref to array element invalid in this context",
3311 				(char *)0);
3312 			printf("\thint: instead of, e.g., x[rs] qu[3], use\n");
3313 			printf("\tchan nm_3 = qu[3]; x[rs] nm_3;\n");
3314 			printf("\tand use nm_3 in sends/recvs instead of qu[3]\n");
3315 		}
3316 		/* an xr or xs reference to an array element
3317 		 * becomes an exclusion tag on the array itself -
3318 		 * which could result in invalidly labeling
3319 		 * operations on other elements of this array to
3320 		 * be also safe under the partial order reduction
3321 		 * (see procedure has_global())
3322 		 */
3323 
3324 		if (evalindex == 2)
3325 		{	fprintf(fd, "[%%d]");
3326 		} else if (evalindex == 1)
3327 		{	evalindex = 0;		/* no good if index is indexed array */
3328 			fprintf(fd, ", ");
3329 			putstmnt(fd, n->lft, m);
3330 			evalindex = 1;
3331 		} else
3332 		{	if (terse
3333 			|| (n->lft
3334 			&&  n->lft->ntyp == CONST
3335 			&&  n->lft->val < s->nel)
3336 			|| (!n->lft && s->nel > 0))
3337 			{	cat3("[", n->lft, "]");
3338 			} else
3339 			{	/* attempt to catch arrays that are indexed with an array element in the same array
3340 				 * this causes trouble in the verifier in the backtracking
3341 				 * e.g., restoring a[?] in the assignment: a [a[1]] = x where a[1] == 1
3342 				 * but it is hard when the array is inside a structure, so the names dont match
3343 				 */
3344 #if 0
3345 				if (n->lft->ntyp == NAME)
3346 				{	printf("%4d: Basename %s	index %s\n",
3347 						n->lft->ln, s->name, n->lft->sym->name);
3348 				}
3349 #endif
3350 				cat3("[ Index(", n->lft, ", ");
3351 				fprintf(fd, "%d) ]", s->nel);
3352 		}	}
3353 	} else
3354 	{	if (n->lft	/* effectively a scalar, but with an index */
3355 		&& (n->lft->ntyp != CONST
3356 		||  n->lft->val != 0))
3357 		{	fatal("ref to scalar '%s' using array index", (char *) ptr);
3358 	}	}
3359 
3360 	if (s->type == STRUCT && n->rgt && n->rgt->lft)
3361 	{	putname(fd, ".", n->rgt->lft, m, "");
3362 	}
3363 shortcut:
3364 	fprintf(fd, suff, 0);
3365 }
3366 
3367 void
putremote(FILE * fd,Lextok * n,int m)3368 putremote(FILE *fd, Lextok *n, int m)	/* remote reference */
3369 {	int promoted = 0;
3370 	int pt;
3371 
3372 	if (terse)
3373 	{	fprintf(fd, "%s", n->lft->sym->name);	/* proctype name */
3374 		if (n->lft->lft)
3375 		{	fprintf(fd, "[");
3376 			putstmnt(fd, n->lft->lft, m);	/* pid */
3377 			fprintf(fd, "]");
3378 		}
3379 		if (ltl_mode)
3380 		{	fprintf(fd, ":%s", n->sym->name);
3381 		} else
3382 		{	fprintf(fd, ".%s", n->sym->name);
3383 		}
3384 	} else
3385 	{	if (Sym_typ(n) < SHORT)
3386 		{	promoted = 1;
3387 			fprintf(fd, "((int)");
3388 		}
3389 
3390 		pt = fproc(n->lft->sym->name);
3391 		fprintf(fd, "((P%d *)Pptr(", pt);
3392 		if (n->lft->lft)
3393 		{	fprintf(fd, "BASE+");
3394 			putstmnt(fd, n->lft->lft, m);
3395 		} else
3396 			fprintf(fd, "f_pid(%d)", pt);
3397 		fprintf(fd, "))->%s", n->sym->name);
3398 	}
3399 	if (n->rgt)
3400 	{	fprintf(fd, "[");
3401 		putstmnt(fd, n->rgt, m);	/* array var ref */
3402 		fprintf(fd, "]");
3403 	}
3404 	if (promoted) fprintf(fd, ")");
3405 }
3406 
3407 static int
getweight(Lextok * n)3408 getweight(Lextok *n)
3409 {	/* this piece of code is a remnant of early versions
3410 	 * of the verifier -- in the current version of Spin
3411 	 * only non-zero values matter - so this could probably
3412 	 * simply return 1 in all cases.
3413 	 */
3414 	switch (n->ntyp) {
3415 	case 'r':     return 4;
3416 	case 's':     return 2;
3417 	case TIMEOUT: return 1;
3418 	case 'c':     if (has_typ(n->lft, TIMEOUT)) return 1;
3419 	}
3420 	return 3;
3421 }
3422 
3423 int
has_typ(Lextok * n,int m)3424 has_typ(Lextok *n, int m)
3425 {
3426 	if (!n) return 0;
3427 	if (n->ntyp == m) return 1;
3428 	return (has_typ(n->lft, m) || has_typ(n->rgt, m));
3429 }
3430 
3431 static int runcount, opcount;
3432 
3433 static void
do_count(Lextok * n,int checkop)3434 do_count(Lextok *n, int checkop)
3435 {
3436 	if (!n) return;
3437 
3438 	switch (n->ntyp) {
3439 	case RUN:
3440 		runcount++;
3441 		break;
3442 	default:
3443 		if (checkop) opcount++;
3444 		break;
3445 	}
3446 	do_count(n->lft, checkop && (n->ntyp != RUN));
3447 	do_count(n->rgt, checkop);
3448 }
3449 
3450 void
count_runs(Lextok * n)3451 count_runs(Lextok *n)
3452 {
3453 	runcount = opcount = 0;
3454 	do_count(n, 1);
3455 	if (runcount > 1)
3456 		fatal("more than one run operator in expression", "");
3457 	if (runcount == 1 && opcount > 1)
3458 		fatal("use of run operator in compound expression", "");
3459 }
3460 
3461 void
any_runs(Lextok * n)3462 any_runs(Lextok *n)
3463 {
3464 	runcount = opcount = 0;
3465 	do_count(n, 0);
3466 	if (runcount >= 1)
3467 		fatal("run operator used in invalid context", "");
3468 }
3469