xref: /plan9-contrib/sys/src/cmd/spin/spinlex.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
1219b2ee8SDavid du Colombier /***** spin: spinlex.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 
97dd7cddfSDavid du Colombier #include <stdlib.h>
10*de2caf28SDavid du Colombier #include <assert.h>
11*de2caf28SDavid du Colombier #include <errno.h>
12*de2caf28SDavid du Colombier #include <ctype.h>
13219b2ee8SDavid du Colombier #include "spin.h"
14219b2ee8SDavid du Colombier #include "y.tab.h"
15219b2ee8SDavid du Colombier 
167dd7cddfSDavid du Colombier #define MAXINL	16	/* max recursion depth inline fcts */
177dd7cddfSDavid du Colombier #define MAXPAR	32	/* max params to an inline call */
187dd7cddfSDavid du Colombier #define MAXLEN	512	/* max len of an actual parameter text */
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier typedef struct IType {
217dd7cddfSDavid du Colombier 	Symbol *nm;		/* name of the type */
227dd7cddfSDavid du Colombier 	Lextok *cn;		/* contents */
237dd7cddfSDavid du Colombier 	Lextok *params;		/* formal pars if any */
24*de2caf28SDavid du Colombier 	Lextok *rval;		/* variable to assign return value, if any */
257dd7cddfSDavid du Colombier 	char   **anms;		/* literal text for actual pars */
26312a1df1SDavid du Colombier 	char   *prec;		/* precondition for c_code or c_expr */
2700d97012SDavid du Colombier 	int    uiid;		/* unique inline id */
28*de2caf28SDavid du Colombier 	int    is_expr;		/* c_expr in an ltl formula */
297dd7cddfSDavid du Colombier 	int    dln, cln;	/* def and call linenr */
307dd7cddfSDavid du Colombier 	Symbol *dfn, *cfn;	/* def and call filename */
317dd7cddfSDavid du Colombier 	struct IType *nxt;	/* linked list */
327dd7cddfSDavid du Colombier } IType;
33219b2ee8SDavid du Colombier 
34312a1df1SDavid du Colombier typedef struct C_Added {
35312a1df1SDavid du Colombier 	Symbol *s;
36312a1df1SDavid du Colombier 	Symbol *t;
37312a1df1SDavid du Colombier 	Symbol *ival;
38*de2caf28SDavid du Colombier 	Symbol *fnm;
39*de2caf28SDavid du Colombier 	int	lno;
40312a1df1SDavid du Colombier 	struct C_Added *nxt;
41312a1df1SDavid du Colombier } C_Added;
42219b2ee8SDavid du Colombier 
43*de2caf28SDavid du Colombier extern RunList	*X_lst;
44*de2caf28SDavid du Colombier extern ProcList	*ready;
4500d97012SDavid du Colombier extern Symbol	*Fname, *oFname;
46312a1df1SDavid du Colombier extern Symbol	*context, *owner;
47312a1df1SDavid du Colombier extern YYSTYPE	yylval;
48*de2caf28SDavid du Colombier extern short	has_last, has_code, has_priority;
49*de2caf28SDavid du Colombier extern int	verbose, IArgs, hastrack, separate, in_for;
50*de2caf28SDavid du Colombier extern int	implied_semis, ltl_mode, in_seq, par_cnt;
51312a1df1SDavid du Colombier 
52312a1df1SDavid du Colombier short	has_stack = 0;
53312a1df1SDavid du Colombier int	lineno  = 1;
5400d97012SDavid du Colombier int	scope_seq[128], scope_level = 0;
5500d97012SDavid du Colombier char	CurScope[MAXSCOPESZ];
567dd7cddfSDavid du Colombier char	yytext[2048];
577dd7cddfSDavid du Colombier FILE	*yyin, *yyout;
58219b2ee8SDavid du Colombier 
59312a1df1SDavid du Colombier static C_Added	*c_added, *c_tracked;
60312a1df1SDavid du Colombier static IType	*Inline_stub[MAXINL];
617dd7cddfSDavid du Colombier static char	*ReDiRect;
62312a1df1SDavid du Colombier static char	*Inliner[MAXINL], IArg_cont[MAXPAR][MAXLEN];
63312a1df1SDavid du Colombier static unsigned char	in_comment=0;
64312a1df1SDavid du Colombier static int	IArgno = 0, Inlining = -1;
657dd7cddfSDavid du Colombier static int	check_name(char *);
66*de2caf28SDavid du Colombier static int	last_token = 0;
677dd7cddfSDavid du Colombier 
687dd7cddfSDavid du Colombier #define ValToken(x, y)	{ if (in_comment) goto again; \
69*de2caf28SDavid du Colombier 			yylval = nn(ZN,0,ZN,ZN); \
70*de2caf28SDavid du Colombier 			yylval->val = x; \
71*de2caf28SDavid du Colombier 			last_token = y; \
72*de2caf28SDavid du Colombier 			return y; \
73*de2caf28SDavid du Colombier 			}
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier #define SymToken(x, y)	{ if (in_comment) goto again; \
76*de2caf28SDavid du Colombier 			yylval = nn(ZN,0,ZN,ZN); \
77*de2caf28SDavid du Colombier 			yylval->sym = x; \
78*de2caf28SDavid du Colombier 			last_token = y; \
79*de2caf28SDavid du Colombier 			return y; \
80*de2caf28SDavid du Colombier 			}
81219b2ee8SDavid du Colombier 
82312a1df1SDavid du Colombier static int  getinline(void);
83312a1df1SDavid du Colombier static void uninline(void);
84312a1df1SDavid du Colombier 
85*de2caf28SDavid du Colombier static int PushBack;
86*de2caf28SDavid du Colombier static int PushedBack;
87*de2caf28SDavid du Colombier static char pushedback[4096];
88219b2ee8SDavid du Colombier 
89*de2caf28SDavid du Colombier static void
push_back(char * s)90*de2caf28SDavid du Colombier push_back(char *s)
91*de2caf28SDavid du Colombier {
92*de2caf28SDavid du Colombier 	if (PushedBack + strlen(s) > 4094)
93*de2caf28SDavid du Colombier 	{	fatal("select statement too large", 0);
94*de2caf28SDavid du Colombier 	}
95*de2caf28SDavid du Colombier 	strcat(pushedback, s);
96*de2caf28SDavid du Colombier 	PushedBack += strlen(s);
97*de2caf28SDavid du Colombier }
98312a1df1SDavid du Colombier 
99312a1df1SDavid du Colombier static int
Getchar(void)100312a1df1SDavid du Colombier Getchar(void)
101312a1df1SDavid du Colombier {	int c;
10200d97012SDavid du Colombier 
103*de2caf28SDavid du Colombier 	if (PushedBack > 0 && PushBack < PushedBack)
104*de2caf28SDavid du Colombier 	{	c = pushedback[PushBack++];
105*de2caf28SDavid du Colombier 		if (PushBack == PushedBack)
106*de2caf28SDavid du Colombier 		{	pushedback[0] = '\0';
107*de2caf28SDavid du Colombier 			PushBack = PushedBack = 0;
108*de2caf28SDavid du Colombier 		}
109*de2caf28SDavid du Colombier 		return c;	/* expanded select statement */
110*de2caf28SDavid du Colombier 	}
111312a1df1SDavid du Colombier 	if (Inlining<0)
112*de2caf28SDavid du Colombier 	{	do {	c = getc(yyin);
113*de2caf28SDavid du Colombier 		} while (c == 0);	// ignore null chars
114*de2caf28SDavid du Colombier 		// eventually there will always be an EOF
115*de2caf28SDavid du Colombier 	} else
116*de2caf28SDavid du Colombier 	{	c = getinline();
117*de2caf28SDavid du Colombier 	}
118*de2caf28SDavid du Colombier #if 0
11900d97012SDavid du Colombier 	if (0)
12000d97012SDavid du Colombier 	{	printf("<%c:%d>[%d] ", c, c, Inlining);
12100d97012SDavid du Colombier 	} else
12200d97012SDavid du Colombier 	{	printf("%c", c);
12300d97012SDavid du Colombier 	}
124*de2caf28SDavid du Colombier #endif
125312a1df1SDavid du Colombier 	return c;
126312a1df1SDavid du Colombier }
127312a1df1SDavid du Colombier 
128312a1df1SDavid du Colombier static void
Ungetch(int c)129312a1df1SDavid du Colombier Ungetch(int c)
130312a1df1SDavid du Colombier {
131*de2caf28SDavid du Colombier 	if (PushedBack > 0 && PushBack > 0)
132*de2caf28SDavid du Colombier 	{	PushBack--;
133*de2caf28SDavid du Colombier 		return;
134*de2caf28SDavid du Colombier 	}
135*de2caf28SDavid du Colombier 
136312a1df1SDavid du Colombier 	if (Inlining<0)
137*de2caf28SDavid du Colombier 	{	ungetc(c,yyin);
138*de2caf28SDavid du Colombier 	} else
139*de2caf28SDavid du Colombier 	{	uninline();
140*de2caf28SDavid du Colombier 	}
14100d97012SDavid du Colombier 	if (0)
142*de2caf28SDavid du Colombier 	{	printf("\n<bs{%d}bs>\n", c);
14300d97012SDavid du Colombier 	}
144312a1df1SDavid du Colombier }
1457dd7cddfSDavid du Colombier 
1467dd7cddfSDavid du Colombier static int
notdollar(int c)14700d97012SDavid du Colombier notdollar(int c)
14800d97012SDavid du Colombier {	return (c != '$' && c != '\n');
14900d97012SDavid du Colombier }
15000d97012SDavid du Colombier 
15100d97012SDavid du Colombier static int
notquote(int c)152219b2ee8SDavid du Colombier notquote(int c)
153219b2ee8SDavid du Colombier {	return (c != '\"' && c != '\n');
154219b2ee8SDavid du Colombier }
155219b2ee8SDavid du Colombier 
156219b2ee8SDavid du Colombier int
isalnum_(int c)157219b2ee8SDavid du Colombier isalnum_(int c)
158219b2ee8SDavid du Colombier {	return (isalnum(c) || c == '_');
159219b2ee8SDavid du Colombier }
160219b2ee8SDavid du Colombier 
1617dd7cddfSDavid du Colombier static int
isalpha_(int c)1627dd7cddfSDavid du Colombier isalpha_(int c)
1637dd7cddfSDavid du Colombier {	return isalpha(c);	/* could be macro */
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier 
1667dd7cddfSDavid du Colombier static int
isdigit_(int c)1677dd7cddfSDavid du Colombier isdigit_(int c)
1687dd7cddfSDavid du Colombier {	return isdigit(c);	/* could be macro */
1697dd7cddfSDavid du Colombier }
1707dd7cddfSDavid du Colombier 
1717dd7cddfSDavid du Colombier static void
getword(int first,int (* tst)(int))172219b2ee8SDavid du Colombier getword(int first, int (*tst)(int))
17300d97012SDavid du Colombier {	int i=0, c;
174219b2ee8SDavid du Colombier 
1757dd7cddfSDavid du Colombier 	yytext[i++]= (char) first;
176219b2ee8SDavid du Colombier 	while (tst(c = Getchar()))
177*de2caf28SDavid du Colombier 	{	if (c == EOF)
178*de2caf28SDavid du Colombier 		{	break;
179*de2caf28SDavid du Colombier 		}
180*de2caf28SDavid du Colombier 		yytext[i++] = (char) c;
181312a1df1SDavid du Colombier 		if (c == '\\')
18200d97012SDavid du Colombier 		{	c = Getchar();
18300d97012SDavid du Colombier 			yytext[i++] = (char) c;	/* no tst */
18400d97012SDavid du Colombier 	}	}
185219b2ee8SDavid du Colombier 	yytext[i] = '\0';
186*de2caf28SDavid du Colombier 
187219b2ee8SDavid du Colombier 	Ungetch(c);
188219b2ee8SDavid du Colombier }
189219b2ee8SDavid du Colombier 
1907dd7cddfSDavid du Colombier static int
follow(int tok,int ifyes,int ifno)191219b2ee8SDavid du Colombier follow(int tok, int ifyes, int ifno)
192219b2ee8SDavid du Colombier {	int c;
193219b2ee8SDavid du Colombier 
194219b2ee8SDavid du Colombier 	if ((c = Getchar()) == tok)
195*de2caf28SDavid du Colombier 	{	return ifyes;
196*de2caf28SDavid du Colombier 	}
197219b2ee8SDavid du Colombier 	Ungetch(c);
198219b2ee8SDavid du Colombier 
199219b2ee8SDavid du Colombier 	return ifno;
200219b2ee8SDavid du Colombier }
201219b2ee8SDavid du Colombier 
2027dd7cddfSDavid du Colombier static IType *seqnames;
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier static void
def_inline(Symbol * s,int ln,char * ptr,char * prc,Lextok * nms)205312a1df1SDavid du Colombier def_inline(Symbol *s, int ln, char *ptr, char *prc, Lextok *nms)
2067dd7cddfSDavid du Colombier {	IType *tmp;
20700d97012SDavid du Colombier 	int  cnt = 0;
20800d97012SDavid du Colombier 	char *nw = (char *) emalloc(strlen(ptr)+1);
2097dd7cddfSDavid du Colombier 	strcpy(nw, ptr);
2107dd7cddfSDavid du Colombier 
21100d97012SDavid du Colombier 	for (tmp = seqnames; tmp; cnt++, tmp = tmp->nxt)
2127dd7cddfSDavid du Colombier 		if (!strcmp(s->name, tmp->nm->name))
2137dd7cddfSDavid du Colombier 		{	non_fatal("procedure name %s redefined",
2147dd7cddfSDavid du Colombier 				tmp->nm->name);
2157dd7cddfSDavid du Colombier 			tmp->cn = (Lextok *) nw;
2167dd7cddfSDavid du Colombier 			tmp->params = nms;
2177dd7cddfSDavid du Colombier 			tmp->dln = ln;
2187dd7cddfSDavid du Colombier 			tmp->dfn = Fname;
2197dd7cddfSDavid du Colombier 			return;
2207dd7cddfSDavid du Colombier 		}
2217dd7cddfSDavid du Colombier 	tmp = (IType *) emalloc(sizeof(IType));
2227dd7cddfSDavid du Colombier 	tmp->nm = s;
2237dd7cddfSDavid du Colombier 	tmp->cn = (Lextok *) nw;
2247dd7cddfSDavid du Colombier 	tmp->params = nms;
225312a1df1SDavid du Colombier 	if (strlen(prc) > 0)
22600d97012SDavid du Colombier 	{	tmp->prec = (char *) emalloc(strlen(prc)+1);
227312a1df1SDavid du Colombier 		strcpy(tmp->prec, prc);
228312a1df1SDavid du Colombier 	}
2297dd7cddfSDavid du Colombier 	tmp->dln = ln;
2307dd7cddfSDavid du Colombier 	tmp->dfn = Fname;
23100d97012SDavid du Colombier 	tmp->uiid = cnt+1;	/* so that 0 means: not an inline */
2327dd7cddfSDavid du Colombier 	tmp->nxt = seqnames;
2337dd7cddfSDavid du Colombier 	seqnames = tmp;
2347dd7cddfSDavid du Colombier }
2357dd7cddfSDavid du Colombier 
236312a1df1SDavid du Colombier void
gencodetable(FILE * fd)237312a1df1SDavid du Colombier gencodetable(FILE *fd)
238312a1df1SDavid du Colombier {	IType *tmp;
239312a1df1SDavid du Colombier 	char *q;
240312a1df1SDavid du Colombier 	int cnt;
241312a1df1SDavid du Colombier 
242312a1df1SDavid du Colombier 	if (separate == 2) return;
243312a1df1SDavid du Colombier 
244312a1df1SDavid du Colombier 	fprintf(fd, "struct {\n");
245312a1df1SDavid du Colombier 	fprintf(fd, "	char *c; char *t;\n");
246312a1df1SDavid du Colombier 	fprintf(fd, "} code_lookup[] = {\n");
247312a1df1SDavid du Colombier 
248312a1df1SDavid du Colombier 	if (has_code)
249312a1df1SDavid du Colombier 	for (tmp = seqnames; tmp; tmp = tmp->nxt)
250312a1df1SDavid du Colombier 		if (tmp->nm->type == CODE_FRAG
251312a1df1SDavid du Colombier 		||  tmp->nm->type == CODE_DECL)
252312a1df1SDavid du Colombier 		{	fprintf(fd, "\t{ \"%s\", ",
253312a1df1SDavid du Colombier 				tmp->nm->name);
254312a1df1SDavid du Colombier 			q = (char *) tmp->cn;
255312a1df1SDavid du Colombier 
256312a1df1SDavid du Colombier 			while (*q == '\n' || *q == '\r' || *q == '\\')
257312a1df1SDavid du Colombier 				q++;
258312a1df1SDavid du Colombier 
259312a1df1SDavid du Colombier 			fprintf(fd, "\"");
260312a1df1SDavid du Colombier 			cnt = 0;
261312a1df1SDavid du Colombier 			while (*q && cnt < 1024) /* pangen1.h allows 2048 */
262312a1df1SDavid du Colombier 			{	switch (*q) {
263312a1df1SDavid du Colombier 				case '"':
264312a1df1SDavid du Colombier 					fprintf(fd, "\\\"");
265312a1df1SDavid du Colombier 					break;
266312a1df1SDavid du Colombier 				case '%':
267312a1df1SDavid du Colombier 					fprintf(fd, "%%");
268312a1df1SDavid du Colombier 					break;
269312a1df1SDavid du Colombier 				case '\n':
270312a1df1SDavid du Colombier 					fprintf(fd, "\\n");
271312a1df1SDavid du Colombier 					break;
272312a1df1SDavid du Colombier 				default:
273312a1df1SDavid du Colombier 					putc(*q, fd);
274312a1df1SDavid du Colombier 					break;
275312a1df1SDavid du Colombier 				}
276312a1df1SDavid du Colombier 				q++; cnt++;
277312a1df1SDavid du Colombier 			}
278312a1df1SDavid du Colombier 			if (*q) fprintf(fd, "...");
279312a1df1SDavid du Colombier 			fprintf(fd, "\"");
280312a1df1SDavid du Colombier 			fprintf(fd, " },\n");
281312a1df1SDavid du Colombier 		}
282312a1df1SDavid du Colombier 
283312a1df1SDavid du Colombier 	fprintf(fd, "	{ (char *) 0, \"\" }\n");
284312a1df1SDavid du Colombier 	fprintf(fd, "};\n");
285312a1df1SDavid du Colombier }
286312a1df1SDavid du Colombier 
2877dd7cddfSDavid du Colombier static int
iseqname(char * t)2887dd7cddfSDavid du Colombier iseqname(char *t)
2897dd7cddfSDavid du Colombier {	IType *tmp;
2907dd7cddfSDavid du Colombier 
2917dd7cddfSDavid du Colombier 	for (tmp = seqnames; tmp; tmp = tmp->nxt)
2927dd7cddfSDavid du Colombier 	{	if (!strcmp(t, tmp->nm->name))
2937dd7cddfSDavid du Colombier 			return 1;
2947dd7cddfSDavid du Colombier 	}
2957dd7cddfSDavid du Colombier 	return 0;
2967dd7cddfSDavid du Colombier }
2977dd7cddfSDavid du Colombier 
298*de2caf28SDavid du Colombier Lextok *
return_statement(Lextok * n)299*de2caf28SDavid du Colombier return_statement(Lextok *n)
300*de2caf28SDavid du Colombier {
301*de2caf28SDavid du Colombier 	if (Inline_stub[Inlining]->rval)
302*de2caf28SDavid du Colombier 	{	Lextok *g = nn(ZN, NAME, ZN, ZN);
303*de2caf28SDavid du Colombier 		Lextok *h = Inline_stub[Inlining]->rval;
304*de2caf28SDavid du Colombier 		g->sym = lookup("rv_");
305*de2caf28SDavid du Colombier 		return nn(h, ASGN, h, n);
306*de2caf28SDavid du Colombier 	} else
307*de2caf28SDavid du Colombier 	{	fatal("return statement outside inline", (char *) 0);
308*de2caf28SDavid du Colombier 	}
309*de2caf28SDavid du Colombier 	return ZN;
310*de2caf28SDavid du Colombier }
311*de2caf28SDavid du Colombier 
3127dd7cddfSDavid du Colombier static int
getinline(void)3137dd7cddfSDavid du Colombier getinline(void)
3147dd7cddfSDavid du Colombier {	int c;
3157dd7cddfSDavid du Colombier 
3167dd7cddfSDavid du Colombier 	if (ReDiRect)
3177dd7cddfSDavid du Colombier 	{	c = *ReDiRect++;
3187dd7cddfSDavid du Colombier 		if (c == '\0')
3197dd7cddfSDavid du Colombier 		{	ReDiRect = (char *) 0;
3207dd7cddfSDavid du Colombier 			c = *Inliner[Inlining]++;
3217dd7cddfSDavid du Colombier 		}
3227dd7cddfSDavid du Colombier 	} else
323*de2caf28SDavid du Colombier 	{
3247dd7cddfSDavid du Colombier 		c = *Inliner[Inlining]++;
325*de2caf28SDavid du Colombier 	}
3267dd7cddfSDavid du Colombier 
3277dd7cddfSDavid du Colombier 	if (c == '\0')
328*de2caf28SDavid du Colombier 	{
329*de2caf28SDavid du Colombier 		lineno = Inline_stub[Inlining]->cln;
3307dd7cddfSDavid du Colombier 		Fname  = Inline_stub[Inlining]->cfn;
3317dd7cddfSDavid du Colombier 		Inlining--;
332*de2caf28SDavid du Colombier 
3337dd7cddfSDavid du Colombier #if 0
3347dd7cddfSDavid du Colombier 		if (verbose&32)
33500d97012SDavid du Colombier 		printf("spin: %s:%d, done inlining %s\n",
33600d97012SDavid du Colombier 			Fname, lineno, Inline_stub[Inlining+1]->nm->name);
3377dd7cddfSDavid du Colombier #endif
3387dd7cddfSDavid du Colombier 		return Getchar();
3397dd7cddfSDavid du Colombier 	}
3407dd7cddfSDavid du Colombier 	return c;
3417dd7cddfSDavid du Colombier }
3427dd7cddfSDavid du Colombier 
3437dd7cddfSDavid du Colombier static void
uninline(void)3447dd7cddfSDavid du Colombier uninline(void)
3457dd7cddfSDavid du Colombier {
3467dd7cddfSDavid du Colombier 	if (ReDiRect)
3477dd7cddfSDavid du Colombier 		ReDiRect--;
3487dd7cddfSDavid du Colombier 	else
3497dd7cddfSDavid du Colombier 		Inliner[Inlining]--;
3507dd7cddfSDavid du Colombier }
3517dd7cddfSDavid du Colombier 
35200d97012SDavid du Colombier int
is_inline(void)35300d97012SDavid du Colombier is_inline(void)
35400d97012SDavid du Colombier {
35500d97012SDavid du Colombier 	if (Inlining < 0)
35600d97012SDavid du Colombier 		return 0;	/* i.e., not an inline */
35700d97012SDavid du Colombier 	if (Inline_stub[Inlining] == NULL)
35800d97012SDavid du Colombier 		fatal("unexpected, inline_stub not set", 0);
35900d97012SDavid du Colombier 	return Inline_stub[Inlining]->uiid;
36000d97012SDavid du Colombier }
36100d97012SDavid du Colombier 
362312a1df1SDavid du Colombier IType *
find_inline(char * s)363312a1df1SDavid du Colombier find_inline(char *s)
364312a1df1SDavid du Colombier {	IType *tmp;
365312a1df1SDavid du Colombier 
366312a1df1SDavid du Colombier 	for (tmp = seqnames; tmp; tmp = tmp->nxt)
367312a1df1SDavid du Colombier 		if (!strcmp(s, tmp->nm->name))
368312a1df1SDavid du Colombier 			break;
369312a1df1SDavid du Colombier 	if (!tmp)
370312a1df1SDavid du Colombier 		fatal("cannot happen, missing inline def %s", s);
37100d97012SDavid du Colombier 
372312a1df1SDavid du Colombier 	return tmp;
373312a1df1SDavid du Colombier }
374312a1df1SDavid du Colombier 
375312a1df1SDavid du Colombier void
c_state(Symbol * s,Symbol * t,Symbol * ival)376312a1df1SDavid du Colombier c_state(Symbol *s, Symbol *t, Symbol *ival)	/* name, scope, ival */
377312a1df1SDavid du Colombier {	C_Added *r;
378312a1df1SDavid du Colombier 
379312a1df1SDavid du Colombier 	r = (C_Added *) emalloc(sizeof(C_Added));
380312a1df1SDavid du Colombier 	r->s = s;	/* pointer to a data object */
381312a1df1SDavid du Colombier 	r->t = t;	/* size of object, or "global", or "local proctype_name"  */
382312a1df1SDavid du Colombier 	r->ival = ival;
383*de2caf28SDavid du Colombier 	r->lno = lineno;
384*de2caf28SDavid du Colombier 	r->fnm = Fname;
385312a1df1SDavid du Colombier 	r->nxt = c_added;
386*de2caf28SDavid du Colombier 
387*de2caf28SDavid du Colombier 	if(strncmp(r->s->name, "\"unsigned unsigned", 18) == 0)
388*de2caf28SDavid du Colombier 	{	int i;
389*de2caf28SDavid du Colombier 		for (i = 10; i < 18; i++)
390*de2caf28SDavid du Colombier 		{	r->s->name[i] = ' ';
391*de2caf28SDavid du Colombier 		}
392*de2caf28SDavid du Colombier 	/*	printf("corrected <%s>\n", r->s->name);	*/
393*de2caf28SDavid du Colombier 	}
394312a1df1SDavid du Colombier 	c_added = r;
395312a1df1SDavid du Colombier }
396312a1df1SDavid du Colombier 
397312a1df1SDavid du Colombier void
c_track(Symbol * s,Symbol * t,Symbol * stackonly)398312a1df1SDavid du Colombier c_track(Symbol *s, Symbol *t, Symbol *stackonly)	/* name, size */
399312a1df1SDavid du Colombier {	C_Added *r;
400312a1df1SDavid du Colombier 
401312a1df1SDavid du Colombier 	r = (C_Added *) emalloc(sizeof(C_Added));
402312a1df1SDavid du Colombier 	r->s = s;
403312a1df1SDavid du Colombier 	r->t = t;
404312a1df1SDavid du Colombier 	r->ival = stackonly;	/* abuse of name */
405312a1df1SDavid du Colombier 	r->nxt = c_tracked;
406*de2caf28SDavid du Colombier 	r->fnm = Fname;
407*de2caf28SDavid du Colombier 	r->lno = lineno;
408312a1df1SDavid du Colombier 	c_tracked = r;
409312a1df1SDavid du Colombier 
410312a1df1SDavid du Colombier 	if (stackonly != ZS)
411312a1df1SDavid du Colombier 	{	if (strcmp(stackonly->name, "\"Matched\"") == 0)
412312a1df1SDavid du Colombier 			r->ival = ZS;	/* the default */
413312a1df1SDavid du Colombier 		else if (strcmp(stackonly->name, "\"UnMatched\"") != 0
414312a1df1SDavid du Colombier 		     &&  strcmp(stackonly->name, "\"unMatched\"") != 0
415312a1df1SDavid du Colombier 		     &&  strcmp(stackonly->name, "\"StackOnly\"") != 0)
416312a1df1SDavid du Colombier 			non_fatal("expecting '[Un]Matched', saw %s", stackonly->name);
417312a1df1SDavid du Colombier 		else
41800d97012SDavid du Colombier 			has_stack = 1;	/* unmatched stack */
419312a1df1SDavid du Colombier 	}
420312a1df1SDavid du Colombier }
421312a1df1SDavid du Colombier 
422312a1df1SDavid du Colombier char *
skip_white(char * p)423*de2caf28SDavid du Colombier skip_white(char *p)
424*de2caf28SDavid du Colombier {
425*de2caf28SDavid du Colombier 	if (p != NULL)
426*de2caf28SDavid du Colombier 	{	while (*p == ' ' || *p == '\t')
427*de2caf28SDavid du Colombier 			p++;
428*de2caf28SDavid du Colombier 	} else
429*de2caf28SDavid du Colombier 	{	fatal("bad format - 1", (char *) 0);
430*de2caf28SDavid du Colombier 	}
431*de2caf28SDavid du Colombier 	return p;
432*de2caf28SDavid du Colombier }
433312a1df1SDavid du Colombier 
434*de2caf28SDavid du Colombier char *
skip_nonwhite(char * p)435*de2caf28SDavid du Colombier skip_nonwhite(char *p)
436*de2caf28SDavid du Colombier {
437*de2caf28SDavid du Colombier 	if (p != NULL)
438*de2caf28SDavid du Colombier 	{	while (*p != ' ' && *p != '\t')
439*de2caf28SDavid du Colombier 			p++;
440*de2caf28SDavid du Colombier 	} else
441*de2caf28SDavid du Colombier 	{	fatal("bad format - 2", (char *) 0);
442*de2caf28SDavid du Colombier 	}
443*de2caf28SDavid du Colombier 	return p;
444*de2caf28SDavid du Colombier }
445312a1df1SDavid du Colombier 
446*de2caf28SDavid du Colombier static char *
jump_etc(C_Added * r)447*de2caf28SDavid du Colombier jump_etc(C_Added *r)
448*de2caf28SDavid du Colombier {	char *op = r->s->name;
449*de2caf28SDavid du Colombier 	char *p = op;
450*de2caf28SDavid du Colombier 	char *q = (char *) 0;
451*de2caf28SDavid du Colombier 	int oln = lineno;
452*de2caf28SDavid du Colombier 	Symbol *ofnm = Fname;
453*de2caf28SDavid du Colombier 
454*de2caf28SDavid du Colombier 	/* try to get the type separated from the name */
455*de2caf28SDavid du Colombier 	lineno = r->lno;
456*de2caf28SDavid du Colombier 	Fname  = r->fnm;
457*de2caf28SDavid du Colombier 
458*de2caf28SDavid du Colombier 	p = skip_white(p);	/* initial white space */
459*de2caf28SDavid du Colombier 
460*de2caf28SDavid du Colombier 	if (strncmp(p, "enum", strlen("enum")) == 0) /* special case: a two-part typename */
461*de2caf28SDavid du Colombier 	{	p += strlen("enum")+1;
462*de2caf28SDavid du Colombier 		p = skip_white(p);
463*de2caf28SDavid du Colombier 	}
464*de2caf28SDavid du Colombier 	if (strncmp(p, "unsigned", strlen("unsigned")) == 0) /* possibly a two-part typename */
465*de2caf28SDavid du Colombier 	{	p += strlen("unsigned")+1;
466*de2caf28SDavid du Colombier 		q = p = skip_white(p);
467*de2caf28SDavid du Colombier 	}
468*de2caf28SDavid du Colombier 	p = skip_nonwhite(p);	/* type name */
469*de2caf28SDavid du Colombier 	p = skip_white(p);	/* white space */
470*de2caf28SDavid du Colombier 	while (*p == '*') p++;	/* decorations */
471*de2caf28SDavid du Colombier 	p = skip_white(p);	/* white space */
472312a1df1SDavid du Colombier 
473312a1df1SDavid du Colombier 	if (*p == '\0')
474*de2caf28SDavid du Colombier 	{	if (q)
475*de2caf28SDavid du Colombier 		{	p = q;	/* unsigned with implied 'int' */
476*de2caf28SDavid du Colombier 		} else
477*de2caf28SDavid du Colombier 		{	fatal("c_state format (%s)", op);
478*de2caf28SDavid du Colombier 	}	}
479312a1df1SDavid du Colombier 
480312a1df1SDavid du Colombier 	if (strchr(p, '[')
481*de2caf28SDavid du Colombier 	&& (!r->ival
482*de2caf28SDavid du Colombier 	||  !r->ival->name
483*de2caf28SDavid du Colombier 	||  !strchr(r->ival->name, '{')))	/* was !strchr(p, '{')) */
484312a1df1SDavid du Colombier 	{	non_fatal("array initialization error, c_state (%s)", p);
485*de2caf28SDavid du Colombier 		p = (char *) 0;
486312a1df1SDavid du Colombier 	}
487312a1df1SDavid du Colombier 
488*de2caf28SDavid du Colombier 	lineno = oln;
489*de2caf28SDavid du Colombier 	Fname = ofnm;
490*de2caf28SDavid du Colombier 
491312a1df1SDavid du Colombier 	return p;
492312a1df1SDavid du Colombier }
493312a1df1SDavid du Colombier 
494312a1df1SDavid du Colombier void
c_add_globinit(FILE * fd)495312a1df1SDavid du Colombier c_add_globinit(FILE *fd)
496312a1df1SDavid du Colombier {	C_Added *r;
497312a1df1SDavid du Colombier 	char *p, *q;
498312a1df1SDavid du Colombier 
499312a1df1SDavid du Colombier 	fprintf(fd, "void\nglobinit(void)\n{\n");
500312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)
501312a1df1SDavid du Colombier 	{	if (r->ival == ZS)
502312a1df1SDavid du Colombier 			continue;
503312a1df1SDavid du Colombier 
504312a1df1SDavid du Colombier 		if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0)
505312a1df1SDavid du Colombier 		{	for (q = r->ival->name; *q; q++)
506312a1df1SDavid du Colombier 			{	if (*q == '\"')
507312a1df1SDavid du Colombier 					*q = ' ';
508312a1df1SDavid du Colombier 				if (*q == '\\')
509312a1df1SDavid du Colombier 					*q++ = ' '; /* skip over the next */
510312a1df1SDavid du Colombier 			}
511*de2caf28SDavid du Colombier 			p = jump_etc(r);	/* e.g., "int **q" */
512312a1df1SDavid du Colombier 			if (p)
513312a1df1SDavid du Colombier 			fprintf(fd, "	now.%s = %s;\n", p, r->ival->name);
514312a1df1SDavid du Colombier 
515312a1df1SDavid du Colombier 		} else
516312a1df1SDavid du Colombier 		if (strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0)
517312a1df1SDavid du Colombier 		{	for (q = r->ival->name; *q; q++)
518312a1df1SDavid du Colombier 			{	if (*q == '\"')
519312a1df1SDavid du Colombier 					*q = ' ';
520312a1df1SDavid du Colombier 				if (*q == '\\')
521312a1df1SDavid du Colombier 					*q++ = ' '; /* skip over the next */
522312a1df1SDavid du Colombier 			}
523*de2caf28SDavid du Colombier 			p = jump_etc(r);	/* e.g., "int **q" */
524312a1df1SDavid du Colombier 			if (p)
525312a1df1SDavid du Colombier 			fprintf(fd, "	%s = %s;\n", p, r->ival->name);	/* no now. prefix */
526312a1df1SDavid du Colombier 
527312a1df1SDavid du Colombier 	}	}
528312a1df1SDavid du Colombier 	fprintf(fd, "}\n");
529312a1df1SDavid du Colombier }
530312a1df1SDavid du Colombier 
531312a1df1SDavid du Colombier void
c_add_locinit(FILE * fd,int tpnr,char * pnm)532312a1df1SDavid du Colombier c_add_locinit(FILE *fd, int tpnr, char *pnm)
533312a1df1SDavid du Colombier {	C_Added *r;
534312a1df1SDavid du Colombier 	char *p, *q, *s;
535312a1df1SDavid du Colombier 	int frst = 1;
536312a1df1SDavid du Colombier 
537312a1df1SDavid du Colombier 	fprintf(fd, "void\nlocinit%d(int h)\n{\n", tpnr);
538312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)
539312a1df1SDavid du Colombier 		if (r->ival != ZS
540312a1df1SDavid du Colombier 		&&  strncmp(r->t->name, " Local", strlen(" Local")) == 0)
541312a1df1SDavid du Colombier 		{	for (q = r->ival->name; *q; q++)
542312a1df1SDavid du Colombier 				if (*q == '\"')
543312a1df1SDavid du Colombier 					*q = ' ';
544*de2caf28SDavid du Colombier 			p = jump_etc(r);	/* e.g., "int **q" */
545312a1df1SDavid du Colombier 
546312a1df1SDavid du Colombier 			q = r->t->name + strlen(" Local");
547312a1df1SDavid du Colombier 			while (*q == ' ' || *q == '\t')
548312a1df1SDavid du Colombier 				q++;			/* process name */
549312a1df1SDavid du Colombier 
550312a1df1SDavid du Colombier 			s = (char *) emalloc(strlen(q)+1);
551312a1df1SDavid du Colombier 			strcpy(s, q);
552312a1df1SDavid du Colombier 
553312a1df1SDavid du Colombier 			q = &s[strlen(s)-1];
554312a1df1SDavid du Colombier 			while (*q == ' ' || *q == '\t')
555312a1df1SDavid du Colombier 				*q-- = '\0';
556312a1df1SDavid du Colombier 
557312a1df1SDavid du Colombier 			if (strcmp(pnm, s) != 0)
558312a1df1SDavid du Colombier 				continue;
559312a1df1SDavid du Colombier 
560312a1df1SDavid du Colombier 			if (frst)
561*de2caf28SDavid du Colombier 			{	fprintf(fd, "\tuchar *_this = pptr(h);\n");
562312a1df1SDavid du Colombier 				frst = 0;
563312a1df1SDavid du Colombier 			}
564312a1df1SDavid du Colombier 
565312a1df1SDavid du Colombier 			if (p)
566*de2caf28SDavid du Colombier 			{	fprintf(fd, "\t\t((P%d *)_this)->%s = %s;\n",
567312a1df1SDavid du Colombier 					tpnr, p, r->ival->name);
568*de2caf28SDavid du Colombier 			}
569312a1df1SDavid du Colombier 		}
570312a1df1SDavid du Colombier 	fprintf(fd, "}\n");
571312a1df1SDavid du Colombier }
572312a1df1SDavid du Colombier 
573312a1df1SDavid du Colombier /* tracking:
574312a1df1SDavid du Colombier 	1. for non-global and non-local c_state decls: add up all the sizes in c_added
575312a1df1SDavid du Colombier 	2. add a global char array of that size into now
576312a1df1SDavid du Colombier 	3. generate a routine that memcpy's the required values into that array
577312a1df1SDavid du Colombier 	4. generate a call to that routine
578312a1df1SDavid du Colombier  */
579312a1df1SDavid du Colombier 
580312a1df1SDavid du Colombier void
c_preview(void)581312a1df1SDavid du Colombier c_preview(void)
582312a1df1SDavid du Colombier {	C_Added *r;
583312a1df1SDavid du Colombier 
584312a1df1SDavid du Colombier 	hastrack = 0;
585312a1df1SDavid du Colombier 	if (c_tracked)
586312a1df1SDavid du Colombier 		hastrack = 1;
587312a1df1SDavid du Colombier 	else
588312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)
589312a1df1SDavid du Colombier 		if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0
590312a1df1SDavid du Colombier 		&&  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0
591312a1df1SDavid du Colombier 		&&  strncmp(r->t->name, " Local",  strlen(" Local"))  != 0)
592312a1df1SDavid du Colombier 		{	hastrack = 1;	/* c_state variant now obsolete */
593312a1df1SDavid du Colombier 			break;
594312a1df1SDavid du Colombier 		}
595312a1df1SDavid du Colombier }
596312a1df1SDavid du Colombier 
597312a1df1SDavid du Colombier int
c_add_sv(FILE * fd)598312a1df1SDavid du Colombier c_add_sv(FILE *fd)	/* 1+2 -- called in pangen1.c */
599312a1df1SDavid du Colombier {	C_Added *r;
600312a1df1SDavid du Colombier 	int cnt = 0;
601312a1df1SDavid du Colombier 
602312a1df1SDavid du Colombier 	if (!c_added && !c_tracked) return 0;
603312a1df1SDavid du Colombier 
604312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)	/* pickup global decls */
605312a1df1SDavid du Colombier 		if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0)
606312a1df1SDavid du Colombier 			fprintf(fd, "	%s;\n", r->s->name);
607312a1df1SDavid du Colombier 
608312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)
609312a1df1SDavid du Colombier 		if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0
610312a1df1SDavid du Colombier 		&&  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0
611312a1df1SDavid du Colombier 		&&  strncmp(r->t->name, " Local",  strlen(" Local"))  != 0)
612312a1df1SDavid du Colombier 		{	cnt++;	/* obsolete use */
613312a1df1SDavid du Colombier 		}
614312a1df1SDavid du Colombier 
615312a1df1SDavid du Colombier 	for (r = c_tracked; r; r = r->nxt)
616312a1df1SDavid du Colombier 		cnt++;		/* preferred use */
617312a1df1SDavid du Colombier 
618312a1df1SDavid du Colombier 	if (cnt == 0) return 0;
619312a1df1SDavid du Colombier 
620312a1df1SDavid du Colombier 	cnt = 0;
621312a1df1SDavid du Colombier 	fprintf(fd, "	uchar c_state[");
622312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)
623312a1df1SDavid du Colombier 		if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0
624312a1df1SDavid du Colombier 		&&  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0
625312a1df1SDavid du Colombier 		&&  strncmp(r->t->name, " Local",  strlen(" Local"))  != 0)
626312a1df1SDavid du Colombier 		{	fprintf(fd, "%ssizeof(%s)",
627312a1df1SDavid du Colombier 				(cnt==0)?"":"+", r->t->name);
628312a1df1SDavid du Colombier 			cnt++;
629312a1df1SDavid du Colombier 		}
630312a1df1SDavid du Colombier 
631312a1df1SDavid du Colombier 	for (r = c_tracked; r; r = r->nxt)
632312a1df1SDavid du Colombier 	{	if (r->ival != ZS) continue;
633312a1df1SDavid du Colombier 
634312a1df1SDavid du Colombier 		fprintf(fd, "%s%s",
635312a1df1SDavid du Colombier 			(cnt==0)?"":"+", r->t->name);
636312a1df1SDavid du Colombier 		cnt++;
637312a1df1SDavid du Colombier 	}
638312a1df1SDavid du Colombier 
639312a1df1SDavid du Colombier 	if (cnt == 0) fprintf(fd, "4");	/* now redundant */
640312a1df1SDavid du Colombier 	fprintf(fd, "];\n");
641312a1df1SDavid du Colombier 	return 1;
642312a1df1SDavid du Colombier }
643312a1df1SDavid du Colombier 
644312a1df1SDavid du Colombier void
c_stack_size(FILE * fd)64500d97012SDavid du Colombier c_stack_size(FILE *fd)
64600d97012SDavid du Colombier {	C_Added *r;
64700d97012SDavid du Colombier 	int cnt = 0;
64800d97012SDavid du Colombier 
64900d97012SDavid du Colombier 	for (r = c_tracked; r; r = r->nxt)
65000d97012SDavid du Colombier 		if (r->ival != ZS)
65100d97012SDavid du Colombier 		{	fprintf(fd, "%s%s",
65200d97012SDavid du Colombier 				(cnt==0)?"":"+", r->t->name);
65300d97012SDavid du Colombier 			cnt++;
65400d97012SDavid du Colombier 		}
65500d97012SDavid du Colombier 	if (cnt == 0)
65600d97012SDavid du Colombier 	{	fprintf(fd, "WS");
65700d97012SDavid du Colombier 	}
65800d97012SDavid du Colombier }
65900d97012SDavid du Colombier 
66000d97012SDavid du Colombier void
c_add_stack(FILE * fd)661312a1df1SDavid du Colombier c_add_stack(FILE *fd)
662312a1df1SDavid du Colombier {	C_Added *r;
663312a1df1SDavid du Colombier 	int cnt = 0;
664312a1df1SDavid du Colombier 
66500d97012SDavid du Colombier 	if ((!c_added && !c_tracked) || !has_stack)
66600d97012SDavid du Colombier 	{	return;
66700d97012SDavid du Colombier 	}
668312a1df1SDavid du Colombier 
669312a1df1SDavid du Colombier 	for (r = c_tracked; r; r = r->nxt)
670312a1df1SDavid du Colombier 		if (r->ival != ZS)
67100d97012SDavid du Colombier 		{	cnt++;
672312a1df1SDavid du Colombier 		}
673312a1df1SDavid du Colombier 
67400d97012SDavid du Colombier 	if (cnt > 0)
67500d97012SDavid du Colombier 	{	fprintf(fd, "	uchar c_stack[StackSize];\n");
67600d97012SDavid du Colombier 	}
677312a1df1SDavid du Colombier }
678312a1df1SDavid du Colombier 
679312a1df1SDavid du Colombier void
c_add_hidden(FILE * fd)680312a1df1SDavid du Colombier c_add_hidden(FILE *fd)
681312a1df1SDavid du Colombier {	C_Added *r;
682312a1df1SDavid du Colombier 
683312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)	/* pickup hidden decls */
684312a1df1SDavid du Colombier 		if (strncmp(r->t->name, "\"Hidden\"", strlen("\"Hidden\"")) == 0)
685312a1df1SDavid du Colombier 		{	r->s->name[strlen(r->s->name)-1] = ' ';
686312a1df1SDavid du Colombier 			fprintf(fd, "%s;	/* Hidden */\n", &r->s->name[1]);
687312a1df1SDavid du Colombier 			r->s->name[strlen(r->s->name)-1] = '"';
688312a1df1SDavid du Colombier 		}
689312a1df1SDavid du Colombier 	/* called before c_add_def - quotes are still there */
690312a1df1SDavid du Colombier }
691312a1df1SDavid du Colombier 
692312a1df1SDavid du Colombier void
c_add_loc(FILE * fd,char * s)693312a1df1SDavid du Colombier c_add_loc(FILE *fd, char *s)	/* state vector entries for proctype s */
694312a1df1SDavid du Colombier {	C_Added *r;
695312a1df1SDavid du Colombier 	static char buf[1024];
696312a1df1SDavid du Colombier 	char *p;
697312a1df1SDavid du Colombier 
698312a1df1SDavid du Colombier 	if (!c_added) return;
699312a1df1SDavid du Colombier 
700312a1df1SDavid du Colombier 	strcpy(buf, s);
701312a1df1SDavid du Colombier 	strcat(buf, " ");
702312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)	/* pickup local decls */
703*de2caf28SDavid du Colombier 	{	if (strncmp(r->t->name, " Local", strlen(" Local")) == 0)
704312a1df1SDavid du Colombier 		{	p = r->t->name + strlen(" Local");
705*de2caf28SDavid du Colombier fprintf(fd, "/* XXX p=<%s>, s=<%s>, buf=<%s> r->s->name=<%s>XXX */\n", p, s, buf, r->s->name);
706312a1df1SDavid du Colombier 			while (*p == ' ' || *p == '\t')
707*de2caf28SDavid du Colombier 			{	p++;
708312a1df1SDavid du Colombier 			}
709*de2caf28SDavid du Colombier 			if (strcmp(p, buf) == 0
710*de2caf28SDavid du Colombier 			||  (strncmp(p, "init", 4) == 0 && strncmp(buf, ":init:", 6) == 0))
711*de2caf28SDavid du Colombier 			{	fprintf(fd, "	%s;\n", r->s->name);
712*de2caf28SDavid du Colombier 	}	}	}
713312a1df1SDavid du Colombier }
714312a1df1SDavid du Colombier void
c_add_def(FILE * fd)715312a1df1SDavid du Colombier c_add_def(FILE *fd)	/* 3 - called in plunk_c_fcts() */
716312a1df1SDavid du Colombier {	C_Added *r;
717312a1df1SDavid du Colombier 
718*de2caf28SDavid du Colombier 	fprintf(fd, "#if defined(C_States) && (HAS_TRACK==1)\n");
719312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)
720312a1df1SDavid du Colombier 	{	r->s->name[strlen(r->s->name)-1] = ' ';
721312a1df1SDavid du Colombier 		r->s->name[0] = ' '; /* remove the "s */
722312a1df1SDavid du Colombier 
723312a1df1SDavid du Colombier 		r->t->name[strlen(r->t->name)-1] = ' ';
724312a1df1SDavid du Colombier 		r->t->name[0] = ' ';
725312a1df1SDavid du Colombier 
726312a1df1SDavid du Colombier 		if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
727312a1df1SDavid du Colombier 		||  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0
728312a1df1SDavid du Colombier 		||  strncmp(r->t->name, " Local",  strlen(" Local"))  == 0)
729312a1df1SDavid du Colombier 			continue;
730312a1df1SDavid du Colombier 
731312a1df1SDavid du Colombier 		if (strchr(r->s->name, '&'))
732312a1df1SDavid du Colombier 			fatal("dereferencing state object: %s", r->s->name);
733312a1df1SDavid du Colombier 
734312a1df1SDavid du Colombier 		fprintf(fd, "extern %s %s;\n", r->t->name, r->s->name);
735312a1df1SDavid du Colombier 	}
736312a1df1SDavid du Colombier 	for (r = c_tracked; r; r = r->nxt)
737312a1df1SDavid du Colombier 	{	r->s->name[strlen(r->s->name)-1] = ' ';
738312a1df1SDavid du Colombier 		r->s->name[0] = ' '; /* remove " */
739312a1df1SDavid du Colombier 
740312a1df1SDavid du Colombier 		r->t->name[strlen(r->t->name)-1] = ' ';
741312a1df1SDavid du Colombier 		r->t->name[0] = ' ';
742312a1df1SDavid du Colombier 	}
743312a1df1SDavid du Colombier 
744312a1df1SDavid du Colombier 	if (separate == 2)
745312a1df1SDavid du Colombier 	{	fprintf(fd, "#endif\n");
746312a1df1SDavid du Colombier 		return;
747312a1df1SDavid du Colombier 	}
748312a1df1SDavid du Colombier 
749312a1df1SDavid du Colombier 	if (has_stack)
75000d97012SDavid du Colombier 	{	fprintf(fd, "int cpu_printf(const char *, ...);\n");
75100d97012SDavid du Colombier 		fprintf(fd, "void\nc_stack(uchar *p_t_r)\n{\n");
752312a1df1SDavid du Colombier 		fprintf(fd, "#ifdef VERBOSE\n");
75300d97012SDavid du Colombier 		fprintf(fd, "	cpu_printf(\"c_stack %%u\\n\", p_t_r);\n");
754312a1df1SDavid du Colombier 		fprintf(fd, "#endif\n");
755312a1df1SDavid du Colombier 		for (r = c_tracked; r; r = r->nxt)
756312a1df1SDavid du Colombier 		{	if (r->ival == ZS) continue;
757312a1df1SDavid du Colombier 
758312a1df1SDavid du Colombier 			fprintf(fd, "\tif(%s)\n", r->s->name);
759312a1df1SDavid du Colombier 			fprintf(fd, "\t\tmemcpy(p_t_r, %s, %s);\n",
760312a1df1SDavid du Colombier 				r->s->name, r->t->name);
761312a1df1SDavid du Colombier 			fprintf(fd, "\telse\n");
762312a1df1SDavid du Colombier 			fprintf(fd, "\t\tmemset(p_t_r, 0, %s);\n",
763312a1df1SDavid du Colombier 				r->t->name);
764312a1df1SDavid du Colombier 			fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
765312a1df1SDavid du Colombier 		}
766312a1df1SDavid du Colombier 		fprintf(fd, "}\n\n");
767312a1df1SDavid du Colombier 	}
768312a1df1SDavid du Colombier 
769f3793cddSDavid du Colombier 	fprintf(fd, "void\nc_update(uchar *p_t_r)\n{\n");
770312a1df1SDavid du Colombier 	fprintf(fd, "#ifdef VERBOSE\n");
771*de2caf28SDavid du Colombier 	fprintf(fd, "	printf(\"c_update %%p\\n\", p_t_r);\n");
772312a1df1SDavid du Colombier 	fprintf(fd, "#endif\n");
773312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)
774312a1df1SDavid du Colombier 	{	if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
775312a1df1SDavid du Colombier 		||  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0
776312a1df1SDavid du Colombier 		||  strncmp(r->t->name, " Local",  strlen(" Local"))  == 0)
777312a1df1SDavid du Colombier 			continue;
778312a1df1SDavid du Colombier 
779312a1df1SDavid du Colombier 		fprintf(fd, "\tmemcpy(p_t_r, &%s, sizeof(%s));\n",
780312a1df1SDavid du Colombier 			r->s->name, r->t->name);
781312a1df1SDavid du Colombier 		fprintf(fd, "\tp_t_r += sizeof(%s);\n", r->t->name);
782312a1df1SDavid du Colombier 	}
783312a1df1SDavid du Colombier 
784312a1df1SDavid du Colombier 	for (r = c_tracked; r; r = r->nxt)
785312a1df1SDavid du Colombier 	{	if (r->ival) continue;
786312a1df1SDavid du Colombier 
787312a1df1SDavid du Colombier 		fprintf(fd, "\tif(%s)\n", r->s->name);
788312a1df1SDavid du Colombier 		fprintf(fd, "\t\tmemcpy(p_t_r, %s, %s);\n",
789312a1df1SDavid du Colombier 			r->s->name, r->t->name);
790312a1df1SDavid du Colombier 		fprintf(fd, "\telse\n");
791312a1df1SDavid du Colombier 		fprintf(fd, "\t\tmemset(p_t_r, 0, %s);\n",
792312a1df1SDavid du Colombier 			r->t->name);
793312a1df1SDavid du Colombier 		fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
794312a1df1SDavid du Colombier 	}
795312a1df1SDavid du Colombier 
796312a1df1SDavid du Colombier 	fprintf(fd, "}\n");
797312a1df1SDavid du Colombier 
798312a1df1SDavid du Colombier 	if (has_stack)
799f3793cddSDavid du Colombier 	{	fprintf(fd, "void\nc_unstack(uchar *p_t_r)\n{\n");
800312a1df1SDavid du Colombier 		fprintf(fd, "#ifdef VERBOSE\n");
80100d97012SDavid du Colombier 		fprintf(fd, "	cpu_printf(\"c_unstack %%u\\n\", p_t_r);\n");
802312a1df1SDavid du Colombier 		fprintf(fd, "#endif\n");
803312a1df1SDavid du Colombier 		for (r = c_tracked; r; r = r->nxt)
804312a1df1SDavid du Colombier 		{	if (r->ival == ZS) continue;
805312a1df1SDavid du Colombier 
806312a1df1SDavid du Colombier 			fprintf(fd, "\tif(%s)\n", r->s->name);
807312a1df1SDavid du Colombier 			fprintf(fd, "\t\tmemcpy(%s, p_t_r, %s);\n",
808312a1df1SDavid du Colombier 				r->s->name, r->t->name);
809312a1df1SDavid du Colombier 			fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
810312a1df1SDavid du Colombier 		}
811312a1df1SDavid du Colombier 		fprintf(fd, "}\n");
812312a1df1SDavid du Colombier 	}
813312a1df1SDavid du Colombier 
814f3793cddSDavid du Colombier 	fprintf(fd, "void\nc_revert(uchar *p_t_r)\n{\n");
815312a1df1SDavid du Colombier 	fprintf(fd, "#ifdef VERBOSE\n");
816*de2caf28SDavid du Colombier 	fprintf(fd, "	printf(\"c_revert %%p\\n\", p_t_r);\n");
817312a1df1SDavid du Colombier 	fprintf(fd, "#endif\n");
818312a1df1SDavid du Colombier 	for (r = c_added; r; r = r->nxt)
819312a1df1SDavid du Colombier 	{	if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
820312a1df1SDavid du Colombier 		||  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0
821312a1df1SDavid du Colombier 		||  strncmp(r->t->name, " Local",  strlen(" Local"))  == 0)
822312a1df1SDavid du Colombier 			continue;
823312a1df1SDavid du Colombier 
824312a1df1SDavid du Colombier 		fprintf(fd, "\tmemcpy(&%s, p_t_r, sizeof(%s));\n",
825312a1df1SDavid du Colombier 			r->s->name, r->t->name);
826312a1df1SDavid du Colombier 		fprintf(fd, "\tp_t_r += sizeof(%s);\n", r->t->name);
827312a1df1SDavid du Colombier 	}
828312a1df1SDavid du Colombier 	for (r = c_tracked; r; r = r->nxt)
829312a1df1SDavid du Colombier 	{	if (r->ival != ZS) continue;
830312a1df1SDavid du Colombier 
831312a1df1SDavid du Colombier 		fprintf(fd, "\tif(%s)\n", r->s->name);
832312a1df1SDavid du Colombier 		fprintf(fd, "\t\tmemcpy(%s, p_t_r, %s);\n",
833312a1df1SDavid du Colombier 			r->s->name, r->t->name);
834312a1df1SDavid du Colombier 		fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
835312a1df1SDavid du Colombier 	}
836312a1df1SDavid du Colombier 
837312a1df1SDavid du Colombier 	fprintf(fd, "}\n");
838312a1df1SDavid du Colombier 	fprintf(fd, "#endif\n");
839312a1df1SDavid du Colombier }
840312a1df1SDavid du Colombier 
841312a1df1SDavid du Colombier void
plunk_reverse(FILE * fd,IType * p,int matchthis)842312a1df1SDavid du Colombier plunk_reverse(FILE *fd, IType *p, int matchthis)
843312a1df1SDavid du Colombier {	char *y, *z;
844312a1df1SDavid du Colombier 
845312a1df1SDavid du Colombier 	if (!p) return;
846312a1df1SDavid du Colombier 	plunk_reverse(fd, p->nxt, matchthis);
847312a1df1SDavid du Colombier 
848312a1df1SDavid du Colombier 	if (!p->nm->context
849*de2caf28SDavid du Colombier 	&&   p->nm->type == matchthis
850*de2caf28SDavid du Colombier 	&&   p->is_expr == 0)
851312a1df1SDavid du Colombier 	{	fprintf(fd, "\n/* start of %s */\n", p->nm->name);
852312a1df1SDavid du Colombier 		z = (char *) p->cn;
853312a1df1SDavid du Colombier 		while (*z == '\n' || *z == '\r' || *z == '\\')
854*de2caf28SDavid du Colombier 		{	z++;
855*de2caf28SDavid du Colombier 		}
856312a1df1SDavid du Colombier 		/* e.g.: \#include "..." */
857312a1df1SDavid du Colombier 
858312a1df1SDavid du Colombier 		y = z;
859312a1df1SDavid du Colombier 		while ((y = strstr(y, "\\#")) != NULL)
860312a1df1SDavid du Colombier 		{	*y = '\n'; y++;
861312a1df1SDavid du Colombier 		}
862312a1df1SDavid du Colombier 
863312a1df1SDavid du Colombier 		fprintf(fd, "%s\n", z);
864312a1df1SDavid du Colombier 		fprintf(fd, "\n/* end of %s */\n", p->nm->name);
865312a1df1SDavid du Colombier 	}
866312a1df1SDavid du Colombier }
867312a1df1SDavid du Colombier 
868312a1df1SDavid du Colombier void
plunk_c_decls(FILE * fd)869312a1df1SDavid du Colombier plunk_c_decls(FILE *fd)
870312a1df1SDavid du Colombier {
871312a1df1SDavid du Colombier 	plunk_reverse(fd, seqnames, CODE_DECL);
872312a1df1SDavid du Colombier }
873312a1df1SDavid du Colombier 
874312a1df1SDavid du Colombier void
plunk_c_fcts(FILE * fd)875312a1df1SDavid du Colombier plunk_c_fcts(FILE *fd)
876312a1df1SDavid du Colombier {
877312a1df1SDavid du Colombier 	if (separate == 2 && hastrack)
878312a1df1SDavid du Colombier 	{	c_add_def(fd);
879312a1df1SDavid du Colombier 		return;
880312a1df1SDavid du Colombier 	}
881312a1df1SDavid du Colombier 
882312a1df1SDavid du Colombier 	c_add_hidden(fd);
883312a1df1SDavid du Colombier 	plunk_reverse(fd, seqnames, CODE_FRAG);
884312a1df1SDavid du Colombier 
885312a1df1SDavid du Colombier 	if (c_added || c_tracked)	/* enables calls to c_revert and c_update */
886312a1df1SDavid du Colombier 		fprintf(fd, "#define C_States	1\n");
887312a1df1SDavid du Colombier 	else
888312a1df1SDavid du Colombier 		fprintf(fd, "#undef C_States\n");
889312a1df1SDavid du Colombier 
890312a1df1SDavid du Colombier 	if (hastrack)
891312a1df1SDavid du Colombier 		c_add_def(fd);
892312a1df1SDavid du Colombier 
893312a1df1SDavid du Colombier 	c_add_globinit(fd);
894312a1df1SDavid du Colombier 	do_locinits(fd);
895312a1df1SDavid du Colombier }
896312a1df1SDavid du Colombier 
897312a1df1SDavid du Colombier static void
check_inline(IType * tmp)898312a1df1SDavid du Colombier check_inline(IType *tmp)
899312a1df1SDavid du Colombier {	char buf[128];
900312a1df1SDavid du Colombier 	ProcList *p;
901312a1df1SDavid du Colombier 
902*de2caf28SDavid du Colombier 	if (!X_lst) return;
903312a1df1SDavid du Colombier 
904*de2caf28SDavid du Colombier 	for (p = ready; p; p = p->nxt)
905*de2caf28SDavid du Colombier 	{	if (strcmp(p->n->name, X_lst->n->name) == 0)
906312a1df1SDavid du Colombier 			continue;
907312a1df1SDavid du Colombier 		sprintf(buf, "P%s->", p->n->name);
908312a1df1SDavid du Colombier 		if (strstr((char *)tmp->cn, buf))
909312a1df1SDavid du Colombier 		{	printf("spin: in proctype %s, ref to object in proctype %s\n",
910*de2caf28SDavid du Colombier 				X_lst->n->name, p->n->name);
911312a1df1SDavid du Colombier 			fatal("invalid variable ref in '%s'", tmp->nm->name);
912312a1df1SDavid du Colombier 	}	}
913312a1df1SDavid du Colombier }
914312a1df1SDavid du Colombier 
915*de2caf28SDavid du Colombier extern short terse;
916*de2caf28SDavid du Colombier extern short nocast;
917*de2caf28SDavid du Colombier 
918312a1df1SDavid du Colombier void
plunk_expr(FILE * fd,char * s)919312a1df1SDavid du Colombier plunk_expr(FILE *fd, char *s)
920312a1df1SDavid du Colombier {	IType *tmp;
921*de2caf28SDavid du Colombier 	char *q;
922312a1df1SDavid du Colombier 
923312a1df1SDavid du Colombier 	tmp = find_inline(s);
924312a1df1SDavid du Colombier 	check_inline(tmp);
925312a1df1SDavid du Colombier 
926*de2caf28SDavid du Colombier 	if (terse && nocast)
927*de2caf28SDavid du Colombier 	{	for (q = (char *) tmp->cn; q && *q != '\0'; q++)
928*de2caf28SDavid du Colombier 		{	fflush(fd);
929*de2caf28SDavid du Colombier 			if (*q == '"')
930*de2caf28SDavid du Colombier 			{	fprintf(fd, "\\");
931*de2caf28SDavid du Colombier 			}
932*de2caf28SDavid du Colombier 			fprintf(fd, "%c", *q);
933*de2caf28SDavid du Colombier 		}
934*de2caf28SDavid du Colombier 	} else
935*de2caf28SDavid du Colombier 	{	fprintf(fd, "%s", (char *) tmp->cn);
936*de2caf28SDavid du Colombier 	}
937312a1df1SDavid du Colombier }
938312a1df1SDavid du Colombier 
939312a1df1SDavid du Colombier void
preruse(FILE * fd,Lextok * n)940312a1df1SDavid du Colombier preruse(FILE *fd, Lextok *n)	/* check a condition for c_expr with preconditions */
941312a1df1SDavid du Colombier {	IType *tmp;
942312a1df1SDavid du Colombier 
943312a1df1SDavid du Colombier 	if (!n) return;
944312a1df1SDavid du Colombier 	if (n->ntyp == C_EXPR)
945312a1df1SDavid du Colombier 	{	tmp = find_inline(n->sym->name);
946312a1df1SDavid du Colombier 		if (tmp->prec)
947312a1df1SDavid du Colombier 		{	fprintf(fd, "if (!(%s)) { if (!readtrail) { depth++; ", tmp->prec);
948*de2caf28SDavid du Colombier 			fprintf(fd, "trpt++; trpt->pr = II; trpt->o_t = t; trpt->st = tt; ");
949*de2caf28SDavid du Colombier 			fprintf(fd, "uerror(\"c_expr line %d precondition false: %s\"); continue;",
950*de2caf28SDavid du Colombier 				tmp->dln, tmp->prec);
951*de2caf28SDavid du Colombier 			fprintf(fd, " } else { printf(\"pan: precondition false: %s\\n\"); ",
952*de2caf28SDavid du Colombier 				tmp->prec);
953312a1df1SDavid du Colombier 			fprintf(fd, "_m = 3; goto P999; } } \n\t\t");
954312a1df1SDavid du Colombier 		}
955312a1df1SDavid du Colombier 	} else
956312a1df1SDavid du Colombier 	{	preruse(fd, n->rgt);
957312a1df1SDavid du Colombier 		preruse(fd, n->lft);
958312a1df1SDavid du Colombier 	}
959312a1df1SDavid du Colombier }
960312a1df1SDavid du Colombier 
961312a1df1SDavid du Colombier int
glob_inline(char * s)962312a1df1SDavid du Colombier glob_inline(char *s)
963312a1df1SDavid du Colombier {	IType *tmp;
964312a1df1SDavid du Colombier 	char *bdy;
965312a1df1SDavid du Colombier 
966312a1df1SDavid du Colombier 	tmp = find_inline(s);
967312a1df1SDavid du Colombier 	bdy = (char *) tmp->cn;
968312a1df1SDavid du Colombier 	return (strstr(bdy, "now.")		/* global ref or   */
969312a1df1SDavid du Colombier 	||      strchr(bdy, '(') > bdy);	/* possible C-function call */
970312a1df1SDavid du Colombier }
971312a1df1SDavid du Colombier 
972*de2caf28SDavid du Colombier char *
put_inline(FILE * fd,char * s)973*de2caf28SDavid du Colombier put_inline(FILE *fd, char *s)
974*de2caf28SDavid du Colombier {	IType *tmp;
975*de2caf28SDavid du Colombier 
976*de2caf28SDavid du Colombier 	tmp = find_inline(s);
977*de2caf28SDavid du Colombier 	check_inline(tmp);
978*de2caf28SDavid du Colombier 	return (char *) tmp->cn;
979*de2caf28SDavid du Colombier }
980*de2caf28SDavid du Colombier 
981*de2caf28SDavid du Colombier void
mark_last(void)982*de2caf28SDavid du Colombier mark_last(void)
983*de2caf28SDavid du Colombier {
984*de2caf28SDavid du Colombier 	if (seqnames)
985*de2caf28SDavid du Colombier 	{	seqnames->is_expr = 1;
986*de2caf28SDavid du Colombier 	}
987*de2caf28SDavid du Colombier }
988*de2caf28SDavid du Colombier 
989312a1df1SDavid du Colombier void
plunk_inline(FILE * fd,char * s,int how,int gencode)99000d97012SDavid du Colombier plunk_inline(FILE *fd, char *s, int how, int gencode)	/* c_code with precondition */
991312a1df1SDavid du Colombier {	IType *tmp;
992312a1df1SDavid du Colombier 
993312a1df1SDavid du Colombier 	tmp = find_inline(s);
994312a1df1SDavid du Colombier 	check_inline(tmp);
995312a1df1SDavid du Colombier 
996312a1df1SDavid du Colombier 	fprintf(fd, "{ ");
997312a1df1SDavid du Colombier 	if (how && tmp->prec)
99800d97012SDavid du Colombier 	{	fprintf(fd, "if (!(%s)) { if (!readtrail) {",
99900d97012SDavid du Colombier 			tmp->prec);
1000*de2caf28SDavid du Colombier 		fprintf(fd, " uerror(\"c_code line %d precondition false: %s\"); continue; ",
1001*de2caf28SDavid du Colombier 			tmp->dln,
100200d97012SDavid du Colombier 			tmp->prec);
100300d97012SDavid du Colombier 		fprintf(fd, "} else { ");
100400d97012SDavid du Colombier 		fprintf(fd, "printf(\"pan: precondition false: %s\\n\"); _m = 3; goto P999; } } ",
100500d97012SDavid du Colombier 			tmp->prec);
1006312a1df1SDavid du Colombier 	}
100700d97012SDavid du Colombier 
100800d97012SDavid du Colombier 	if (!gencode)	/* not in d_step */
100900d97012SDavid du Colombier 	{	fprintf(fd, "\n\t\tsv_save();");
101000d97012SDavid du Colombier 	}
101100d97012SDavid du Colombier 
1012312a1df1SDavid du Colombier 	fprintf(fd, "%s", (char *) tmp->cn);
1013312a1df1SDavid du Colombier 	fprintf(fd, " }\n");
1014312a1df1SDavid du Colombier }
1015312a1df1SDavid du Colombier 
1016*de2caf28SDavid du Colombier int
side_scan(char * t,char * pat)1017*de2caf28SDavid du Colombier side_scan(char *t, char *pat)
1018*de2caf28SDavid du Colombier {	char *r = strstr(t, pat);
1019*de2caf28SDavid du Colombier 	return (r
1020*de2caf28SDavid du Colombier 		&& *(r-1) != '"'
1021*de2caf28SDavid du Colombier 		&& *(r-1) != '\'');
1022*de2caf28SDavid du Colombier }
1023*de2caf28SDavid du Colombier 
1024312a1df1SDavid du Colombier void
no_side_effects(char * s)1025312a1df1SDavid du Colombier no_side_effects(char *s)
1026312a1df1SDavid du Colombier {	IType *tmp;
1027312a1df1SDavid du Colombier 	char *t;
1028*de2caf28SDavid du Colombier 	char *z;
1029312a1df1SDavid du Colombier 
1030312a1df1SDavid du Colombier 	/* could still defeat this check via hidden
1031312a1df1SDavid du Colombier 	 * side effects in function calls,
1032312a1df1SDavid du Colombier 	 * but this will catch at least some cases
1033312a1df1SDavid du Colombier 	 */
1034312a1df1SDavid du Colombier 
1035312a1df1SDavid du Colombier 	tmp = find_inline(s);
1036312a1df1SDavid du Colombier 	t = (char *) tmp->cn;
1037*de2caf28SDavid du Colombier 	while (t && *t == ' ')
1038*de2caf28SDavid du Colombier 	{	t++;
1039*de2caf28SDavid du Colombier 	}
1040312a1df1SDavid du Colombier 
1041*de2caf28SDavid du Colombier 	z = strchr(t, '(');
1042*de2caf28SDavid du Colombier 	if (z
1043*de2caf28SDavid du Colombier 	&&  z > t
1044*de2caf28SDavid du Colombier 	&&  isalnum((int) *(z-1))
1045*de2caf28SDavid du Colombier 	&&  strncmp(t, "spin_mutex_free(", strlen("spin_mutex_free(")) != 0)
1046*de2caf28SDavid du Colombier 	{	goto bad;	/* fct call */
1047*de2caf28SDavid du Colombier 	}
1048*de2caf28SDavid du Colombier 
1049*de2caf28SDavid du Colombier 	if (side_scan(t, ";")
1050*de2caf28SDavid du Colombier 	||  side_scan(t, "++")
1051*de2caf28SDavid du Colombier 	||  side_scan(t, "--"))
1052312a1df1SDavid du Colombier 	{
1053312a1df1SDavid du Colombier bad:		lineno = tmp->dln;
1054312a1df1SDavid du Colombier 		Fname = tmp->dfn;
1055312a1df1SDavid du Colombier 		non_fatal("c_expr %s has side-effects", s);
1056312a1df1SDavid du Colombier 		return;
1057312a1df1SDavid du Colombier 	}
1058312a1df1SDavid du Colombier 	while ((t = strchr(t, '=')) != NULL)
1059312a1df1SDavid du Colombier 	{	if (*(t-1) == '!'
1060312a1df1SDavid du Colombier 		||  *(t-1) == '>'
1061*de2caf28SDavid du Colombier 		||  *(t-1) == '<'
1062*de2caf28SDavid du Colombier 		||  *(t-1) == '"'
1063*de2caf28SDavid du Colombier 		||  *(t-1) == '\'')
1064*de2caf28SDavid du Colombier 		{	t += 2;
1065312a1df1SDavid du Colombier 			continue;
1066312a1df1SDavid du Colombier 		}
1067312a1df1SDavid du Colombier 		t++;
1068312a1df1SDavid du Colombier 		if (*t != '=')
1069312a1df1SDavid du Colombier 			goto bad;
1070312a1df1SDavid du Colombier 		t++;
1071312a1df1SDavid du Colombier 	}
1072312a1df1SDavid du Colombier }
1073312a1df1SDavid du Colombier 
10747dd7cddfSDavid du Colombier void
pickup_inline(Symbol * t,Lextok * apars,Lextok * rval)1075*de2caf28SDavid du Colombier pickup_inline(Symbol *t, Lextok *apars, Lextok *rval)
10767dd7cddfSDavid du Colombier {	IType *tmp; Lextok *p, *q; int j;
10777dd7cddfSDavid du Colombier 
1078312a1df1SDavid du Colombier 	tmp = find_inline(t->name);
10797dd7cddfSDavid du Colombier 
10807dd7cddfSDavid du Colombier 	if (++Inlining >= MAXINL)
108100d97012SDavid du Colombier 		fatal("inlines nested too deeply", 0);
10827dd7cddfSDavid du Colombier 	tmp->cln = lineno;	/* remember calling point */
10837dd7cddfSDavid du Colombier 	tmp->cfn = Fname;	/* and filename */
1084*de2caf28SDavid du Colombier 	tmp->rval = rval;
10857dd7cddfSDavid du Colombier 
10867dd7cddfSDavid du Colombier 	for (p = apars, q = tmp->params, j = 0; p && q; p = p->rgt, q = q->rgt)
10877dd7cddfSDavid du Colombier 		j++; /* count them */
10887dd7cddfSDavid du Colombier 	if (p || q)
10897dd7cddfSDavid du Colombier 		fatal("wrong nr of params on call of '%s'", t->name);
10907dd7cddfSDavid du Colombier 
10917dd7cddfSDavid du Colombier 	tmp->anms  = (char **) emalloc(j * sizeof(char *));
10927dd7cddfSDavid du Colombier 	for (p = apars, j = 0; p; p = p->rgt, j++)
109300d97012SDavid du Colombier 	{	tmp->anms[j] = (char *) emalloc(strlen(IArg_cont[j])+1);
10947dd7cddfSDavid du Colombier 		strcpy(tmp->anms[j], IArg_cont[j]);
10957dd7cddfSDavid du Colombier 	}
10967dd7cddfSDavid du Colombier 
10977dd7cddfSDavid du Colombier 	lineno = tmp->dln;	/* linenr of def */
10987dd7cddfSDavid du Colombier 	Fname = tmp->dfn;	/* filename of same */
10997dd7cddfSDavid du Colombier 	Inliner[Inlining] = (char *)tmp->cn;
11007dd7cddfSDavid du Colombier 	Inline_stub[Inlining] = tmp;
11017dd7cddfSDavid du Colombier #if 0
11027dd7cddfSDavid du Colombier 	if (verbose&32)
110300d97012SDavid du Colombier 	printf("spin: %s:%d, inlining '%s' (from %s:%d)\n",
110400d97012SDavid du Colombier 		tmp->cfn->name, tmp->cln, t->name, tmp->dfn->name, tmp->dln);
11057dd7cddfSDavid du Colombier #endif
11067dd7cddfSDavid du Colombier 	for (j = 0; j < Inlining; j++)
1107*de2caf28SDavid du Colombier 	{	if (Inline_stub[j] == Inline_stub[Inlining])
1108*de2caf28SDavid du Colombier 		{	fatal("cyclic inline attempt on: %s", t->name);
1109*de2caf28SDavid du Colombier 	}	}
1110*de2caf28SDavid du Colombier 	last_token = SEMI;	/* avoid insertion of extra semi */
11117dd7cddfSDavid du Colombier }
11127dd7cddfSDavid du Colombier 
1113*de2caf28SDavid du Colombier extern int pp_mode;
1114*de2caf28SDavid du Colombier 
11157dd7cddfSDavid du Colombier static void
do_directive(int first)1116312a1df1SDavid du Colombier do_directive(int first)
11177dd7cddfSDavid du Colombier {	int c = first;	/* handles lines starting with pound */
11187dd7cddfSDavid du Colombier 
11197dd7cddfSDavid du Colombier 	getword(c, isalpha_);
11207dd7cddfSDavid du Colombier 
1121312a1df1SDavid du Colombier 	if (strcmp(yytext, "#ident") == 0)
1122312a1df1SDavid du Colombier 		goto done;
1123312a1df1SDavid du Colombier 
11247dd7cddfSDavid du Colombier 	if ((c = Getchar()) != ' ')
11257dd7cddfSDavid du Colombier 		fatal("malformed preprocessor directive - # .", 0);
11267dd7cddfSDavid du Colombier 
11277dd7cddfSDavid du Colombier 	if (!isdigit_(c = Getchar()))
11287dd7cddfSDavid du Colombier 		fatal("malformed preprocessor directive - # .lineno", 0);
11297dd7cddfSDavid du Colombier 
11307dd7cddfSDavid du Colombier 	getword(c, isdigit_);
11317dd7cddfSDavid du Colombier 	lineno = atoi(yytext);	/* pickup the line number */
11327dd7cddfSDavid du Colombier 
11337dd7cddfSDavid du Colombier 	if ((c = Getchar()) == '\n')
11347dd7cddfSDavid du Colombier 		return;	/* no filename */
11357dd7cddfSDavid du Colombier 
11367dd7cddfSDavid du Colombier 	if (c != ' ')
11377dd7cddfSDavid du Colombier 		fatal("malformed preprocessor directive - .fname", 0);
11387dd7cddfSDavid du Colombier 
11397dd7cddfSDavid du Colombier 	if ((c = Getchar()) != '\"')
114000d97012SDavid du Colombier 	{	printf("got %c, expected \" -- lineno %d\n", c, lineno);
114100d97012SDavid du Colombier 		fatal("malformed preprocessor directive - .fname (%s)", yytext);
114200d97012SDavid du Colombier 	}
11437dd7cddfSDavid du Colombier 
114400d97012SDavid du Colombier 	getword(Getchar(), notquote);	/* was getword(c, notquote); */
11457dd7cddfSDavid du Colombier 	if (Getchar() != '\"')
11467dd7cddfSDavid du Colombier 		fatal("malformed preprocessor directive - fname.", 0);
11477dd7cddfSDavid du Colombier 
114800d97012SDavid du Colombier 	/* strcat(yytext, "\""); */
11497dd7cddfSDavid du Colombier 	Fname = lookup(yytext);
1150312a1df1SDavid du Colombier done:
11517dd7cddfSDavid du Colombier 	while (Getchar() != '\n')
11527dd7cddfSDavid du Colombier 		;
11537dd7cddfSDavid du Colombier }
11547dd7cddfSDavid du Colombier 
11557dd7cddfSDavid du Colombier void
precondition(char * q)1156312a1df1SDavid du Colombier precondition(char *q)
1157312a1df1SDavid du Colombier {	int c, nest = 1;
1158312a1df1SDavid du Colombier 
1159312a1df1SDavid du Colombier 	for (;;)
1160312a1df1SDavid du Colombier 	{	c = Getchar();
1161312a1df1SDavid du Colombier 		*q++ = c;
1162312a1df1SDavid du Colombier 		switch (c) {
1163312a1df1SDavid du Colombier 		case '\n':
1164312a1df1SDavid du Colombier 			lineno++;
1165312a1df1SDavid du Colombier 			break;
1166312a1df1SDavid du Colombier 		case '[':
1167312a1df1SDavid du Colombier 			nest++;
1168312a1df1SDavid du Colombier 			break;
1169312a1df1SDavid du Colombier 		case ']':
1170312a1df1SDavid du Colombier 			if (--nest <= 0)
1171312a1df1SDavid du Colombier 			{	*--q = '\0';
1172312a1df1SDavid du Colombier 				return;
1173312a1df1SDavid du Colombier 			}
1174312a1df1SDavid du Colombier 			break;
1175312a1df1SDavid du Colombier 		}
1176312a1df1SDavid du Colombier 	}
117700d97012SDavid du Colombier 	fatal("cannot happen", (char *) 0); /* unreachable */
1178312a1df1SDavid du Colombier }
1179312a1df1SDavid du Colombier 
118000d97012SDavid du Colombier 
1181312a1df1SDavid du Colombier Symbol *
prep_inline(Symbol * s,Lextok * nms)11827dd7cddfSDavid du Colombier prep_inline(Symbol *s, Lextok *nms)
11837dd7cddfSDavid du Colombier {	int c, nest = 1, dln, firstchar, cnr;
118400d97012SDavid du Colombier 	char *p;
11857dd7cddfSDavid du Colombier 	Lextok *t;
118600d97012SDavid du Colombier 	static char Buf1[SOMETHINGBIG], Buf2[RATHERSMALL];
1187312a1df1SDavid du Colombier 	static int c_code = 1;
11887dd7cddfSDavid du Colombier 
11897dd7cddfSDavid du Colombier 	for (t = nms; t; t = t->rgt)
11907dd7cddfSDavid du Colombier 		if (t->lft)
11917dd7cddfSDavid du Colombier 		{	if (t->lft->ntyp != NAME)
119200d97012SDavid du Colombier 			fatal("bad param to inline %s", s?s->name:"--");
11937dd7cddfSDavid du Colombier 			t->lft->sym->hidden |= 32;
11947dd7cddfSDavid du Colombier 		}
11957dd7cddfSDavid du Colombier 
1196312a1df1SDavid du Colombier 	if (!s)	/* C_Code fragment */
1197312a1df1SDavid du Colombier 	{	s = (Symbol *) emalloc(sizeof(Symbol));
119800d97012SDavid du Colombier 		s->name = (char *) emalloc(strlen("c_code")+26);
1199312a1df1SDavid du Colombier 		sprintf(s->name, "c_code%d", c_code++);
1200312a1df1SDavid du Colombier 		s->context = context;
1201312a1df1SDavid du Colombier 		s->type = CODE_FRAG;
1202312a1df1SDavid du Colombier 	} else
1203*de2caf28SDavid du Colombier 	{	s->type = PREDEF;
1204*de2caf28SDavid du Colombier 	}
1205312a1df1SDavid du Colombier 
120600d97012SDavid du Colombier 	p = &Buf1[0];
120700d97012SDavid du Colombier 	Buf2[0] = '\0';
12087dd7cddfSDavid du Colombier 	for (;;)
12097dd7cddfSDavid du Colombier 	{	c = Getchar();
12107dd7cddfSDavid du Colombier 		switch (c) {
1211312a1df1SDavid du Colombier 		case '[':
1212312a1df1SDavid du Colombier 			if (s->type != CODE_FRAG)
1213312a1df1SDavid du Colombier 				goto bad;
121400d97012SDavid du Colombier 			precondition(&Buf2[0]);	/* e.g., c_code [p] { r = p-r; } */
1215312a1df1SDavid du Colombier 			continue;
12167dd7cddfSDavid du Colombier 		case '{':
12177dd7cddfSDavid du Colombier 			break;
12187dd7cddfSDavid du Colombier 		case '\n':
12197dd7cddfSDavid du Colombier 			lineno++;
12207dd7cddfSDavid du Colombier 			/* fall through */
12217dd7cddfSDavid du Colombier 		case ' ': case '\t': case '\f': case '\r':
12227dd7cddfSDavid du Colombier 			continue;
1223312a1df1SDavid du Colombier 		default :
1224312a1df1SDavid du Colombier 			 printf("spin: saw char '%c'\n", c);
1225312a1df1SDavid du Colombier bad:			 fatal("bad inline: %s", s->name);
12267dd7cddfSDavid du Colombier 		}
12277dd7cddfSDavid du Colombier 		break;
12287dd7cddfSDavid du Colombier 	}
12297dd7cddfSDavid du Colombier 	dln = lineno;
1230312a1df1SDavid du Colombier 	if (s->type == CODE_FRAG)
1231312a1df1SDavid du Colombier 	{	if (verbose&32)
1232*de2caf28SDavid du Colombier 		{	sprintf(Buf1, "\t/* line %d %s */\n\t\t",
1233312a1df1SDavid du Colombier 				lineno, Fname->name);
1234312a1df1SDavid du Colombier 		} else
1235*de2caf28SDavid du Colombier 		{	strcpy(Buf1, "");
1236*de2caf28SDavid du Colombier 		}
1237*de2caf28SDavid du Colombier 	} else
1238*de2caf28SDavid du Colombier 	{	sprintf(Buf1, "\n#line %d \"%s\"\n{", lineno, Fname->name);
1239*de2caf28SDavid du Colombier 	}
124000d97012SDavid du Colombier 	p += strlen(Buf1);
12417dd7cddfSDavid du Colombier 	firstchar = 1;
12427dd7cddfSDavid du Colombier 
12437dd7cddfSDavid du Colombier 	cnr = 1; /* not zero */
12447dd7cddfSDavid du Colombier more:
124500d97012SDavid du Colombier 	c = Getchar();
124600d97012SDavid du Colombier 	*p++ = (char) c;
124700d97012SDavid du Colombier 	if (p - Buf1 >= SOMETHINGBIG)
12487dd7cddfSDavid du Colombier 		fatal("inline text too long", 0);
12497dd7cddfSDavid du Colombier 	switch (c) {
12507dd7cddfSDavid du Colombier 	case '\n':
12517dd7cddfSDavid du Colombier 		lineno++;
12527dd7cddfSDavid du Colombier 		cnr = 0;
12537dd7cddfSDavid du Colombier 		break;
12547dd7cddfSDavid du Colombier 	case '{':
12557dd7cddfSDavid du Colombier 		cnr++;
12567dd7cddfSDavid du Colombier 		nest++;
12577dd7cddfSDavid du Colombier 		break;
12587dd7cddfSDavid du Colombier 	case '}':
12597dd7cddfSDavid du Colombier 		cnr++;
12607dd7cddfSDavid du Colombier 		if (--nest <= 0)
12617dd7cddfSDavid du Colombier 		{	*p = '\0';
1262312a1df1SDavid du Colombier 			if (s->type == CODE_FRAG)
1263*de2caf28SDavid du Colombier 			{	*--p = '\0';	/* remove trailing '}' */
1264*de2caf28SDavid du Colombier 			}
126500d97012SDavid du Colombier 			def_inline(s, dln, &Buf1[0], &Buf2[0], nms);
126600d97012SDavid du Colombier 			if (firstchar)
1267*de2caf28SDavid du Colombier 			{	printf("%3d: %s, warning: empty inline definition (%s)\n",
1268312a1df1SDavid du Colombier 					dln, Fname->name, s->name);
1269*de2caf28SDavid du Colombier 			}
1270312a1df1SDavid du Colombier 			return s;	/* normal return */
12717dd7cddfSDavid du Colombier 		}
12727dd7cddfSDavid du Colombier 		break;
12737dd7cddfSDavid du Colombier 	case '#':
12747dd7cddfSDavid du Colombier 		if (cnr == 0)
12757dd7cddfSDavid du Colombier 		{	p--;
1276312a1df1SDavid du Colombier 			do_directive(c); /* reads to newline */
127700d97012SDavid du Colombier 		} else
127800d97012SDavid du Colombier 		{	firstchar = 0;
127900d97012SDavid du Colombier 			cnr++;
128000d97012SDavid du Colombier 		}
12817dd7cddfSDavid du Colombier 		break;
12827dd7cddfSDavid du Colombier 	case '\t':
12837dd7cddfSDavid du Colombier 	case ' ':
12847dd7cddfSDavid du Colombier 	case '\f':
12857dd7cddfSDavid du Colombier 		cnr++;
12867dd7cddfSDavid du Colombier 		break;
1287*de2caf28SDavid du Colombier 	case '"':
1288*de2caf28SDavid du Colombier 		do {
1289*de2caf28SDavid du Colombier 			c = Getchar();
1290*de2caf28SDavid du Colombier 			*p++ = (char) c;
1291*de2caf28SDavid du Colombier 			if (c == '\\')
1292*de2caf28SDavid du Colombier 			{	*p++ = (char) Getchar();
1293*de2caf28SDavid du Colombier 			}
1294*de2caf28SDavid du Colombier 			if (p - Buf1 >= SOMETHINGBIG)
1295*de2caf28SDavid du Colombier 			{	fatal("inline text too long", 0);
1296*de2caf28SDavid du Colombier 			}
1297*de2caf28SDavid du Colombier 		} while (c != '"');	/* end of string */
1298*de2caf28SDavid du Colombier 		/* *p = '\0'; */
1299*de2caf28SDavid du Colombier 		break;
1300*de2caf28SDavid du Colombier 	case '\'':
1301*de2caf28SDavid du Colombier 		c = Getchar();
1302*de2caf28SDavid du Colombier 		*p++ = (char) c;
1303*de2caf28SDavid du Colombier 		if (c == '\\')
1304*de2caf28SDavid du Colombier 		{	*p++ = (char) Getchar();
1305*de2caf28SDavid du Colombier 		}
1306*de2caf28SDavid du Colombier 		c = Getchar();
1307*de2caf28SDavid du Colombier 		*p++ = (char) c;
1308*de2caf28SDavid du Colombier 		assert(c == '\'');
1309*de2caf28SDavid du Colombier 		break;
131000d97012SDavid du Colombier 	default:
131100d97012SDavid du Colombier 		firstchar = 0;
131200d97012SDavid du Colombier 		cnr++;
131300d97012SDavid du Colombier 		break;
13147dd7cddfSDavid du Colombier 	}
13157dd7cddfSDavid du Colombier 	goto more;
13167dd7cddfSDavid du Colombier }
13177dd7cddfSDavid du Colombier 
131800d97012SDavid du Colombier static void
set_cur_scope(void)131900d97012SDavid du Colombier set_cur_scope(void)
132000d97012SDavid du Colombier {	int i;
132100d97012SDavid du Colombier 	char tmpbuf[256];
132200d97012SDavid du Colombier 
132300d97012SDavid du Colombier 	strcpy(CurScope, "_");
132400d97012SDavid du Colombier 
132500d97012SDavid du Colombier 	if (context)
132600d97012SDavid du Colombier 	for (i = 0; i < scope_level; i++)
132700d97012SDavid du Colombier 	{	sprintf(tmpbuf, "%d_", scope_seq[i]);
132800d97012SDavid du Colombier 		strcat(CurScope, tmpbuf);
132900d97012SDavid du Colombier 	}
133000d97012SDavid du Colombier }
133100d97012SDavid du Colombier 
13327dd7cddfSDavid du Colombier static int
pre_proc(void)1333*de2caf28SDavid du Colombier pre_proc(void)
1334*de2caf28SDavid du Colombier {	char b[512];
1335*de2caf28SDavid du Colombier 	int c, i = 0;
1336*de2caf28SDavid du Colombier 
1337*de2caf28SDavid du Colombier 	b[i++] = '#';
1338*de2caf28SDavid du Colombier 	while ((c = Getchar()) != '\n' && c != EOF)
1339*de2caf28SDavid du Colombier 	{	b[i++] = (char) c;
1340*de2caf28SDavid du Colombier 	}
1341*de2caf28SDavid du Colombier 	b[i] = '\0';
1342*de2caf28SDavid du Colombier 	yylval = nn(ZN, 0, ZN, ZN);
1343*de2caf28SDavid du Colombier 	yylval->sym = lookup(b);
1344*de2caf28SDavid du Colombier 	return PREPROC;
1345*de2caf28SDavid du Colombier }
1346*de2caf28SDavid du Colombier 
1347*de2caf28SDavid du Colombier static int specials[] = {
1348*de2caf28SDavid du Colombier 	'}', ')', ']',
1349*de2caf28SDavid du Colombier 	OD, FI, ELSE, BREAK,
1350*de2caf28SDavid du Colombier 	C_CODE, C_EXPR, C_DECL,
1351*de2caf28SDavid du Colombier 	NAME, CONST, INCR, DECR, 0
1352*de2caf28SDavid du Colombier };
1353*de2caf28SDavid du Colombier 
1354*de2caf28SDavid du Colombier int
follows_token(int c)1355*de2caf28SDavid du Colombier follows_token(int c)
1356*de2caf28SDavid du Colombier {	int i;
1357*de2caf28SDavid du Colombier 
1358*de2caf28SDavid du Colombier 	for (i = 0; specials[i]; i++)
1359*de2caf28SDavid du Colombier 	{	if (c == specials[i])
1360*de2caf28SDavid du Colombier 		{	return 1;
1361*de2caf28SDavid du Colombier 	}	}
1362*de2caf28SDavid du Colombier 	return 0;
1363*de2caf28SDavid du Colombier }
1364*de2caf28SDavid du Colombier #define DEFER_LTL
1365*de2caf28SDavid du Colombier #ifdef DEFER_LTL
1366*de2caf28SDavid du Colombier /* defer ltl formula to the end of the spec
1367*de2caf28SDavid du Colombier  * no matter where they appear in the original
1368*de2caf28SDavid du Colombier  */
1369*de2caf28SDavid du Colombier 
1370*de2caf28SDavid du Colombier static int deferred = 0;
1371*de2caf28SDavid du Colombier static FILE *defer_fd;
1372*de2caf28SDavid du Colombier 
1373*de2caf28SDavid du Colombier int
get_deferred(void)1374*de2caf28SDavid du Colombier get_deferred(void)
1375*de2caf28SDavid du Colombier {
1376*de2caf28SDavid du Colombier 	if (!defer_fd)
1377*de2caf28SDavid du Colombier 	{	return 0;	/* nothing was deferred */
1378*de2caf28SDavid du Colombier 	}
1379*de2caf28SDavid du Colombier 	fclose(defer_fd);
1380*de2caf28SDavid du Colombier 
1381*de2caf28SDavid du Colombier 	defer_fd = fopen(TMP_FILE2, "r");
1382*de2caf28SDavid du Colombier 	if (!defer_fd)
1383*de2caf28SDavid du Colombier 	{	non_fatal("cannot retrieve deferred ltl formula", (char *) 0);
1384*de2caf28SDavid du Colombier 		return 0;
1385*de2caf28SDavid du Colombier 	}
1386*de2caf28SDavid du Colombier 	fclose(yyin);
1387*de2caf28SDavid du Colombier 	yyin = defer_fd;
1388*de2caf28SDavid du Colombier 	return 1;
1389*de2caf28SDavid du Colombier }
1390*de2caf28SDavid du Colombier 
1391*de2caf28SDavid du Colombier void
zap_deferred(void)1392*de2caf28SDavid du Colombier zap_deferred(void)
1393*de2caf28SDavid du Colombier {
1394*de2caf28SDavid du Colombier 	(void) unlink(TMP_FILE2);
1395*de2caf28SDavid du Colombier }
1396*de2caf28SDavid du Colombier 
1397*de2caf28SDavid du Colombier int
put_deferred(void)1398*de2caf28SDavid du Colombier put_deferred(void)
1399*de2caf28SDavid du Colombier {	int c, cnt;
1400*de2caf28SDavid du Colombier 	if (!defer_fd)
1401*de2caf28SDavid du Colombier 	{	defer_fd = fopen(TMP_FILE2, "w+");
1402*de2caf28SDavid du Colombier 		if (!defer_fd)
1403*de2caf28SDavid du Colombier 		{	non_fatal("cannot defer ltl expansion", (char *) 0);
1404*de2caf28SDavid du Colombier 			return 0;
1405*de2caf28SDavid du Colombier 	}	}
1406*de2caf28SDavid du Colombier 	fprintf(defer_fd, "ltl ");
1407*de2caf28SDavid du Colombier 	cnt = 0;
1408*de2caf28SDavid du Colombier 	while ((c = getc(yyin)) != EOF)
1409*de2caf28SDavid du Colombier 	{	if (c == '{')
1410*de2caf28SDavid du Colombier 		{	cnt++;
1411*de2caf28SDavid du Colombier 		}
1412*de2caf28SDavid du Colombier 		if (c == '}')
1413*de2caf28SDavid du Colombier 		{	cnt--;
1414*de2caf28SDavid du Colombier 			if (cnt == 0)
1415*de2caf28SDavid du Colombier 			{	break;
1416*de2caf28SDavid du Colombier 		}	}
1417*de2caf28SDavid du Colombier 		fprintf(defer_fd, "%c", c);
1418*de2caf28SDavid du Colombier 	}
1419*de2caf28SDavid du Colombier 	fprintf(defer_fd, "}\n");
1420*de2caf28SDavid du Colombier 	fflush(defer_fd);
1421*de2caf28SDavid du Colombier 	return 1;
1422*de2caf28SDavid du Colombier }
1423*de2caf28SDavid du Colombier #endif
1424*de2caf28SDavid du Colombier 
1425*de2caf28SDavid du Colombier #define EXPAND_SELECT
1426*de2caf28SDavid du Colombier #ifdef EXPAND_SELECT
1427*de2caf28SDavid du Colombier static char tmp_hold[256];
1428*de2caf28SDavid du Colombier static int  tmp_has;
1429*de2caf28SDavid du Colombier 
1430*de2caf28SDavid du Colombier void
new_select(void)1431*de2caf28SDavid du Colombier new_select(void)
1432*de2caf28SDavid du Colombier {	tmp_hold[0] = '\0';
1433*de2caf28SDavid du Colombier 	tmp_has = 0;
1434*de2caf28SDavid du Colombier }
1435*de2caf28SDavid du Colombier 
1436*de2caf28SDavid du Colombier static int
scan_to(int stop,int (* tst)(int),char * buf,int bufsz)1437*de2caf28SDavid du Colombier scan_to(int stop, int (*tst)(int), char *buf, int bufsz)
1438*de2caf28SDavid du Colombier {	int c, i = 0;
1439*de2caf28SDavid du Colombier 
1440*de2caf28SDavid du Colombier 	do {	c = Getchar();
1441*de2caf28SDavid du Colombier 		if (tmp_has < sizeof(tmp_hold))
1442*de2caf28SDavid du Colombier 		{	tmp_hold[tmp_has++] = c;
1443*de2caf28SDavid du Colombier 		}
1444*de2caf28SDavid du Colombier 		if (c == '\n')
1445*de2caf28SDavid du Colombier 		{	lineno++;
1446*de2caf28SDavid du Colombier 		} else if (buf && i < bufsz-1)
1447*de2caf28SDavid du Colombier 		{	buf[i++] = c;
1448*de2caf28SDavid du Colombier 		} else if (buf && i >= bufsz-1)
1449*de2caf28SDavid du Colombier 		{	buf[bufsz-1] = '\0';
1450*de2caf28SDavid du Colombier 			fatal("name too long", buf);
1451*de2caf28SDavid du Colombier 		}
1452*de2caf28SDavid du Colombier 		if (tst && !tst(c) && c != ' ' && c != '\t')
1453*de2caf28SDavid du Colombier 		{	break;
1454*de2caf28SDavid du Colombier 		}
1455*de2caf28SDavid du Colombier 	} while (c != stop && c != EOF);
1456*de2caf28SDavid du Colombier 
1457*de2caf28SDavid du Colombier 	if (buf)
1458*de2caf28SDavid du Colombier 	{	if (i <= 0)
1459*de2caf28SDavid du Colombier 		{	fatal("input error", (char *) 0);
1460*de2caf28SDavid du Colombier 		}
1461*de2caf28SDavid du Colombier 		buf[i-1] = '\0';
1462*de2caf28SDavid du Colombier 	}
1463*de2caf28SDavid du Colombier 
1464*de2caf28SDavid du Colombier 	if (c != stop)
1465*de2caf28SDavid du Colombier 	{	if (0)
1466*de2caf28SDavid du Colombier 		{	printf("saw: '%c', expected '%c'\n", c, stop);
1467*de2caf28SDavid du Colombier 		}
1468*de2caf28SDavid du Colombier 		if (tmp_has < sizeof(tmp_hold))
1469*de2caf28SDavid du Colombier 		{	tmp_hold[tmp_has] = '\0';
1470*de2caf28SDavid du Colombier 			push_back(tmp_hold);
1471*de2caf28SDavid du Colombier 			if (0)
1472*de2caf28SDavid du Colombier 			{	printf("pushed back: <'%s'>\n", tmp_hold);
1473*de2caf28SDavid du Colombier 			}
1474*de2caf28SDavid du Colombier 			return 0; /* internal expansion fails */
1475*de2caf28SDavid du Colombier 		} else
1476*de2caf28SDavid du Colombier 		{	fatal("expecting select ( name : constant .. constant )", 0);
1477*de2caf28SDavid du Colombier 	}	}
1478*de2caf28SDavid du Colombier 	return 1;		/* success */
1479*de2caf28SDavid du Colombier }
1480*de2caf28SDavid du Colombier #endif
1481*de2caf28SDavid du Colombier 
1482*de2caf28SDavid du Colombier int
lex(void)1483219b2ee8SDavid du Colombier lex(void)
1484219b2ee8SDavid du Colombier {	int c;
1485219b2ee8SDavid du Colombier again:
1486219b2ee8SDavid du Colombier 	c = Getchar();
1487*de2caf28SDavid du Colombier /* more: */
14887dd7cddfSDavid du Colombier 	yytext[0] = (char) c;
1489219b2ee8SDavid du Colombier 	yytext[1] = '\0';
1490219b2ee8SDavid du Colombier 	switch (c) {
149100d97012SDavid du Colombier 	case EOF:
1492*de2caf28SDavid du Colombier #ifdef DEFER_LTL
1493*de2caf28SDavid du Colombier 		if (!deferred)
1494*de2caf28SDavid du Colombier 		{	deferred = 1;
1495*de2caf28SDavid du Colombier 			if (get_deferred())
1496*de2caf28SDavid du Colombier 			{	goto again;
1497*de2caf28SDavid du Colombier 			}
1498*de2caf28SDavid du Colombier 		} else
1499*de2caf28SDavid du Colombier 		{	zap_deferred();
1500*de2caf28SDavid du Colombier 		}
1501*de2caf28SDavid du Colombier #endif
150200d97012SDavid du Colombier 		return c;
1503219b2ee8SDavid du Colombier 	case '\n':		/* newline */
1504219b2ee8SDavid du Colombier 		lineno++;
1505*de2caf28SDavid du Colombier 		/* make most semi-colons optional */
1506*de2caf28SDavid du Colombier 		if (implied_semis
1507*de2caf28SDavid du Colombier 	/*	&&  context	*/
1508*de2caf28SDavid du Colombier 		&&  in_seq
1509*de2caf28SDavid du Colombier 		&&  par_cnt == 0
1510*de2caf28SDavid du Colombier 		&&  follows_token(last_token))
1511*de2caf28SDavid du Colombier 		{	if (last_token == '}')
1512*de2caf28SDavid du Colombier 			{	do {	c = Getchar();
1513*de2caf28SDavid du Colombier 					if (c == '\n')
1514*de2caf28SDavid du Colombier 					{	lineno++;
1515*de2caf28SDavid du Colombier 					}
1516*de2caf28SDavid du Colombier 				} while (c == ' ' || c == '\t' ||
1517*de2caf28SDavid du Colombier 					 c == '\f' || c == '\n' ||
1518*de2caf28SDavid du Colombier 					 c == '\r');
1519*de2caf28SDavid du Colombier 				Ungetch(c);
1520*de2caf28SDavid du Colombier 				if (0) printf("%d: saw %d\n", lineno, c);
1521*de2caf28SDavid du Colombier 				if (c == 'u') /* first letter of UNLESS */
1522*de2caf28SDavid du Colombier 				{	goto again;
1523*de2caf28SDavid du Colombier 			}	}
1524*de2caf28SDavid du Colombier 			if (0)
1525*de2caf28SDavid du Colombier 			{	printf("insert ; line %d, last_token %d in_seq %d\n",
1526*de2caf28SDavid du Colombier 				 lineno-1, last_token, in_seq);
1527*de2caf28SDavid du Colombier 			}
1528*de2caf28SDavid du Colombier 			ValToken(1, SEMI);
1529*de2caf28SDavid du Colombier 		}
1530*de2caf28SDavid du Colombier 		/* else fall thru */
15317dd7cddfSDavid du Colombier 	case '\r':		/* carriage return */
1532219b2ee8SDavid du Colombier 		goto again;
1533219b2ee8SDavid du Colombier 
15347dd7cddfSDavid du Colombier 	case  ' ': case '\t': case '\f':	/* white space */
1535219b2ee8SDavid du Colombier 		goto again;
1536219b2ee8SDavid du Colombier 
1537219b2ee8SDavid du Colombier 	case '#':		/* preprocessor directive */
15387dd7cddfSDavid du Colombier 		if (in_comment) goto again;
1539*de2caf28SDavid du Colombier 		if (pp_mode)
1540*de2caf28SDavid du Colombier 		{	last_token = PREPROC;
1541*de2caf28SDavid du Colombier 			return pre_proc();
1542*de2caf28SDavid du Colombier 		}
1543312a1df1SDavid du Colombier 		do_directive(c);
1544219b2ee8SDavid du Colombier 		goto again;
1545219b2ee8SDavid du Colombier 
1546219b2ee8SDavid du Colombier 	case '\"':
1547219b2ee8SDavid du Colombier 		getword(c, notquote);
1548219b2ee8SDavid du Colombier 		if (Getchar() != '\"')
1549219b2ee8SDavid du Colombier 			fatal("string not terminated", yytext);
1550219b2ee8SDavid du Colombier 		strcat(yytext, "\"");
15517dd7cddfSDavid du Colombier 		SymToken(lookup(yytext), STRING)
15527dd7cddfSDavid du Colombier 
155300d97012SDavid du Colombier 	case '$':
155400d97012SDavid du Colombier 		getword('\"', notdollar);
155500d97012SDavid du Colombier 		if (Getchar() != '$')
155600d97012SDavid du Colombier 			fatal("ltl definition not terminated", yytext);
155700d97012SDavid du Colombier 		strcat(yytext, "\"");
155800d97012SDavid du Colombier 		SymToken(lookup(yytext), STRING)
155900d97012SDavid du Colombier 
15607dd7cddfSDavid du Colombier 	case '\'':	/* new 3.0.9 */
15617dd7cddfSDavid du Colombier 		c = Getchar();
15627dd7cddfSDavid du Colombier 		if (c == '\\')
15637dd7cddfSDavid du Colombier 		{	c = Getchar();
15647dd7cddfSDavid du Colombier 			if (c == 'n') c = '\n';
15657dd7cddfSDavid du Colombier 			else if (c == 'r') c = '\r';
15667dd7cddfSDavid du Colombier 			else if (c == 't') c = '\t';
15677dd7cddfSDavid du Colombier 			else if (c == 'f') c = '\f';
15687dd7cddfSDavid du Colombier 		}
1569312a1df1SDavid du Colombier 		if (Getchar() != '\'' && !in_comment)
1570312a1df1SDavid du Colombier 			fatal("character quote missing: %s", yytext);
15717dd7cddfSDavid du Colombier 		ValToken(c, CONST)
1572219b2ee8SDavid du Colombier 
1573219b2ee8SDavid du Colombier 	default:
1574219b2ee8SDavid du Colombier 		break;
1575219b2ee8SDavid du Colombier 	}
1576219b2ee8SDavid du Colombier 
15777dd7cddfSDavid du Colombier 	if (isdigit_(c))
1578*de2caf28SDavid du Colombier 	{	long int nr;
1579*de2caf28SDavid du Colombier 		getword(c, isdigit_);
1580*de2caf28SDavid du Colombier 		errno = 0;
1581*de2caf28SDavid du Colombier 		nr = strtol(yytext, NULL, 10);
1582*de2caf28SDavid du Colombier 		if (errno != 0)
1583*de2caf28SDavid du Colombier 		{	fprintf(stderr, "spin: value out of range: '%s' read as '%d'\n",
1584*de2caf28SDavid du Colombier 				yytext, (int) nr);
1585*de2caf28SDavid du Colombier 		}
1586*de2caf28SDavid du Colombier 		ValToken((int)nr, CONST)
1587219b2ee8SDavid du Colombier 	}
1588219b2ee8SDavid du Colombier 
15897dd7cddfSDavid du Colombier 	if (isalpha_(c) || c == '_')
1590219b2ee8SDavid du Colombier 	{	getword(c, isalnum_);
1591219b2ee8SDavid du Colombier 		if (!in_comment)
15927dd7cddfSDavid du Colombier 		{	c = check_name(yytext);
1593*de2caf28SDavid du Colombier 
1594*de2caf28SDavid du Colombier /* replace timeout with (timeout) */
1595*de2caf28SDavid du Colombier 			if (c == TIMEOUT
1596*de2caf28SDavid du Colombier 			&&  Inlining < 0
1597*de2caf28SDavid du Colombier 			&&  last_token != '(')
1598*de2caf28SDavid du Colombier 			{	push_back("timeout)");
1599*de2caf28SDavid du Colombier 				last_token = '(';
1600*de2caf28SDavid du Colombier 				return '(';
1601*de2caf28SDavid du Colombier 			}
1602*de2caf28SDavid du Colombier /* end */
1603*de2caf28SDavid du Colombier 
1604*de2caf28SDavid du Colombier #ifdef EXPAND_SELECT
1605*de2caf28SDavid du Colombier 			if (c == SELECT && Inlining < 0)
1606*de2caf28SDavid du Colombier 			{	char name[64], from[32], upto[32];
1607*de2caf28SDavid du Colombier 				int i, a, b;
1608*de2caf28SDavid du Colombier 				new_select();
1609*de2caf28SDavid du Colombier 				if (!scan_to('(', 0, 0, 0)
1610*de2caf28SDavid du Colombier 				||  !scan_to(':', isalnum, name, sizeof(name))
1611*de2caf28SDavid du Colombier 				||  !scan_to('.', isdigit, from, sizeof(from))
1612*de2caf28SDavid du Colombier 				||  !scan_to('.', 0, 0, 0)
1613*de2caf28SDavid du Colombier 				||  !scan_to(')', isdigit, upto, sizeof(upto)))
1614*de2caf28SDavid du Colombier 				{	goto not_expanded;
1615*de2caf28SDavid du Colombier 				}
1616*de2caf28SDavid du Colombier 				a = atoi(from);
1617*de2caf28SDavid du Colombier 				b = atoi(upto);
1618*de2caf28SDavid du Colombier 				if (0)
1619*de2caf28SDavid du Colombier 				{	printf("Select %s from %d to %d\n",
1620*de2caf28SDavid du Colombier 						name, a, b);
1621*de2caf28SDavid du Colombier 				}
1622*de2caf28SDavid du Colombier 				if (a > b)
1623*de2caf28SDavid du Colombier 				{	non_fatal("bad range in select statement", 0);
1624*de2caf28SDavid du Colombier 					goto again;
1625*de2caf28SDavid du Colombier 				}
1626*de2caf28SDavid du Colombier 				if (b - a <= 32)
1627*de2caf28SDavid du Colombier 				{	push_back("if ");
1628*de2caf28SDavid du Colombier 					for (i = a; i <= b; i++)
1629*de2caf28SDavid du Colombier 					{	char buf[256];
1630*de2caf28SDavid du Colombier 						push_back(":: ");
1631*de2caf28SDavid du Colombier 						sprintf(buf, "%s = %d ",
1632*de2caf28SDavid du Colombier 							name, i);
1633*de2caf28SDavid du Colombier 						push_back(buf);
1634*de2caf28SDavid du Colombier 					}
1635*de2caf28SDavid du Colombier 					push_back("fi ");
1636*de2caf28SDavid du Colombier 				} else
1637*de2caf28SDavid du Colombier 				{	char buf[256];
1638*de2caf28SDavid du Colombier 					sprintf(buf, "%s = %d; do ",
1639*de2caf28SDavid du Colombier 						name, a);
1640*de2caf28SDavid du Colombier 					push_back(buf);
1641*de2caf28SDavid du Colombier 					sprintf(buf, ":: (%s < %d) -> %s++ ",
1642*de2caf28SDavid du Colombier 						name, b, name);
1643*de2caf28SDavid du Colombier 					push_back(buf);
1644*de2caf28SDavid du Colombier 					push_back(":: break od; ");
1645*de2caf28SDavid du Colombier 				}
1646*de2caf28SDavid du Colombier 				goto again;
1647*de2caf28SDavid du Colombier 			}
1648*de2caf28SDavid du Colombier not_expanded:
1649*de2caf28SDavid du Colombier #endif
1650*de2caf28SDavid du Colombier 
1651*de2caf28SDavid du Colombier #ifdef DEFER_LTL
1652*de2caf28SDavid du Colombier 			if (c == LTL && !deferred)
1653*de2caf28SDavid du Colombier 			{	if (put_deferred())
1654*de2caf28SDavid du Colombier 				{	goto again;
1655*de2caf28SDavid du Colombier 			}	}
1656*de2caf28SDavid du Colombier #endif
1657*de2caf28SDavid du Colombier 			if (c)
1658*de2caf28SDavid du Colombier 			{	last_token = c;
1659*de2caf28SDavid du Colombier 				return c;
1660*de2caf28SDavid du Colombier 			}
16617dd7cddfSDavid du Colombier 			/* else fall through */
16627dd7cddfSDavid du Colombier 		}
16637dd7cddfSDavid du Colombier 		goto again;
1664219b2ee8SDavid du Colombier 	}
1665219b2ee8SDavid du Colombier 
166600d97012SDavid du Colombier 	if (ltl_mode)
166700d97012SDavid du Colombier 	{	switch (c) {
166800d97012SDavid du Colombier 		case '-': c = follow('>', IMPLIES,    '-'); break;
166900d97012SDavid du Colombier 		case '[': c = follow(']', ALWAYS,     '['); break;
167000d97012SDavid du Colombier 		case '<': c = follow('>', EVENTUALLY, '<');
167100d97012SDavid du Colombier 			  if (c == '<')
167200d97012SDavid du Colombier 			  {	c = Getchar();
167300d97012SDavid du Colombier 				if (c == '-')
167400d97012SDavid du Colombier 				{	c = follow('>', EQUIV, '-');
167500d97012SDavid du Colombier 					if (c == '-')
167600d97012SDavid du Colombier 					{	Ungetch(c);
167700d97012SDavid du Colombier 						c = '<';
167800d97012SDavid du Colombier 					}
167900d97012SDavid du Colombier 				} else
168000d97012SDavid du Colombier 				{	Ungetch(c);
168100d97012SDavid du Colombier 					c = '<';
168200d97012SDavid du Colombier 			  }	}
168300d97012SDavid du Colombier 		default:  break;
168400d97012SDavid du Colombier 	}	}
168500d97012SDavid du Colombier 
1686219b2ee8SDavid du Colombier 	switch (c) {
1687219b2ee8SDavid du Colombier 	case '/': c = follow('*', 0, '/');
1688219b2ee8SDavid du Colombier 		  if (!c) { in_comment = 1; goto again; }
1689219b2ee8SDavid du Colombier 		  break;
1690219b2ee8SDavid du Colombier 	case '*': c = follow('/', 0, '*');
1691219b2ee8SDavid du Colombier 		  if (!c) { in_comment = 0; goto again; }
1692219b2ee8SDavid du Colombier 		  break;
1693219b2ee8SDavid du Colombier 	case ':': c = follow(':', SEP, ':'); break;
1694*de2caf28SDavid du Colombier 	case '-': c = follow('>', ARROW, follow('-', DECR, '-')); break;
1695219b2ee8SDavid du Colombier 	case '+': c = follow('+', INCR, '+'); break;
1696219b2ee8SDavid du Colombier 	case '<': c = follow('<', LSHIFT, follow('=', LE, LT)); break;
1697219b2ee8SDavid du Colombier 	case '>': c = follow('>', RSHIFT, follow('=', GE, GT)); break;
1698219b2ee8SDavid du Colombier 	case '=': c = follow('=', EQ, ASGN); break;
1699219b2ee8SDavid du Colombier 	case '!': c = follow('=', NE, follow('!', O_SND, SND)); break;
1700219b2ee8SDavid du Colombier 	case '?': c = follow('?', R_RCV, RCV); break;
1701219b2ee8SDavid du Colombier 	case '&': c = follow('&', AND, '&'); break;
1702219b2ee8SDavid du Colombier 	case '|': c = follow('|', OR, '|'); break;
1703219b2ee8SDavid du Colombier 	case ';': c = SEMI; break;
170400d97012SDavid du Colombier 	case '.': c = follow('.', DOTDOT, '.'); break;
170500d97012SDavid du Colombier 	case '{': scope_seq[scope_level++]++; set_cur_scope(); break;
170600d97012SDavid du Colombier 	case '}': scope_level--; set_cur_scope(); break;
1707219b2ee8SDavid du Colombier 	default : break;
1708219b2ee8SDavid du Colombier 	}
1709*de2caf28SDavid du Colombier 	ValToken(0, c)
1710219b2ee8SDavid du Colombier }
1711219b2ee8SDavid du Colombier 
1712219b2ee8SDavid du Colombier static struct {
171300d97012SDavid du Colombier 	char *s;	int tok;
171400d97012SDavid du Colombier } LTL_syms[] = {
171500d97012SDavid du Colombier 	/* [], <>, ->, and <-> are intercepted in lex() */
171600d97012SDavid du Colombier 	{ "U",		UNTIL   },
171700d97012SDavid du Colombier 	{ "V",		RELEASE },
171800d97012SDavid du Colombier 	{ "W",		WEAK_UNTIL },
171900d97012SDavid du Colombier 	{ "X",		NEXT    },
172000d97012SDavid du Colombier 	{ "always",	ALWAYS  },
172100d97012SDavid du Colombier 	{ "eventually",	EVENTUALLY },
172200d97012SDavid du Colombier 	{ "until",	UNTIL   },
172300d97012SDavid du Colombier 	{ "stronguntil",UNTIL   },
172400d97012SDavid du Colombier 	{ "weakuntil",	WEAK_UNTIL   },
172500d97012SDavid du Colombier 	{ "release",	RELEASE },
172600d97012SDavid du Colombier 	{ "next",	NEXT    },
172700d97012SDavid du Colombier 	{ "implies",	IMPLIES },
172800d97012SDavid du Colombier 	{ "equivalent",	EQUIV   },
172900d97012SDavid du Colombier 	{ 0, 		0       },
173000d97012SDavid du Colombier };
173100d97012SDavid du Colombier 
173200d97012SDavid du Colombier static struct {
1733219b2ee8SDavid du Colombier 	char *s;	int tok;	int val;	char *sym;
1734219b2ee8SDavid du Colombier } Names[] = {
17357dd7cddfSDavid du Colombier 	{"active",	ACTIVE,		0,		0},
17367dd7cddfSDavid du Colombier 	{"assert",	ASSERT,		0,		0},
17377dd7cddfSDavid du Colombier 	{"atomic",	ATOMIC,		0,		0},
17387dd7cddfSDavid du Colombier 	{"bit",		TYPE,		BIT,		0},
17397dd7cddfSDavid du Colombier 	{"bool",	TYPE,		BIT,		0},
17407dd7cddfSDavid du Colombier 	{"break",	BREAK,		0,		0},
17417dd7cddfSDavid du Colombier 	{"byte",	TYPE,		BYTE,		0},
1742312a1df1SDavid du Colombier 	{"c_code",	C_CODE,		0,		0},
1743312a1df1SDavid du Colombier 	{"c_decl",	C_DECL,		0,		0},
1744312a1df1SDavid du Colombier 	{"c_expr",	C_EXPR,		0,		0},
1745312a1df1SDavid du Colombier 	{"c_state",	C_STATE,	0,		0},
1746312a1df1SDavid du Colombier 	{"c_track",	C_TRACK,	0,		0},
17477dd7cddfSDavid du Colombier 	{"D_proctype",	D_PROCTYPE,	0,		0},
17487dd7cddfSDavid du Colombier 	{"do",		DO,		0,		0},
17497dd7cddfSDavid du Colombier 	{"chan",	TYPE,		CHAN,		0},
17507dd7cddfSDavid du Colombier 	{"else", 	ELSE,		0,		0},
17517dd7cddfSDavid du Colombier 	{"empty",	EMPTY,		0,		0},
17527dd7cddfSDavid du Colombier 	{"enabled",	ENABLED,	0,		0},
17537dd7cddfSDavid du Colombier 	{"eval",	EVAL,		0,		0},
17547dd7cddfSDavid du Colombier 	{"false",	CONST,		0,		0},
17557dd7cddfSDavid du Colombier 	{"fi",		FI,		0,		0},
175600d97012SDavid du Colombier 	{"for",		FOR,		0,		0},
17577dd7cddfSDavid du Colombier 	{"full",	FULL,		0,		0},
1758*de2caf28SDavid du Colombier 	{"get_priority", GET_P,		0,		0},
17597dd7cddfSDavid du Colombier 	{"goto",	GOTO,		0,		0},
17607dd7cddfSDavid du Colombier 	{"hidden",	HIDDEN,		0,		":hide:"},
17617dd7cddfSDavid du Colombier 	{"if",		IF,		0,		0},
176200d97012SDavid du Colombier 	{"in",		IN,		0,		0},
17637dd7cddfSDavid du Colombier 	{"init",	INIT,		0,		":init:"},
176400d97012SDavid du Colombier 	{"inline",	INLINE,		0,		0},
17657dd7cddfSDavid du Colombier 	{"int",		TYPE,		INT,		0},
17667dd7cddfSDavid du Colombier 	{"len",		LEN,		0,		0},
1767312a1df1SDavid du Colombier 	{"local",	ISLOCAL,	0,		":local:"},
176800d97012SDavid du Colombier 	{"ltl",		LTL,		0,		":ltl:"},
17697dd7cddfSDavid du Colombier 	{"mtype",	TYPE,		MTYPE,		0},
17707dd7cddfSDavid du Colombier 	{"nempty",	NEMPTY,		0,		0},
17717dd7cddfSDavid du Colombier 	{"never",	CLAIM,		0,		":never:"},
17727dd7cddfSDavid du Colombier 	{"nfull",	NFULL,		0,		0},
17737dd7cddfSDavid du Colombier 	{"notrace",	TRACE,		0,		":notrace:"},
17747dd7cddfSDavid du Colombier 	{"np_",		NONPROGRESS,	0,		0},
17757dd7cddfSDavid du Colombier 	{"od",		OD,		0,		0},
17767dd7cddfSDavid du Colombier 	{"of",		OF,		0,		0},
17777dd7cddfSDavid du Colombier 	{"pc_value",	PC_VAL,		0,		0},
1778312a1df1SDavid du Colombier 	{"pid",		TYPE,		BYTE,		0},
17797dd7cddfSDavid du Colombier 	{"printf",	PRINT,		0,		0},
1780312a1df1SDavid du Colombier 	{"printm",	PRINTM,		0,		0},
17817dd7cddfSDavid du Colombier 	{"priority",	PRIORITY,	0,		0},
17827dd7cddfSDavid du Colombier 	{"proctype",	PROCTYPE,	0,		0},
17837dd7cddfSDavid du Colombier 	{"provided",	PROVIDED,	0,		0},
1784*de2caf28SDavid du Colombier 	{"return",	RETURN,		0,		0},
17857dd7cddfSDavid du Colombier 	{"run",		RUN,		0,		0},
17867dd7cddfSDavid du Colombier 	{"d_step",	D_STEP,		0,		0},
178700d97012SDavid du Colombier 	{"select",	SELECT,		0,		0},
1788*de2caf28SDavid du Colombier 	{"set_priority", SET_P,		0,		0},
17897dd7cddfSDavid du Colombier 	{"short",	TYPE,		SHORT,		0},
17907dd7cddfSDavid du Colombier 	{"skip",	CONST,		1,		0},
17917dd7cddfSDavid du Colombier 	{"timeout",	TIMEOUT,	0,		0},
17927dd7cddfSDavid du Colombier 	{"trace",	TRACE,		0,		":trace:"},
17937dd7cddfSDavid du Colombier 	{"true",	CONST,		1,		0},
17947dd7cddfSDavid du Colombier 	{"show",	SHOW,		0,		":show:"},
17957dd7cddfSDavid du Colombier 	{"typedef",	TYPEDEF,	0,		0},
17967dd7cddfSDavid du Colombier 	{"unless",	UNLESS,		0,		0},
17977dd7cddfSDavid du Colombier 	{"unsigned",	TYPE,		UNSIGNED,	0},
17987dd7cddfSDavid du Colombier 	{"xr",		XU,		XR,		0},
17997dd7cddfSDavid du Colombier 	{"xs",		XU,		XS,		0},
18007dd7cddfSDavid du Colombier 	{0, 		0,		0,		0},
1801219b2ee8SDavid du Colombier };
1802219b2ee8SDavid du Colombier 
18037dd7cddfSDavid du Colombier static int
check_name(char * s)1804219b2ee8SDavid du Colombier check_name(char *s)
1805312a1df1SDavid du Colombier {	int i;
1806219b2ee8SDavid du Colombier 
1807219b2ee8SDavid du Colombier 	yylval = nn(ZN, 0, ZN, ZN);
180800d97012SDavid du Colombier 
180900d97012SDavid du Colombier 	if (ltl_mode)
181000d97012SDavid du Colombier 	{	for (i = 0; LTL_syms[i].s; i++)
181100d97012SDavid du Colombier 		{	if (strcmp(s, LTL_syms[i].s) == 0)
181200d97012SDavid du Colombier 			{	return LTL_syms[i].tok;
181300d97012SDavid du Colombier 	}	}	}
181400d97012SDavid du Colombier 
1815219b2ee8SDavid du Colombier 	for (i = 0; Names[i].s; i++)
181600d97012SDavid du Colombier 	{	if (strcmp(s, Names[i].s) == 0)
1817219b2ee8SDavid du Colombier 		{	yylval->val = Names[i].val;
1818219b2ee8SDavid du Colombier 			if (Names[i].sym)
1819219b2ee8SDavid du Colombier 				yylval->sym = lookup(Names[i].sym);
1820*de2caf28SDavid du Colombier 			if (Names[i].tok == IN && !in_for)
1821*de2caf28SDavid du Colombier 			{	continue;
1822*de2caf28SDavid du Colombier 			}
1823219b2ee8SDavid du Colombier 			return Names[i].tok;
182400d97012SDavid du Colombier 	}	}
1825219b2ee8SDavid du Colombier 
1826312a1df1SDavid du Colombier 	if ((yylval->val = ismtype(s)) != 0)
1827219b2ee8SDavid du Colombier 	{	yylval->ismtyp = 1;
1828*de2caf28SDavid du Colombier 		yylval->sym = (Symbol *) emalloc(sizeof(Symbol));
1829*de2caf28SDavid du Colombier 		yylval->sym->name = (char *) emalloc(strlen(s)+1);
1830*de2caf28SDavid du Colombier 		strcpy(yylval->sym->name, s);
1831219b2ee8SDavid du Colombier 		return CONST;
1832219b2ee8SDavid du Colombier 	}
1833219b2ee8SDavid du Colombier 
1834219b2ee8SDavid du Colombier 	if (strcmp(s, "_last") == 0)
1835219b2ee8SDavid du Colombier 		has_last++;
1836219b2ee8SDavid du Colombier 
1837*de2caf28SDavid du Colombier 	if (strcmp(s, "_priority") == 0)
1838*de2caf28SDavid du Colombier 		has_priority++;
1839*de2caf28SDavid du Colombier 
18407dd7cddfSDavid du Colombier 	if (Inlining >= 0 && !ReDiRect)
18417dd7cddfSDavid du Colombier 	{	Lextok *tt, *t = Inline_stub[Inlining]->params;
1842312a1df1SDavid du Colombier 
1843312a1df1SDavid du Colombier 		for (i = 0; t; t = t->rgt, i++)				/* formal pars */
1844312a1df1SDavid du Colombier 		 if (!strcmp(s, t->lft->sym->name)			/* varname matches formal */
1845312a1df1SDavid du Colombier 		 &&   strcmp(s, Inline_stub[Inlining]->anms[i]) != 0)	/* actual pars */
18467dd7cddfSDavid du Colombier 		 {
18477dd7cddfSDavid du Colombier #if 0
18487dd7cddfSDavid du Colombier 			if (verbose&32)
18497dd7cddfSDavid du Colombier 			printf("\tline %d, replace %s in call of '%s' with %s\n",
18507dd7cddfSDavid du Colombier 				lineno, s,
18517dd7cddfSDavid du Colombier 				Inline_stub[Inlining]->nm->name,
18527dd7cddfSDavid du Colombier 				Inline_stub[Inlining]->anms[i]);
18537dd7cddfSDavid du Colombier #endif
1854312a1df1SDavid du Colombier 			for (tt = Inline_stub[Inlining]->params; tt; tt = tt->rgt)
18557dd7cddfSDavid du Colombier 				if (!strcmp(Inline_stub[Inlining]->anms[i],
18567dd7cddfSDavid du Colombier 					tt->lft->sym->name))
18577dd7cddfSDavid du Colombier 				{	/* would be cyclic if not caught */
185800d97012SDavid du Colombier 					printf("spin: %s:%d replacement value: %s\n",
185900d97012SDavid du Colombier 						oFname->name?oFname->name:"--", lineno, tt->lft->sym->name);
186000d97012SDavid du Colombier 					fatal("formal par of %s contains replacement value",
1861312a1df1SDavid du Colombier 						Inline_stub[Inlining]->nm->name);
18627dd7cddfSDavid du Colombier 					yylval->ntyp = tt->lft->ntyp;
18637dd7cddfSDavid du Colombier 					yylval->sym = lookup(tt->lft->sym->name);
18647dd7cddfSDavid du Colombier 					return NAME;
18657dd7cddfSDavid du Colombier 				}
186600d97012SDavid du Colombier 
186700d97012SDavid du Colombier 			/* check for occurrence of param as field of struct */
186800d97012SDavid du Colombier 			{ char *ptr = Inline_stub[Inlining]->anms[i];
1869*de2caf28SDavid du Colombier 				char *optr = ptr;
187000d97012SDavid du Colombier 				while ((ptr = strstr(ptr, s)) != NULL)
1871*de2caf28SDavid du Colombier 				{	if ((ptr > optr && *(ptr-1) == '.')
187200d97012SDavid du Colombier 					||  *(ptr+strlen(s)) == '.')
187300d97012SDavid du Colombier 					{	fatal("formal par of %s used in structure name",
187400d97012SDavid du Colombier 						Inline_stub[Inlining]->nm->name);
187500d97012SDavid du Colombier 					}
187600d97012SDavid du Colombier 					ptr++;
187700d97012SDavid du Colombier 			}	}
18787dd7cddfSDavid du Colombier 			ReDiRect = Inline_stub[Inlining]->anms[i];
18797dd7cddfSDavid du Colombier 			return 0;
18807dd7cddfSDavid du Colombier 	}	 }
1881219b2ee8SDavid du Colombier 
18827dd7cddfSDavid du Colombier 	yylval->sym = lookup(s);	/* symbol table */
1883219b2ee8SDavid du Colombier 	if (isutype(s))
1884219b2ee8SDavid du Colombier 		return UNAME;
1885219b2ee8SDavid du Colombier 	if (isproctype(s))
1886219b2ee8SDavid du Colombier 		return PNAME;
18877dd7cddfSDavid du Colombier 	if (iseqname(s))
18887dd7cddfSDavid du Colombier 		return INAME;
1889219b2ee8SDavid du Colombier 
1890219b2ee8SDavid du Colombier 	return NAME;
1891219b2ee8SDavid du Colombier }
1892219b2ee8SDavid du Colombier 
1893219b2ee8SDavid du Colombier int
yylex(void)1894219b2ee8SDavid du Colombier yylex(void)
1895219b2ee8SDavid du Colombier {	static int last = 0;
1896219b2ee8SDavid du Colombier 	static int hold = 0;
1897219b2ee8SDavid du Colombier 	int c;
1898219b2ee8SDavid du Colombier 	/*
1899219b2ee8SDavid du Colombier 	 * repair two common syntax mistakes with
1900219b2ee8SDavid du Colombier 	 * semi-colons before or after a '}'
1901219b2ee8SDavid du Colombier 	 */
1902219b2ee8SDavid du Colombier 	if (hold)
1903219b2ee8SDavid du Colombier 	{	c = hold;
1904219b2ee8SDavid du Colombier 		hold = 0;
1905*de2caf28SDavid du Colombier 		last_token = c;
1906219b2ee8SDavid du Colombier 	} else
1907219b2ee8SDavid du Colombier 	{	c = lex();
1908219b2ee8SDavid du Colombier 		if (last == ELSE
1909219b2ee8SDavid du Colombier 		&&  c != SEMI
1910*de2caf28SDavid du Colombier 		&&  c != ARROW
1911219b2ee8SDavid du Colombier 		&&  c != FI)
1912219b2ee8SDavid du Colombier 		{	hold = c;
1913219b2ee8SDavid du Colombier 			last = 0;
1914*de2caf28SDavid du Colombier 			last_token = SEMI;
1915219b2ee8SDavid du Colombier 			return SEMI;
1916219b2ee8SDavid du Colombier 		}
1917219b2ee8SDavid du Colombier 		if (last == '}'
1918219b2ee8SDavid du Colombier 		&&  c != PROCTYPE
1919219b2ee8SDavid du Colombier 		&&  c != INIT
1920219b2ee8SDavid du Colombier 		&&  c != CLAIM
1921219b2ee8SDavid du Colombier 		&&  c != SEP
1922219b2ee8SDavid du Colombier 		&&  c != FI
1923219b2ee8SDavid du Colombier 		&&  c != OD
1924219b2ee8SDavid du Colombier 		&&  c != '}'
1925219b2ee8SDavid du Colombier 		&&  c != UNLESS
1926219b2ee8SDavid du Colombier 		&&  c != SEMI
1927*de2caf28SDavid du Colombier 		&&  c != ARROW
1928219b2ee8SDavid du Colombier 		&&  c != EOF)
1929219b2ee8SDavid du Colombier 		{	hold = c;
1930219b2ee8SDavid du Colombier 			last = 0;
1931*de2caf28SDavid du Colombier 			last_token = SEMI;
1932219b2ee8SDavid du Colombier 			return SEMI;	/* insert ';' */
1933219b2ee8SDavid du Colombier 		}
1934*de2caf28SDavid du Colombier 		if (c == SEMI || c == ARROW)
1935312a1df1SDavid du Colombier 		{	/* if context, we're not in a typedef
1936219b2ee8SDavid du Colombier 			 * because they're global.
1937219b2ee8SDavid du Colombier 			 * if owner, we're at the end of a ref
1938219b2ee8SDavid du Colombier 			 * to a struct field -- prevent that the
1939219b2ee8SDavid du Colombier 			 * lookahead is interpreted as a field of
1940219b2ee8SDavid du Colombier 			 * the same struct...
1941219b2ee8SDavid du Colombier 			 */
1942219b2ee8SDavid du Colombier 			if (context) owner = ZS;
1943219b2ee8SDavid du Colombier 			hold = lex();	/* look ahead */
1944219b2ee8SDavid du Colombier 			if (hold == '}'
1945*de2caf28SDavid du Colombier 			||  hold == ARROW
1946219b2ee8SDavid du Colombier 			||  hold == SEMI)
1947219b2ee8SDavid du Colombier 			{	c = hold; /* omit ';' */
1948219b2ee8SDavid du Colombier 				hold = 0;
1949219b2ee8SDavid du Colombier 			}
1950219b2ee8SDavid du Colombier 		}
1951219b2ee8SDavid du Colombier 	}
1952219b2ee8SDavid du Colombier 	last = c;
19537dd7cddfSDavid du Colombier 
19547dd7cddfSDavid du Colombier 	if (IArgs)
19557dd7cddfSDavid du Colombier 	{	static int IArg_nst = 0;
1956312a1df1SDavid du Colombier 
19577dd7cddfSDavid du Colombier 		if (strcmp(yytext, ",") == 0)
19587dd7cddfSDavid du Colombier 		{	IArg_cont[++IArgno][0] = '\0';
19597dd7cddfSDavid du Colombier 		} else if (strcmp(yytext, "(") == 0)
19607dd7cddfSDavid du Colombier 		{	if (IArg_nst++ == 0)
19617dd7cddfSDavid du Colombier 			{	IArgno = 0;
19627dd7cddfSDavid du Colombier 				IArg_cont[0][0] = '\0';
19637dd7cddfSDavid du Colombier 			} else
1964*de2caf28SDavid du Colombier 			{	assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
19657dd7cddfSDavid du Colombier 				strcat(IArg_cont[IArgno], yytext);
1966*de2caf28SDavid du Colombier 			}
1967312a1df1SDavid du Colombier 		} else if (strcmp(yytext, ")") == 0)
1968312a1df1SDavid du Colombier 		{	if (--IArg_nst > 0)
1969*de2caf28SDavid du Colombier 			{	assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
1970312a1df1SDavid du Colombier 				strcat(IArg_cont[IArgno], yytext);
1971*de2caf28SDavid du Colombier 			}
1972312a1df1SDavid du Colombier 		} else if (c == CONST && yytext[0] == '\'')
1973312a1df1SDavid du Colombier 		{	sprintf(yytext, "'%c'", yylval->val);
1974*de2caf28SDavid du Colombier 			assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
1975312a1df1SDavid du Colombier 			strcat(IArg_cont[IArgno], yytext);
197600d97012SDavid du Colombier 		} else if (c == CONST)
197700d97012SDavid du Colombier 		{	sprintf(yytext, "%d", yylval->val);
1978*de2caf28SDavid du Colombier 			assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
197900d97012SDavid du Colombier 			strcat(IArg_cont[IArgno], yytext);
1980312a1df1SDavid du Colombier 		} else
1981f3793cddSDavid du Colombier 		{
1982f3793cddSDavid du Colombier 			switch (c) {
1983*de2caf28SDavid du Colombier 			case ARROW:	strcpy(yytext, "->"); break; /* NEW */
1984f3793cddSDavid du Colombier 			case SEP:	strcpy(yytext, "::"); break;
1985f3793cddSDavid du Colombier 			case SEMI:	strcpy(yytext, ";"); break;
1986f3793cddSDavid du Colombier 			case DECR:	strcpy(yytext, "--"); break;
1987f3793cddSDavid du Colombier 			case INCR: 	strcpy(yytext, "++"); break;
1988f3793cddSDavid du Colombier 			case LSHIFT:	strcpy(yytext, "<<"); break;
1989f3793cddSDavid du Colombier 			case RSHIFT:	strcpy(yytext, ">>"); break;
1990f3793cddSDavid du Colombier 			case LE:	strcpy(yytext, "<="); break;
1991f3793cddSDavid du Colombier 			case LT:	strcpy(yytext, "<"); break;
1992f3793cddSDavid du Colombier 			case GE:	strcpy(yytext, ">="); break;
1993f3793cddSDavid du Colombier 			case GT:	strcpy(yytext, ">"); break;
1994f3793cddSDavid du Colombier 			case EQ:	strcpy(yytext, "=="); break;
1995f3793cddSDavid du Colombier 			case ASGN:	strcpy(yytext, "="); break;
1996f3793cddSDavid du Colombier 			case NE:	strcpy(yytext, "!="); break;
1997f3793cddSDavid du Colombier 			case R_RCV:	strcpy(yytext, "??"); break;
1998f3793cddSDavid du Colombier 			case RCV:	strcpy(yytext, "?"); break;
1999f3793cddSDavid du Colombier 			case O_SND:	strcpy(yytext, "!!"); break;
2000f3793cddSDavid du Colombier 			case SND:	strcpy(yytext, "!"); break;
2001f3793cddSDavid du Colombier 			case AND: 	strcpy(yytext, "&&"); break;
2002f3793cddSDavid du Colombier 			case OR:	strcpy(yytext, "||"); break;
2003f3793cddSDavid du Colombier 			}
2004*de2caf28SDavid du Colombier 			assert(strlen(IArg_cont[IArgno])+strlen(yytext) < sizeof(IArg_cont));
2005f3793cddSDavid du Colombier 			strcat(IArg_cont[IArgno], yytext);
2006312a1df1SDavid du Colombier 		}
20077dd7cddfSDavid du Colombier 	}
2008219b2ee8SDavid du Colombier 	return c;
2009219b2ee8SDavid du Colombier }
2010