xref: /plan9-contrib/sys/src/cmd/spin/main.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
1219b2ee8SDavid du Colombier /***** spin: main.c *****/
2219b2ee8SDavid du Colombier 
3*de2caf28SDavid du Colombier /*
4*de2caf28SDavid du Colombier  * This file is part of the public release of Spin. It is subject to the
5*de2caf28SDavid du Colombier  * terms in the LICENSE file that is included in this source directory.
6*de2caf28SDavid du Colombier  * Tool documentation is available at http://spinroot.com
7*de2caf28SDavid du Colombier  */
8219b2ee8SDavid du Colombier 
9219b2ee8SDavid du Colombier #include <stdlib.h>
10*de2caf28SDavid du Colombier #include <assert.h>
117dd7cddfSDavid du Colombier #include "spin.h"
127dd7cddfSDavid du Colombier #include "version.h"
1300d97012SDavid du Colombier #include <sys/types.h>
1400d97012SDavid du Colombier #include <sys/stat.h>
157dd7cddfSDavid du Colombier #include <signal.h>
167dd7cddfSDavid du Colombier #include <time.h>
177dd7cddfSDavid du Colombier #ifdef PC
187dd7cddfSDavid du Colombier  #include <io.h>
197dd7cddfSDavid du Colombier #else
20219b2ee8SDavid du Colombier  #include <unistd.h>
217dd7cddfSDavid du Colombier #endif
22f3793cddSDavid du Colombier #include "y.tab.h"
23219b2ee8SDavid du Colombier 
247dd7cddfSDavid du Colombier extern int	DstepStart, lineno, tl_terse;
257dd7cddfSDavid du Colombier extern FILE	*yyin, *yyout, *tl_out;
267dd7cddfSDavid du Colombier extern Symbol	*context;
277dd7cddfSDavid du Colombier extern char	*claimproc;
28312a1df1SDavid du Colombier extern void	repro_src(void);
297dd7cddfSDavid du Colombier extern void	qhide(int);
3000d97012SDavid du Colombier extern char	CurScope[MAXSCOPESZ];
31*de2caf28SDavid du Colombier extern short	has_provided, has_code, has_ltl, has_accept;
32*de2caf28SDavid du Colombier extern int	realread, buzzed;
33*de2caf28SDavid du Colombier extern void	ana_src(int, int);
34*de2caf28SDavid du Colombier extern void	putprelude(void);
35*de2caf28SDavid du Colombier 
36*de2caf28SDavid du Colombier static void	add_comptime(char *);
37*de2caf28SDavid du Colombier static void	add_runtime(char *);
38219b2ee8SDavid du Colombier 
39219b2ee8SDavid du Colombier Symbol	*Fname, *oFname;
40219b2ee8SDavid du Colombier 
41312a1df1SDavid du Colombier int	Etimeouts;	/* nr timeouts in program */
42312a1df1SDavid du Colombier int	Ntimeouts;	/* nr timeouts in never claim */
43312a1df1SDavid du Colombier int	analyze, columns, dumptab, has_remote, has_remvar;
44312a1df1SDavid du Colombier int	interactive, jumpsteps, m_loss, nr_errs, cutoff;
45312a1df1SDavid du Colombier int	s_trail, ntrail, verbose, xspin, notabs, rvopt;
46312a1df1SDavid du Colombier int	no_print, no_wrapup, Caccess, limited_vis, like_java;
47312a1df1SDavid du Colombier int	separate;	/* separate compilation */
48312a1df1SDavid du Colombier int	export_ast;	/* pangen5.c */
49*de2caf28SDavid du Colombier int	norecompile;	/* main.c */
5000d97012SDavid du Colombier int	old_scope_rules;	/* use pre 5.3.0 rules */
51*de2caf28SDavid du Colombier int	old_priority_rules;	/* use pre 6.2.0 rules */
52*de2caf28SDavid du Colombier int	product, Strict;
53*de2caf28SDavid du Colombier short	replay;
54312a1df1SDavid du Colombier 
55*de2caf28SDavid du Colombier int	merger = 1, deadvar = 1, implied_semis = 1;
5600d97012SDavid du Colombier int	ccache = 0; /* oyvind teig: 5.2.0 case caching off by default */
57312a1df1SDavid du Colombier 
58*de2caf28SDavid du Colombier static int preprocessonly, SeedUsed, itsr, itsr_n, sw_or_bt;
5900d97012SDavid du Colombier static int seedy;	/* be verbose about chosen seed */
6000d97012SDavid du Colombier static int inlineonly;	/* show inlined code */
6100d97012SDavid du Colombier static int dataflow = 1;
62312a1df1SDavid du Colombier 
637dd7cddfSDavid du Colombier #if 0
647dd7cddfSDavid du Colombier meaning of flags on verbose:
657dd7cddfSDavid du Colombier 	1	-g global variable values
667dd7cddfSDavid du Colombier 	2	-l local variable values
677dd7cddfSDavid du Colombier 	4	-p all process actions
687dd7cddfSDavid du Colombier 	8	-r receives
697dd7cddfSDavid du Colombier 	16	-s sends
707dd7cddfSDavid du Colombier 	32	-v verbose
717dd7cddfSDavid du Colombier 	64	-w very verbose
727dd7cddfSDavid du Colombier #endif
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier static char	Operator[] = "operator: ";
757dd7cddfSDavid du Colombier static char	Keyword[]  = "keyword: ";
767dd7cddfSDavid du Colombier static char	Function[] = "function-name: ";
777dd7cddfSDavid du Colombier static char	**add_ltl  = (char **) 0;
787dd7cddfSDavid du Colombier static char	**ltl_file = (char **) 0;
797dd7cddfSDavid du Colombier static char	**nvr_file = (char **) 0;
8000d97012SDavid du Colombier static char	*ltl_claims = (char *) 0;
81*de2caf28SDavid du Colombier static char	*pan_runtime = "";
82*de2caf28SDavid du Colombier static char	*pan_comptime = "";
83*de2caf28SDavid du Colombier static char	*formula = NULL;
8400d97012SDavid du Colombier static FILE	*fd_ltl = (FILE *) 0;
857dd7cddfSDavid du Colombier static char	*PreArg[64];
867dd7cddfSDavid du Colombier static int	PreCnt = 0;
877dd7cddfSDavid du Colombier static char	out1[64];
887dd7cddfSDavid du Colombier 
8900d97012SDavid du Colombier char	**trailfilename;	/* new option 'k' */
9000d97012SDavid du Colombier 
9100d97012SDavid du Colombier void	explain(int);
9200d97012SDavid du Colombier 
93*de2caf28SDavid du Colombier #ifndef CPP
9400d97012SDavid du Colombier 	/* to use visual C++:
95*de2caf28SDavid du Colombier 		#define CPP	"cl -E/E"
96*de2caf28SDavid du Colombier 	   or call spin as:	spin -P"CL -E/E"
9700d97012SDavid du Colombier 
9800d97012SDavid du Colombier 	   on OS2:
9900d97012SDavid du Colombier 		#define CPP	"icc -E/Pd+ -E/Q+"
100*de2caf28SDavid du Colombier 	   or call spin as:	spin -P"icc -E/Pd+ -E/Q+"
101*de2caf28SDavid du Colombier 	   make sure the -E arg is always at the end,
102*de2caf28SDavid du Colombier 	   in each case, because the command line
103*de2caf28SDavid du Colombier 	   can later be truncated at that point
10400d97012SDavid du Colombier 	*/
105*de2caf28SDavid du Colombier  #if 1
106*de2caf28SDavid du Colombier 	#define CPP	"gcc -std=gnu99 -Wformat-overflow=0 -E -x c"
10700d97012SDavid du Colombier 	/* if gcc-4 is available, this setting is modified below */
1087dd7cddfSDavid du Colombier  #else
109*de2caf28SDavid du Colombier 	#if defined(PC) || defined(MAC)
110*de2caf28SDavid du Colombier 		#define CPP	"gcc -std=gnu99 -E -x c"
111*de2caf28SDavid du Colombier 	#else
1127dd7cddfSDavid du Colombier 		#ifdef SOLARIS
1137dd7cddfSDavid du Colombier 			#define CPP	"/usr/ccs/lib/cpp"
1147dd7cddfSDavid du Colombier 		#else
115*de2caf28SDavid du Colombier 			#define CPP	"cpp"	/* sometimes: "/lib/cpp" */
1167dd7cddfSDavid du Colombier 		#endif
1177dd7cddfSDavid du Colombier 	#endif
1187dd7cddfSDavid du Colombier  #endif
1197dd7cddfSDavid du Colombier #endif
12000d97012SDavid du Colombier 
121*de2caf28SDavid du Colombier static char	PreProc[512];
122312a1df1SDavid du Colombier extern int	depth; /* at least some steps were made */
123219b2ee8SDavid du Colombier 
124*de2caf28SDavid du Colombier int
WhatSeed(void)125*de2caf28SDavid du Colombier WhatSeed(void)
126*de2caf28SDavid du Colombier {
127*de2caf28SDavid du Colombier 	return SeedUsed;
128*de2caf28SDavid du Colombier }
129*de2caf28SDavid du Colombier 
130*de2caf28SDavid du Colombier void
final_fiddle(void)131*de2caf28SDavid du Colombier final_fiddle(void)
132*de2caf28SDavid du Colombier {	char *has_a, *has_l, *has_f;
133*de2caf28SDavid du Colombier 
134*de2caf28SDavid du Colombier 	/* no -a or -l but has_accept: add -a */
135*de2caf28SDavid du Colombier 	/* no -a or -l in pan_runtime: add -DSAFETY to pan_comptime */
136*de2caf28SDavid du Colombier 	/* -a or -l but no -f then add -DNOFAIR */
137*de2caf28SDavid du Colombier 
138*de2caf28SDavid du Colombier 	has_a = strstr(pan_runtime, "-a");
139*de2caf28SDavid du Colombier 	has_l = strstr(pan_runtime, "-l");
140*de2caf28SDavid du Colombier 	has_f = strstr(pan_runtime, "-f");
141*de2caf28SDavid du Colombier 
142*de2caf28SDavid du Colombier 	if (!has_l && !has_a && strstr(pan_comptime, "-DNP"))
143*de2caf28SDavid du Colombier 	{	add_runtime("-l");
144*de2caf28SDavid du Colombier 		has_l = strstr(pan_runtime, "-l");
145*de2caf28SDavid du Colombier 	}
146*de2caf28SDavid du Colombier 
147*de2caf28SDavid du Colombier 	if (!has_a && !has_l
148*de2caf28SDavid du Colombier 	&&  !strstr(pan_comptime, "-DSAFETY"))
149*de2caf28SDavid du Colombier 	{	if (has_accept
150*de2caf28SDavid du Colombier 		&& !strstr(pan_comptime, "-DBFS")
151*de2caf28SDavid du Colombier 		&& !strstr(pan_comptime, "-DNOCLAIM"))
152*de2caf28SDavid du Colombier 		{	add_runtime("-a");
153*de2caf28SDavid du Colombier 			has_a = pan_runtime;
154*de2caf28SDavid du Colombier 		} else
155*de2caf28SDavid du Colombier 		{	add_comptime("-DSAFETY");
156*de2caf28SDavid du Colombier 	}	}
157*de2caf28SDavid du Colombier 
158*de2caf28SDavid du Colombier 	if ((has_a || has_l) && !has_f
159*de2caf28SDavid du Colombier 	&&  !strstr(pan_comptime, "-DNOFAIR"))
160*de2caf28SDavid du Colombier 	{	add_comptime("-DNOFAIR");
161*de2caf28SDavid du Colombier 	}
162*de2caf28SDavid du Colombier }
163*de2caf28SDavid du Colombier 
164*de2caf28SDavid du Colombier static int
change_param(char * t,char * what,int range,int bottom)165*de2caf28SDavid du Colombier change_param(char *t, char *what, int range, int bottom)
166*de2caf28SDavid du Colombier {	char *ptr;
167*de2caf28SDavid du Colombier 	int v;
168*de2caf28SDavid du Colombier 
169*de2caf28SDavid du Colombier 	assert(range < 1000 && range > 0);
170*de2caf28SDavid du Colombier 	if ((ptr = strstr(t, what)) != NULL)
171*de2caf28SDavid du Colombier 	{	ptr += strlen(what);
172*de2caf28SDavid du Colombier 		if (!isdigit((int) *ptr))
173*de2caf28SDavid du Colombier 		{	return 0;
174*de2caf28SDavid du Colombier 		}
175*de2caf28SDavid du Colombier 		v = atoi(ptr) + 1;	/* was: v = (atoi(ptr)+1)%range */
176*de2caf28SDavid du Colombier 		if (v >= range)
177*de2caf28SDavid du Colombier 		{	v = bottom;
178*de2caf28SDavid du Colombier 		}
179*de2caf28SDavid du Colombier 		if (v >= 100)
180*de2caf28SDavid du Colombier 		{	*ptr++ = '0' + (v/100); v %= 100;
181*de2caf28SDavid du Colombier 			*ptr++ = '0' + (v/10);
182*de2caf28SDavid du Colombier 			*ptr   = '0' + (v%10);
183*de2caf28SDavid du Colombier 		} else if (v >= 10)
184*de2caf28SDavid du Colombier 		{	*ptr++ = '0' + (v/10);
185*de2caf28SDavid du Colombier 			*ptr++ = '0' + (v%10);
186*de2caf28SDavid du Colombier 			*ptr   = ' ';
187*de2caf28SDavid du Colombier 		} else
188*de2caf28SDavid du Colombier 		{	*ptr++ = '0' + v;
189*de2caf28SDavid du Colombier 			*ptr++ = ' ';
190*de2caf28SDavid du Colombier 			*ptr   = ' ';
191*de2caf28SDavid du Colombier 	}	}
192*de2caf28SDavid du Colombier 	return 1;
193*de2caf28SDavid du Colombier }
194*de2caf28SDavid du Colombier 
195*de2caf28SDavid du Colombier static void
change_rs(char * t)196*de2caf28SDavid du Colombier change_rs(char *t)
197*de2caf28SDavid du Colombier {	char *ptr;
198*de2caf28SDavid du Colombier 	int cnt = 0;
199*de2caf28SDavid du Colombier 	long v;
200*de2caf28SDavid du Colombier 
201*de2caf28SDavid du Colombier 	if ((ptr = strstr(t, "-RS")) != NULL)
202*de2caf28SDavid du Colombier 	{	ptr += 3;
203*de2caf28SDavid du Colombier 		/* room for at least 10 digits */
204*de2caf28SDavid du Colombier 		v = Rand()%1000000000L;
205*de2caf28SDavid du Colombier 		while (v/10 > 0)
206*de2caf28SDavid du Colombier 		{	*ptr++ = '0' + v%10;
207*de2caf28SDavid du Colombier 			v /= 10;
208*de2caf28SDavid du Colombier 			cnt++;
209*de2caf28SDavid du Colombier 		}
210*de2caf28SDavid du Colombier 		*ptr++ = '0' + v;
211*de2caf28SDavid du Colombier 		cnt++;
212*de2caf28SDavid du Colombier 		while (cnt++ < 10)
213*de2caf28SDavid du Colombier 		{	*ptr++ = ' ';
214*de2caf28SDavid du Colombier 	}	}
215*de2caf28SDavid du Colombier }
216*de2caf28SDavid du Colombier 
217*de2caf28SDavid du Colombier int
omit_str(char * in,char * s)218*de2caf28SDavid du Colombier omit_str(char *in, char *s)
219*de2caf28SDavid du Colombier {	char *ptr = strstr(in, s);
220*de2caf28SDavid du Colombier 	int i, nr = -1;
221*de2caf28SDavid du Colombier 
222*de2caf28SDavid du Colombier 	if (ptr)
223*de2caf28SDavid du Colombier 	{	for (i = 0; i < (int) strlen(s); i++)
224*de2caf28SDavid du Colombier 		{	*ptr++ = ' ';
225*de2caf28SDavid du Colombier 		}
226*de2caf28SDavid du Colombier 		if (isdigit((int) *ptr))
227*de2caf28SDavid du Colombier 		{	nr = atoi(ptr);
228*de2caf28SDavid du Colombier 			while (isdigit((int) *ptr))
229*de2caf28SDavid du Colombier 			{	*ptr++ = ' ';
230*de2caf28SDavid du Colombier 	}	}	}
231*de2caf28SDavid du Colombier 	return nr;
232*de2caf28SDavid du Colombier }
233*de2caf28SDavid du Colombier 
234*de2caf28SDavid du Colombier void
string_trim(char * t)235*de2caf28SDavid du Colombier string_trim(char *t)
236*de2caf28SDavid du Colombier {	int n = strlen(t) - 1;
237*de2caf28SDavid du Colombier 
238*de2caf28SDavid du Colombier 	while (n > 0 && t[n] == ' ')
239*de2caf28SDavid du Colombier 	{	t[n--] = '\0';
240*de2caf28SDavid du Colombier 	}
241*de2caf28SDavid du Colombier }
242*de2caf28SDavid du Colombier 
243*de2caf28SDavid du Colombier int
e_system(int v,const char * s)244*de2caf28SDavid du Colombier e_system(int v, const char *s)
245*de2caf28SDavid du Colombier {	static int count = 1;
246*de2caf28SDavid du Colombier 
247*de2caf28SDavid du Colombier 	/* v == 0 : checks to find non-linked version of gcc */
248*de2caf28SDavid du Colombier 	/* v == 1 : all other commands */
249*de2caf28SDavid du Colombier 	/* v == 2 : preprocessing the promela input */
250*de2caf28SDavid du Colombier 
251*de2caf28SDavid du Colombier 	if (v == 1)
252*de2caf28SDavid du Colombier 	{	if (verbose&(32|64))	/* -v or -w */
253*de2caf28SDavid du Colombier 		{	printf("cmd%02d: %s\n", count++, s);
254*de2caf28SDavid du Colombier 			fflush(stdout);
255*de2caf28SDavid du Colombier 		}
256*de2caf28SDavid du Colombier 		if (verbose&64)		/* only -w */
257*de2caf28SDavid du Colombier 		{	return 0;	/* suppress the call to system(s) */
258*de2caf28SDavid du Colombier 	}	}
259*de2caf28SDavid du Colombier 	return system(s);
260*de2caf28SDavid du Colombier }
261*de2caf28SDavid du Colombier 
262219b2ee8SDavid du Colombier void
alldone(int estatus)2637dd7cddfSDavid du Colombier alldone(int estatus)
264*de2caf28SDavid du Colombier {	char *ptr;
265*de2caf28SDavid du Colombier #if defined(WIN32) || defined(WIN64)
266*de2caf28SDavid du Colombier 	struct _stat x;
267*de2caf28SDavid du Colombier #else
268*de2caf28SDavid du Colombier 	struct stat x;
269*de2caf28SDavid du Colombier #endif
270*de2caf28SDavid du Colombier 	if (preprocessonly == 0 &&  strlen(out1) > 0)
271*de2caf28SDavid du Colombier 	{	(void) unlink((const char *) out1);
272*de2caf28SDavid du Colombier 	}
273312a1df1SDavid du Colombier 
274*de2caf28SDavid du Colombier 	(void) unlink(TMP_FILE1);
275*de2caf28SDavid du Colombier 	(void) unlink(TMP_FILE2);
276*de2caf28SDavid du Colombier 
277*de2caf28SDavid du Colombier 	if (!buzzed && seedy && !analyze && !export_ast
278312a1df1SDavid du Colombier 	&& !s_trail && !preprocessonly && depth > 0)
279*de2caf28SDavid du Colombier 	{	printf("seed used: %d\n", SeedUsed);
280*de2caf28SDavid du Colombier 	}
281312a1df1SDavid du Colombier 
282*de2caf28SDavid du Colombier 	if (!buzzed && xspin && (analyze || s_trail))
2837dd7cddfSDavid du Colombier 	{	if (estatus)
284*de2caf28SDavid du Colombier 		{	printf("spin: %d error(s) - aborting\n",
2857dd7cddfSDavid du Colombier 				estatus);
286*de2caf28SDavid du Colombier 		} else
287*de2caf28SDavid du Colombier 		{	printf("Exit-Status 0\n");
288*de2caf28SDavid du Colombier 	}	}
289*de2caf28SDavid du Colombier 
290*de2caf28SDavid du Colombier 	if (buzzed && replay && !has_code && !estatus)
291*de2caf28SDavid du Colombier 	{	extern QH *qh_lst;
292*de2caf28SDavid du Colombier 		QH *j;
293*de2caf28SDavid du Colombier 		int i;
294*de2caf28SDavid du Colombier 
295*de2caf28SDavid du Colombier 		pan_runtime = (char *) emalloc(2048);	/* more than enough */
296*de2caf28SDavid du Colombier 		sprintf(pan_runtime, "-n%d ", SeedUsed);
297*de2caf28SDavid du Colombier 		if (jumpsteps)
298*de2caf28SDavid du Colombier 		{	sprintf(&pan_runtime[strlen(pan_runtime)], "-j%d ", jumpsteps);
299*de2caf28SDavid du Colombier 		}
300*de2caf28SDavid du Colombier 		if (trailfilename)
301*de2caf28SDavid du Colombier 		{	sprintf(&pan_runtime[strlen(pan_runtime)], "-k%s ", *trailfilename);
302*de2caf28SDavid du Colombier 		}
303*de2caf28SDavid du Colombier 		if (cutoff)
304*de2caf28SDavid du Colombier 		{	sprintf(&pan_runtime[strlen(pan_runtime)], "-u%d ", cutoff);
305*de2caf28SDavid du Colombier 		}
306*de2caf28SDavid du Colombier 		for (i = 1; i <= PreCnt; i++)
307*de2caf28SDavid du Colombier 		{	strcat(pan_runtime, PreArg[i]);
308*de2caf28SDavid du Colombier 			strcat(pan_runtime, " ");
309*de2caf28SDavid du Colombier 		}
310*de2caf28SDavid du Colombier 		for (j = qh_lst; j; j = j->nxt)
311*de2caf28SDavid du Colombier 		{	sprintf(&pan_runtime[strlen(pan_runtime)], "-q%d ", j->n);
312*de2caf28SDavid du Colombier 		}
313*de2caf28SDavid du Colombier 		if (strcmp(PreProc, CPP) != 0)
314*de2caf28SDavid du Colombier 		{	sprintf(&pan_runtime[strlen(pan_runtime)], "\"-P%s\" ", PreProc);
315*de2caf28SDavid du Colombier 		}
316*de2caf28SDavid du Colombier 		/* -oN options 1..5 are ignored in simulations */
317*de2caf28SDavid du Colombier 		if (old_priority_rules) strcat(pan_runtime, "-o6 ");
318*de2caf28SDavid du Colombier 		if (!implied_semis)  strcat(pan_runtime, "-o7 ");
319*de2caf28SDavid du Colombier 		if (no_print)        strcat(pan_runtime, "-b ");
320*de2caf28SDavid du Colombier 		if (no_wrapup)       strcat(pan_runtime, "-B ");
321*de2caf28SDavid du Colombier 		if (columns == 1)    strcat(pan_runtime, "-c ");
322*de2caf28SDavid du Colombier 		if (columns == 2)    strcat(pan_runtime, "-M ");
323*de2caf28SDavid du Colombier 		if (seedy == 1)      strcat(pan_runtime, "-h ");
324*de2caf28SDavid du Colombier 		if (like_java == 1)  strcat(pan_runtime, "-J ");
325*de2caf28SDavid du Colombier 		if (old_scope_rules) strcat(pan_runtime, "-O ");
326*de2caf28SDavid du Colombier 		if (notabs)          strcat(pan_runtime, "-T ");
327*de2caf28SDavid du Colombier 		if (verbose&1)       strcat(pan_runtime, "-g ");
328*de2caf28SDavid du Colombier 		if (verbose&2)       strcat(pan_runtime, "-l ");
329*de2caf28SDavid du Colombier 		if (verbose&4)       strcat(pan_runtime, "-p ");
330*de2caf28SDavid du Colombier 		if (verbose&8)       strcat(pan_runtime, "-r ");
331*de2caf28SDavid du Colombier 		if (verbose&16)      strcat(pan_runtime, "-s ");
332*de2caf28SDavid du Colombier 		if (verbose&32)      strcat(pan_runtime, "-v ");
333*de2caf28SDavid du Colombier 		if (verbose&64)      strcat(pan_runtime, "-w ");
334*de2caf28SDavid du Colombier 		if (m_loss)          strcat(pan_runtime, "-m ");
335*de2caf28SDavid du Colombier 
336*de2caf28SDavid du Colombier 		char *tmp = (char *) emalloc(strlen("spin -t") +
337*de2caf28SDavid du Colombier 				strlen(pan_runtime) + strlen(Fname->name) + 8);
338*de2caf28SDavid du Colombier 
339*de2caf28SDavid du Colombier 		sprintf(tmp, "spin -t %s %s", pan_runtime, Fname->name);
340*de2caf28SDavid du Colombier 		estatus = e_system(1, tmp);	/* replay */
341*de2caf28SDavid du Colombier 		exit(estatus);	/* replay without c_code */
342*de2caf28SDavid du Colombier 	}
343*de2caf28SDavid du Colombier 
344*de2caf28SDavid du Colombier 	if (buzzed && (!replay || has_code) && !estatus)
345*de2caf28SDavid du Colombier 	{	char *tmp, *tmp2 = NULL, *P_X;
346*de2caf28SDavid du Colombier 		char *C_X = (buzzed == 2) ? "-O" : "";
347*de2caf28SDavid du Colombier 
348*de2caf28SDavid du Colombier 		if (replay && strlen(pan_comptime) == 0)
349*de2caf28SDavid du Colombier 		{
350*de2caf28SDavid du Colombier #if defined(WIN32) || defined(WIN64)
351*de2caf28SDavid du Colombier 			P_X = "pan";
352*de2caf28SDavid du Colombier #else
353*de2caf28SDavid du Colombier 			P_X = "./pan";
354*de2caf28SDavid du Colombier #endif
355*de2caf28SDavid du Colombier 			if (stat(P_X, (struct stat *)&x) < 0)
356*de2caf28SDavid du Colombier 			{	goto recompile;	/* no executable pan for replay */
357*de2caf28SDavid du Colombier 			}
358*de2caf28SDavid du Colombier 			tmp = (char *) emalloc(8 + strlen(P_X) + strlen(pan_runtime) +4);
359*de2caf28SDavid du Colombier 			/* the final +4 is too allow adding " &" in some cases */
360*de2caf28SDavid du Colombier 			sprintf(tmp, "%s %s", P_X, pan_runtime);
361*de2caf28SDavid du Colombier 			goto runit;
362*de2caf28SDavid du Colombier 		}
363*de2caf28SDavid du Colombier #if defined(WIN32) || defined(WIN64)
364*de2caf28SDavid du Colombier 		P_X = "-o pan pan.c && pan";
365*de2caf28SDavid du Colombier #else
366*de2caf28SDavid du Colombier 		P_X = "-o pan pan.c && ./pan";
367*de2caf28SDavid du Colombier #endif
368*de2caf28SDavid du Colombier 		/* swarm and biterate randomization additions */
369*de2caf28SDavid du Colombier 		if (!replay && itsr)	/* iterative search refinement */
370*de2caf28SDavid du Colombier 		{	if (!strstr(pan_comptime, "-DBITSTATE"))
371*de2caf28SDavid du Colombier 			{	add_comptime("-DBITSTATE");
372*de2caf28SDavid du Colombier 			}
373*de2caf28SDavid du Colombier 			if (!strstr(pan_comptime, "-DPUTPID"))
374*de2caf28SDavid du Colombier 			{	add_comptime("-DPUTPID");
375*de2caf28SDavid du Colombier 			}
376*de2caf28SDavid du Colombier 			if (!strstr(pan_comptime, "-DT_RAND")
377*de2caf28SDavid du Colombier 			&&  !strstr(pan_comptime, "-DT_REVERSE"))
378*de2caf28SDavid du Colombier 			{	add_runtime("-T0  ");	/* controls t_reverse */
379*de2caf28SDavid du Colombier 			}
380*de2caf28SDavid du Colombier 			if (!strstr(pan_runtime, "-P")	/* runtime flag */
381*de2caf28SDavid du Colombier 			||   pan_runtime[2] < '0'
382*de2caf28SDavid du Colombier 			||   pan_runtime[2] > '1') /* no -P0 or -P1 */
383*de2caf28SDavid du Colombier 			{	add_runtime("-P0  ");	/* controls p_reverse */
384*de2caf28SDavid du Colombier 			}
385*de2caf28SDavid du Colombier 			if (!strstr(pan_runtime, "-w"))
386*de2caf28SDavid du Colombier 			{	add_runtime("-w18 ");	/* -w18 = 256K */
387*de2caf28SDavid du Colombier 			} else
388*de2caf28SDavid du Colombier 			{	char nv[32];
389*de2caf28SDavid du Colombier 				int x;
390*de2caf28SDavid du Colombier 				x = omit_str(pan_runtime, "-w");
391*de2caf28SDavid du Colombier 				if (x >= 0)
392*de2caf28SDavid du Colombier 				{	sprintf(nv, "-w%d  ", x);
393*de2caf28SDavid du Colombier 					add_runtime(nv); /* added spaces */
394*de2caf28SDavid du Colombier 			}	}
395*de2caf28SDavid du Colombier 			if (!strstr(pan_runtime, "-h"))
396*de2caf28SDavid du Colombier 			{	add_runtime("-h0  ");	/* 0..499 */
397*de2caf28SDavid du Colombier 				/* leave 2 spaces for increments up to -h499 */
398*de2caf28SDavid du Colombier 			} else if (!strstr(pan_runtime, "-hash"))
399*de2caf28SDavid du Colombier 			{	char nv[32];
400*de2caf28SDavid du Colombier 				int x;
401*de2caf28SDavid du Colombier 				x = omit_str(pan_runtime, "-h");
402*de2caf28SDavid du Colombier 				if (x >= 0)
403*de2caf28SDavid du Colombier 				{	sprintf(nv, "-h%d  ", x%500);
404*de2caf28SDavid du Colombier 					add_runtime(nv); /* added spaces */
405*de2caf28SDavid du Colombier 			}	}
406*de2caf28SDavid du Colombier 			if (!strstr(pan_runtime, "-k"))
407*de2caf28SDavid du Colombier 			{	add_runtime("-k1  ");	/* 1..3 */
408*de2caf28SDavid du Colombier 			} else
409*de2caf28SDavid du Colombier 			{	char nv[32];
410*de2caf28SDavid du Colombier 				int x;
411*de2caf28SDavid du Colombier 				x = omit_str(pan_runtime, "-k");
412*de2caf28SDavid du Colombier 				if (x >= 0)
413*de2caf28SDavid du Colombier 				{	sprintf(nv, "-k%d  ", x%4);
414*de2caf28SDavid du Colombier 					add_runtime(nv); /* added spaces */
415*de2caf28SDavid du Colombier 			}	}
416*de2caf28SDavid du Colombier 			if (strstr(pan_runtime, "-p_rotate"))
417*de2caf28SDavid du Colombier 			{	char nv[32];
418*de2caf28SDavid du Colombier 				int x;
419*de2caf28SDavid du Colombier 				x = omit_str(pan_runtime, "-p_rotate");
420*de2caf28SDavid du Colombier 				if (x < 0)
421*de2caf28SDavid du Colombier 				{	x = 0;
422*de2caf28SDavid du Colombier 				}
423*de2caf28SDavid du Colombier 				sprintf(nv, "-p_rotate%d  ", x%256);
424*de2caf28SDavid du Colombier 				add_runtime(nv); /* added spaces */
425*de2caf28SDavid du Colombier 			} else if (strstr(pan_runtime, "-p_permute") == 0)
426*de2caf28SDavid du Colombier 			{	add_runtime("-p_rotate0  ");
427*de2caf28SDavid du Colombier 			}
428*de2caf28SDavid du Colombier 			if (strstr(pan_runtime, "-RS"))
429*de2caf28SDavid du Colombier 			{	(void) omit_str(pan_runtime, "-RS");
430*de2caf28SDavid du Colombier 			}
431*de2caf28SDavid du Colombier 			/* need room for at least 10 digits */
432*de2caf28SDavid du Colombier 			add_runtime("-RS1234567890 ");
433*de2caf28SDavid du Colombier 			change_rs(pan_runtime);
434*de2caf28SDavid du Colombier 		}
435*de2caf28SDavid du Colombier recompile:
436*de2caf28SDavid du Colombier 		if (strstr(PreProc, "cpp"))	/* unix/linux */
437*de2caf28SDavid du Colombier 		{	strcpy(PreProc, "gcc");	/* need compiler */
438*de2caf28SDavid du Colombier 		} else if ((tmp = strstr(PreProc, "-E")) != NULL)
439*de2caf28SDavid du Colombier 		{	*tmp = '\0'; /* strip preprocessing flags */
440*de2caf28SDavid du Colombier 		}
441*de2caf28SDavid du Colombier 
442*de2caf28SDavid du Colombier 		final_fiddle();
443*de2caf28SDavid du Colombier 		tmp = (char *) emalloc(8 +	/* account for alignment */
444*de2caf28SDavid du Colombier 				strlen(PreProc) +
445*de2caf28SDavid du Colombier 				strlen(C_X) +
446*de2caf28SDavid du Colombier 				strlen(pan_comptime) +
447*de2caf28SDavid du Colombier 				strlen(P_X) +
448*de2caf28SDavid du Colombier 				strlen(pan_runtime) +
449*de2caf28SDavid du Colombier 				strlen(" -p_reverse & "));
450*de2caf28SDavid du Colombier 		tmp2 = tmp;
451*de2caf28SDavid du Colombier 
452*de2caf28SDavid du Colombier 		/* P_X ends with " && ./pan " */
453*de2caf28SDavid du Colombier 		sprintf(tmp, "%s %s %s %s %s",
454*de2caf28SDavid du Colombier 			PreProc, C_X, pan_comptime, P_X, pan_runtime);
455*de2caf28SDavid du Colombier 
456*de2caf28SDavid du Colombier 		if (!replay)
457*de2caf28SDavid du Colombier 		{	if (itsr < 0)		/* swarm only */
458*de2caf28SDavid du Colombier 			{	strcat(tmp, " &"); /* after ./pan */
459*de2caf28SDavid du Colombier 				itsr = -itsr;	/* now same as biterate */
460*de2caf28SDavid du Colombier 			}
461*de2caf28SDavid du Colombier 			/* do compilation first
462*de2caf28SDavid du Colombier 			 * split cc command from run command
463*de2caf28SDavid du Colombier 			 * leave cc in tmp, and set tmp2 to run
464*de2caf28SDavid du Colombier 			 */
465*de2caf28SDavid du Colombier 			if ((ptr = strstr(tmp, " && ")) != NULL)
466*de2caf28SDavid du Colombier 			{	tmp2 = ptr + 4;	/* first run */
467*de2caf28SDavid du Colombier 				*ptr = '\0';
468*de2caf28SDavid du Colombier 		}	}
469*de2caf28SDavid du Colombier 
470*de2caf28SDavid du Colombier 		if (has_ltl)
471*de2caf28SDavid du Colombier 		{	(void) unlink("_spin_nvr.tmp");
472*de2caf28SDavid du Colombier 		}
473*de2caf28SDavid du Colombier 
474*de2caf28SDavid du Colombier 		if (!norecompile)
475*de2caf28SDavid du Colombier 		{	/* make sure that if compilation fails we do not continue */
476*de2caf28SDavid du Colombier #ifdef PC
477*de2caf28SDavid du Colombier 			(void) unlink("./pan.exe");
478*de2caf28SDavid du Colombier #else
479*de2caf28SDavid du Colombier 			(void) unlink("./pan");
480*de2caf28SDavid du Colombier #endif
481*de2caf28SDavid du Colombier 		}
482*de2caf28SDavid du Colombier runit:
483*de2caf28SDavid du Colombier 		if (norecompile && tmp != tmp2)
484*de2caf28SDavid du Colombier 		{	estatus = 0;
485*de2caf28SDavid du Colombier 		} else
486*de2caf28SDavid du Colombier 		{	estatus = e_system(1, tmp);	/* compile or run */
487*de2caf28SDavid du Colombier 		}
488*de2caf28SDavid du Colombier 		if (replay || estatus < 0)
489*de2caf28SDavid du Colombier 		{	goto skipahead;
490*de2caf28SDavid du Colombier 		}
491*de2caf28SDavid du Colombier 		/* !replay */
492*de2caf28SDavid du Colombier 		if (itsr == 0 && !sw_or_bt)			/* single run */
493*de2caf28SDavid du Colombier 		{	estatus = e_system(1, tmp2);
494*de2caf28SDavid du Colombier 		} else if (itsr > 0)	/* iterative search refinement */
495*de2caf28SDavid du Colombier 		{	int is_swarm = 0;
496*de2caf28SDavid du Colombier 			if (tmp2 != tmp)	/* swarm: did only compilation so far */
497*de2caf28SDavid du Colombier 			{	tmp = tmp2;	/* now we point to the run command */
498*de2caf28SDavid du Colombier 				estatus = e_system(1, tmp);	/* first run */
499*de2caf28SDavid du Colombier 				itsr--;
500*de2caf28SDavid du Colombier 			}
501*de2caf28SDavid du Colombier 			itsr--;			/* count down */
502*de2caf28SDavid du Colombier 
503*de2caf28SDavid du Colombier 			/* the following are added back randomly later */
504*de2caf28SDavid du Colombier 			(void) omit_str(tmp, "-p_reverse");	/* replaced by spaces */
505*de2caf28SDavid du Colombier 			(void) omit_str(tmp, "-p_normal");
506*de2caf28SDavid du Colombier 
507*de2caf28SDavid du Colombier 			if (strstr(tmp, " &") != NULL)
508*de2caf28SDavid du Colombier 			{	(void) omit_str(tmp, " &");
509*de2caf28SDavid du Colombier 				is_swarm = 1;
510*de2caf28SDavid du Colombier 			}
511*de2caf28SDavid du Colombier 
512*de2caf28SDavid du Colombier 			/* increase -w every itsr_n-th run */
513*de2caf28SDavid du Colombier 			if ((itsr_n > 0 && (itsr == 0 || (itsr%itsr_n) != 0))
514*de2caf28SDavid du Colombier 			||  (change_param(tmp, "-w", 36, 18) >= 0))	/* max 4G bit statespace */
515*de2caf28SDavid du Colombier 			{	(void) change_param(tmp, "-h", 500, 0);	/* hash function 0.499 */
516*de2caf28SDavid du Colombier 				(void) change_param(tmp, "-p_rotate", 256, 0); /* if defined */
517*de2caf28SDavid du Colombier 				(void) change_param(tmp, "-k", 4, 1);	/* nr bits per state 0->1,2,3 */
518*de2caf28SDavid du Colombier 				(void) change_param(tmp, "-T", 2, 0);	/* with or without t_reverse*/
519*de2caf28SDavid du Colombier 				(void) change_param(tmp, "-P", 2, 0);	/* -P 0..1 != p_reverse */
520*de2caf28SDavid du Colombier 				change_rs(tmp);			/* change random seed */
521*de2caf28SDavid du Colombier 				string_trim(tmp);
522*de2caf28SDavid du Colombier 				if (rand()%5 == 0)		/* 20% of all runs */
523*de2caf28SDavid du Colombier 				{	strcat(tmp, " -p_reverse ");
524*de2caf28SDavid du Colombier 					/* at end, so this overrides -p_rotateN, if there */
525*de2caf28SDavid du Colombier 					/* but -P0..1 disable this in 50% of the cases */
526*de2caf28SDavid du Colombier 					/* so its really activated in 10% of all runs */
527*de2caf28SDavid du Colombier 				} else if (rand()%6 == 0) /* override p_rotate and p_reverse */
528*de2caf28SDavid du Colombier 				{	strcat(tmp, " -p_normal ");
529*de2caf28SDavid du Colombier 				}
530*de2caf28SDavid du Colombier 				if (is_swarm)
531*de2caf28SDavid du Colombier 				{	strcat(tmp, " &");
532*de2caf28SDavid du Colombier 				}
533*de2caf28SDavid du Colombier 				goto runit;
534*de2caf28SDavid du Colombier 		}	}
535*de2caf28SDavid du Colombier skipahead:
536*de2caf28SDavid du Colombier 		(void) unlink("pan.b");
537*de2caf28SDavid du Colombier 		(void) unlink("pan.c");
538*de2caf28SDavid du Colombier 		(void) unlink("pan.h");
539*de2caf28SDavid du Colombier 		(void) unlink("pan.m");
540*de2caf28SDavid du Colombier 		(void) unlink("pan.p");
541*de2caf28SDavid du Colombier 		(void) unlink("pan.t");
5427dd7cddfSDavid du Colombier 	}
5437dd7cddfSDavid du Colombier 	exit(estatus);
5447dd7cddfSDavid du Colombier }
545*de2caf28SDavid du Colombier #if 0
546*de2caf28SDavid du Colombier 	-P0	normal active process creation
547*de2caf28SDavid du Colombier 	-P1	reversed order for *active* process creation != p_reverse
548*de2caf28SDavid du Colombier 
549*de2caf28SDavid du Colombier 	-T0	normal transition exploration
550*de2caf28SDavid du Colombier 	-T1	reversed order of transition exploration
551*de2caf28SDavid du Colombier 
552*de2caf28SDavid du Colombier 	-DP_RAND	(random starting point +- -DP_REVERSE)
553*de2caf28SDavid du Colombier 	-DPERMUTED	(also enables -p_rotateN and -p_reverse)
554*de2caf28SDavid du Colombier 	-DP_REVERSE	(same as -DPERMUTED with -p_reverse, but 7% faster)
555*de2caf28SDavid du Colombier 
556*de2caf28SDavid du Colombier 	-DT_RAND	(random starting point -- optionally with -T0..1)
557*de2caf28SDavid du Colombier 	-DT_REVERSE	(superseded by -T0..1 options)
558*de2caf28SDavid du Colombier 
559*de2caf28SDavid du Colombier 	 -hash generates new hash polynomial for -h0
560*de2caf28SDavid du Colombier 
561*de2caf28SDavid du Colombier 	permutation modes:
562*de2caf28SDavid du Colombier 	 -permuted (adds -DPERMUTED) -- this is also the default with -swarm
563*de2caf28SDavid du Colombier 	 -t_reverse (same as -T1)
564*de2caf28SDavid du Colombier 	 -p_reverse (similar to -P1)
565*de2caf28SDavid du Colombier 	 -p_rotateN
566*de2caf28SDavid du Colombier 	 -p_normal
567*de2caf28SDavid du Colombier 
568*de2caf28SDavid du Colombier 	less useful would be (since there is less non-determinism in transitions):
569*de2caf28SDavid du Colombier 		-t_rotateN -- a controlled version of -DT_RAND
570*de2caf28SDavid du Colombier 
571*de2caf28SDavid du Colombier 	compiling with -DPERMUTED enables a number of new runtime options,
572*de2caf28SDavid du Colombier 	that -swarmN,M will also exploit:
573*de2caf28SDavid du Colombier 		-p_permute (default)
574*de2caf28SDavid du Colombier 		-p_rotateN
575*de2caf28SDavid du Colombier 		-p_reverse
576*de2caf28SDavid du Colombier #endif
577219b2ee8SDavid du Colombier 
5787dd7cddfSDavid du Colombier void
preprocess(char * a,char * b,int a_tmp)5797dd7cddfSDavid du Colombier preprocess(char *a, char *b, int a_tmp)
580*de2caf28SDavid du Colombier {	char precmd[1024], cmd[2048];
581*de2caf28SDavid du Colombier 	int i;
5827dd7cddfSDavid du Colombier #ifdef PC
583*de2caf28SDavid du Colombier 	/* gcc is sometimes a symbolic link to gcc-4
584*de2caf28SDavid du Colombier 	   that does not work well in cygwin, so we try
585*de2caf28SDavid du Colombier 	   to use the actual executable that is used.
586*de2caf28SDavid du Colombier 	   the code below assumes we are on a cygwin-like system
587*de2caf28SDavid du Colombier 	 */
588*de2caf28SDavid du Colombier 	if (strncmp(PreProc, "gcc ", strlen("gcc ")) == 0)
589*de2caf28SDavid du Colombier 	{	if (e_system(0, "gcc-4 --version > pan.pre 2>&1") == 0)
590*de2caf28SDavid du Colombier 		{	strcpy(PreProc, "gcc-4 -std=gnu99 -Wformat-overflow=0 -E -x c");
591*de2caf28SDavid du Colombier 		} else if (e_system(0, "gcc-3 --version > pan.pre 2>&1") == 0)
592*de2caf28SDavid du Colombier 		{	strcpy(PreProc, "gcc-3 -std=gnu99 -Wformat-overflow=0 -E -x c");
59300d97012SDavid du Colombier 	}	}
5947dd7cddfSDavid du Colombier #endif
595*de2caf28SDavid du Colombier 
596*de2caf28SDavid du Colombier 	assert(strlen(PreProc) < sizeof(precmd));
5977dd7cddfSDavid du Colombier 	strcpy(precmd, PreProc);
5987dd7cddfSDavid du Colombier 	for (i = 1; i <= PreCnt; i++)
5997dd7cddfSDavid du Colombier 	{	strcat(precmd, " ");
6007dd7cddfSDavid du Colombier 		strcat(precmd, PreArg[i]);
6017dd7cddfSDavid du Colombier 	}
60200d97012SDavid du Colombier 	if (strlen(precmd) > sizeof(precmd))
60300d97012SDavid du Colombier 	{	fprintf(stdout, "spin: too many -D args, aborting\n");
60400d97012SDavid du Colombier 		alldone(1);
60500d97012SDavid du Colombier 	}
606*de2caf28SDavid du Colombier 	sprintf(cmd, "%s \"%s\" > \"%s\"", precmd, a, b);
607*de2caf28SDavid du Colombier 	if (e_system(2, (const char *)cmd))	/* preprocessing step */
6087dd7cddfSDavid du Colombier 	{	(void) unlink((const char *) b);
6097dd7cddfSDavid du Colombier 		if (a_tmp) (void) unlink((const char *) a);
610*de2caf28SDavid du Colombier 		fprintf(stdout, "spin: preprocessing failed %s\n", cmd);
611312a1df1SDavid du Colombier 		alldone(1); /* no return, error exit */
6127dd7cddfSDavid du Colombier 	}
613312a1df1SDavid du Colombier 	if (a_tmp) (void) unlink((const char *) a);
6147dd7cddfSDavid du Colombier }
6157dd7cddfSDavid du Colombier 
6167dd7cddfSDavid du Colombier void
usage(void)6177dd7cddfSDavid du Colombier usage(void)
6187dd7cddfSDavid du Colombier {
6197dd7cddfSDavid du Colombier 	printf("use: spin [-option] ... [-option] file\n");
6207dd7cddfSDavid du Colombier 	printf("\tNote: file must always be the last argument\n");
621312a1df1SDavid du Colombier 	printf("\t-A apply slicing algorithm\n");
6227dd7cddfSDavid du Colombier 	printf("\t-a generate a verifier in pan.c\n");
6237dd7cddfSDavid du Colombier 	printf("\t-B no final state details in simulations\n");
6247dd7cddfSDavid du Colombier 	printf("\t-b don't execute printfs in simulation\n");
625312a1df1SDavid du Colombier 	printf("\t-C print channel access info (combine with -g etc.)\n");
6267dd7cddfSDavid du Colombier 	printf("\t-c columnated -s -r simulation output\n");
627219b2ee8SDavid du Colombier 	printf("\t-d produce symbol-table information\n");
6287dd7cddfSDavid du Colombier 	printf("\t-Dyyy pass -Dyyy to the preprocessor\n");
6297dd7cddfSDavid du Colombier 	printf("\t-Eyyy pass yyy to the preprocessor\n");
63000d97012SDavid du Colombier 	printf("\t-e compute synchronous product of multiple never claims (modified by -L)\n");
6317dd7cddfSDavid du Colombier 	printf("\t-f \"..formula..\"  translate LTL ");
6327dd7cddfSDavid du Colombier 	printf("into never claim\n");
63300d97012SDavid du Colombier 	printf("\t-F file  like -f, but with the LTL formula stored in a 1-line file\n");
634219b2ee8SDavid du Colombier 	printf("\t-g print all global variables\n");
635312a1df1SDavid du Colombier 	printf("\t-h at end of run, print value of seed for random nr generator used\n");
636219b2ee8SDavid du Colombier 	printf("\t-i interactive (random simulation)\n");
637312a1df1SDavid du Colombier 	printf("\t-I show result of inlining and preprocessing\n");
6387dd7cddfSDavid du Colombier 	printf("\t-J reverse eval order of nested unlesses\n");
6397dd7cddfSDavid du Colombier 	printf("\t-jN skip the first N steps ");
6407dd7cddfSDavid du Colombier 	printf("in simulation trail\n");
64100d97012SDavid du Colombier 	printf("\t-k fname use the trailfile stored in file fname, see also -t\n");
64200d97012SDavid du Colombier 	printf("\t-L when using -e, use strict language intersection\n");
643219b2ee8SDavid du Colombier 	printf("\t-l print all local variables\n");
644*de2caf28SDavid du Colombier 	printf("\t-M generate msc-flow in tcl/tk format\n");
645219b2ee8SDavid du Colombier 	printf("\t-m lose msgs sent to full queues\n");
64600d97012SDavid du Colombier 	printf("\t-N fname use never claim stored in file fname\n");
647219b2ee8SDavid du Colombier 	printf("\t-nN seed for random nr generator\n");
64800d97012SDavid du Colombier 	printf("\t-O use old scope rules (pre 5.3.0)\n");
6497dd7cddfSDavid du Colombier 	printf("\t-o1 turn off dataflow-optimizations in verifier\n");
650312a1df1SDavid du Colombier 	printf("\t-o2 don't hide write-only variables in verifier\n");
6517dd7cddfSDavid du Colombier 	printf("\t-o3 turn off statement merging in verifier\n");
65200d97012SDavid du Colombier 	printf("\t-o4 turn on rendezvous optiomizations in verifier\n");
65300d97012SDavid du Colombier 	printf("\t-o5 turn on case caching (reduces size of pan.m, but affects reachability reports)\n");
654*de2caf28SDavid du Colombier 	printf("\t-o6 revert to the old rules for interpreting priority tags (pre version 6.2)\n");
655*de2caf28SDavid du Colombier 	printf("\t-o7 revert to the old rules for semi-colon usage (pre version 6.3)\n");
6567dd7cddfSDavid du Colombier 	printf("\t-Pxxx use xxx for preprocessing\n");
657219b2ee8SDavid du Colombier 	printf("\t-p print all statements\n");
658*de2caf28SDavid du Colombier 	printf("\t-pp pretty-print (reformat) stdin, write stdout\n");
6597dd7cddfSDavid du Colombier 	printf("\t-qN suppress io for queue N in printouts\n");
660219b2ee8SDavid du Colombier 	printf("\t-r print receive events\n");
661*de2caf28SDavid du Colombier 	printf("\t-replay  replay an error trail-file found earlier\n");
662*de2caf28SDavid du Colombier 	printf("\t	if the model contains embedded c-code, the ./pan executable is used\n");
663*de2caf28SDavid du Colombier 	printf("\t	otherwise spin itself is used to replay the trailfile\n");
664*de2caf28SDavid du Colombier 	printf("\t	note that pan recognizes different runtime options than spin itself\n");
665*de2caf28SDavid du Colombier 	printf("\t-run  (or -search) generate a verifier, and compile and run it\n");
666*de2caf28SDavid du Colombier 	printf("\t      options before -search are interpreted by spin to parse the input\n");
667*de2caf28SDavid du Colombier 	printf("\t      options following a -search are used to compile and run the verifier pan\n");
668*de2caf28SDavid du Colombier 	printf("\t	    valid options that can follow a -search argument include:\n");
669*de2caf28SDavid du Colombier 	printf("\t	    -bfs	perform a breadth-first search\n");
670*de2caf28SDavid du Colombier 	printf("\t	    -bfspar	perform a parallel breadth-first search\n");
671*de2caf28SDavid du Colombier 	printf("\t	    -dfspar	perform a parallel depth-first search, same as -DNCORE=4\n");
672*de2caf28SDavid du Colombier 	printf("\t	    -bcs	use the bounded-context-switching algorithm\n");
673*de2caf28SDavid du Colombier 	printf("\t	    -bitstate	or -bit, use bitstate storage\n");
674*de2caf28SDavid du Colombier 	printf("\t	    -biterateN,M use bitstate with iterative search refinement (-w18..-w35)\n");
675*de2caf28SDavid du Colombier 	printf("\t			perform N randomized runs and increment -w every M runs\n");
676*de2caf28SDavid du Colombier 	printf("\t			default value for N is 10, default for M is 1\n");
677*de2caf28SDavid du Colombier 	printf("\t			(use N,N to keep -w fixed for all runs)\n");
678*de2caf28SDavid du Colombier 	printf("\t			(add -w to see which commands will be executed)\n");
679*de2caf28SDavid du Colombier 	printf("\t			(add -W if ./pan exists and need not be recompiled)\n");
680*de2caf28SDavid du Colombier 	printf("\t	    -swarmN,M like -biterate, but running all iterations in parallel\n");
681*de2caf28SDavid du Colombier 	printf("\t	    -link file.c  link executable pan to file.c\n");
682*de2caf28SDavid du Colombier 	printf("\t	    -collapse	use collapse state compression\n");
683*de2caf28SDavid du Colombier 	printf("\t	    -noreduce	do not use partial order reduction\n");
684*de2caf28SDavid du Colombier 	printf("\t	    -hc  	use hash-compact storage\n");
685*de2caf28SDavid du Colombier 	printf("\t	    -noclaim	ignore all ltl and never claims\n");
686*de2caf28SDavid du Colombier 	printf("\t	    -p_permute	use process scheduling order random permutation\n");
687*de2caf28SDavid du Colombier 	printf("\t	    -p_rotateN	use process scheduling order rotation by N\n");
688*de2caf28SDavid du Colombier 	printf("\t	    -p_reverse	use process scheduling order reversal\n");
689*de2caf28SDavid du Colombier 	printf("\t	    -rhash      randomly pick one of the -p_... options\n");
690*de2caf28SDavid du Colombier 	printf("\t	    -ltl p	verify the ltl property named p\n");
691*de2caf28SDavid du Colombier 	printf("\t	    -safety	compile for safety properties only\n");
692*de2caf28SDavid du Colombier 	printf("\t	    -i	    	use the dfs iterative shortening algorithm\n");
693*de2caf28SDavid du Colombier 	printf("\t	    -a	    	search for acceptance cycles\n");
694*de2caf28SDavid du Colombier 	printf("\t	    -l	    	search for non-progress cycles\n");
695*de2caf28SDavid du Colombier 	printf("\t	similarly, a -D... parameter can be specified to modify the compilation\n");
696*de2caf28SDavid du Colombier 	printf("\t	and any valid runtime pan argument can be specified for the verification\n");
697312a1df1SDavid du Colombier 	printf("\t-S1 and -S2 separate pan source for claim and model\n");
698219b2ee8SDavid du Colombier 	printf("\t-s print send events\n");
699312a1df1SDavid du Colombier 	printf("\t-T do not indent printf output\n");
70000d97012SDavid du Colombier 	printf("\t-t[N] follow [Nth] simulation trail, see also -k\n");
701312a1df1SDavid du Colombier 	printf("\t-Uyyy pass -Uyyy to the preprocessor\n");
702312a1df1SDavid du Colombier 	printf("\t-uN stop a simulation run after N steps\n");
703219b2ee8SDavid du Colombier 	printf("\t-v verbose, more warnings\n");
7047dd7cddfSDavid du Colombier 	printf("\t-w very verbose (when combined with -l or -g)\n");
7057dd7cddfSDavid du Colombier 	printf("\t-[XYZ] reserved for use by xspin interface\n");
706219b2ee8SDavid du Colombier 	printf("\t-V print version number and exit\n");
7077dd7cddfSDavid du Colombier 	alldone(1);
7087dd7cddfSDavid du Colombier }
7097dd7cddfSDavid du Colombier 
710*de2caf28SDavid du Colombier int
optimizations(int nr)71100d97012SDavid du Colombier optimizations(int nr)
7127dd7cddfSDavid du Colombier {
7137dd7cddfSDavid du Colombier 	switch (nr) {
7147dd7cddfSDavid du Colombier 	case '1':
7157dd7cddfSDavid du Colombier 		dataflow = 1 - dataflow; /* dataflow */
7167dd7cddfSDavid du Colombier 		if (verbose&32)
7177dd7cddfSDavid du Colombier 		printf("spin: dataflow optimizations turned %s\n",
7187dd7cddfSDavid du Colombier 			dataflow?"on":"off");
7197dd7cddfSDavid du Colombier 		break;
7207dd7cddfSDavid du Colombier 	case '2':
7217dd7cddfSDavid du Colombier 		/* dead variable elimination */
7227dd7cddfSDavid du Colombier 		deadvar = 1 - deadvar;
7237dd7cddfSDavid du Colombier 		if (verbose&32)
7247dd7cddfSDavid du Colombier 		printf("spin: dead variable elimination turned %s\n",
7257dd7cddfSDavid du Colombier 			deadvar?"on":"off");
7267dd7cddfSDavid du Colombier 		break;
7277dd7cddfSDavid du Colombier 	case '3':
7287dd7cddfSDavid du Colombier 		/* statement merging */
7297dd7cddfSDavid du Colombier 		merger = 1 - merger;
7307dd7cddfSDavid du Colombier 		if (verbose&32)
7317dd7cddfSDavid du Colombier 		printf("spin: statement merging turned %s\n",
7327dd7cddfSDavid du Colombier 			merger?"on":"off");
7337dd7cddfSDavid du Colombier 		break;
7347dd7cddfSDavid du Colombier 
7357dd7cddfSDavid du Colombier 	case '4':
7367dd7cddfSDavid du Colombier 		/* rv optimization */
7377dd7cddfSDavid du Colombier 		rvopt = 1 - rvopt;
7387dd7cddfSDavid du Colombier 		if (verbose&32)
7397dd7cddfSDavid du Colombier 		printf("spin: rendezvous optimization turned %s\n",
7407dd7cddfSDavid du Colombier 			rvopt?"on":"off");
7417dd7cddfSDavid du Colombier 		break;
7427dd7cddfSDavid du Colombier 	case '5':
7437dd7cddfSDavid du Colombier 		/* case caching */
7447dd7cddfSDavid du Colombier 		ccache = 1 - ccache;
7457dd7cddfSDavid du Colombier 		if (verbose&32)
7467dd7cddfSDavid du Colombier 		printf("spin: case caching turned %s\n",
7477dd7cddfSDavid du Colombier 			ccache?"on":"off");
7487dd7cddfSDavid du Colombier 		break;
749*de2caf28SDavid du Colombier 	case '6':
750*de2caf28SDavid du Colombier 		old_priority_rules = 1;
751*de2caf28SDavid du Colombier 		if (verbose&32)
752*de2caf28SDavid du Colombier 		printf("spin: using old priority rules (pre version 6.2)\n");
753*de2caf28SDavid du Colombier 		return 0; /* no break */
754*de2caf28SDavid du Colombier 	case '7':
755*de2caf28SDavid du Colombier 		implied_semis = 0;
756*de2caf28SDavid du Colombier 		if (verbose&32)
757*de2caf28SDavid du Colombier 		printf("spin: no implied semi-colons (pre version 6.3)\n");
758*de2caf28SDavid du Colombier 		return 0; /* no break */
7597dd7cddfSDavid du Colombier 	default:
7607dd7cddfSDavid du Colombier 		printf("spin: bad or missing parameter on -o\n");
7617dd7cddfSDavid du Colombier 		usage();
7627dd7cddfSDavid du Colombier 		break;
7637dd7cddfSDavid du Colombier 	}
764*de2caf28SDavid du Colombier 	return 1;
765*de2caf28SDavid du Colombier }
766*de2caf28SDavid du Colombier 
767*de2caf28SDavid du Colombier static void
add_comptime(char * s)768*de2caf28SDavid du Colombier add_comptime(char *s)
769*de2caf28SDavid du Colombier {	char *tmp;
770*de2caf28SDavid du Colombier 
771*de2caf28SDavid du Colombier 	if (!s || strstr(pan_comptime, s))
772*de2caf28SDavid du Colombier 	{	return;
773*de2caf28SDavid du Colombier 	}
774*de2caf28SDavid du Colombier 
775*de2caf28SDavid du Colombier 	tmp = (char *) emalloc(strlen(pan_comptime)+strlen(s)+2);
776*de2caf28SDavid du Colombier 	sprintf(tmp, "%s %s", pan_comptime, s);
777*de2caf28SDavid du Colombier 	pan_comptime = tmp;
778*de2caf28SDavid du Colombier }
779*de2caf28SDavid du Colombier 
780*de2caf28SDavid du Colombier static struct {
781*de2caf28SDavid du Colombier 	char *ifsee, *thendo;
782*de2caf28SDavid du Colombier 	int keeparg;
783*de2caf28SDavid du Colombier } pats[] = {
784*de2caf28SDavid du Colombier 	{ "-bfspar",	"-DBFS_PAR",	0 },
785*de2caf28SDavid du Colombier 	{ "-bfs",	"-DBFS",	0 },
786*de2caf28SDavid du Colombier 	{ "-bcs",	"-DBCS",	0 },
787*de2caf28SDavid du Colombier 	{ "-bitstate",	"-DBITSTATE",	0 },
788*de2caf28SDavid du Colombier 	{ "-bit",	"-DBITSTATE",	0 },
789*de2caf28SDavid du Colombier 	{ "-hc",	"-DHC4",	0 },
790*de2caf28SDavid du Colombier 	{ "-collapse",	"-DCOLLAPSE",	0 },
791*de2caf28SDavid du Colombier 	{ "-noclaim",	"-DNOCLAIM",	0 },
792*de2caf28SDavid du Colombier 	{ "-noreduce",	"-DNOREDUCE",	0 },
793*de2caf28SDavid du Colombier 	{ "-np",	"-DNP",		0 },
794*de2caf28SDavid du Colombier 	{ "-permuted",	"-DPERMUTED",	0 },
795*de2caf28SDavid du Colombier 	{ "-p_permute", "-DPERMUTED",	1 },
796*de2caf28SDavid du Colombier 	{ "-p_rotate",	"-DPERMUTED",	1 },
797*de2caf28SDavid du Colombier 	{ "-p_reverse",	"-DPERMUTED",	1 },
798*de2caf28SDavid du Colombier 	{ "-rhash",	"-DPERMUTED",	1 },
799*de2caf28SDavid du Colombier 	{ "-safety",	"-DSAFETY",	0 },
800*de2caf28SDavid du Colombier 	{ "-i",		"-DREACH",	1 },
801*de2caf28SDavid du Colombier 	{ "-l",		"-DNP",		1 },
802*de2caf28SDavid du Colombier 	{ 0, 0 }
803*de2caf28SDavid du Colombier };
804*de2caf28SDavid du Colombier 
805*de2caf28SDavid du Colombier static void
set_itsr_n(char * s)806*de2caf28SDavid du Colombier set_itsr_n(char *s)	/* e.g., -swarm12,3 */
807*de2caf28SDavid du Colombier {	char *tmp;
808*de2caf28SDavid du Colombier 
809*de2caf28SDavid du Colombier 	if ((tmp = strchr(s, ',')) != NULL)
810*de2caf28SDavid du Colombier 	{	tmp++;
811*de2caf28SDavid du Colombier 		if (*tmp != '\0' && isdigit((int) *tmp))
812*de2caf28SDavid du Colombier 		{	itsr_n = atoi(tmp);
813*de2caf28SDavid du Colombier 			if (itsr_n < 2)
814*de2caf28SDavid du Colombier 			{	itsr_n = 0;
815*de2caf28SDavid du Colombier 	}	}	}
816*de2caf28SDavid du Colombier }
817*de2caf28SDavid du Colombier 
818*de2caf28SDavid du Colombier static void
add_runtime(char * s)819*de2caf28SDavid du Colombier add_runtime(char *s)
820*de2caf28SDavid du Colombier {	char *tmp;
821*de2caf28SDavid du Colombier 	int i;
822*de2caf28SDavid du Colombier 
823*de2caf28SDavid du Colombier 	if (strncmp(s, "-biterate", strlen("-biterate")) == 0)
824*de2caf28SDavid du Colombier 	{	itsr = 10;	/* default nr of sequential iterations */
825*de2caf28SDavid du Colombier 		sw_or_bt = 1;
826*de2caf28SDavid du Colombier 		if (isdigit((int) s[9]))
827*de2caf28SDavid du Colombier 		{	itsr = atoi(&s[9]);
828*de2caf28SDavid du Colombier 			if (itsr < 1)
829*de2caf28SDavid du Colombier 			{	itsr = 1;
830*de2caf28SDavid du Colombier 			}
831*de2caf28SDavid du Colombier 			set_itsr_n(s);
832*de2caf28SDavid du Colombier 		}
833*de2caf28SDavid du Colombier 		return;
834*de2caf28SDavid du Colombier 	}
835*de2caf28SDavid du Colombier 	if (strncmp(s, "-swarm", strlen("-swarm")) == 0)
836*de2caf28SDavid du Colombier 	{	itsr = -10;	/* parallel iterations */
837*de2caf28SDavid du Colombier 		sw_or_bt = 1;
838*de2caf28SDavid du Colombier 		if (isdigit((int) s[6]))
839*de2caf28SDavid du Colombier 		{	itsr = atoi(&s[6]);
840*de2caf28SDavid du Colombier 			if (itsr < 1)
841*de2caf28SDavid du Colombier 			{	itsr = 1;
842*de2caf28SDavid du Colombier 			}
843*de2caf28SDavid du Colombier 			itsr = -itsr;
844*de2caf28SDavid du Colombier 			set_itsr_n(s);
845*de2caf28SDavid du Colombier 		}
846*de2caf28SDavid du Colombier 		return;
847*de2caf28SDavid du Colombier 	}
848*de2caf28SDavid du Colombier 
849*de2caf28SDavid du Colombier 	for (i = 0; pats[i].ifsee; i++)
850*de2caf28SDavid du Colombier 	{	if (strncmp(s, pats[i].ifsee, strlen(pats[i].ifsee)) == 0)
851*de2caf28SDavid du Colombier 		{	add_comptime(pats[i].thendo);
852*de2caf28SDavid du Colombier 			if (pats[i].keeparg)
853*de2caf28SDavid du Colombier 			{	break;
854*de2caf28SDavid du Colombier 			}
855*de2caf28SDavid du Colombier 			return;
856*de2caf28SDavid du Colombier 	}	}
857*de2caf28SDavid du Colombier 	if (strncmp(s, "-dfspar", strlen("-dfspar")) == 0)
858*de2caf28SDavid du Colombier 	{	add_comptime("-DNCORE=4");
859*de2caf28SDavid du Colombier 		return;
860*de2caf28SDavid du Colombier 	}
861*de2caf28SDavid du Colombier 
862*de2caf28SDavid du Colombier 	tmp = (char *) emalloc(strlen(pan_runtime)+strlen(s)+2);
863*de2caf28SDavid du Colombier 	sprintf(tmp, "%s %s", pan_runtime, s);
864*de2caf28SDavid du Colombier 	pan_runtime = tmp;
865*de2caf28SDavid du Colombier }
866*de2caf28SDavid du Colombier 
867*de2caf28SDavid du Colombier ssize_t
getline(char ** lineptr,size_t * n,FILE * stream)868*de2caf28SDavid du Colombier getline(char **lineptr, size_t *n, FILE *stream)
869*de2caf28SDavid du Colombier {	static char buffer[8192];
870*de2caf28SDavid du Colombier 
871*de2caf28SDavid du Colombier 	*lineptr = (char *) &buffer;
872*de2caf28SDavid du Colombier 
873*de2caf28SDavid du Colombier 	if (!fgets(buffer, sizeof(buffer), stream))
874*de2caf28SDavid du Colombier 	{	return 0;
875*de2caf28SDavid du Colombier 	}
876*de2caf28SDavid du Colombier 	return 1;
8777dd7cddfSDavid du Colombier }
8787dd7cddfSDavid du Colombier 
8797dd7cddfSDavid du Colombier int
main(int argc,char * argv[])8807dd7cddfSDavid du Colombier main(int argc, char *argv[])
881312a1df1SDavid du Colombier {	Symbol *s;
8827dd7cddfSDavid du Colombier 	int T = (int) time((time_t *)0);
8837dd7cddfSDavid du Colombier 	int usedopts = 0;
8847dd7cddfSDavid du Colombier 
8857dd7cddfSDavid du Colombier 	yyin  = stdin;
8867dd7cddfSDavid du Colombier 	yyout = stdout;
8877dd7cddfSDavid du Colombier 	tl_out = stdout;
88800d97012SDavid du Colombier 	strcpy(CurScope, "_");
8897dd7cddfSDavid du Colombier 
890*de2caf28SDavid du Colombier 	assert(strlen(CPP) < sizeof(PreProc));
891*de2caf28SDavid du Colombier 	strcpy(PreProc, CPP);
892*de2caf28SDavid du Colombier 
89300d97012SDavid du Colombier 	/* unused flags: y, z, G, L, Q, R, W */
8947dd7cddfSDavid du Colombier 	while (argc > 1 && argv[1][0] == '-')
8957dd7cddfSDavid du Colombier 	{	switch (argv[1][1]) {
896312a1df1SDavid du Colombier 		case 'A': export_ast = 1; break;
897*de2caf28SDavid du Colombier 		case 'a': analyze = 1; break;
8987dd7cddfSDavid du Colombier 		case 'B': no_wrapup = 1; break;
8997dd7cddfSDavid du Colombier 		case 'b': no_print = 1; break;
9007dd7cddfSDavid du Colombier 		case 'C': Caccess = 1; break;
9017dd7cddfSDavid du Colombier 		case 'c': columns = 1; break;
9027dd7cddfSDavid du Colombier 		case 'D': PreArg[++PreCnt] = (char *) &argv[1][0];
903312a1df1SDavid du Colombier 			  break;	/* define */
9047dd7cddfSDavid du Colombier 		case 'd': dumptab =  1; break;
9057dd7cddfSDavid du Colombier 		case 'E': PreArg[++PreCnt] = (char *) &argv[1][2];
9067dd7cddfSDavid du Colombier 			  break;
90700d97012SDavid du Colombier 		case 'e': product++; break; /* see also 'L' */
9087dd7cddfSDavid du Colombier 		case 'F': ltl_file = (char **) (argv+2);
9097dd7cddfSDavid du Colombier 			  argc--; argv++; break;
9107dd7cddfSDavid du Colombier 		case 'f': add_ltl = (char **) argv;
9117dd7cddfSDavid du Colombier 			  argc--; argv++; break;
9127dd7cddfSDavid du Colombier 		case 'g': verbose +=  1; break;
913312a1df1SDavid du Colombier 		case 'h': seedy = 1; break;
9147dd7cddfSDavid du Colombier 		case 'i': interactive = 1; break;
915312a1df1SDavid du Colombier 		case 'I': inlineonly = 1; break;
9167dd7cddfSDavid du Colombier 		case 'J': like_java = 1; break;
9177dd7cddfSDavid du Colombier 		case 'j': jumpsteps = atoi(&argv[1][2]); break;
91800d97012SDavid du Colombier 		case 'k': s_trail = 1;
91900d97012SDavid du Colombier 			  trailfilename = (char **) (argv+2);
92000d97012SDavid du Colombier 			  argc--; argv++; break;
92100d97012SDavid du Colombier 		case 'L': Strict++; break; /* modified -e */
9227dd7cddfSDavid du Colombier 		case 'l': verbose +=  2; break;
9237dd7cddfSDavid du Colombier 		case 'M': columns = 2; break;
9247dd7cddfSDavid du Colombier 		case 'm': m_loss   =  1; break;
9257dd7cddfSDavid du Colombier 		case 'N': nvr_file = (char **) (argv+2);
9267dd7cddfSDavid du Colombier 			  argc--; argv++; break;
9277dd7cddfSDavid du Colombier 		case 'n': T = atoi(&argv[1][2]); tl_terse = 1; break;
92800d97012SDavid du Colombier 		case 'O': old_scope_rules = 1; break;
929*de2caf28SDavid du Colombier 		case 'o': usedopts += optimizations(argv[1][2]); break;
930*de2caf28SDavid du Colombier 		case 'P': assert(strlen((const char *) &argv[1][2]) < sizeof(PreProc));
931*de2caf28SDavid du Colombier 			  strcpy(PreProc, (const char *) &argv[1][2]);
932*de2caf28SDavid du Colombier 			  break;
933*de2caf28SDavid du Colombier 		case 'p': if (argv[1][2] == 'p')
934*de2caf28SDavid du Colombier 			  {	pretty_print();
935*de2caf28SDavid du Colombier 				alldone(0);
936*de2caf28SDavid du Colombier 			  }
937*de2caf28SDavid du Colombier 			  verbose +=  4; break;
93800d97012SDavid du Colombier 		case 'q': if (isdigit((int) argv[1][2]))
9397dd7cddfSDavid du Colombier 				qhide(atoi(&argv[1][2]));
9407dd7cddfSDavid du Colombier 			  break;
941*de2caf28SDavid du Colombier 		case 'r':
942*de2caf28SDavid du Colombier 			  if (strcmp(&argv[1][1], "run") == 0)
943*de2caf28SDavid du Colombier 			  {	Srand((unsigned int) T);
944*de2caf28SDavid du Colombier samecase:			if (buzzed != 0)
945*de2caf28SDavid du Colombier 				{ fatal("cannot combine -x with -run -replay or -search", (char *)0);
946*de2caf28SDavid du Colombier 				}
947*de2caf28SDavid du Colombier 				buzzed  = 2;
948*de2caf28SDavid du Colombier 				analyze = 1;
949*de2caf28SDavid du Colombier 				argc--; argv++;
950*de2caf28SDavid du Colombier 				/* process all remaining arguments, except -w/-W, as relating to pan: */
951*de2caf28SDavid du Colombier 				while (argc > 1 && argv[1][0] == '-')
952*de2caf28SDavid du Colombier 				{ switch (argv[1][1]) {
953*de2caf28SDavid du Colombier 				  case 'D': /* eg -DNP */
954*de2caf28SDavid du Colombier 			/*	  case 'E': conflicts with runtime arg */
955*de2caf28SDavid du Colombier 				  case 'O': /* eg -O2 */
956*de2caf28SDavid du Colombier 				  case 'U': /* to undefine a macro */
957*de2caf28SDavid du Colombier 					add_comptime(argv[1]);
958*de2caf28SDavid du Colombier 					break;
959*de2caf28SDavid du Colombier #if 0
960*de2caf28SDavid du Colombier 				  case 'w': /* conflicts with bitstate runtime arg */
961*de2caf28SDavid du Colombier 					verbose += 64;
962*de2caf28SDavid du Colombier 					break;
963*de2caf28SDavid du Colombier #endif
964*de2caf28SDavid du Colombier 				  case 'W':
965*de2caf28SDavid du Colombier 					norecompile = 1;
966*de2caf28SDavid du Colombier 					break;
967*de2caf28SDavid du Colombier 				  case 'l':
968*de2caf28SDavid du Colombier 					if (strcmp(&argv[1][1], "ltl") == 0)
969*de2caf28SDavid du Colombier 					{	add_runtime("-N");
970*de2caf28SDavid du Colombier 						argc--; argv++;
971*de2caf28SDavid du Colombier 						add_runtime(argv[1]); /* prop name */
972*de2caf28SDavid du Colombier 						break;
973*de2caf28SDavid du Colombier 					}
974*de2caf28SDavid du Colombier 					if (strcmp(&argv[1][1], "link") == 0)
975*de2caf28SDavid du Colombier 					{	argc--; argv++;
976*de2caf28SDavid du Colombier 						add_comptime(argv[1]);
977*de2caf28SDavid du Colombier 						break;
978*de2caf28SDavid du Colombier 					}
979*de2caf28SDavid du Colombier 					/* else fall through */
980*de2caf28SDavid du Colombier 				  default:
981*de2caf28SDavid du Colombier 					add_runtime(argv[1]); /* -bfs etc. */
982*de2caf28SDavid du Colombier 					break;
983*de2caf28SDavid du Colombier 				  }
984*de2caf28SDavid du Colombier 				  argc--; argv++;
985*de2caf28SDavid du Colombier 				}
986*de2caf28SDavid du Colombier 				argc++; argv--;
987*de2caf28SDavid du Colombier 			  } else if (strcmp(&argv[1][1], "replay") == 0)
988*de2caf28SDavid du Colombier 			  {	replay = 1;
989*de2caf28SDavid du Colombier 				add_runtime("-r");
990*de2caf28SDavid du Colombier 				goto samecase;
991*de2caf28SDavid du Colombier 			  } else
992*de2caf28SDavid du Colombier 			  {	verbose +=  8;
993*de2caf28SDavid du Colombier 			  }
994*de2caf28SDavid du Colombier 			  break;
995*de2caf28SDavid du Colombier 		case 'S': separate = atoi(&argv[1][2]); /* S1 or S2 */
996*de2caf28SDavid du Colombier 			  /* generate code for separate compilation */
997*de2caf28SDavid du Colombier 			  analyze = 1; break;
998*de2caf28SDavid du Colombier 		case 's':
999*de2caf28SDavid du Colombier 			  if (strcmp(&argv[1][1], "simulate") == 0)
1000*de2caf28SDavid du Colombier 			  {	break; /* ignore */
1001*de2caf28SDavid du Colombier 			  }
1002*de2caf28SDavid du Colombier 			  if (strcmp(&argv[1][1], "search") == 0)
1003*de2caf28SDavid du Colombier 			  {	goto samecase;
1004*de2caf28SDavid du Colombier 			  }
1005*de2caf28SDavid du Colombier 			  verbose += 16; break;
1006312a1df1SDavid du Colombier 		case 'T': notabs = 1; break;
10077dd7cddfSDavid du Colombier 		case 't': s_trail  =  1;
100800d97012SDavid du Colombier 			  if (isdigit((int)argv[1][2]))
1009*de2caf28SDavid du Colombier 			  {	ntrail = atoi(&argv[1][2]);
1010*de2caf28SDavid du Colombier 			  }
10117dd7cddfSDavid du Colombier 			  break;
1012312a1df1SDavid du Colombier 		case 'U': PreArg[++PreCnt] = (char *) &argv[1][0];
1013312a1df1SDavid du Colombier 			  break;	/* undefine */
1014*de2caf28SDavid du Colombier 		case 'u': cutoff = atoi(&argv[1][2]); break;
10157dd7cddfSDavid du Colombier 		case 'v': verbose += 32; break;
101600d97012SDavid du Colombier 		case 'V': printf("%s\n", SpinVersion);
10177dd7cddfSDavid du Colombier 			  alldone(0);
10187dd7cddfSDavid du Colombier 			  break;
10197dd7cddfSDavid du Colombier 		case 'w': verbose += 64; break;
1020*de2caf28SDavid du Colombier 		case 'W': norecompile = 1; break;	/* 6.4.7: for swarm/biterate */
1021*de2caf28SDavid du Colombier 		case 'x': /* internal - reserved use */
1022*de2caf28SDavid du Colombier 			  if (buzzed != 0)
1023*de2caf28SDavid du Colombier 			  {	fatal("cannot combine -x with -run -search or -replay", (char *)0);
1024*de2caf28SDavid du Colombier 			  }
1025*de2caf28SDavid du Colombier 			  buzzed = 1;	/* implies also -a -o3 */
1026*de2caf28SDavid du Colombier 			  pan_runtime = "-d";
1027*de2caf28SDavid du Colombier 			  analyze = 1;
1028*de2caf28SDavid du Colombier 			  usedopts += optimizations('3');
1029*de2caf28SDavid du Colombier 			  break;
1030312a1df1SDavid du Colombier 		case 'X': xspin = notabs = 1;
10317dd7cddfSDavid du Colombier #ifndef PC
10327dd7cddfSDavid du Colombier 			  signal(SIGPIPE, alldone); /* not posix... */
10337dd7cddfSDavid du Colombier #endif
10347dd7cddfSDavid du Colombier 			  break;
10357dd7cddfSDavid du Colombier 		case 'Y': limited_vis = 1; break;	/* used by xspin */
10367dd7cddfSDavid du Colombier 		case 'Z': preprocessonly = 1; break;	/* used by xspin */
10377dd7cddfSDavid du Colombier 
10387dd7cddfSDavid du Colombier 		default : usage(); break;
1039219b2ee8SDavid du Colombier 		}
1040f3793cddSDavid du Colombier 		argc--; argv++;
1041219b2ee8SDavid du Colombier 	}
104200d97012SDavid du Colombier 
1043*de2caf28SDavid du Colombier 	if (columns == 2 && !cutoff)
1044*de2caf28SDavid du Colombier 	{	cutoff = 1024;
1045*de2caf28SDavid du Colombier 	}
1046*de2caf28SDavid du Colombier 
10477dd7cddfSDavid du Colombier 	if (usedopts && !analyze)
1048*de2caf28SDavid du Colombier 		printf("spin: warning -o[1..5] option ignored in simulations\n");
1049219b2ee8SDavid du Colombier 
10507dd7cddfSDavid du Colombier 	if (ltl_file)
1051*de2caf28SDavid du Colombier 	{	add_ltl = ltl_file-2; add_ltl[1][1] = 'f';
10527dd7cddfSDavid du Colombier 		if (!(tl_out = fopen(*ltl_file, "r")))
10537dd7cddfSDavid du Colombier 		{	printf("spin: cannot open %s\n", *ltl_file);
10547dd7cddfSDavid du Colombier 			alldone(1);
1055219b2ee8SDavid du Colombier 		}
1056*de2caf28SDavid du Colombier 		size_t linebuffsize = 0;
1057*de2caf28SDavid du Colombier 		ssize_t length = getline(&formula, &linebuffsize, tl_out);
1058*de2caf28SDavid du Colombier 		if (!formula || !length)
105900d97012SDavid du Colombier 		{	printf("spin: cannot read %s\n", *ltl_file);
106000d97012SDavid du Colombier 		}
10617dd7cddfSDavid du Colombier 		fclose(tl_out);
10627dd7cddfSDavid du Colombier 		tl_out = stdout;
1063*de2caf28SDavid du Colombier 		*ltl_file = formula;
10647dd7cddfSDavid du Colombier 	}
10657dd7cddfSDavid du Colombier 	if (argc > 1)
106600d97012SDavid du Colombier 	{	FILE *fd = stdout;
106700d97012SDavid du Colombier 		char cmd[512], out2[512];
1068312a1df1SDavid du Colombier 
1069312a1df1SDavid du Colombier 		/* must remain in current dir */
1070312a1df1SDavid du Colombier 		strcpy(out1, "pan.pre");
1071312a1df1SDavid du Colombier 
10727dd7cddfSDavid du Colombier 		if (add_ltl || nvr_file)
1073*de2caf28SDavid du Colombier 		{	assert(strlen(argv[1]) < sizeof(out2));
1074*de2caf28SDavid du Colombier 			sprintf(out2, "%s.nvr", argv[1]);
107500d97012SDavid du Colombier 			if ((fd = fopen(out2, MFLAGS)) == NULL)
107600d97012SDavid du Colombier 			{	printf("spin: cannot create tmp file %s\n",
107700d97012SDavid du Colombier 					out2);
10787dd7cddfSDavid du Colombier 				alldone(1);
10797dd7cddfSDavid du Colombier 			}
108000d97012SDavid du Colombier 			fprintf(fd, "#include \"%s\"\n", argv[1]);
108100d97012SDavid du Colombier 		}
108200d97012SDavid du Colombier 
108300d97012SDavid du Colombier 		if (add_ltl)
108400d97012SDavid du Colombier 		{	tl_out = fd;
108500d97012SDavid du Colombier 			nr_errs = tl_main(2, add_ltl);
108600d97012SDavid du Colombier 			fclose(fd);
108700d97012SDavid du Colombier 			preprocess(out2, out1, 1);
108800d97012SDavid du Colombier 		} else if (nvr_file)
108900d97012SDavid du Colombier 		{	fprintf(fd, "#include \"%s\"\n", *nvr_file);
10907dd7cddfSDavid du Colombier 			fclose(fd);
10917dd7cddfSDavid du Colombier 			preprocess(out2, out1, 1);
10927dd7cddfSDavid du Colombier 		} else
109300d97012SDavid du Colombier 		{	preprocess(argv[1], out1, 0);
109400d97012SDavid du Colombier 		}
10957dd7cddfSDavid du Colombier 
10967dd7cddfSDavid du Colombier 		if (preprocessonly)
1097*de2caf28SDavid du Colombier 		{	alldone(0);
1098*de2caf28SDavid du Colombier 		}
1099312a1df1SDavid du Colombier 
11007dd7cddfSDavid du Colombier 		if (!(yyin = fopen(out1, "r")))
11017dd7cddfSDavid du Colombier 		{	printf("spin: cannot open %s\n", out1);
11027dd7cddfSDavid du Colombier 			alldone(1);
11037dd7cddfSDavid du Colombier 		}
11047dd7cddfSDavid du Colombier 
1105*de2caf28SDavid du Colombier 		assert(strlen(argv[1])+1 < sizeof(cmd));
1106*de2caf28SDavid du Colombier 
110700d97012SDavid du Colombier 		if (strncmp(argv[1], "progress", (size_t) 8) == 0
110800d97012SDavid du Colombier 		||  strncmp(argv[1], "accept", (size_t) 6) == 0)
1109*de2caf28SDavid du Colombier 		{	sprintf(cmd, "_%s", argv[1]);
1110*de2caf28SDavid du Colombier 		} else
1111*de2caf28SDavid du Colombier 		{	strcpy(cmd, argv[1]);
1112*de2caf28SDavid du Colombier 		}
11137dd7cddfSDavid du Colombier 		oFname = Fname = lookup(cmd);
1114219b2ee8SDavid du Colombier 		if (oFname->name[0] == '\"')
1115312a1df1SDavid du Colombier 		{	int i = (int) strlen(oFname->name);
1116219b2ee8SDavid du Colombier 			oFname->name[i-1] = '\0';
1117219b2ee8SDavid du Colombier 			oFname = lookup(&oFname->name[1]);
1118219b2ee8SDavid du Colombier 		}
1119219b2ee8SDavid du Colombier 	} else
11207dd7cddfSDavid du Colombier 	{	oFname = Fname = lookup("<stdin>");
11217dd7cddfSDavid du Colombier 		if (add_ltl)
11227dd7cddfSDavid du Colombier 		{	if (argc > 0)
11237dd7cddfSDavid du Colombier 				exit(tl_main(2, add_ltl));
11247dd7cddfSDavid du Colombier 			printf("spin: missing argument to -f\n");
11257dd7cddfSDavid du Colombier 			alldone(1);
11267dd7cddfSDavid du Colombier 		}
112700d97012SDavid du Colombier 		printf("%s\n", SpinVersion);
1128*de2caf28SDavid du Colombier 		fprintf(stderr, "spin: error, no filename specified\n");
11297dd7cddfSDavid du Colombier 		fflush(stdout);
113000d97012SDavid du Colombier 		alldone(1);
11317dd7cddfSDavid du Colombier 	}
11327dd7cddfSDavid du Colombier 	if (columns == 2)
1133*de2caf28SDavid du Colombier 	{	if (xspin || (verbose & (1|4|8|16|32)))
11347dd7cddfSDavid du Colombier 		{	printf("spin: -c precludes all flags except -t\n");
11357dd7cddfSDavid du Colombier 			alldone(1);
11367dd7cddfSDavid du Colombier 		}
11377dd7cddfSDavid du Colombier 		putprelude();
11387dd7cddfSDavid du Colombier 	}
11397dd7cddfSDavid du Colombier 	if (columns && !(verbose&8) && !(verbose&16))
1140*de2caf28SDavid du Colombier 	{	verbose += (8+16);
1141*de2caf28SDavid du Colombier 	}
11427dd7cddfSDavid du Colombier 	if (columns == 2 && limited_vis)
1143*de2caf28SDavid du Colombier 	{	verbose += (1+4);
1144*de2caf28SDavid du Colombier 	}
1145*de2caf28SDavid du Colombier 
114600d97012SDavid du Colombier 	Srand((unsigned int) T);	/* defined in run.c */
1147312a1df1SDavid du Colombier 	SeedUsed = T;
1148312a1df1SDavid du Colombier 	s = lookup("_");	s->type = PREDEF; /* write-only global var */
1149219b2ee8SDavid du Colombier 	s = lookup("_p");	s->type = PREDEF;
1150219b2ee8SDavid du Colombier 	s = lookup("_pid");	s->type = PREDEF;
1151219b2ee8SDavid du Colombier 	s = lookup("_last");	s->type = PREDEF;
11527dd7cddfSDavid du Colombier 	s = lookup("_nr_pr");	s->type = PREDEF; /* new 3.3.10 */
1153*de2caf28SDavid du Colombier 	s = lookup("_priority"); s->type = PREDEF; /* new 6.2.0 */
1154312a1df1SDavid du Colombier 
1155219b2ee8SDavid du Colombier 	yyparse();
11567dd7cddfSDavid du Colombier 	fclose(yyin);
115700d97012SDavid du Colombier 
115800d97012SDavid du Colombier 	if (ltl_claims)
115900d97012SDavid du Colombier 	{	Symbol *r;
116000d97012SDavid du Colombier 		fclose(fd_ltl);
116100d97012SDavid du Colombier 		if (!(yyin = fopen(ltl_claims, "r")))
116200d97012SDavid du Colombier 		{	fatal("cannot open %s", ltl_claims);
116300d97012SDavid du Colombier 		}
116400d97012SDavid du Colombier 		r = oFname;
116500d97012SDavid du Colombier 		oFname = Fname = lookup(ltl_claims);
116600d97012SDavid du Colombier 		lineno = 0;
116700d97012SDavid du Colombier 		yyparse();
116800d97012SDavid du Colombier 		fclose(yyin);
116900d97012SDavid du Colombier 		oFname = Fname = r;
117000d97012SDavid du Colombier 		if (0)
117100d97012SDavid du Colombier 		{	(void) unlink(ltl_claims);
117200d97012SDavid du Colombier 	}	}
117300d97012SDavid du Colombier 
1174312a1df1SDavid du Colombier 	loose_ends();
1175312a1df1SDavid du Colombier 
1176312a1df1SDavid du Colombier 	if (inlineonly)
1177312a1df1SDavid du Colombier 	{	repro_src();
1178312a1df1SDavid du Colombier 		return 0;
1179312a1df1SDavid du Colombier 	}
1180312a1df1SDavid du Colombier 
11817dd7cddfSDavid du Colombier 	chanaccess();
1182312a1df1SDavid du Colombier 	if (!Caccess)
1183*de2caf28SDavid du Colombier 	{	if (has_provided && merger)
1184*de2caf28SDavid du Colombier 		{	merger = 0;	/* cannot use statement merging in this case */
1185*de2caf28SDavid du Colombier 		}
1186*de2caf28SDavid du Colombier 		if (!s_trail && (dataflow || merger) && (!replay || has_code))
1187*de2caf28SDavid du Colombier 		{	ana_src(dataflow, merger);
1188*de2caf28SDavid du Colombier 		}
11897dd7cddfSDavid du Colombier 		sched();
11907dd7cddfSDavid du Colombier 		alldone(nr_errs);
1191312a1df1SDavid du Colombier 	}
1192*de2caf28SDavid du Colombier 
1193312a1df1SDavid du Colombier 	return 0;
1194219b2ee8SDavid du Colombier }
1195219b2ee8SDavid du Colombier 
119600d97012SDavid du Colombier void
ltl_list(char * nm,char * fm)119700d97012SDavid du Colombier ltl_list(char *nm, char *fm)
119800d97012SDavid du Colombier {
1199*de2caf28SDavid du Colombier 	if (s_trail
1200*de2caf28SDavid du Colombier 	||  analyze
1201*de2caf28SDavid du Colombier 	||  dumptab)	/* when generating pan.c or replaying a trace */
120200d97012SDavid du Colombier 	{	if (!ltl_claims)
120300d97012SDavid du Colombier 		{	ltl_claims = "_spin_nvr.tmp";
120400d97012SDavid du Colombier 			if ((fd_ltl = fopen(ltl_claims, MFLAGS)) == NULL)
120500d97012SDavid du Colombier 			{	fatal("cannot open tmp file %s", ltl_claims);
120600d97012SDavid du Colombier 			}
120700d97012SDavid du Colombier 			tl_out = fd_ltl;
120800d97012SDavid du Colombier 		}
120900d97012SDavid du Colombier 		add_ltl = (char **) emalloc(5 * sizeof(char *));
121000d97012SDavid du Colombier 		add_ltl[1] = "-c";
121100d97012SDavid du Colombier 		add_ltl[2] = nm;
121200d97012SDavid du Colombier 		add_ltl[3] = "-f";
121300d97012SDavid du Colombier 		add_ltl[4] = (char *) emalloc(strlen(fm)+4);
121400d97012SDavid du Colombier 		strcpy(add_ltl[4], "!(");
121500d97012SDavid du Colombier 		strcat(add_ltl[4], fm);
121600d97012SDavid du Colombier 		strcat(add_ltl[4], ")");
121700d97012SDavid du Colombier 		/* add_ltl[4] = fm; */
121800d97012SDavid du Colombier 		nr_errs += tl_main(4, add_ltl);
121900d97012SDavid du Colombier 
122000d97012SDavid du Colombier 		fflush(tl_out);
122100d97012SDavid du Colombier 		/* should read this file after the main file is read */
122200d97012SDavid du Colombier 	}
122300d97012SDavid du Colombier }
122400d97012SDavid du Colombier 
1225219b2ee8SDavid du Colombier void
non_fatal(char * s1,char * s2)1226219b2ee8SDavid du Colombier non_fatal(char *s1, char *s2)
12277dd7cddfSDavid du Colombier {	extern char yytext[];
1228219b2ee8SDavid du Colombier 
122900d97012SDavid du Colombier 	printf("spin: %s:%d, Error: ",
1230*de2caf28SDavid du Colombier 		Fname?Fname->name:(oFname?oFname->name:"nofilename"), lineno);
1231*de2caf28SDavid du Colombier #if 1
1232*de2caf28SDavid du Colombier 	printf(s1, s2); /* avoids a gcc warning */
1233*de2caf28SDavid du Colombier #else
1234219b2ee8SDavid du Colombier 	if (s2)
1235219b2ee8SDavid du Colombier 		printf(s1, s2);
1236219b2ee8SDavid du Colombier 	else
1237219b2ee8SDavid du Colombier 		printf(s1);
1238*de2caf28SDavid du Colombier #endif
123900d97012SDavid du Colombier 	if (strlen(yytext)>1)
1240219b2ee8SDavid du Colombier 		printf(" near '%s'", yytext);
12417dd7cddfSDavid du Colombier 	printf("\n");
1242219b2ee8SDavid du Colombier 	nr_errs++;
1243219b2ee8SDavid du Colombier }
1244219b2ee8SDavid du Colombier 
1245219b2ee8SDavid du Colombier void
fatal(char * s1,char * s2)1246219b2ee8SDavid du Colombier fatal(char *s1, char *s2)
1247219b2ee8SDavid du Colombier {
1248219b2ee8SDavid du Colombier 	non_fatal(s1, s2);
124900d97012SDavid du Colombier 	(void) unlink("pan.b");
125000d97012SDavid du Colombier 	(void) unlink("pan.c");
125100d97012SDavid du Colombier 	(void) unlink("pan.h");
125200d97012SDavid du Colombier 	(void) unlink("pan.m");
125300d97012SDavid du Colombier 	(void) unlink("pan.t");
1254*de2caf28SDavid du Colombier 	(void) unlink("pan.p");
125500d97012SDavid du Colombier 	(void) unlink("pan.pre");
1256*de2caf28SDavid du Colombier 	if (!(verbose&32))
1257*de2caf28SDavid du Colombier 	{	(void) unlink("_spin_nvr.tmp");
1258*de2caf28SDavid du Colombier 	}
12597dd7cddfSDavid du Colombier 	alldone(1);
1260219b2ee8SDavid du Colombier }
1261219b2ee8SDavid du Colombier 
1262219b2ee8SDavid du Colombier char *
emalloc(size_t n)126300d97012SDavid du Colombier emalloc(size_t n)
1264219b2ee8SDavid du Colombier {	char *tmp;
126500d97012SDavid du Colombier 	static unsigned long cnt = 0;
1266219b2ee8SDavid du Colombier 
1267f3793cddSDavid du Colombier 	if (n == 0)
1268f3793cddSDavid du Colombier 		return NULL;	/* robert shelton 10/20/06 */
1269f3793cddSDavid du Colombier 
1270219b2ee8SDavid du Colombier 	if (!(tmp = (char *) malloc(n)))
127100d97012SDavid du Colombier 	{	printf("spin: allocated %ld Gb, wanted %d bytes more\n",
127200d97012SDavid du Colombier 			cnt/(1024*1024*1024), (int) n);
1273219b2ee8SDavid du Colombier 		fatal("not enough memory", (char *)0);
127400d97012SDavid du Colombier 	}
127500d97012SDavid du Colombier 	cnt += (unsigned long) n;
1276219b2ee8SDavid du Colombier 	memset(tmp, 0, n);
1277219b2ee8SDavid du Colombier 	return tmp;
1278219b2ee8SDavid du Colombier }
1279219b2ee8SDavid du Colombier 
12807dd7cddfSDavid du Colombier void
trapwonly(Lextok * n)128100d97012SDavid du Colombier trapwonly(Lextok *n /* , char *unused */)
1282*de2caf28SDavid du Colombier {	short i;
12837dd7cddfSDavid du Colombier 
1284*de2caf28SDavid du Colombier 	if (!n)
1285*de2caf28SDavid du Colombier 	{	fatal("unexpected error,", (char *) 0);
1286*de2caf28SDavid du Colombier 	}
12877dd7cddfSDavid du Colombier 
1288*de2caf28SDavid du Colombier 	i = (n->sym)?n->sym->type:0;
1289*de2caf28SDavid du Colombier 
1290*de2caf28SDavid du Colombier 	/* printf("%s	realread %d type %d\n", n->sym?n->sym->name:"--", realread, i); */
1291*de2caf28SDavid du Colombier 
1292*de2caf28SDavid du Colombier 	if (realread
1293*de2caf28SDavid du Colombier 	&& (i == MTYPE
1294*de2caf28SDavid du Colombier 	||  i == BIT
1295*de2caf28SDavid du Colombier 	||  i == BYTE
1296*de2caf28SDavid du Colombier 	||  i == SHORT
1297*de2caf28SDavid du Colombier 	||  i == INT
1298*de2caf28SDavid du Colombier 	||  i == UNSIGNED))
1299*de2caf28SDavid du Colombier 	{	n->sym->hidden |= 128;	/* var is read at least once */
1300*de2caf28SDavid du Colombier 	}
13017dd7cddfSDavid du Colombier }
13027dd7cddfSDavid du Colombier 
13037dd7cddfSDavid du Colombier void
setaccess(Symbol * sp,Symbol * what,int cnt,int t)13047dd7cddfSDavid du Colombier setaccess(Symbol *sp, Symbol *what, int cnt, int t)
13057dd7cddfSDavid du Colombier {	Access *a;
13067dd7cddfSDavid du Colombier 
13077dd7cddfSDavid du Colombier 	for (a = sp->access; a; a = a->lnk)
13087dd7cddfSDavid du Colombier 		if (a->who == context
13097dd7cddfSDavid du Colombier 		&&  a->what == what
13107dd7cddfSDavid du Colombier 		&&  a->cnt == cnt
13117dd7cddfSDavid du Colombier 		&&  a->typ == t)
13127dd7cddfSDavid du Colombier 			return;
13137dd7cddfSDavid du Colombier 
13147dd7cddfSDavid du Colombier 	a = (Access *) emalloc(sizeof(Access));
13157dd7cddfSDavid du Colombier 	a->who = context;
13167dd7cddfSDavid du Colombier 	a->what = what;
13177dd7cddfSDavid du Colombier 	a->cnt = cnt;
13187dd7cddfSDavid du Colombier 	a->typ = t;
13197dd7cddfSDavid du Colombier 	a->lnk = sp->access;
13207dd7cddfSDavid du Colombier 	sp->access = a;
13217dd7cddfSDavid du Colombier }
13227dd7cddfSDavid du Colombier 
1323219b2ee8SDavid du Colombier Lextok *
nn(Lextok * s,int t,Lextok * ll,Lextok * rl)1324219b2ee8SDavid du Colombier nn(Lextok *s, int t, Lextok *ll, Lextok *rl)
1325219b2ee8SDavid du Colombier {	Lextok *n = (Lextok *) emalloc(sizeof(Lextok));
1326312a1df1SDavid du Colombier 	static int warn_nn = 0;
1327219b2ee8SDavid du Colombier 
132800d97012SDavid du Colombier 	n->uiid = is_inline();	/* record origin of the statement */
1329*de2caf28SDavid du Colombier 	n->ntyp = (unsigned short) t;
1330219b2ee8SDavid du Colombier 	if (s && s->fn)
1331219b2ee8SDavid du Colombier 	{	n->ln = s->ln;
1332219b2ee8SDavid du Colombier 		n->fn = s->fn;
1333219b2ee8SDavid du Colombier 	} else if (rl && rl->fn)
1334219b2ee8SDavid du Colombier 	{	n->ln = rl->ln;
1335219b2ee8SDavid du Colombier 		n->fn = rl->fn;
1336219b2ee8SDavid du Colombier 	} else if (ll && ll->fn)
1337219b2ee8SDavid du Colombier 	{	n->ln = ll->ln;
1338219b2ee8SDavid du Colombier 		n->fn = ll->fn;
1339219b2ee8SDavid du Colombier 	} else
1340219b2ee8SDavid du Colombier 	{	n->ln = lineno;
1341219b2ee8SDavid du Colombier 		n->fn = Fname;
1342219b2ee8SDavid du Colombier 	}
1343219b2ee8SDavid du Colombier 	if (s) n->sym  = s->sym;
1344219b2ee8SDavid du Colombier 	n->lft  = ll;
1345219b2ee8SDavid du Colombier 	n->rgt  = rl;
1346219b2ee8SDavid du Colombier 	n->indstep = DstepStart;
1347219b2ee8SDavid du Colombier 
1348219b2ee8SDavid du Colombier 	if (t == TIMEOUT) Etimeouts++;
1349219b2ee8SDavid du Colombier 
13507dd7cddfSDavid du Colombier 	if (!context) return n;
13517dd7cddfSDavid du Colombier 
13527dd7cddfSDavid du Colombier 	if (t == 'r' || t == 's')
13537dd7cddfSDavid du Colombier 		setaccess(n->sym, ZS, 0, t);
13547dd7cddfSDavid du Colombier 	if (t == 'R')
13557dd7cddfSDavid du Colombier 		setaccess(n->sym, ZS, 0, 'P');
13567dd7cddfSDavid du Colombier 
1357219b2ee8SDavid du Colombier 	if (context->name == claimproc)
13587dd7cddfSDavid du Colombier 	{	int forbidden = separate;
13597dd7cddfSDavid du Colombier 		switch (t) {
13607dd7cddfSDavid du Colombier 		case ASGN:
13617dd7cddfSDavid du Colombier 			printf("spin: Warning, never claim has side-effect\n");
13627dd7cddfSDavid du Colombier 			break;
13637dd7cddfSDavid du Colombier 		case 'r': case 's':
13647dd7cddfSDavid du Colombier 			non_fatal("never claim contains i/o stmnts",(char *)0);
1365219b2ee8SDavid du Colombier 			break;
1366219b2ee8SDavid du Colombier 		case TIMEOUT:
1367219b2ee8SDavid du Colombier 			/* never claim polls timeout */
13687dd7cddfSDavid du Colombier 			if (Ntimeouts && Etimeouts)
13697dd7cddfSDavid du Colombier 				forbidden = 0;
1370219b2ee8SDavid du Colombier 			Ntimeouts++; Etimeouts--;
1371219b2ee8SDavid du Colombier 			break;
1372219b2ee8SDavid du Colombier 		case LEN: case EMPTY: case FULL:
1373219b2ee8SDavid du Colombier 		case 'R': case NFULL: case NEMPTY:
13747dd7cddfSDavid du Colombier 			/* status becomes non-exclusive */
13757dd7cddfSDavid du Colombier 			if (n->sym && !(n->sym->xu&XX))
13767dd7cddfSDavid du Colombier 			{	n->sym->xu |= XX;
13777dd7cddfSDavid du Colombier 				if (separate == 2) {
13787dd7cddfSDavid du Colombier 				printf("spin: warning, make sure that the S1 model\n");
13797dd7cddfSDavid du Colombier 				printf("      also polls channel '%s' in its claim\n",
13807dd7cddfSDavid du Colombier 				n->sym->name);
13817dd7cddfSDavid du Colombier 			}	}
13827dd7cddfSDavid du Colombier 			forbidden = 0;
1383219b2ee8SDavid du Colombier 			break;
1384312a1df1SDavid du Colombier 		case 'c':
1385312a1df1SDavid du Colombier 			AST_track(n, 0);	/* register as a slice criterion */
1386312a1df1SDavid du Colombier 			/* fall thru */
1387219b2ee8SDavid du Colombier 		default:
13887dd7cddfSDavid du Colombier 			forbidden = 0;
1389219b2ee8SDavid du Colombier 			break;
1390219b2ee8SDavid du Colombier 		}
13917dd7cddfSDavid du Colombier 		if (forbidden)
13927dd7cddfSDavid du Colombier 		{	printf("spin: never, saw "); explain(t); printf("\n");
13937dd7cddfSDavid du Colombier 			fatal("incompatible with separate compilation",(char *)0);
13947dd7cddfSDavid du Colombier 		}
1395312a1df1SDavid du Colombier 	} else if ((t == ENABLED || t == PC_VAL) && !(warn_nn&t))
1396312a1df1SDavid du Colombier 	{	printf("spin: Warning, using %s outside never claim\n",
13977dd7cddfSDavid du Colombier 			(t == ENABLED)?"enabled()":"pc_value()");
1398312a1df1SDavid du Colombier 		warn_nn |= t;
13997dd7cddfSDavid du Colombier 	} else if (t == NONPROGRESS)
1400312a1df1SDavid du Colombier 	{	fatal("spin: Error, using np_ outside never claim\n", (char *)0);
14017dd7cddfSDavid du Colombier 	}
1402219b2ee8SDavid du Colombier 	return n;
1403219b2ee8SDavid du Colombier }
1404219b2ee8SDavid du Colombier 
1405219b2ee8SDavid du Colombier Lextok *
rem_lab(Symbol * a,Lextok * b,Symbol * c)1406312a1df1SDavid du Colombier rem_lab(Symbol *a, Lextok *b, Symbol *c)	/* proctype name, pid, label name */
1407219b2ee8SDavid du Colombier {	Lextok *tmp1, *tmp2, *tmp3;
1408219b2ee8SDavid du Colombier 
1409219b2ee8SDavid du Colombier 	has_remote++;
1410312a1df1SDavid du Colombier 	c->type = LABEL;	/* refered to in global context here */
1411312a1df1SDavid du Colombier 	fix_dest(c, a);		/* in case target of rem_lab is jump */
1412219b2ee8SDavid du Colombier 	tmp1 = nn(ZN, '?',   b, ZN); tmp1->sym = a;
1413219b2ee8SDavid du Colombier 	tmp1 = nn(ZN, 'p', tmp1, ZN);
1414219b2ee8SDavid du Colombier 	tmp1->sym = lookup("_p");
1415219b2ee8SDavid du Colombier 	tmp2 = nn(ZN, NAME,  ZN, ZN); tmp2->sym = a;
1416219b2ee8SDavid du Colombier 	tmp3 = nn(ZN, 'q', tmp2, ZN); tmp3->sym = c;
1417219b2ee8SDavid du Colombier 	return nn(ZN, EQ, tmp1, tmp3);
1418312a1df1SDavid du Colombier #if 0
1419312a1df1SDavid du Colombier 	      .---------------EQ-------.
1420312a1df1SDavid du Colombier 	     /                          \
1421312a1df1SDavid du Colombier 	   'p' -sym-> _p               'q' -sym-> c (label name)
1422312a1df1SDavid du Colombier 	   /                           /
1423312a1df1SDavid du Colombier 	 '?' -sym-> a (proctype)     NAME -sym-> a (proctype name)
1424312a1df1SDavid du Colombier 	 /
1425312a1df1SDavid du Colombier 	b (pid expr)
1426312a1df1SDavid du Colombier #endif
1427312a1df1SDavid du Colombier }
1428312a1df1SDavid du Colombier 
1429312a1df1SDavid du Colombier Lextok *
rem_var(Symbol * a,Lextok * b,Symbol * c,Lextok * ndx)1430312a1df1SDavid du Colombier rem_var(Symbol *a, Lextok *b, Symbol *c, Lextok *ndx)
1431312a1df1SDavid du Colombier {	Lextok *tmp1;
1432312a1df1SDavid du Colombier 
1433312a1df1SDavid du Colombier 	has_remote++;
1434312a1df1SDavid du Colombier 	has_remvar++;
1435312a1df1SDavid du Colombier 	dataflow = 0;	/* turn off dead variable resets 4.2.5 */
1436*de2caf28SDavid du Colombier 	merger   = 0;	/* turn off statement merging for locals 6.4.9 */
1437312a1df1SDavid du Colombier 	tmp1 = nn(ZN, '?', b, ZN); tmp1->sym = a;
1438312a1df1SDavid du Colombier 	tmp1 = nn(ZN, 'p', tmp1, ndx);
1439312a1df1SDavid du Colombier 	tmp1->sym = c;
1440312a1df1SDavid du Colombier 	return tmp1;
1441312a1df1SDavid du Colombier #if 0
1442312a1df1SDavid du Colombier 	cannot refer to struct elements
1443312a1df1SDavid du Colombier 	only to scalars and arrays
1444312a1df1SDavid du Colombier 
1445312a1df1SDavid du Colombier 	    'p' -sym-> c (variable name)
1446312a1df1SDavid du Colombier 	    / \______  possible arrayindex on c
1447312a1df1SDavid du Colombier 	   /
1448312a1df1SDavid du Colombier 	 '?' -sym-> a (proctype)
1449312a1df1SDavid du Colombier 	 /
1450312a1df1SDavid du Colombier 	b (pid expr)
1451312a1df1SDavid du Colombier #endif
1452219b2ee8SDavid du Colombier }
1453219b2ee8SDavid du Colombier 
145400d97012SDavid du Colombier void
explain(int n)1455219b2ee8SDavid du Colombier explain(int n)
14567dd7cddfSDavid du Colombier {	FILE *fd = stdout;
1457219b2ee8SDavid du Colombier 	switch (n) {
1458219b2ee8SDavid du Colombier 	default:	if (n > 0 && n < 256)
145900d97012SDavid du Colombier 				fprintf(fd, "'%c' = ", n);
146000d97012SDavid du Colombier 			fprintf(fd, "%d", n);
1461219b2ee8SDavid du Colombier 			break;
14627dd7cddfSDavid du Colombier 	case '\b':	fprintf(fd, "\\b"); break;
14637dd7cddfSDavid du Colombier 	case '\t':	fprintf(fd, "\\t"); break;
14647dd7cddfSDavid du Colombier 	case '\f':	fprintf(fd, "\\f"); break;
14657dd7cddfSDavid du Colombier 	case '\n':	fprintf(fd, "\\n"); break;
14667dd7cddfSDavid du Colombier 	case '\r':	fprintf(fd, "\\r"); break;
14677dd7cddfSDavid du Colombier 	case 'c':	fprintf(fd, "condition"); break;
14687dd7cddfSDavid du Colombier 	case 's':	fprintf(fd, "send"); break;
14697dd7cddfSDavid du Colombier 	case 'r':	fprintf(fd, "recv"); break;
14707dd7cddfSDavid du Colombier 	case 'R':	fprintf(fd, "recv poll %s", Operator); break;
14717dd7cddfSDavid du Colombier 	case '@':	fprintf(fd, "@"); break;
14727dd7cddfSDavid du Colombier 	case '?':	fprintf(fd, "(x->y:z)"); break;
147300d97012SDavid du Colombier #if 1
147400d97012SDavid du Colombier 	case NEXT:	fprintf(fd, "X"); break;
147500d97012SDavid du Colombier 	case ALWAYS:	fprintf(fd, "[]"); break;
147600d97012SDavid du Colombier 	case EVENTUALLY: fprintf(fd, "<>"); break;
147700d97012SDavid du Colombier 	case IMPLIES:	fprintf(fd, "->"); break;
147800d97012SDavid du Colombier 	case EQUIV:	fprintf(fd, "<->"); break;
147900d97012SDavid du Colombier 	case UNTIL:	fprintf(fd, "U"); break;
148000d97012SDavid du Colombier 	case WEAK_UNTIL: fprintf(fd, "W"); break;
148100d97012SDavid du Colombier 	case IN: fprintf(fd, "%sin", Keyword); break;
148200d97012SDavid du Colombier #endif
14837dd7cddfSDavid du Colombier 	case ACTIVE:	fprintf(fd, "%sactive",	Keyword); break;
14847dd7cddfSDavid du Colombier 	case AND:	fprintf(fd, "%s&&",	Operator); break;
14857dd7cddfSDavid du Colombier 	case ASGN:	fprintf(fd, "%s=",	Operator); break;
14867dd7cddfSDavid du Colombier 	case ASSERT:	fprintf(fd, "%sassert",	Function); break;
14877dd7cddfSDavid du Colombier 	case ATOMIC:	fprintf(fd, "%satomic",	Keyword); break;
14887dd7cddfSDavid du Colombier 	case BREAK:	fprintf(fd, "%sbreak",	Keyword); break;
1489312a1df1SDavid du Colombier 	case C_CODE:	fprintf(fd, "%sc_code",	Keyword); break;
1490312a1df1SDavid du Colombier 	case C_DECL:	fprintf(fd, "%sc_decl",	Keyword); break;
1491312a1df1SDavid du Colombier 	case C_EXPR:	fprintf(fd, "%sc_expr",	Keyword); break;
1492312a1df1SDavid du Colombier 	case C_STATE:	fprintf(fd, "%sc_state",Keyword); break;
1493312a1df1SDavid du Colombier 	case C_TRACK:	fprintf(fd, "%sc_track",Keyword); break;
14947dd7cddfSDavid du Colombier 	case CLAIM:	fprintf(fd, "%snever",	Keyword); break;
14957dd7cddfSDavid du Colombier 	case CONST:	fprintf(fd, "a constant"); break;
14967dd7cddfSDavid du Colombier 	case DECR:	fprintf(fd, "%s--",	Operator); break;
14977dd7cddfSDavid du Colombier 	case D_STEP:	fprintf(fd, "%sd_step",	Keyword); break;
1498312a1df1SDavid du Colombier 	case D_PROCTYPE: fprintf(fd, "%sd_proctype", Keyword); break;
14997dd7cddfSDavid du Colombier 	case DO:	fprintf(fd, "%sdo",	Keyword); break;
15007dd7cddfSDavid du Colombier 	case DOT:	fprintf(fd, "."); break;
15017dd7cddfSDavid du Colombier 	case ELSE:	fprintf(fd, "%selse",	Keyword); break;
15027dd7cddfSDavid du Colombier 	case EMPTY:	fprintf(fd, "%sempty",	Function); break;
15037dd7cddfSDavid du Colombier 	case ENABLED:	fprintf(fd, "%senabled",Function); break;
15047dd7cddfSDavid du Colombier 	case EQ:	fprintf(fd, "%s==",	Operator); break;
15057dd7cddfSDavid du Colombier 	case EVAL:	fprintf(fd, "%seval",	Function); break;
15067dd7cddfSDavid du Colombier 	case FI:	fprintf(fd, "%sfi",	Keyword); break;
15077dd7cddfSDavid du Colombier 	case FULL:	fprintf(fd, "%sfull",	Function); break;
15087dd7cddfSDavid du Colombier 	case GE:	fprintf(fd, "%s>=",	Operator); break;
1509*de2caf28SDavid du Colombier 	case GET_P:	fprintf(fd, "%sget_priority",Function); break;
15107dd7cddfSDavid du Colombier 	case GOTO:	fprintf(fd, "%sgoto",	Keyword); break;
15117dd7cddfSDavid du Colombier 	case GT:	fprintf(fd, "%s>",	Operator); break;
1512312a1df1SDavid du Colombier 	case HIDDEN:	fprintf(fd, "%shidden",	Keyword); break;
15137dd7cddfSDavid du Colombier 	case IF:	fprintf(fd, "%sif",	Keyword); break;
15147dd7cddfSDavid du Colombier 	case INCR:	fprintf(fd, "%s++",	Operator); break;
15157dd7cddfSDavid du Colombier 	case INAME:	fprintf(fd, "inline name"); break;
15167dd7cddfSDavid du Colombier 	case INLINE:	fprintf(fd, "%sinline",	Keyword); break;
15177dd7cddfSDavid du Colombier 	case INIT:	fprintf(fd, "%sinit",	Keyword); break;
1518312a1df1SDavid du Colombier 	case ISLOCAL:	fprintf(fd, "%slocal",  Keyword); break;
15197dd7cddfSDavid du Colombier 	case LABEL:	fprintf(fd, "a label-name"); break;
15207dd7cddfSDavid du Colombier 	case LE:	fprintf(fd, "%s<=",	Operator); break;
15217dd7cddfSDavid du Colombier 	case LEN:	fprintf(fd, "%slen",	Function); break;
15227dd7cddfSDavid du Colombier 	case LSHIFT:	fprintf(fd, "%s<<",	Operator); break;
15237dd7cddfSDavid du Colombier 	case LT:	fprintf(fd, "%s<",	Operator); break;
15247dd7cddfSDavid du Colombier 	case MTYPE:	fprintf(fd, "%smtype",	Keyword); break;
15257dd7cddfSDavid du Colombier 	case NAME:	fprintf(fd, "an identifier"); break;
15267dd7cddfSDavid du Colombier 	case NE:	fprintf(fd, "%s!=",	Operator); break;
15277dd7cddfSDavid du Colombier 	case NEG:	fprintf(fd, "%s! (not)",Operator); break;
15287dd7cddfSDavid du Colombier 	case NEMPTY:	fprintf(fd, "%snempty",	Function); break;
15297dd7cddfSDavid du Colombier 	case NFULL:	fprintf(fd, "%snfull",	Function); break;
15307dd7cddfSDavid du Colombier 	case NON_ATOMIC: fprintf(fd, "sub-sequence"); break;
15317dd7cddfSDavid du Colombier 	case NONPROGRESS: fprintf(fd, "%snp_",	Function); break;
15327dd7cddfSDavid du Colombier 	case OD:	fprintf(fd, "%sod",	Keyword); break;
15337dd7cddfSDavid du Colombier 	case OF:	fprintf(fd, "%sof",	Keyword); break;
15347dd7cddfSDavid du Colombier 	case OR:	fprintf(fd, "%s||",	Operator); break;
15357dd7cddfSDavid du Colombier 	case O_SND:	fprintf(fd, "%s!!",	Operator); break;
15367dd7cddfSDavid du Colombier 	case PC_VAL:	fprintf(fd, "%spc_value",Function); break;
15377dd7cddfSDavid du Colombier 	case PNAME:	fprintf(fd, "process name"); break;
15387dd7cddfSDavid du Colombier 	case PRINT:	fprintf(fd, "%sprintf",	Function); break;
1539312a1df1SDavid du Colombier 	case PRINTM:	fprintf(fd, "%sprintm",	Function); break;
1540312a1df1SDavid du Colombier 	case PRIORITY:	fprintf(fd, "%spriority", Keyword); break;
15417dd7cddfSDavid du Colombier 	case PROCTYPE:	fprintf(fd, "%sproctype",Keyword); break;
1542312a1df1SDavid du Colombier 	case PROVIDED:	fprintf(fd, "%sprovided",Keyword); break;
15437dd7cddfSDavid du Colombier 	case RCV:	fprintf(fd, "%s?",	Operator); break;
15447dd7cddfSDavid du Colombier 	case R_RCV:	fprintf(fd, "%s??",	Operator); break;
15457dd7cddfSDavid du Colombier 	case RSHIFT:	fprintf(fd, "%s>>",	Operator); break;
15467dd7cddfSDavid du Colombier 	case RUN:	fprintf(fd, "%srun",	Operator); break;
15477dd7cddfSDavid du Colombier 	case SEP:	fprintf(fd, "token: ::"); break;
15487dd7cddfSDavid du Colombier 	case SEMI:	fprintf(fd, ";"); break;
1549*de2caf28SDavid du Colombier 	case ARROW:	fprintf(fd, "->"); break;
1550*de2caf28SDavid du Colombier 	case SET_P:	fprintf(fd, "%sset_priority",Function); break;
1551312a1df1SDavid du Colombier 	case SHOW:	fprintf(fd, "%sshow", Keyword); break;
15527dd7cddfSDavid du Colombier 	case SND:	fprintf(fd, "%s!",	Operator); break;
15537dd7cddfSDavid du Colombier 	case STRING:	fprintf(fd, "a string"); break;
1554312a1df1SDavid du Colombier 	case TRACE:	fprintf(fd, "%strace", Keyword); break;
15557dd7cddfSDavid du Colombier 	case TIMEOUT:	fprintf(fd, "%stimeout",Keyword); break;
15567dd7cddfSDavid du Colombier 	case TYPE:	fprintf(fd, "data typename"); break;
15577dd7cddfSDavid du Colombier 	case TYPEDEF:	fprintf(fd, "%stypedef",Keyword); break;
15587dd7cddfSDavid du Colombier 	case XU:	fprintf(fd, "%sx[rs]",	Keyword); break;
15597dd7cddfSDavid du Colombier 	case UMIN:	fprintf(fd, "%s- (unary minus)", Operator); break;
15607dd7cddfSDavid du Colombier 	case UNAME:	fprintf(fd, "a typename"); break;
15617dd7cddfSDavid du Colombier 	case UNLESS:	fprintf(fd, "%sunless",	Keyword); break;
1562219b2ee8SDavid du Colombier 	}
1563219b2ee8SDavid du Colombier }
156400d97012SDavid du Colombier 
156500d97012SDavid du Colombier 
1566