xref: /plan9/sys/src/cmd/spin/spin.y (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
1219b2ee8SDavid du Colombier /***** spin: spin.y *****/
2219b2ee8SDavid du Colombier 
3312a1df1SDavid du Colombier /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
47dd7cddfSDavid du Colombier /* All Rights Reserved.  This software is for educational purposes only.  */
5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6312a1df1SDavid du Colombier /* this code.  Permission is given to distribute this code provided that  */
7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged.  */
8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9312a1df1SDavid du Colombier /*             http://spinroot.com/                                       */
10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
11219b2ee8SDavid du Colombier 
12219b2ee8SDavid du Colombier %{
13219b2ee8SDavid du Colombier #include "spin.h"
14*00d97012SDavid du Colombier #include <sys/types.h>
15*00d97012SDavid du Colombier #ifndef PC
16*00d97012SDavid du Colombier #include <unistd.h>
17*00d97012SDavid du Colombier #endif
18219b2ee8SDavid du Colombier #include <stdarg.h>
19219b2ee8SDavid du Colombier 
20219b2ee8SDavid du Colombier #define YYDEBUG	0
21219b2ee8SDavid du Colombier #define Stop	nn(ZN,'@',ZN,ZN)
22*00d97012SDavid du Colombier #define PART0	"place initialized var decl of "
23*00d97012SDavid du Colombier #define PART1	"place initialized chan decl of "
24*00d97012SDavid du Colombier #define PART2	" at start of proctype "
25*00d97012SDavid du Colombier 
26*00d97012SDavid du Colombier static	Lextok *ltl_to_string(Lextok *);
27219b2ee8SDavid du Colombier 
28219b2ee8SDavid du Colombier extern  Symbol	*context, *owner;
29*00d97012SDavid du Colombier extern	Lextok *for_body(Lextok *, int);
30*00d97012SDavid du Colombier extern	void for_setup(Lextok *, Lextok *, Lextok *);
31*00d97012SDavid du Colombier extern	Lextok *for_index(Lextok *, Lextok *);
32*00d97012SDavid du Colombier extern	Lextok *sel_index(Lextok *, Lextok *, Lextok *);
33*00d97012SDavid du Colombier extern  int	u_sync, u_async, dumptab, scope_level;
34*00d97012SDavid du Colombier extern	int	initialization_ok, split_decl;
357dd7cddfSDavid du Colombier extern	short	has_sorted, has_random, has_enabled, has_pcvalue, has_np;
36312a1df1SDavid du Colombier extern	short	has_code, has_state, has_io;
37312a1df1SDavid du Colombier extern	void	count_runs(Lextok *);
38f3793cddSDavid du Colombier extern	void	no_internals(Lextok *);
39f3793cddSDavid du Colombier extern	void	any_runs(Lextok *);
40*00d97012SDavid du Colombier extern	void	ltl_list(char *, char *);
417dd7cddfSDavid du Colombier extern	void	validref(Lextok *, Lextok *);
427dd7cddfSDavid du Colombier extern	char	yytext[];
43219b2ee8SDavid du Colombier 
44219b2ee8SDavid du Colombier int	Mpars = 0;	/* max nr of message parameters  */
45*00d97012SDavid du Colombier int	nclaims = 0;	/* nr of never claims */
46*00d97012SDavid du Colombier int	ltl_mode = 0;	/* set when parsing an ltl formula */
477dd7cddfSDavid du Colombier int	Expand_Ok = 0, realread = 1, IArgs = 0, NamesNotAdded = 0;
48*00d97012SDavid du Colombier int	in_for = 0;
49219b2ee8SDavid du Colombier char	*claimproc = (char *) 0;
507dd7cddfSDavid du Colombier char	*eventmap = (char *) 0;
51*00d97012SDavid du Colombier static	char *ltl_name;
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier static	int	Embedded = 0, inEventMap = 0, has_ini = 0;
547dd7cddfSDavid du Colombier 
55219b2ee8SDavid du Colombier %}
56219b2ee8SDavid du Colombier 
57312a1df1SDavid du Colombier %token	ASSERT PRINT PRINTM
58312a1df1SDavid du Colombier %token	C_CODE C_DECL C_EXPR C_STATE C_TRACK
597dd7cddfSDavid du Colombier %token	RUN LEN ENABLED EVAL PC_VAL
607dd7cddfSDavid du Colombier %token	TYPEDEF MTYPE INLINE LABEL OF
61219b2ee8SDavid du Colombier %token	GOTO BREAK ELSE SEMI
62*00d97012SDavid du Colombier %token	IF FI DO OD FOR SELECT IN SEP DOTDOT
63219b2ee8SDavid du Colombier %token	ATOMIC NON_ATOMIC D_STEP UNLESS
647dd7cddfSDavid du Colombier %token  TIMEOUT NONPROGRESS
657dd7cddfSDavid du Colombier %token	ACTIVE PROCTYPE D_PROCTYPE
667dd7cddfSDavid du Colombier %token	HIDDEN SHOW ISLOCAL
677dd7cddfSDavid du Colombier %token	PRIORITY PROVIDED
68219b2ee8SDavid du Colombier %token	FULL EMPTY NFULL NEMPTY
69219b2ee8SDavid du Colombier %token	CONST TYPE XU			/* val */
707dd7cddfSDavid du Colombier %token	NAME UNAME PNAME INAME		/* sym */
71*00d97012SDavid du Colombier %token	STRING CLAIM TRACE INIT	LTL	/* sym */
72219b2ee8SDavid du Colombier 
73219b2ee8SDavid du Colombier %right	ASGN
747dd7cddfSDavid du Colombier %left	SND O_SND RCV R_RCV /* SND doubles as boolean negation */
75*00d97012SDavid du Colombier %left	IMPLIES EQUIV			/* ltl */
76219b2ee8SDavid du Colombier %left	OR
77219b2ee8SDavid du Colombier %left	AND
78*00d97012SDavid du Colombier %left	ALWAYS EVENTUALLY		/* ltl */
79*00d97012SDavid du Colombier %left	UNTIL WEAK_UNTIL RELEASE	/* ltl */
80*00d97012SDavid du Colombier %right	NEXT				/* ltl */
81219b2ee8SDavid du Colombier %left	'|'
827dd7cddfSDavid du Colombier %left	'^'
83219b2ee8SDavid du Colombier %left	'&'
84219b2ee8SDavid du Colombier %left	EQ NE
85219b2ee8SDavid du Colombier %left	GT LT GE LE
86219b2ee8SDavid du Colombier %left	LSHIFT RSHIFT
87219b2ee8SDavid du Colombier %left	'+' '-'
88219b2ee8SDavid du Colombier %left	'*' '/' '%'
89219b2ee8SDavid du Colombier %left	INCR DECR
90219b2ee8SDavid du Colombier %right	'~' UMIN NEG
91219b2ee8SDavid du Colombier %left	DOT
92219b2ee8SDavid du Colombier %%
93219b2ee8SDavid du Colombier 
947dd7cddfSDavid du Colombier /** PROMELA Grammar Rules **/
95219b2ee8SDavid du Colombier 
967dd7cddfSDavid du Colombier program	: units		{ yytext[0] = '\0'; }
97219b2ee8SDavid du Colombier 	;
98219b2ee8SDavid du Colombier 
99219b2ee8SDavid du Colombier units	: unit
100219b2ee8SDavid du Colombier 	| units unit
101219b2ee8SDavid du Colombier 	;
102219b2ee8SDavid du Colombier 
103219b2ee8SDavid du Colombier unit	: proc		/* proctype { }       */
104219b2ee8SDavid du Colombier 	| init		/* init { }           */
105219b2ee8SDavid du Colombier 	| claim		/* never claim        */
106*00d97012SDavid du Colombier 	| ltl		/* ltl formula        */
1077dd7cddfSDavid du Colombier 	| events	/* event assertions   */
108219b2ee8SDavid du Colombier 	| one_decl	/* variables, chans   */
109219b2ee8SDavid du Colombier 	| utype		/* user defined types */
110312a1df1SDavid du Colombier 	| c_fcts	/* c functions etc.   */
1117dd7cddfSDavid du Colombier 	| ns		/* named sequence     */
112219b2ee8SDavid du Colombier 	| SEMI		/* optional separator */
113219b2ee8SDavid du Colombier 	| error
114219b2ee8SDavid du Colombier 	;
115219b2ee8SDavid du Colombier 
116219b2ee8SDavid du Colombier proc	: inst		/* optional instantiator */
1177dd7cddfSDavid du Colombier 	  proctype NAME	{
1187dd7cddfSDavid du Colombier 			  setptype($3, PROCTYPE, ZN);
119219b2ee8SDavid du Colombier 			  setpname($3);
120219b2ee8SDavid du Colombier 			  context = $3->sym;
1217dd7cddfSDavid du Colombier 			  context->ini = $2; /* linenr and file */
122219b2ee8SDavid du Colombier 			  Expand_Ok++; /* expand struct names in decl */
1237dd7cddfSDavid du Colombier 			  has_ini = 0;
124219b2ee8SDavid du Colombier 			}
1257dd7cddfSDavid du Colombier 	  '(' decl ')'	{ Expand_Ok--;
1267dd7cddfSDavid du Colombier 			  if (has_ini)
1277dd7cddfSDavid du Colombier 			  fatal("initializer in parameter list", (char *) 0);
1287dd7cddfSDavid du Colombier 			}
1297dd7cddfSDavid du Colombier 	  Opt_priority
1307dd7cddfSDavid du Colombier 	  Opt_enabler
1317dd7cddfSDavid du Colombier 	  body		{ ProcList *rl;
132219b2ee8SDavid du Colombier 			  if ($1 != ZN && $1->val > 0)
133219b2ee8SDavid du Colombier 			  {	int j;
134*00d97012SDavid du Colombier 				rl = ready($3->sym, $6, $11->sq, $2->val, $10, A_PROC);
135219b2ee8SDavid du Colombier 			  	for (j = 0; j < $1->val; j++)
136*00d97012SDavid du Colombier 				{	runnable(rl, $9?$9->val:1, 1);
137*00d97012SDavid du Colombier 				}
1387dd7cddfSDavid du Colombier 				announce(":root:");
1397dd7cddfSDavid du Colombier 				if (dumptab) $3->sym->ini = $1;
140*00d97012SDavid du Colombier 			  } else
141*00d97012SDavid du Colombier 			  {	rl = ready($3->sym, $6, $11->sq, $2->val, $10, P_PROC);
142*00d97012SDavid du Colombier 			  }
143*00d97012SDavid du Colombier 			  if (rl && has_ini == 1)	/* global initializations, unsafe */
144*00d97012SDavid du Colombier 			  {	/* printf("proctype %s has initialized data\n",
145*00d97012SDavid du Colombier 					$3->sym->name);
146*00d97012SDavid du Colombier 				 */
147*00d97012SDavid du Colombier 				rl->unsafe = 1;
148219b2ee8SDavid du Colombier 			  }
149219b2ee8SDavid du Colombier 			  context = ZS;
150219b2ee8SDavid du Colombier 			}
151219b2ee8SDavid du Colombier 	;
152219b2ee8SDavid du Colombier 
1537dd7cddfSDavid du Colombier proctype: PROCTYPE	{ $$ = nn(ZN,CONST,ZN,ZN); $$->val = 0; }
1547dd7cddfSDavid du Colombier 	| D_PROCTYPE	{ $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
1557dd7cddfSDavid du Colombier 	;
1567dd7cddfSDavid du Colombier 
157219b2ee8SDavid du Colombier inst	: /* empty */	{ $$ = ZN; }
158219b2ee8SDavid du Colombier 	| ACTIVE	{ $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
159219b2ee8SDavid du Colombier 	| ACTIVE '[' CONST ']' {
160219b2ee8SDavid du Colombier 			  $$ = nn(ZN,CONST,ZN,ZN); $$->val = $3->val;
161312a1df1SDavid du Colombier 			  if ($3->val > 255)
162312a1df1SDavid du Colombier 				non_fatal("max nr of processes is 255\n", "");
163219b2ee8SDavid du Colombier 			}
1647dd7cddfSDavid du Colombier 	| ACTIVE '[' NAME ']' {
1657dd7cddfSDavid du Colombier 			  $$ = nn(ZN,CONST,ZN,ZN);
1667dd7cddfSDavid du Colombier 			  $$->val = 0;
1677dd7cddfSDavid du Colombier 			  if (!$3->sym->type)
168*00d97012SDavid du Colombier 				fatal("undeclared variable %s",
169312a1df1SDavid du Colombier 					$3->sym->name);
1707dd7cddfSDavid du Colombier 			  else if ($3->sym->ini->ntyp != CONST)
171*00d97012SDavid du Colombier 				fatal("need constant initializer for %s\n",
1727dd7cddfSDavid du Colombier 					$3->sym->name);
1737dd7cddfSDavid du Colombier 			  else
1747dd7cddfSDavid du Colombier 				$$->val = $3->sym->ini->val;
1757dd7cddfSDavid du Colombier 			}
176219b2ee8SDavid du Colombier 	;
177219b2ee8SDavid du Colombier 
178219b2ee8SDavid du Colombier init	: INIT		{ context = $1->sym; }
1797dd7cddfSDavid du Colombier 	  Opt_priority
1807dd7cddfSDavid du Colombier 	  body		{ ProcList *rl;
181*00d97012SDavid du Colombier 			  rl = ready(context, ZN, $4->sq, 0, ZN, I_PROC);
1827dd7cddfSDavid du Colombier 			  runnable(rl, $3?$3->val:1, 1);
1837dd7cddfSDavid du Colombier 			  announce(":root:");
184219b2ee8SDavid du Colombier 			  context = ZS;
185219b2ee8SDavid du Colombier         		}
186219b2ee8SDavid du Colombier 	;
187219b2ee8SDavid du Colombier 
188*00d97012SDavid du Colombier ltl	: LTL optname2		{ ltl_mode = 1; ltl_name = $2->sym->name; }
189*00d97012SDavid du Colombier 	  ltl_body		{ if ($4) ltl_list($2->sym->name, $4->sym->name);
190*00d97012SDavid du Colombier 			  ltl_mode = 0;
191*00d97012SDavid du Colombier 			}
192*00d97012SDavid du Colombier 	;
193*00d97012SDavid du Colombier 
194*00d97012SDavid du Colombier ltl_body: '{' full_expr OS '}' { $$ = ltl_to_string($2); }
195*00d97012SDavid du Colombier 	| error		{ $$ = NULL; }
196*00d97012SDavid du Colombier 	;
197*00d97012SDavid du Colombier 
198*00d97012SDavid du Colombier claim	: CLAIM	optname	{ if ($2 != ZN)
199*00d97012SDavid du Colombier 			  {	$1->sym = $2->sym;	/* new 5.3.0 */
200*00d97012SDavid du Colombier 			  }
201*00d97012SDavid du Colombier 			  nclaims++;
202*00d97012SDavid du Colombier 			  context = $1->sym;
203*00d97012SDavid du Colombier 			  if (claimproc && !strcmp(claimproc, $1->sym->name))
204*00d97012SDavid du Colombier 			  {	fatal("claim %s redefined", claimproc);
205*00d97012SDavid du Colombier 			  }
206219b2ee8SDavid du Colombier 			  claimproc = $1->sym->name;
207219b2ee8SDavid du Colombier 			}
208*00d97012SDavid du Colombier 	  body		{ (void) ready($1->sym, ZN, $4->sq, 0, ZN, N_CLAIM);
209219b2ee8SDavid du Colombier         		  context = ZS;
210219b2ee8SDavid du Colombier         		}
211219b2ee8SDavid du Colombier 	;
212219b2ee8SDavid du Colombier 
213*00d97012SDavid du Colombier optname : /* empty */	{ char tb[32];
214*00d97012SDavid du Colombier 			  memset(tb, 0, 32);
215*00d97012SDavid du Colombier 			  sprintf(tb, "never_%d", nclaims);
216*00d97012SDavid du Colombier 			  $$ = nn(ZN, NAME, ZN, ZN);
217*00d97012SDavid du Colombier 			  $$->sym = lookup(tb);
218*00d97012SDavid du Colombier 			}
219*00d97012SDavid du Colombier 	| NAME		{ $$ = $1; }
220*00d97012SDavid du Colombier 	;
221*00d97012SDavid du Colombier 
222*00d97012SDavid du Colombier optname2 : /* empty */ { char tb[32]; static int nltl = 0;
223*00d97012SDavid du Colombier 			  memset(tb, 0, 32);
224*00d97012SDavid du Colombier 			  sprintf(tb, "ltl_%d", nltl++);
225*00d97012SDavid du Colombier 			  $$ = nn(ZN, NAME, ZN, ZN);
226*00d97012SDavid du Colombier 			  $$->sym = lookup(tb);
227*00d97012SDavid du Colombier 			}
228*00d97012SDavid du Colombier 	| NAME		{ $$ = $1; }
229*00d97012SDavid du Colombier 	;
230*00d97012SDavid du Colombier 
2317dd7cddfSDavid du Colombier events : TRACE		{ context = $1->sym;
2327dd7cddfSDavid du Colombier 			  if (eventmap)
2337dd7cddfSDavid du Colombier 				non_fatal("trace %s redefined", eventmap);
2347dd7cddfSDavid du Colombier 			  eventmap = $1->sym->name;
2357dd7cddfSDavid du Colombier 			  inEventMap++;
2367dd7cddfSDavid du Colombier 			}
237*00d97012SDavid du Colombier 	  body		{
238*00d97012SDavid du Colombier 			  if (strcmp($1->sym->name, ":trace:") == 0)
239*00d97012SDavid du Colombier 			  {	(void) ready($1->sym, ZN, $3->sq, 0, ZN, E_TRACE);
240*00d97012SDavid du Colombier 			  } else
241*00d97012SDavid du Colombier 			  {	(void) ready($1->sym, ZN, $3->sq, 0, ZN, N_TRACE);
242*00d97012SDavid du Colombier 			  }
2437dd7cddfSDavid du Colombier         		  context = ZS;
2447dd7cddfSDavid du Colombier 			  inEventMap--;
2457dd7cddfSDavid du Colombier 			}
246219b2ee8SDavid du Colombier 	;
2477dd7cddfSDavid du Colombier 
248219b2ee8SDavid du Colombier utype	: TYPEDEF NAME		{ if (context)
249219b2ee8SDavid du Colombier 				   fatal("typedef %s must be global",
250219b2ee8SDavid du Colombier 						$2->sym->name);
251219b2ee8SDavid du Colombier 				   owner = $2->sym;
252219b2ee8SDavid du Colombier 				}
253219b2ee8SDavid du Colombier 	  '{' decl_lst '}'	{ setuname($5); owner = ZS; }
254219b2ee8SDavid du Colombier 	;
255219b2ee8SDavid du Colombier 
2567dd7cddfSDavid du Colombier nm	: NAME			{ $$ = $1; }
2577dd7cddfSDavid du Colombier 	| INAME			{ $$ = $1;
2587dd7cddfSDavid du Colombier 				  if (IArgs)
2597dd7cddfSDavid du Colombier 				  fatal("invalid use of '%s'", $1->sym->name);
2607dd7cddfSDavid du Colombier 				}
2617dd7cddfSDavid du Colombier 	;
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier ns	: INLINE nm '('		{ NamesNotAdded++; }
264312a1df1SDavid du Colombier 	  args ')'		{ prep_inline($2->sym, $5);
265312a1df1SDavid du Colombier 				  NamesNotAdded--;
266312a1df1SDavid du Colombier 				}
267312a1df1SDavid du Colombier 	;
268312a1df1SDavid du Colombier 
269312a1df1SDavid du Colombier c_fcts	: ccode			{ /* leaves pseudo-inlines with sym of
270312a1df1SDavid du Colombier 				   * type CODE_FRAG or CODE_DECL in global context
271312a1df1SDavid du Colombier 				   */
272312a1df1SDavid du Colombier 				}
273312a1df1SDavid du Colombier 	| cstate
274312a1df1SDavid du Colombier 	;
275312a1df1SDavid du Colombier 
276312a1df1SDavid du Colombier cstate	: C_STATE STRING STRING	{
277312a1df1SDavid du Colombier 				  c_state($2->sym, $3->sym, ZS);
278312a1df1SDavid du Colombier 				  has_code = has_state = 1;
279312a1df1SDavid du Colombier 				}
280312a1df1SDavid du Colombier 	| C_TRACK STRING STRING {
281312a1df1SDavid du Colombier 				  c_track($2->sym, $3->sym, ZS);
282312a1df1SDavid du Colombier 				  has_code = has_state = 1;
283312a1df1SDavid du Colombier 				}
284312a1df1SDavid du Colombier 	| C_STATE STRING STRING	STRING {
285312a1df1SDavid du Colombier 				  c_state($2->sym, $3->sym, $4->sym);
286312a1df1SDavid du Colombier 				  has_code = has_state = 1;
287312a1df1SDavid du Colombier 				}
288312a1df1SDavid du Colombier 	| C_TRACK STRING STRING STRING {
289312a1df1SDavid du Colombier 				  c_track($2->sym, $3->sym, $4->sym);
290312a1df1SDavid du Colombier 				  has_code = has_state = 1;
291312a1df1SDavid du Colombier 				}
292312a1df1SDavid du Colombier 	;
293312a1df1SDavid du Colombier 
294312a1df1SDavid du Colombier ccode	: C_CODE		{ Symbol *s;
295312a1df1SDavid du Colombier 				  NamesNotAdded++;
296312a1df1SDavid du Colombier 				  s = prep_inline(ZS, ZN);
297312a1df1SDavid du Colombier 				  NamesNotAdded--;
298312a1df1SDavid du Colombier 				  $$ = nn(ZN, C_CODE, ZN, ZN);
299312a1df1SDavid du Colombier 				  $$->sym = s;
300312a1df1SDavid du Colombier 				  has_code = 1;
301312a1df1SDavid du Colombier 				}
302312a1df1SDavid du Colombier 	| C_DECL		{ Symbol *s;
303312a1df1SDavid du Colombier 				  NamesNotAdded++;
304312a1df1SDavid du Colombier 				  s = prep_inline(ZS, ZN);
305312a1df1SDavid du Colombier 				  NamesNotAdded--;
306312a1df1SDavid du Colombier 				  s->type = CODE_DECL;
307312a1df1SDavid du Colombier 				  $$ = nn(ZN, C_CODE, ZN, ZN);
308312a1df1SDavid du Colombier 				  $$->sym = s;
309312a1df1SDavid du Colombier 				  has_code = 1;
310312a1df1SDavid du Colombier 				}
311312a1df1SDavid du Colombier 	;
312312a1df1SDavid du Colombier cexpr	: C_EXPR		{ Symbol *s;
313312a1df1SDavid du Colombier 				  NamesNotAdded++;
314312a1df1SDavid du Colombier 				  s = prep_inline(ZS, ZN);
315312a1df1SDavid du Colombier 				  NamesNotAdded--;
316312a1df1SDavid du Colombier 				  $$ = nn(ZN, C_EXPR, ZN, ZN);
317312a1df1SDavid du Colombier 				  $$->sym = s;
318312a1df1SDavid du Colombier 				  no_side_effects(s->name);
319312a1df1SDavid du Colombier 				  has_code = 1;
320312a1df1SDavid du Colombier 				}
3217dd7cddfSDavid du Colombier 	;
3227dd7cddfSDavid du Colombier 
323219b2ee8SDavid du Colombier body	: '{'			{ open_seq(1); }
324219b2ee8SDavid du Colombier           sequence OS		{ add_seq(Stop); }
325*00d97012SDavid du Colombier           '}'			{ $$->sq = close_seq(0);
326*00d97012SDavid du Colombier 				  if (scope_level != 0)
327*00d97012SDavid du Colombier 				  {	non_fatal("missing '}' ?", 0);
328*00d97012SDavid du Colombier 					scope_level = 0;
329*00d97012SDavid du Colombier 				  }
330*00d97012SDavid du Colombier 				}
331219b2ee8SDavid du Colombier 	;
332219b2ee8SDavid du Colombier 
333219b2ee8SDavid du Colombier sequence: step			{ if ($1) add_seq($1); }
334219b2ee8SDavid du Colombier 	| sequence MS step	{ if ($3) add_seq($3); }
335219b2ee8SDavid du Colombier 	;
336219b2ee8SDavid du Colombier 
337219b2ee8SDavid du Colombier step    : one_decl		{ $$ = ZN; }
338219b2ee8SDavid du Colombier 	| XU vref_lst		{ setxus($2, $1->val); $$ = ZN; }
339312a1df1SDavid du Colombier 	| NAME ':' one_decl	{ fatal("label preceding declaration,", (char *)0); }
340312a1df1SDavid du Colombier 	| NAME ':' XU		{ fatal("label predecing xr/xs claim,", 0); }
341219b2ee8SDavid du Colombier 	| stmnt			{ $$ = $1; }
342219b2ee8SDavid du Colombier 	| stmnt UNLESS stmnt	{ $$ = do_unless($1, $3); }
343219b2ee8SDavid du Colombier 	;
344219b2ee8SDavid du Colombier 
345219b2ee8SDavid du Colombier vis	: /* empty */		{ $$ = ZN; }
346219b2ee8SDavid du Colombier 	| HIDDEN		{ $$ = $1; }
3477dd7cddfSDavid du Colombier 	| SHOW			{ $$ = $1; }
3487dd7cddfSDavid du Colombier 	| ISLOCAL		{ $$ = $1; }
3497dd7cddfSDavid du Colombier 	;
3507dd7cddfSDavid du Colombier 
3517dd7cddfSDavid du Colombier asgn:	/* empty */
3527dd7cddfSDavid du Colombier 	| ASGN
353219b2ee8SDavid du Colombier 	;
354219b2ee8SDavid du Colombier 
355*00d97012SDavid du Colombier one_decl: vis TYPE var_list	{ setptype($3, $2->val, $1);
356*00d97012SDavid du Colombier 				  $$ = $3;
357*00d97012SDavid du Colombier 				}
358219b2ee8SDavid du Colombier 	| vis UNAME var_list	{ setutype($3, $2->sym, $1);
359219b2ee8SDavid du Colombier 				  $$ = expand($3, Expand_Ok);
360219b2ee8SDavid du Colombier 				}
3617dd7cddfSDavid du Colombier 	| vis TYPE asgn '{' nlst '}' {
3627dd7cddfSDavid du Colombier 				  if ($2->val != MTYPE)
3637dd7cddfSDavid du Colombier 					fatal("malformed declaration", 0);
3647dd7cddfSDavid du Colombier 				  setmtype($5);
3657dd7cddfSDavid du Colombier 				  if ($1)
3667dd7cddfSDavid du Colombier 					non_fatal("cannot %s mtype (ignored)",
3677dd7cddfSDavid du Colombier 						$1->sym->name);
3687dd7cddfSDavid du Colombier 				  if (context != ZS)
3697dd7cddfSDavid du Colombier 					fatal("mtype declaration must be global", 0);
3707dd7cddfSDavid du Colombier 				}
371219b2ee8SDavid du Colombier 	;
372219b2ee8SDavid du Colombier 
373219b2ee8SDavid du Colombier decl_lst: one_decl       	{ $$ = nn(ZN, ',', $1, ZN); }
374219b2ee8SDavid du Colombier 	| one_decl SEMI
375219b2ee8SDavid du Colombier 	  decl_lst		{ $$ = nn(ZN, ',', $1, $3); }
376219b2ee8SDavid du Colombier 	;
377219b2ee8SDavid du Colombier 
378219b2ee8SDavid du Colombier decl    : /* empty */		{ $$ = ZN; }
379219b2ee8SDavid du Colombier 	| decl_lst      	{ $$ = $1; }
380219b2ee8SDavid du Colombier 	;
381219b2ee8SDavid du Colombier 
382219b2ee8SDavid du Colombier vref_lst: varref		{ $$ = nn($1, XU, $1, ZN); }
383219b2ee8SDavid du Colombier 	| varref ',' vref_lst	{ $$ = nn($1, XU, $1, $3); }
384219b2ee8SDavid du Colombier 	;
385219b2ee8SDavid du Colombier 
386219b2ee8SDavid du Colombier var_list: ivar           	{ $$ = nn($1, TYPE, ZN, ZN); }
387219b2ee8SDavid du Colombier 	| ivar ',' var_list	{ $$ = nn($1, TYPE, ZN, $3); }
388219b2ee8SDavid du Colombier 	;
389219b2ee8SDavid du Colombier 
3907dd7cddfSDavid du Colombier ivar    : vardcl           	{ $$ = $1;
3917dd7cddfSDavid du Colombier 				  $1->sym->ini = nn(ZN,CONST,ZN,ZN);
3927dd7cddfSDavid du Colombier 				  $1->sym->ini->val = 0;
3937dd7cddfSDavid du Colombier 				}
394*00d97012SDavid du Colombier 	| vardcl ASGN expr   	{ $$ = $1;
395*00d97012SDavid du Colombier 				  $1->sym->ini = $3;
396*00d97012SDavid du Colombier 				  trackvar($1,$3);
397*00d97012SDavid du Colombier 				  if ($3->ntyp == CONST
398*00d97012SDavid du Colombier 				  || ($3->ntyp == NAME && $3->sym->context))
399*00d97012SDavid du Colombier 				  {	has_ini = 2; /* local init */
400*00d97012SDavid du Colombier 				  } else
401*00d97012SDavid du Colombier 				  {	has_ini = 1; /* possibly global */
402*00d97012SDavid du Colombier 				  }
403*00d97012SDavid du Colombier 				  if (!initialization_ok && split_decl)
404*00d97012SDavid du Colombier 				  {	nochan_manip($1, $3, 0);
405*00d97012SDavid du Colombier 				  	no_internals($1);
406*00d97012SDavid du Colombier 					non_fatal(PART0 "'%s'" PART2, $1->sym->name);
407*00d97012SDavid du Colombier 				  }
4087dd7cddfSDavid du Colombier 				}
4097dd7cddfSDavid du Colombier 	| vardcl ASGN ch_init	{ $1->sym->ini = $3;
4107dd7cddfSDavid du Colombier 				  $$ = $1; has_ini = 1;
411*00d97012SDavid du Colombier 				  if (!initialization_ok && split_decl)
412*00d97012SDavid du Colombier 				  {	non_fatal(PART1 "'%s'" PART2, $1->sym->name);
413*00d97012SDavid du Colombier 				  }
4147dd7cddfSDavid du Colombier 				}
415219b2ee8SDavid du Colombier 	;
416219b2ee8SDavid du Colombier 
417219b2ee8SDavid du Colombier ch_init : '[' CONST ']' OF
418*00d97012SDavid du Colombier 	  '{' typ_list '}'	{ if ($2->val)
419*00d97012SDavid du Colombier 					u_async++;
420*00d97012SDavid du Colombier 				  else
421*00d97012SDavid du Colombier 					u_sync++;
422219b2ee8SDavid du Colombier         			  {	int i = cnt_mpars($6);
423219b2ee8SDavid du Colombier 					Mpars = max(Mpars, i);
424219b2ee8SDavid du Colombier 				  }
425219b2ee8SDavid du Colombier         			  $$ = nn(ZN, CHAN, ZN, $6);
426219b2ee8SDavid du Colombier 				  $$->val = $2->val;
427219b2ee8SDavid du Colombier         			}
428219b2ee8SDavid du Colombier 	;
429219b2ee8SDavid du Colombier 
430219b2ee8SDavid du Colombier vardcl  : NAME  		{ $1->sym->nel = 1; $$ = $1; }
4317dd7cddfSDavid du Colombier 	| NAME ':' CONST	{ $1->sym->nbits = $3->val;
432312a1df1SDavid du Colombier 				  if ($3->val >= 8*sizeof(long))
433312a1df1SDavid du Colombier 				  {	non_fatal("width-field %s too large",
434312a1df1SDavid du Colombier 						$1->sym->name);
435312a1df1SDavid du Colombier 					$3->val = 8*sizeof(long)-1;
436312a1df1SDavid du Colombier 				  }
4377dd7cddfSDavid du Colombier 				  $1->sym->nel = 1; $$ = $1;
4387dd7cddfSDavid du Colombier 				}
439*00d97012SDavid du Colombier 	| NAME '[' CONST ']'	{ $1->sym->nel = $3->val; $1->sym->isarray = 1; $$ = $1; }
440219b2ee8SDavid du Colombier 	;
441219b2ee8SDavid du Colombier 
442219b2ee8SDavid du Colombier varref	: cmpnd			{ $$ = mk_explicit($1, Expand_Ok, NAME); }
443219b2ee8SDavid du Colombier 	;
444219b2ee8SDavid du Colombier 
445*00d97012SDavid du Colombier pfld	: NAME			{ $$ = nn($1, NAME, ZN, ZN);
446*00d97012SDavid du Colombier 				  if ($1->sym->isarray && !in_for)
447*00d97012SDavid du Colombier 				  {	non_fatal("missing array index for '%s'",
448*00d97012SDavid du Colombier 						$1->sym->name);
449*00d97012SDavid du Colombier 				  }
450*00d97012SDavid du Colombier 				}
451219b2ee8SDavid du Colombier 	| NAME			{ owner = ZS; }
452219b2ee8SDavid du Colombier 	  '[' expr ']'		{ $$ = nn($1, NAME, $4, ZN); }
453219b2ee8SDavid du Colombier 	;
454219b2ee8SDavid du Colombier 
455219b2ee8SDavid du Colombier cmpnd	: pfld			{ Embedded++;
456219b2ee8SDavid du Colombier 				  if ($1->sym->type == STRUCT)
457219b2ee8SDavid du Colombier 					owner = $1->sym->Snm;
458219b2ee8SDavid du Colombier 				}
459219b2ee8SDavid du Colombier 	  sfld			{ $$ = $1; $$->rgt = $3;
460219b2ee8SDavid du Colombier 				  if ($3 && $1->sym->type != STRUCT)
461219b2ee8SDavid du Colombier 					$1->sym->type = STRUCT;
4627dd7cddfSDavid du Colombier 				  Embedded--;
4637dd7cddfSDavid du Colombier 				  if (!Embedded && !NamesNotAdded
4647dd7cddfSDavid du Colombier 				  &&  !$1->sym->type)
465*00d97012SDavid du Colombier 				   fatal("undeclared variable: %s",
466219b2ee8SDavid du Colombier 						$1->sym->name);
4677dd7cddfSDavid du Colombier 				  if ($3) validref($1, $3->lft);
468219b2ee8SDavid du Colombier 				  owner = ZS;
469219b2ee8SDavid du Colombier 				}
470219b2ee8SDavid du Colombier 	;
471219b2ee8SDavid du Colombier 
472219b2ee8SDavid du Colombier sfld	: /* empty */		{ $$ = ZN; }
473219b2ee8SDavid du Colombier 	| '.' cmpnd %prec DOT	{ $$ = nn(ZN, '.', $2, ZN); }
474219b2ee8SDavid du Colombier 	;
475219b2ee8SDavid du Colombier 
476*00d97012SDavid du Colombier stmnt	: Special		{ $$ = $1; initialization_ok = 0; }
477*00d97012SDavid du Colombier 	| Stmnt			{ $$ = $1; initialization_ok = 0;
4787dd7cddfSDavid du Colombier 				  if (inEventMap)
479f3793cddSDavid du Colombier 				   non_fatal("not an event", (char *)0);
4807dd7cddfSDavid du Colombier 				}
4817dd7cddfSDavid du Colombier 	;
4827dd7cddfSDavid du Colombier 
483*00d97012SDavid du Colombier for_pre : FOR '('				{ in_for = 1; }
484*00d97012SDavid du Colombier 	  varref			{ $$ = $4; }
485*00d97012SDavid du Colombier 	;
486*00d97012SDavid du Colombier 
487*00d97012SDavid du Colombier for_post: '{' sequence OS '}' ;
488*00d97012SDavid du Colombier 
4897dd7cddfSDavid du Colombier Special : varref RCV		{ Expand_Ok++; }
490312a1df1SDavid du Colombier 	  rargs			{ Expand_Ok--; has_io++;
4917dd7cddfSDavid du Colombier 				  $$ = nn($1,  'r', $1, $4);
4927dd7cddfSDavid du Colombier 				  trackchanuse($4, ZN, 'R');
4937dd7cddfSDavid du Colombier 				}
4947dd7cddfSDavid du Colombier 	| varref SND		{ Expand_Ok++; }
495312a1df1SDavid du Colombier 	  margs			{ Expand_Ok--; has_io++;
4967dd7cddfSDavid du Colombier 				  $$ = nn($1, 's', $1, $4);
4977dd7cddfSDavid du Colombier 				  $$->val=0; trackchanuse($4, ZN, 'S');
498f3793cddSDavid du Colombier 				  any_runs($4);
4997dd7cddfSDavid du Colombier 				}
500*00d97012SDavid du Colombier 	| for_pre ':' expr DOTDOT expr ')'	{
501*00d97012SDavid du Colombier 				  for_setup($1, $3, $5); in_for = 0;
502*00d97012SDavid du Colombier 				}
503*00d97012SDavid du Colombier 	  for_post			{ $$ = for_body($1, 1);
504*00d97012SDavid du Colombier 				}
505*00d97012SDavid du Colombier 	| for_pre IN varref ')'	{ $$ = for_index($1, $3); in_for = 0;
506*00d97012SDavid du Colombier 				}
507*00d97012SDavid du Colombier 	  for_post			{ $$ = for_body($5, 1);
508*00d97012SDavid du Colombier 				}
509*00d97012SDavid du Colombier 	| SELECT '(' varref ':' expr DOTDOT expr ')' {
510*00d97012SDavid du Colombier 				  $$ = sel_index($3, $5, $7);
511*00d97012SDavid du Colombier 				}
5127dd7cddfSDavid du Colombier 	| IF options FI 	{ $$ = nn($1, IF, ZN, ZN);
5137dd7cddfSDavid du Colombier         			  $$->sl = $2->sl;
5147dd7cddfSDavid du Colombier 				  prune_opts($$);
5157dd7cddfSDavid du Colombier         			}
5167dd7cddfSDavid du Colombier 	| DO    		{ pushbreak(); }
5177dd7cddfSDavid du Colombier           options OD    	{ $$ = nn($1, DO, ZN, ZN);
5187dd7cddfSDavid du Colombier         			  $$->sl = $3->sl;
5197dd7cddfSDavid du Colombier 				  prune_opts($$);
5207dd7cddfSDavid du Colombier         			}
5217dd7cddfSDavid du Colombier 	| BREAK  		{ $$ = nn(ZN, GOTO, ZN, ZN);
5227dd7cddfSDavid du Colombier 				  $$->sym = break_dest();
5237dd7cddfSDavid du Colombier 				}
5247dd7cddfSDavid du Colombier 	| GOTO NAME		{ $$ = nn($2, GOTO, ZN, ZN);
5257dd7cddfSDavid du Colombier 				  if ($2->sym->type != 0
5267dd7cddfSDavid du Colombier 				  &&  $2->sym->type != LABEL) {
5277dd7cddfSDavid du Colombier 				  	non_fatal("bad label-name %s",
5287dd7cddfSDavid du Colombier 					$2->sym->name);
5297dd7cddfSDavid du Colombier 				  }
5307dd7cddfSDavid du Colombier 				  $2->sym->type = LABEL;
5317dd7cddfSDavid du Colombier 				}
5327dd7cddfSDavid du Colombier 	| NAME ':' stmnt	{ $$ = nn($1, ':',$3, ZN);
5337dd7cddfSDavid du Colombier 				  if ($1->sym->type != 0
5347dd7cddfSDavid du Colombier 				  &&  $1->sym->type != LABEL) {
5357dd7cddfSDavid du Colombier 				  	non_fatal("bad label-name %s",
5367dd7cddfSDavid du Colombier 					$1->sym->name);
5377dd7cddfSDavid du Colombier 				  }
5387dd7cddfSDavid du Colombier 				  $1->sym->type = LABEL;
5397dd7cddfSDavid du Colombier 				}
5407dd7cddfSDavid du Colombier 	;
5417dd7cddfSDavid du Colombier 
542*00d97012SDavid du Colombier Stmnt	: varref ASGN full_expr	{ $$ = nn($1, ASGN, $1, $3);
5437dd7cddfSDavid du Colombier 				  trackvar($1, $3);
5447dd7cddfSDavid du Colombier 				  nochan_manip($1, $3, 0);
545f3793cddSDavid du Colombier 				  no_internals($1);
5467dd7cddfSDavid du Colombier 				}
547219b2ee8SDavid du Colombier 	| varref INCR		{ $$ = nn(ZN,CONST, ZN, ZN); $$->val = 1;
548219b2ee8SDavid du Colombier 				  $$ = nn(ZN,  '+', $1, $$);
549219b2ee8SDavid du Colombier 				  $$ = nn($1, ASGN, $1, $$);
5507dd7cddfSDavid du Colombier 				  trackvar($1, $1);
551f3793cddSDavid du Colombier 				  no_internals($1);
5527dd7cddfSDavid du Colombier 				  if ($1->sym->type == CHAN)
5537dd7cddfSDavid du Colombier 				   fatal("arithmetic on chan", (char *)0);
554219b2ee8SDavid du Colombier 				}
555219b2ee8SDavid du Colombier 	| varref DECR		{ $$ = nn(ZN,CONST, ZN, ZN); $$->val = 1;
556219b2ee8SDavid du Colombier 				  $$ = nn(ZN,  '-', $1, $$);
557219b2ee8SDavid du Colombier 				  $$ = nn($1, ASGN, $1, $$);
5587dd7cddfSDavid du Colombier 				  trackvar($1, $1);
559f3793cddSDavid du Colombier 				  no_internals($1);
5607dd7cddfSDavid du Colombier 				  if ($1->sym->type == CHAN)
5617dd7cddfSDavid du Colombier 				   fatal("arithmetic on chan id's", (char *)0);
562219b2ee8SDavid du Colombier 				}
5637dd7cddfSDavid du Colombier 	| PRINT	'(' STRING	{ realread = 0; }
5647dd7cddfSDavid du Colombier 	  prargs ')'		{ $$ = nn($3, PRINT, $5, ZN); realread = 1; }
565312a1df1SDavid du Colombier 	| PRINTM '(' varref ')'	{ $$ = nn(ZN, PRINTM, $3, ZN); }
566312a1df1SDavid du Colombier 	| PRINTM '(' CONST ')'	{ $$ = nn(ZN, PRINTM, $3, ZN); }
567312a1df1SDavid du Colombier 	| ASSERT full_expr    	{ $$ = nn(ZN, ASSERT, $2, ZN); AST_track($2, 0); }
568312a1df1SDavid du Colombier 	| ccode			{ $$ = $1; }
569219b2ee8SDavid du Colombier 	| varref R_RCV		{ Expand_Ok++; }
570312a1df1SDavid du Colombier 	  rargs			{ Expand_Ok--; has_io++;
571219b2ee8SDavid du Colombier 				  $$ = nn($1,  'r', $1, $4);
572219b2ee8SDavid du Colombier 				  $$->val = has_random = 1;
5737dd7cddfSDavid du Colombier 				  trackchanuse($4, ZN, 'R');
5747dd7cddfSDavid du Colombier 				}
5757dd7cddfSDavid du Colombier 	| varref RCV		{ Expand_Ok++; }
576312a1df1SDavid du Colombier 	  LT rargs GT		{ Expand_Ok--; has_io++;
5777dd7cddfSDavid du Colombier 				  $$ = nn($1, 'r', $1, $5);
5787dd7cddfSDavid du Colombier 				  $$->val = 2;	/* fifo poll */
5797dd7cddfSDavid du Colombier 				  trackchanuse($5, ZN, 'R');
5807dd7cddfSDavid du Colombier 				}
5817dd7cddfSDavid du Colombier 	| varref R_RCV		{ Expand_Ok++; }
582312a1df1SDavid du Colombier 	  LT rargs GT		{ Expand_Ok--; has_io++;	/* rrcv poll */
5837dd7cddfSDavid du Colombier 				  $$ = nn($1, 'r', $1, $5);
5847dd7cddfSDavid du Colombier 				  $$->val = 3; has_random = 1;
5857dd7cddfSDavid du Colombier 				  trackchanuse($5, ZN, 'R');
586219b2ee8SDavid du Colombier 				}
587219b2ee8SDavid du Colombier 	| varref O_SND		{ Expand_Ok++; }
588312a1df1SDavid du Colombier 	  margs			{ Expand_Ok--; has_io++;
589219b2ee8SDavid du Colombier 				  $$ = nn($1, 's', $1, $4);
590219b2ee8SDavid du Colombier 				  $$->val = has_sorted = 1;
5917dd7cddfSDavid du Colombier 				  trackchanuse($4, ZN, 'S');
592f3793cddSDavid du Colombier 				  any_runs($4);
593219b2ee8SDavid du Colombier 				}
594312a1df1SDavid du Colombier 	| full_expr		{ $$ = nn(ZN, 'c', $1, ZN); count_runs($$); }
595219b2ee8SDavid du Colombier 	| ELSE  		{ $$ = nn(ZN,ELSE,ZN,ZN);
596219b2ee8SDavid du Colombier 				}
597219b2ee8SDavid du Colombier 	| ATOMIC   '{'   	{ open_seq(0); }
598219b2ee8SDavid du Colombier           sequence OS '}'   	{ $$ = nn($1, ATOMIC, ZN, ZN);
599219b2ee8SDavid du Colombier         			  $$->sl = seqlist(close_seq(3), 0);
600219b2ee8SDavid du Colombier         			  make_atomic($$->sl->this, 0);
601219b2ee8SDavid du Colombier         			}
602*00d97012SDavid du Colombier 	| D_STEP '{'		{ open_seq(0);
603*00d97012SDavid du Colombier 				  rem_Seq();
604*00d97012SDavid du Colombier 				}
605219b2ee8SDavid du Colombier           sequence OS '}'   	{ $$ = nn($1, D_STEP, ZN, ZN);
606219b2ee8SDavid du Colombier         			  $$->sl = seqlist(close_seq(4), 0);
607219b2ee8SDavid du Colombier         			  make_atomic($$->sl->this, D_ATOM);
608219b2ee8SDavid du Colombier 				  unrem_Seq();
609219b2ee8SDavid du Colombier         			}
610219b2ee8SDavid du Colombier 	| '{'			{ open_seq(0); }
611219b2ee8SDavid du Colombier 	  sequence OS '}'	{ $$ = nn(ZN, NON_ATOMIC, ZN, ZN);
612219b2ee8SDavid du Colombier         			  $$->sl = seqlist(close_seq(5), 0);
613219b2ee8SDavid du Colombier         			}
6147dd7cddfSDavid du Colombier 	| INAME			{ IArgs++; }
6157dd7cddfSDavid du Colombier 	  '(' args ')'		{ pickup_inline($1->sym, $4); IArgs--; }
6167dd7cddfSDavid du Colombier 	  Stmnt			{ $$ = $7; }
617219b2ee8SDavid du Colombier 	;
618219b2ee8SDavid du Colombier 
619219b2ee8SDavid du Colombier options : option		{ $$->sl = seqlist($1->sq, 0); }
620219b2ee8SDavid du Colombier 	| option options	{ $$->sl = seqlist($1->sq, $2->sl); }
621219b2ee8SDavid du Colombier 	;
622219b2ee8SDavid du Colombier 
623219b2ee8SDavid du Colombier option  : SEP   		{ open_seq(0); }
6247dd7cddfSDavid du Colombier           sequence OS		{ $$ = nn(ZN,0,ZN,ZN);
6257dd7cddfSDavid du Colombier 				  $$->sq = close_seq(6); }
626219b2ee8SDavid du Colombier 	;
627219b2ee8SDavid du Colombier 
628219b2ee8SDavid du Colombier OS	: /* empty */
629219b2ee8SDavid du Colombier 	| SEMI			{ /* redundant semi at end of sequence */ }
630219b2ee8SDavid du Colombier 	;
631219b2ee8SDavid du Colombier 
632219b2ee8SDavid du Colombier MS	: SEMI			{ /* at least one semi-colon */ }
633219b2ee8SDavid du Colombier 	| MS SEMI		{ /* but more are okay too   */ }
634219b2ee8SDavid du Colombier 	;
635219b2ee8SDavid du Colombier 
636219b2ee8SDavid du Colombier aname	: NAME			{ $$ = $1; }
637219b2ee8SDavid du Colombier 	| PNAME			{ $$ = $1; }
638219b2ee8SDavid du Colombier 	;
639219b2ee8SDavid du Colombier 
640219b2ee8SDavid du Colombier expr    : '(' expr ')'		{ $$ = $2; }
641219b2ee8SDavid du Colombier 	| expr '+' expr		{ $$ = nn(ZN, '+', $1, $3); }
642219b2ee8SDavid du Colombier 	| expr '-' expr		{ $$ = nn(ZN, '-', $1, $3); }
643219b2ee8SDavid du Colombier 	| expr '*' expr		{ $$ = nn(ZN, '*', $1, $3); }
644219b2ee8SDavid du Colombier 	| expr '/' expr		{ $$ = nn(ZN, '/', $1, $3); }
645219b2ee8SDavid du Colombier 	| expr '%' expr		{ $$ = nn(ZN, '%', $1, $3); }
646219b2ee8SDavid du Colombier 	| expr '&' expr		{ $$ = nn(ZN, '&', $1, $3); }
6477dd7cddfSDavid du Colombier 	| expr '^' expr		{ $$ = nn(ZN, '^', $1, $3); }
648219b2ee8SDavid du Colombier 	| expr '|' expr		{ $$ = nn(ZN, '|', $1, $3); }
649219b2ee8SDavid du Colombier 	| expr GT expr		{ $$ = nn(ZN,  GT, $1, $3); }
650219b2ee8SDavid du Colombier 	| expr LT expr		{ $$ = nn(ZN,  LT, $1, $3); }
651219b2ee8SDavid du Colombier 	| expr GE expr		{ $$ = nn(ZN,  GE, $1, $3); }
652219b2ee8SDavid du Colombier 	| expr LE expr		{ $$ = nn(ZN,  LE, $1, $3); }
653219b2ee8SDavid du Colombier 	| expr EQ expr		{ $$ = nn(ZN,  EQ, $1, $3); }
654219b2ee8SDavid du Colombier 	| expr NE expr		{ $$ = nn(ZN,  NE, $1, $3); }
655219b2ee8SDavid du Colombier 	| expr AND expr		{ $$ = nn(ZN, AND, $1, $3); }
656219b2ee8SDavid du Colombier 	| expr OR  expr		{ $$ = nn(ZN,  OR, $1, $3); }
657219b2ee8SDavid du Colombier 	| expr LSHIFT expr	{ $$ = nn(ZN, LSHIFT,$1, $3); }
658219b2ee8SDavid du Colombier 	| expr RSHIFT expr	{ $$ = nn(ZN, RSHIFT,$1, $3); }
659219b2ee8SDavid du Colombier 	| '~' expr		{ $$ = nn(ZN, '~', $2, ZN); }
660219b2ee8SDavid du Colombier 	| '-' expr %prec UMIN	{ $$ = nn(ZN, UMIN, $2, ZN); }
661219b2ee8SDavid du Colombier 	| SND expr %prec NEG	{ $$ = nn(ZN, '!', $2, ZN); }
662219b2ee8SDavid du Colombier 
663219b2ee8SDavid du Colombier 	| '(' expr SEMI expr ':' expr ')' {
664219b2ee8SDavid du Colombier 				  $$ = nn(ZN,  OR, $4, $6);
665219b2ee8SDavid du Colombier 				  $$ = nn(ZN, '?', $2, $$);
666219b2ee8SDavid du Colombier 				}
667219b2ee8SDavid du Colombier 
6687dd7cddfSDavid du Colombier 	| RUN aname		{ Expand_Ok++;
6697dd7cddfSDavid du Colombier 				  if (!context)
6707dd7cddfSDavid du Colombier 				   fatal("used 'run' outside proctype",
6717dd7cddfSDavid du Colombier 					(char *) 0);
6727dd7cddfSDavid du Colombier 				}
6737dd7cddfSDavid du Colombier 	  '(' args ')'
6747dd7cddfSDavid du Colombier 	  Opt_priority		{ Expand_Ok--;
675219b2ee8SDavid du Colombier 				  $$ = nn($2, RUN, $5, ZN);
6767dd7cddfSDavid du Colombier 				  $$->val = ($7) ? $7->val : 1;
6777dd7cddfSDavid du Colombier 				  trackchanuse($5, $2, 'A'); trackrun($$);
678219b2ee8SDavid du Colombier 				}
679219b2ee8SDavid du Colombier 	| LEN '(' varref ')'	{ $$ = nn($3, LEN, $3, ZN); }
6807dd7cddfSDavid du Colombier 	| ENABLED '(' expr ')'	{ $$ = nn(ZN, ENABLED, $3, ZN);
6817dd7cddfSDavid du Colombier 				  has_enabled++;
6827dd7cddfSDavid du Colombier 				}
683219b2ee8SDavid du Colombier 	| varref RCV		{ Expand_Ok++; }
684312a1df1SDavid du Colombier 	  '[' rargs ']'		{ Expand_Ok--; has_io++;
685219b2ee8SDavid du Colombier 				  $$ = nn($1, 'R', $1, $5);
686219b2ee8SDavid du Colombier 				}
687219b2ee8SDavid du Colombier 	| varref R_RCV		{ Expand_Ok++; }
688312a1df1SDavid du Colombier 	  '[' rargs ']'		{ Expand_Ok--; has_io++;
689219b2ee8SDavid du Colombier 				  $$ = nn($1, 'R', $1, $5);
690219b2ee8SDavid du Colombier 				  $$->val = has_random = 1;
691219b2ee8SDavid du Colombier 				}
692*00d97012SDavid du Colombier 	| varref		{ $$ = $1; trapwonly($1 /*, "varref" */); }
693312a1df1SDavid du Colombier 	| cexpr			{ $$ = $1; }
694219b2ee8SDavid du Colombier 	| CONST 		{ $$ = nn(ZN,CONST,ZN,ZN);
695219b2ee8SDavid du Colombier 				  $$->ismtyp = $1->ismtyp;
696219b2ee8SDavid du Colombier 				  $$->val = $1->val;
697219b2ee8SDavid du Colombier 				}
698219b2ee8SDavid du Colombier 	| TIMEOUT		{ $$ = nn(ZN,TIMEOUT, ZN, ZN); }
6997dd7cddfSDavid du Colombier 	| NONPROGRESS		{ $$ = nn(ZN,NONPROGRESS, ZN, ZN);
7007dd7cddfSDavid du Colombier 				  has_np++;
7017dd7cddfSDavid du Colombier 				}
7027dd7cddfSDavid du Colombier 	| PC_VAL '(' expr ')'	{ $$ = nn(ZN, PC_VAL, $3, ZN);
7037dd7cddfSDavid du Colombier 				  has_pcvalue++;
7047dd7cddfSDavid du Colombier 				}
705312a1df1SDavid du Colombier 	| PNAME '[' expr ']' '@' NAME
706312a1df1SDavid du Colombier 	  			{ $$ = rem_lab($1->sym, $3, $6->sym); }
707312a1df1SDavid du Colombier 	| PNAME '[' expr ']' ':' pfld
708312a1df1SDavid du Colombier 	  			{ $$ = rem_var($1->sym, $3, $6->sym, $6->lft); }
709312a1df1SDavid du Colombier 	| PNAME '@' NAME	{ $$ = rem_lab($1->sym, ZN, $3->sym); }
710312a1df1SDavid du Colombier 	| PNAME ':' pfld	{ $$ = rem_var($1->sym, ZN, $3->sym, $3->lft); }
711*00d97012SDavid du Colombier 	| ltl_expr		{ $$ = $1; }
712219b2ee8SDavid du Colombier 	;
713219b2ee8SDavid du Colombier 
7147dd7cddfSDavid du Colombier Opt_priority:	/* none */	{ $$ = ZN; }
7157dd7cddfSDavid du Colombier 	| PRIORITY CONST	{ $$ = $2; }
7167dd7cddfSDavid du Colombier 	;
7177dd7cddfSDavid du Colombier 
7187dd7cddfSDavid du Colombier full_expr:	expr		{ $$ = $1; }
7197dd7cddfSDavid du Colombier 	| Expr		{ $$ = $1; }
7207dd7cddfSDavid du Colombier 	;
7217dd7cddfSDavid du Colombier 
722*00d97012SDavid du Colombier ltl_expr: expr UNTIL expr	{ $$ = nn(ZN, UNTIL,   $1, $3); }
723*00d97012SDavid du Colombier 	| expr RELEASE expr	{ $$ = nn(ZN, RELEASE, $1, $3); }
724*00d97012SDavid du Colombier 	| expr WEAK_UNTIL expr	{ $$ = nn(ZN, ALWAYS, $1, ZN);
725*00d97012SDavid du Colombier 				  $$ = nn(ZN, OR, $$, nn(ZN, UNTIL, $1, $3));
726*00d97012SDavid du Colombier 				}
727*00d97012SDavid du Colombier 	| expr IMPLIES expr	{
728*00d97012SDavid du Colombier 				$$ = nn(ZN, '!', $1, ZN);
729*00d97012SDavid du Colombier 				$$ = nn(ZN, OR,  $$, $3);
730*00d97012SDavid du Colombier 				}
731*00d97012SDavid du Colombier 	| expr EQUIV expr	{ $$ = nn(ZN, EQUIV,   $1, $3); }
732*00d97012SDavid du Colombier 	| NEXT expr       %prec NEG { $$ = nn(ZN, NEXT,  $2, ZN); }
733*00d97012SDavid du Colombier 	| ALWAYS expr     %prec NEG { $$ = nn(ZN, ALWAYS,$2, ZN); }
734*00d97012SDavid du Colombier 	| EVENTUALLY expr %prec NEG { $$ = nn(ZN, EVENTUALLY, $2, ZN); }
735*00d97012SDavid du Colombier 	;
736*00d97012SDavid du Colombier 
737*00d97012SDavid du Colombier 	/* an Expr cannot be negated - to protect Probe expressions */
738*00d97012SDavid du Colombier Expr	: Probe			{ $$ = $1; }
739*00d97012SDavid du Colombier 	| '(' Expr ')'		{ $$ = $2; }
740*00d97012SDavid du Colombier 	| Expr AND Expr		{ $$ = nn(ZN, AND, $1, $3); }
741*00d97012SDavid du Colombier 	| Expr AND expr		{ $$ = nn(ZN, AND, $1, $3); }
742*00d97012SDavid du Colombier 	| expr AND Expr		{ $$ = nn(ZN, AND, $1, $3); }
743*00d97012SDavid du Colombier 	| Expr OR  Expr		{ $$ = nn(ZN,  OR, $1, $3); }
744*00d97012SDavid du Colombier 	| Expr OR  expr		{ $$ = nn(ZN,  OR, $1, $3); }
745*00d97012SDavid du Colombier 	| expr OR  Expr		{ $$ = nn(ZN,  OR, $1, $3); }
746*00d97012SDavid du Colombier 	;
747*00d97012SDavid du Colombier 
748*00d97012SDavid du Colombier Probe	: FULL '(' varref ')'	{ $$ = nn($3,  FULL, $3, ZN); }
749*00d97012SDavid du Colombier 	| NFULL '(' varref ')'	{ $$ = nn($3, NFULL, $3, ZN); }
750*00d97012SDavid du Colombier 	| EMPTY '(' varref ')'	{ $$ = nn($3, EMPTY, $3, ZN); }
751*00d97012SDavid du Colombier 	| NEMPTY '(' varref ')'	{ $$ = nn($3,NEMPTY, $3, ZN); }
752*00d97012SDavid du Colombier 	;
753*00d97012SDavid du Colombier 
7547dd7cddfSDavid du Colombier Opt_enabler:	/* none */	{ $$ = ZN; }
7557dd7cddfSDavid du Colombier 	| PROVIDED '(' full_expr ')'	{ if (!proper_enabler($3))
7567dd7cddfSDavid du Colombier 				  {	non_fatal("invalid PROVIDED clause",
7577dd7cddfSDavid du Colombier 						(char *)0);
7587dd7cddfSDavid du Colombier 					$$ = ZN;
7597dd7cddfSDavid du Colombier 				  } else
7607dd7cddfSDavid du Colombier 					$$ = $3;
7617dd7cddfSDavid du Colombier 				 }
7627dd7cddfSDavid du Colombier 	| PROVIDED error	{ $$ = ZN;
7637dd7cddfSDavid du Colombier 				  non_fatal("usage: provided ( ..expr.. )",
7647dd7cddfSDavid du Colombier 					(char *)0);
7657dd7cddfSDavid du Colombier 				}
7667dd7cddfSDavid du Colombier 	;
7677dd7cddfSDavid du Colombier 
768219b2ee8SDavid du Colombier basetype: TYPE			{ $$->sym = ZS;
769219b2ee8SDavid du Colombier 				  $$->val = $1->val;
7707dd7cddfSDavid du Colombier 				  if ($$->val == UNSIGNED)
7717dd7cddfSDavid du Colombier 				  fatal("unsigned cannot be used as mesg type", 0);
772219b2ee8SDavid du Colombier 				}
773219b2ee8SDavid du Colombier 	| UNAME			{ $$->sym = $1->sym;
774219b2ee8SDavid du Colombier 				  $$->val = STRUCT;
775219b2ee8SDavid du Colombier 				}
7767dd7cddfSDavid du Colombier 	| error			/* e.g., unsigned ':' const */
777219b2ee8SDavid du Colombier 	;
778219b2ee8SDavid du Colombier 
779219b2ee8SDavid du Colombier typ_list: basetype		{ $$ = nn($1, $1->val, ZN, ZN); }
780219b2ee8SDavid du Colombier 	| basetype ',' typ_list	{ $$ = nn($1, $1->val, ZN, $3); }
781219b2ee8SDavid du Colombier 	;
782219b2ee8SDavid du Colombier 
783219b2ee8SDavid du Colombier args    : /* empty */		{ $$ = ZN; }
784219b2ee8SDavid du Colombier 	| arg			{ $$ = $1; }
785219b2ee8SDavid du Colombier 	;
786219b2ee8SDavid du Colombier 
787219b2ee8SDavid du Colombier prargs  : /* empty */		{ $$ = ZN; }
788219b2ee8SDavid du Colombier 	| ',' arg		{ $$ = $2; }
789219b2ee8SDavid du Colombier 	;
790219b2ee8SDavid du Colombier 
791219b2ee8SDavid du Colombier margs   : arg			{ $$ = $1; }
792219b2ee8SDavid du Colombier 	| expr '(' arg ')'	{ if ($1->ntyp == ',')
793219b2ee8SDavid du Colombier 					$$ = tail_add($1, $3);
794219b2ee8SDavid du Colombier 				  else
795219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, $3);
796219b2ee8SDavid du Colombier 				}
797219b2ee8SDavid du Colombier 	;
798219b2ee8SDavid du Colombier 
799219b2ee8SDavid du Colombier arg     : expr			{ if ($1->ntyp == ',')
800219b2ee8SDavid du Colombier 					$$ = $1;
801219b2ee8SDavid du Colombier 				  else
802219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, ZN);
803219b2ee8SDavid du Colombier 				}
804219b2ee8SDavid du Colombier 	| expr ',' arg		{ if ($1->ntyp == ',')
805219b2ee8SDavid du Colombier 					$$ = tail_add($1, $3);
806219b2ee8SDavid du Colombier 				  else
807219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, $3);
808219b2ee8SDavid du Colombier 				}
809219b2ee8SDavid du Colombier 	;
810219b2ee8SDavid du Colombier 
8117dd7cddfSDavid du Colombier rarg	: varref		{ $$ = $1; trackvar($1, $1);
812*00d97012SDavid du Colombier 				  trapwonly($1 /*, "rarg" */); }
8137dd7cddfSDavid du Colombier 	| EVAL '(' expr ')'	{ $$ = nn(ZN,EVAL,$3,ZN);
814*00d97012SDavid du Colombier 				  trapwonly($1 /*, "eval rarg" */); }
815219b2ee8SDavid du Colombier 	| CONST 		{ $$ = nn(ZN,CONST,ZN,ZN);
816219b2ee8SDavid du Colombier 				  $$->ismtyp = $1->ismtyp;
817219b2ee8SDavid du Colombier 				  $$->val = $1->val;
818219b2ee8SDavid du Colombier 				}
819219b2ee8SDavid du Colombier 	| '-' CONST %prec UMIN	{ $$ = nn(ZN,CONST,ZN,ZN);
820219b2ee8SDavid du Colombier 				  $$->val = - ($2->val);
821219b2ee8SDavid du Colombier 				}
822219b2ee8SDavid du Colombier 	;
823219b2ee8SDavid du Colombier 
824219b2ee8SDavid du Colombier rargs	: rarg			{ if ($1->ntyp == ',')
825219b2ee8SDavid du Colombier 					$$ = $1;
826219b2ee8SDavid du Colombier 				  else
827219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, ZN);
828219b2ee8SDavid du Colombier 				}
829219b2ee8SDavid du Colombier 	| rarg ',' rargs	{ if ($1->ntyp == ',')
830219b2ee8SDavid du Colombier 					$$ = tail_add($1, $3);
831219b2ee8SDavid du Colombier 				  else
832219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, $3);
833219b2ee8SDavid du Colombier 				}
834219b2ee8SDavid du Colombier 	| rarg '(' rargs ')'	{ if ($1->ntyp == ',')
835219b2ee8SDavid du Colombier 					$$ = tail_add($1, $3);
836219b2ee8SDavid du Colombier 				  else
837219b2ee8SDavid du Colombier 				  	$$ = nn(ZN, ',', $1, $3);
838219b2ee8SDavid du Colombier 				}
839219b2ee8SDavid du Colombier 	| '(' rargs ')'		{ $$ = $2; }
840219b2ee8SDavid du Colombier 	;
841219b2ee8SDavid du Colombier 
842219b2ee8SDavid du Colombier nlst	: NAME			{ $$ = nn($1, NAME, ZN, ZN);
843219b2ee8SDavid du Colombier 				  $$ = nn(ZN, ',', $$, ZN); }
8447dd7cddfSDavid du Colombier 	| nlst NAME 		{ $$ = nn($2, NAME, ZN, ZN);
8457dd7cddfSDavid du Colombier 				  $$ = nn(ZN, ',', $$, $1);
846219b2ee8SDavid du Colombier 				}
8477dd7cddfSDavid du Colombier 	| nlst ','		{ $$ = $1; /* commas optional */ }
848219b2ee8SDavid du Colombier 	;
849219b2ee8SDavid du Colombier %%
850219b2ee8SDavid du Colombier 
851*00d97012SDavid du Colombier #define binop(n, sop)	fprintf(fd, "("); recursive(fd, n->lft); \
852*00d97012SDavid du Colombier 			fprintf(fd, ") %s (", sop); recursive(fd, n->rgt); \
853*00d97012SDavid du Colombier 			fprintf(fd, ")");
854*00d97012SDavid du Colombier #define unop(n, sop)	fprintf(fd, "%s (", sop); recursive(fd, n->lft); \
855*00d97012SDavid du Colombier 			fprintf(fd, ")");
856*00d97012SDavid du Colombier 
857*00d97012SDavid du Colombier static void
858*00d97012SDavid du Colombier recursive(FILE *fd, Lextok *n)
859*00d97012SDavid du Colombier {
860*00d97012SDavid du Colombier 	if (n)
861*00d97012SDavid du Colombier 	switch (n->ntyp) {
862*00d97012SDavid du Colombier 	case NEXT:
863*00d97012SDavid du Colombier 		unop(n, "X");
864*00d97012SDavid du Colombier 		break;
865*00d97012SDavid du Colombier 	case ALWAYS:
866*00d97012SDavid du Colombier 		unop(n, "[]");
867*00d97012SDavid du Colombier 		break;
868*00d97012SDavid du Colombier 	case EVENTUALLY:
869*00d97012SDavid du Colombier 		unop(n, "<>");
870*00d97012SDavid du Colombier 		break;
871*00d97012SDavid du Colombier 	case '!':
872*00d97012SDavid du Colombier 		unop(n, "!");
873*00d97012SDavid du Colombier 		break;
874*00d97012SDavid du Colombier 	case UNTIL:
875*00d97012SDavid du Colombier 		binop(n, "U");
876*00d97012SDavid du Colombier 		break;
877*00d97012SDavid du Colombier 	case WEAK_UNTIL:
878*00d97012SDavid du Colombier 		binop(n, "W");
879*00d97012SDavid du Colombier 		break;
880*00d97012SDavid du Colombier 	case RELEASE: /* see http://en.wikipedia.org/wiki/Linear_temporal_logic */
881*00d97012SDavid du Colombier 		binop(n, "V");
882*00d97012SDavid du Colombier 		break;
883*00d97012SDavid du Colombier 	case OR:
884*00d97012SDavid du Colombier 		binop(n, "||");
885*00d97012SDavid du Colombier 		break;
886*00d97012SDavid du Colombier 	case AND:
887*00d97012SDavid du Colombier 		binop(n, "&&");
888*00d97012SDavid du Colombier 		break;
889*00d97012SDavid du Colombier 	case IMPLIES:
890*00d97012SDavid du Colombier 		binop(n, "->");
891*00d97012SDavid du Colombier 		break;
892*00d97012SDavid du Colombier 	case EQUIV:
893*00d97012SDavid du Colombier 		binop(n, "<->");
894*00d97012SDavid du Colombier 		break;
895*00d97012SDavid du Colombier 	default:
896*00d97012SDavid du Colombier 		comment(fd, n, 0);
897*00d97012SDavid du Colombier 		break;
898*00d97012SDavid du Colombier 	}
899*00d97012SDavid du Colombier }
900*00d97012SDavid du Colombier 
901*00d97012SDavid du Colombier #define TMP_FILE	"_S_p_I_n_.tmp"
902*00d97012SDavid du Colombier 
903*00d97012SDavid du Colombier extern int unlink(const char *);
904*00d97012SDavid du Colombier 
905*00d97012SDavid du Colombier static Lextok *
ltl_to_string(Lextok * n)906*00d97012SDavid du Colombier ltl_to_string(Lextok *n)
907*00d97012SDavid du Colombier {	Lextok *m = nn(ZN, 0, ZN, ZN);
908*00d97012SDavid du Colombier 	char *retval;
909*00d97012SDavid du Colombier 	char formula[1024];
910*00d97012SDavid du Colombier 	FILE *tf = fopen(TMP_FILE, "w+"); /* tmpfile() fails on Windows 7 */
911*00d97012SDavid du Colombier 
912*00d97012SDavid du Colombier 	/* convert the parsed ltl to a string
913*00d97012SDavid du Colombier 	   by writing into a file, using existing functions,
914*00d97012SDavid du Colombier 	   and then passing it to the existing interface for
915*00d97012SDavid du Colombier 	   conversion into a never claim
916*00d97012SDavid du Colombier 	  (this means parsing everything twice, which is
917*00d97012SDavid du Colombier 	   a little redundant, but adds only miniscule overhead)
918*00d97012SDavid du Colombier 	 */
919*00d97012SDavid du Colombier 
920*00d97012SDavid du Colombier 	if (!tf)
921*00d97012SDavid du Colombier 	{	fatal("cannot create temporary file", (char *) 0);
922*00d97012SDavid du Colombier 	}
923*00d97012SDavid du Colombier 	recursive(tf, n);
924*00d97012SDavid du Colombier 	(void) fseek(tf, 0L, SEEK_SET);
925*00d97012SDavid du Colombier 
926*00d97012SDavid du Colombier 	memset(formula, 0, sizeof(formula));
927*00d97012SDavid du Colombier 	retval = fgets(formula, sizeof(formula), tf);
928*00d97012SDavid du Colombier 	fclose(tf);
929*00d97012SDavid du Colombier 	(void) unlink(TMP_FILE);
930*00d97012SDavid du Colombier 
931*00d97012SDavid du Colombier 	if (!retval)
932*00d97012SDavid du Colombier 	{	printf("%p\n", retval);
933*00d97012SDavid du Colombier 		fatal("could not translate ltl formula", 0);
934*00d97012SDavid du Colombier 	}
935*00d97012SDavid du Colombier 
936*00d97012SDavid du Colombier 	if (1) printf("ltl %s: %s\n", ltl_name, formula);
937*00d97012SDavid du Colombier 
938*00d97012SDavid du Colombier 	m->sym = lookup(formula);
939*00d97012SDavid du Colombier 
940*00d97012SDavid du Colombier 	return m;
941*00d97012SDavid du Colombier }
942*00d97012SDavid du Colombier 
943219b2ee8SDavid du Colombier void
yyerror(char * fmt,...)944219b2ee8SDavid du Colombier yyerror(char *fmt, ...)
9457dd7cddfSDavid du Colombier {
9467dd7cddfSDavid du Colombier 	non_fatal(fmt, (char *) 0);
947219b2ee8SDavid du Colombier }
948