xref: /inferno-os/utils/iyacc/yacc.c (revision 18eb7a2d4ffc48d0a90687ace604e4e388440626)
1*18eb7a2dSCharles.Forsyth #include <lib9.h>
2*18eb7a2dSCharles.Forsyth #include <bio.h>
3*18eb7a2dSCharles.Forsyth #include <ctype.h>
4*18eb7a2dSCharles.Forsyth 
5*18eb7a2dSCharles.Forsyth #define	Bungetrune	Bungetc		/* ok for now. */
6*18eb7a2dSCharles.Forsyth 
7*18eb7a2dSCharles.Forsyth /*
8*18eb7a2dSCharles.Forsyth  * all these are 32 bit
9*18eb7a2dSCharles.Forsyth  */
10*18eb7a2dSCharles.Forsyth #define TBITSET		((32+NTERMS)/32)	/* BOTCH?? +31 */
11*18eb7a2dSCharles.Forsyth #define BIT(a,i)	((a)[(i)>>5] & (1<<((i)&037)))
12*18eb7a2dSCharles.Forsyth #define SETBIT(a,i)	((a)[(i)>>5] |= (1<<((i)&037)))
13*18eb7a2dSCharles.Forsyth #define NWORDS(n)	(((n)+32)/32)
14*18eb7a2dSCharles.Forsyth 
15*18eb7a2dSCharles.Forsyth #ifndef PARSER
16*18eb7a2dSCharles.Forsyth #define PARSER		"yaccpar"
17*18eb7a2dSCharles.Forsyth #define PARSERS		"yaccpars"
18*18eb7a2dSCharles.Forsyth #endif
19*18eb7a2dSCharles.Forsyth #define TEMPNAME	"y.tmp.XXXXXX"
20*18eb7a2dSCharles.Forsyth #define ACTNAME		"y.acts.XXXXXX"
21*18eb7a2dSCharles.Forsyth #define OFILE		"tab.c"
22*18eb7a2dSCharles.Forsyth #define FILEU		"output"
23*18eb7a2dSCharles.Forsyth #define FILED		"tab.h"
24*18eb7a2dSCharles.Forsyth #define FILEDEBUG	"debug"
25*18eb7a2dSCharles.Forsyth 
26*18eb7a2dSCharles.Forsyth enum
27*18eb7a2dSCharles.Forsyth {
28*18eb7a2dSCharles.Forsyth /*
29*18eb7a2dSCharles.Forsyth  * the following are adjustable
30*18eb7a2dSCharles.Forsyth  * according to memory size
31*18eb7a2dSCharles.Forsyth  */
32*18eb7a2dSCharles.Forsyth 	ACTSIZE		= 30000,
33*18eb7a2dSCharles.Forsyth 	MEMSIZE		= 30000,
34*18eb7a2dSCharles.Forsyth 	NSTATES		= 2000,
35*18eb7a2dSCharles.Forsyth 	NTERMS		= 255,
36*18eb7a2dSCharles.Forsyth 	NPROD		= 800,
37*18eb7a2dSCharles.Forsyth 	NNONTERM	= 300,
38*18eb7a2dSCharles.Forsyth 	TEMPSIZE	= 2000,
39*18eb7a2dSCharles.Forsyth 	CNAMSZ		= 5000,
40*18eb7a2dSCharles.Forsyth 	LSETSIZE	= 2400,
41*18eb7a2dSCharles.Forsyth 	WSETSIZE	= 350,
42*18eb7a2dSCharles.Forsyth 
43*18eb7a2dSCharles.Forsyth 	NAMESIZE	= 50,
44*18eb7a2dSCharles.Forsyth 	NTYPES		= 63,
45*18eb7a2dSCharles.Forsyth 	ISIZE		= 400,
46*18eb7a2dSCharles.Forsyth 
47*18eb7a2dSCharles.Forsyth 	PRIVATE		= 0xE000,	/* unicode private use */
48*18eb7a2dSCharles.Forsyth 
49*18eb7a2dSCharles.Forsyth 	/* relationships which must hold:
50*18eb7a2dSCharles.Forsyth 		TBITSET ints must hold NTERMS+1 bits...
51*18eb7a2dSCharles.Forsyth 		WSETSIZE >= NNONTERM
52*18eb7a2dSCharles.Forsyth 		LSETSIZE >= NNONTERM
53*18eb7a2dSCharles.Forsyth 		TEMPSIZE >= NTERMS + NNONTERM + 1
54*18eb7a2dSCharles.Forsyth 		TEMPSIZE >= NSTATES
55*18eb7a2dSCharles.Forsyth 	*/
56*18eb7a2dSCharles.Forsyth 
57*18eb7a2dSCharles.Forsyth 	NTBASE		= 010000,
58*18eb7a2dSCharles.Forsyth 	ERRCODE		= 8190,
59*18eb7a2dSCharles.Forsyth 	ACCEPTCODE	= 8191,
60*18eb7a2dSCharles.Forsyth 
61*18eb7a2dSCharles.Forsyth 	NOASC		= 0,	/* no assoc. */
62*18eb7a2dSCharles.Forsyth 	LASC		= 1,	/* left assoc. */
63*18eb7a2dSCharles.Forsyth 	RASC		= 2,	/* right assoc. */
64*18eb7a2dSCharles.Forsyth 	BASC		= 3,	/* binary assoc. */
65*18eb7a2dSCharles.Forsyth 
66*18eb7a2dSCharles.Forsyth 	/* flags for state generation */
67*18eb7a2dSCharles.Forsyth 
68*18eb7a2dSCharles.Forsyth 	DONE		= 0,
69*18eb7a2dSCharles.Forsyth 	MUSTDO		= 1,
70*18eb7a2dSCharles.Forsyth 	MUSTLOOKAHEAD	= 2,
71*18eb7a2dSCharles.Forsyth 
72*18eb7a2dSCharles.Forsyth 	/* flags for a rule having an action, and being reduced */
73*18eb7a2dSCharles.Forsyth 
74*18eb7a2dSCharles.Forsyth 	ACTFLAG		= 04,
75*18eb7a2dSCharles.Forsyth 	REDFLAG		= 010,
76*18eb7a2dSCharles.Forsyth 
77*18eb7a2dSCharles.Forsyth 	/* output parser flags */
78*18eb7a2dSCharles.Forsyth 	YYFLAG1		= -1000,
79*18eb7a2dSCharles.Forsyth 
80*18eb7a2dSCharles.Forsyth 	/* parse tokens */
81*18eb7a2dSCharles.Forsyth 	IDENTIFIER	= PRIVATE,
82*18eb7a2dSCharles.Forsyth 	MARK,
83*18eb7a2dSCharles.Forsyth 	TERM,
84*18eb7a2dSCharles.Forsyth 	LEFT,
85*18eb7a2dSCharles.Forsyth 	RIGHT,
86*18eb7a2dSCharles.Forsyth 	BINARY,
87*18eb7a2dSCharles.Forsyth 	PREC,
88*18eb7a2dSCharles.Forsyth 	LCURLY,
89*18eb7a2dSCharles.Forsyth 	IDENTCOLON,
90*18eb7a2dSCharles.Forsyth 	NUMBER,
91*18eb7a2dSCharles.Forsyth 	START,
92*18eb7a2dSCharles.Forsyth 	TYPEDEF,
93*18eb7a2dSCharles.Forsyth 	TYPENAME,
94*18eb7a2dSCharles.Forsyth 	UNION,
95*18eb7a2dSCharles.Forsyth 
96*18eb7a2dSCharles.Forsyth 	ENDFILE		= 0,
97*18eb7a2dSCharles.Forsyth 
98*18eb7a2dSCharles.Forsyth 	EMPTY		= 1,
99*18eb7a2dSCharles.Forsyth 	WHOKNOWS	= 0,
100*18eb7a2dSCharles.Forsyth 	OK		= 1,
101*18eb7a2dSCharles.Forsyth 	NOMORE		= -1000,
102*18eb7a2dSCharles.Forsyth };
103*18eb7a2dSCharles.Forsyth 
104*18eb7a2dSCharles.Forsyth 	/* macros for getting associativity and precedence levels */
105*18eb7a2dSCharles.Forsyth 
106*18eb7a2dSCharles.Forsyth #define ASSOC(i)	((i)&03)
107*18eb7a2dSCharles.Forsyth #define PLEVEL(i)	(((i)>>4)&077)
108*18eb7a2dSCharles.Forsyth #define TYPE(i)		(((i)>>10)&077)
109*18eb7a2dSCharles.Forsyth 
110*18eb7a2dSCharles.Forsyth 	/* macros for setting associativity and precedence levels */
111*18eb7a2dSCharles.Forsyth 
112*18eb7a2dSCharles.Forsyth #define SETASC(i,j)	i |= j
113*18eb7a2dSCharles.Forsyth #define SETPLEV(i,j)	i |= (j<<4)
114*18eb7a2dSCharles.Forsyth #define SETTYPE(i,j)	i |= (j<<10)
115*18eb7a2dSCharles.Forsyth 
116*18eb7a2dSCharles.Forsyth 	/* looping macros */
117*18eb7a2dSCharles.Forsyth 
118*18eb7a2dSCharles.Forsyth #define TLOOP(i)	for(i=1; i<=ntokens; i++)
119*18eb7a2dSCharles.Forsyth #define NTLOOP(i)	for(i=0; i<=nnonter; i++)
120*18eb7a2dSCharles.Forsyth #define PLOOP(s,i)	for(i=s; i<nprod; i++)
121*18eb7a2dSCharles.Forsyth #define SLOOP(i)	for(i=0; i<nstate; i++)
122*18eb7a2dSCharles.Forsyth #define WSBUMP(x)	x++
123*18eb7a2dSCharles.Forsyth #define WSLOOP(s,j)	for(j=s; j<cwp; j++)
124*18eb7a2dSCharles.Forsyth #define ITMLOOP(i,p,q)	for(q=pstate[i+1], p=pstate[i]; p<q; p++)
125*18eb7a2dSCharles.Forsyth #define SETLOOP(i)	for(i=0; i<tbitset; i++)
126*18eb7a2dSCharles.Forsyth 
127*18eb7a2dSCharles.Forsyth 	/* command to clobber tempfiles after use */
128*18eb7a2dSCharles.Forsyth 
129*18eb7a2dSCharles.Forsyth #define	ZAPFILE(x)	if(x) remove(x)
130*18eb7a2dSCharles.Forsyth 
131*18eb7a2dSCharles.Forsyth 	/* I/O descriptors */
132*18eb7a2dSCharles.Forsyth 
133*18eb7a2dSCharles.Forsyth Biobuf*	faction;	/* file for saving actions */
134*18eb7a2dSCharles.Forsyth Biobuf*	fdefine;	/* file for #defines */
135*18eb7a2dSCharles.Forsyth Biobuf*	fdebug;		/* y.debug for strings for debugging */
136*18eb7a2dSCharles.Forsyth Biobuf*	ftable;		/* y.tab.c file */
137*18eb7a2dSCharles.Forsyth Biobuf*	ftemp;		/* tempfile to pass 2 */
138*18eb7a2dSCharles.Forsyth Biobuf*	finput;		/* input file */
139*18eb7a2dSCharles.Forsyth Biobuf*	foutput;	/* y.output file */
140*18eb7a2dSCharles.Forsyth 
141*18eb7a2dSCharles.Forsyth 	/* communication variables between various I/O routines */
142*18eb7a2dSCharles.Forsyth 
143*18eb7a2dSCharles.Forsyth char*	infile;			/* input file name */
144*18eb7a2dSCharles.Forsyth int	numbval;		/* value of an input number */
145*18eb7a2dSCharles.Forsyth char	tokname[NAMESIZE+4];	/* input token name, slop for runes and 0 */
146*18eb7a2dSCharles.Forsyth 
147*18eb7a2dSCharles.Forsyth 	/* structure declarations */
148*18eb7a2dSCharles.Forsyth 
149*18eb7a2dSCharles.Forsyth typedef
150*18eb7a2dSCharles.Forsyth struct
151*18eb7a2dSCharles.Forsyth {
152*18eb7a2dSCharles.Forsyth 	int	lset[TBITSET];
153*18eb7a2dSCharles.Forsyth } Lkset;
154*18eb7a2dSCharles.Forsyth 
155*18eb7a2dSCharles.Forsyth typedef
156*18eb7a2dSCharles.Forsyth struct
157*18eb7a2dSCharles.Forsyth {
158*18eb7a2dSCharles.Forsyth 	int*	pitem;
159*18eb7a2dSCharles.Forsyth 	Lkset*	look;
160*18eb7a2dSCharles.Forsyth } Item;
161*18eb7a2dSCharles.Forsyth 
162*18eb7a2dSCharles.Forsyth typedef
163*18eb7a2dSCharles.Forsyth struct
164*18eb7a2dSCharles.Forsyth {
165*18eb7a2dSCharles.Forsyth 	char*	name;
166*18eb7a2dSCharles.Forsyth 	int	value;
167*18eb7a2dSCharles.Forsyth } Symb;
168*18eb7a2dSCharles.Forsyth 
169*18eb7a2dSCharles.Forsyth typedef
170*18eb7a2dSCharles.Forsyth struct
171*18eb7a2dSCharles.Forsyth {
172*18eb7a2dSCharles.Forsyth 	int*	pitem;
173*18eb7a2dSCharles.Forsyth 	int	flag;
174*18eb7a2dSCharles.Forsyth 	Lkset	ws;
175*18eb7a2dSCharles.Forsyth } Wset;
176*18eb7a2dSCharles.Forsyth 
177*18eb7a2dSCharles.Forsyth 	/* storage of names */
178*18eb7a2dSCharles.Forsyth 
179*18eb7a2dSCharles.Forsyth char	cnames[CNAMSZ];		/* place where token and nonterminal names are stored */
180*18eb7a2dSCharles.Forsyth int	cnamsz = CNAMSZ;	/* size of cnames */
181*18eb7a2dSCharles.Forsyth char*	cnamp = cnames;		/* place where next name is to be put in */
182*18eb7a2dSCharles.Forsyth int	ndefout = 4;		/* number of defined symbols output */
183*18eb7a2dSCharles.Forsyth char*	tempname;
184*18eb7a2dSCharles.Forsyth char*	actname;
185*18eb7a2dSCharles.Forsyth char	ttempname[] = TEMPNAME;
186*18eb7a2dSCharles.Forsyth char	tactname[] = ACTNAME;
187*18eb7a2dSCharles.Forsyth char*	parser = PARSER;
188*18eb7a2dSCharles.Forsyth char*	yydebug;
189*18eb7a2dSCharles.Forsyth char	par[256];		/* full path of parser */
190*18eb7a2dSCharles.Forsyth 
191*18eb7a2dSCharles.Forsyth 	/* storage of types */
192*18eb7a2dSCharles.Forsyth int	ntypes;			/* number of types defined */
193*18eb7a2dSCharles.Forsyth char*	typeset[NTYPES];	/* pointers to type tags */
194*18eb7a2dSCharles.Forsyth 
195*18eb7a2dSCharles.Forsyth 	/* token information */
196*18eb7a2dSCharles.Forsyth 
197*18eb7a2dSCharles.Forsyth int	ntokens = 0 ;		/* number of tokens */
198*18eb7a2dSCharles.Forsyth Symb	tokset[NTERMS];
199*18eb7a2dSCharles.Forsyth int	toklev[NTERMS];		/* vector with the precedence of the terminals */
200*18eb7a2dSCharles.Forsyth 
201*18eb7a2dSCharles.Forsyth 	/* nonterminal information */
202*18eb7a2dSCharles.Forsyth 
203*18eb7a2dSCharles.Forsyth int	nnonter = -1;		/* the number of nonterminals */
204*18eb7a2dSCharles.Forsyth Symb	nontrst[NNONTERM];
205*18eb7a2dSCharles.Forsyth int	start;			/* start symbol */
206*18eb7a2dSCharles.Forsyth 
207*18eb7a2dSCharles.Forsyth 	/* assigned token type values */
208*18eb7a2dSCharles.Forsyth int	extval = 0;
209*18eb7a2dSCharles.Forsyth 
210*18eb7a2dSCharles.Forsyth char*	ytabc = OFILE;	/* name of y.tab.c */
211*18eb7a2dSCharles.Forsyth 
212*18eb7a2dSCharles.Forsyth 	/* grammar rule information */
213*18eb7a2dSCharles.Forsyth 
214*18eb7a2dSCharles.Forsyth int	mem0[MEMSIZE] ;		/* production storage */
215*18eb7a2dSCharles.Forsyth int*	mem = mem0;
216*18eb7a2dSCharles.Forsyth int	nprod = 1;		/* number of productions */
217*18eb7a2dSCharles.Forsyth int*	prdptr[NPROD];		/* pointers to descriptions of productions */
218*18eb7a2dSCharles.Forsyth int	levprd[NPROD];		/* precedence levels for the productions */
219*18eb7a2dSCharles.Forsyth int	rlines[NPROD];		/* line number for this rule */
220*18eb7a2dSCharles.Forsyth 
221*18eb7a2dSCharles.Forsyth 	/* state information */
222*18eb7a2dSCharles.Forsyth 
223*18eb7a2dSCharles.Forsyth int	nstate = 0;		/* number of states */
224*18eb7a2dSCharles.Forsyth Item*	pstate[NSTATES+2];	/* pointers to the descriptions of the states */
225*18eb7a2dSCharles.Forsyth int	tystate[NSTATES];	/* contains type information about the states */
226*18eb7a2dSCharles.Forsyth int	defact[NSTATES];	/* the default actions of states */
227*18eb7a2dSCharles.Forsyth int	tstates[NTERMS];	/* states generated by terminal gotos */
228*18eb7a2dSCharles.Forsyth int	ntstates[NNONTERM]; 	/* states generated by nonterminal gotos */
229*18eb7a2dSCharles.Forsyth int	mstates[NSTATES];	/* chain of overflows of term/nonterm generation lists  */
230*18eb7a2dSCharles.Forsyth int	lastred; 		/* the number of the last reduction of a state */
231*18eb7a2dSCharles.Forsyth 
232*18eb7a2dSCharles.Forsyth 	/* lookahead set information */
233*18eb7a2dSCharles.Forsyth 
234*18eb7a2dSCharles.Forsyth Lkset	lkst[LSETSIZE];
235*18eb7a2dSCharles.Forsyth int	nolook;			/* flag to turn off lookahead computations */
236*18eb7a2dSCharles.Forsyth int	tbitset;		/* size of lookahead sets */
237*18eb7a2dSCharles.Forsyth int	nlset = 0;		/* next lookahead set index */
238*18eb7a2dSCharles.Forsyth int	nolook = 0;		/* flag to suppress lookahead computations */
239*18eb7a2dSCharles.Forsyth Lkset	clset;  		/* temporary storage for lookahead computations */
240*18eb7a2dSCharles.Forsyth 
241*18eb7a2dSCharles.Forsyth 	/* working set information */
242*18eb7a2dSCharles.Forsyth 
243*18eb7a2dSCharles.Forsyth Wset	wsets[WSETSIZE];
244*18eb7a2dSCharles.Forsyth Wset*	cwp;
245*18eb7a2dSCharles.Forsyth 
246*18eb7a2dSCharles.Forsyth 	/* storage for action table */
247*18eb7a2dSCharles.Forsyth 
248*18eb7a2dSCharles.Forsyth int	amem[ACTSIZE];		/* action table storage */
249*18eb7a2dSCharles.Forsyth int*	memp = amem;		/* next free action table position */
250*18eb7a2dSCharles.Forsyth int	indgo[NSTATES];		/* index to the stored goto table */
251*18eb7a2dSCharles.Forsyth 
252*18eb7a2dSCharles.Forsyth 	/* temporary vector, indexable by states, terms, or ntokens */
253*18eb7a2dSCharles.Forsyth 
254*18eb7a2dSCharles.Forsyth int	temp1[TEMPSIZE];	/* temporary storage, indexed by terms + ntokens or states */
255*18eb7a2dSCharles.Forsyth int	lineno = 1;		/* current input line number */
256*18eb7a2dSCharles.Forsyth int	fatfl = 1;  		/* if on, error is fatal */
257*18eb7a2dSCharles.Forsyth int	nerrors = 0;		/* number of errors */
258*18eb7a2dSCharles.Forsyth 
259*18eb7a2dSCharles.Forsyth 	/* statistics collection variables */
260*18eb7a2dSCharles.Forsyth 
261*18eb7a2dSCharles.Forsyth int	zzgoent;
262*18eb7a2dSCharles.Forsyth int	zzgobest;
263*18eb7a2dSCharles.Forsyth int	zzacent;
264*18eb7a2dSCharles.Forsyth int	zzexcp;
265*18eb7a2dSCharles.Forsyth int	zzclose;
266*18eb7a2dSCharles.Forsyth int	zzrrconf;
267*18eb7a2dSCharles.Forsyth int	zzsrconf;
268*18eb7a2dSCharles.Forsyth 
269*18eb7a2dSCharles.Forsyth int*	ggreed = lkst[0].lset;
270*18eb7a2dSCharles.Forsyth int*	pgo = wsets[0].ws.lset;
271*18eb7a2dSCharles.Forsyth int*	yypgo = &nontrst[0].value;
272*18eb7a2dSCharles.Forsyth 
273*18eb7a2dSCharles.Forsyth int	maxspr = 0;  		/* maximum spread of any entry */
274*18eb7a2dSCharles.Forsyth int	maxoff = 0;  		/* maximum offset into a array */
275*18eb7a2dSCharles.Forsyth int*	pmem = mem0;
276*18eb7a2dSCharles.Forsyth int*	maxa;
277*18eb7a2dSCharles.Forsyth int	nxdb = 0;
278*18eb7a2dSCharles.Forsyth int	adb = 0;
279*18eb7a2dSCharles.Forsyth 
280*18eb7a2dSCharles.Forsyth 
281*18eb7a2dSCharles.Forsyth 	/* storage for information about the nonterminals */
282*18eb7a2dSCharles.Forsyth 
283*18eb7a2dSCharles.Forsyth int**	pres[NNONTERM+2];  	/* vector of pointers to productions yielding each nonterminal */
284*18eb7a2dSCharles.Forsyth Lkset*	pfirst[NNONTERM+2];	/* vector of pointers to first sets for each nonterminal */
285*18eb7a2dSCharles.Forsyth int	pempty[NNONTERM+1];	/* vector of nonterminals nontrivially deriving e */
286*18eb7a2dSCharles.Forsyth 
287*18eb7a2dSCharles.Forsyth 	/* random stuff picked out from between functions */
288*18eb7a2dSCharles.Forsyth 
289*18eb7a2dSCharles.Forsyth int	indebug = 0;
290*18eb7a2dSCharles.Forsyth Wset*	zzcwp = wsets;
291*18eb7a2dSCharles.Forsyth int	zzgoent = 0;
292*18eb7a2dSCharles.Forsyth int	zzgobest = 0;
293*18eb7a2dSCharles.Forsyth int	zzacent = 0;
294*18eb7a2dSCharles.Forsyth int	zzexcp = 0;
295*18eb7a2dSCharles.Forsyth int	zzclose = 0;
296*18eb7a2dSCharles.Forsyth int	zzsrconf = 0;
297*18eb7a2dSCharles.Forsyth int*	zzmemsz = mem0;
298*18eb7a2dSCharles.Forsyth int	zzrrconf = 0;
299*18eb7a2dSCharles.Forsyth int	pidebug = 0;		/* debugging flag for putitem */
300*18eb7a2dSCharles.Forsyth int	gsdebug = 0;
301*18eb7a2dSCharles.Forsyth int	cldebug = 0;		/* debugging flag for closure */
302*18eb7a2dSCharles.Forsyth int	pkdebug = 0;
303*18eb7a2dSCharles.Forsyth int	g2debug = 0;
304*18eb7a2dSCharles.Forsyth 
305*18eb7a2dSCharles.Forsyth struct
306*18eb7a2dSCharles.Forsyth {
307*18eb7a2dSCharles.Forsyth 	char*	name;
308*18eb7a2dSCharles.Forsyth 	long	value;
309*18eb7a2dSCharles.Forsyth } resrv[] =
310*18eb7a2dSCharles.Forsyth {
311*18eb7a2dSCharles.Forsyth 	"binary",	BINARY,
312*18eb7a2dSCharles.Forsyth 	"left",		LEFT,
313*18eb7a2dSCharles.Forsyth 	"nonassoc",	BINARY,
314*18eb7a2dSCharles.Forsyth 	"prec",		PREC,
315*18eb7a2dSCharles.Forsyth 	"right",	RIGHT,
316*18eb7a2dSCharles.Forsyth 	"start",	START,
317*18eb7a2dSCharles.Forsyth 	"term",		TERM,
318*18eb7a2dSCharles.Forsyth 	"token",	TERM,
319*18eb7a2dSCharles.Forsyth 	"type",		TYPEDEF,
320*18eb7a2dSCharles.Forsyth 	"union",	UNION,
321*18eb7a2dSCharles.Forsyth 	0,
322*18eb7a2dSCharles.Forsyth };
323*18eb7a2dSCharles.Forsyth 
324*18eb7a2dSCharles.Forsyth 	/* define functions */
325*18eb7a2dSCharles.Forsyth 
326*18eb7a2dSCharles.Forsyth void	main(int, char**);
327*18eb7a2dSCharles.Forsyth void	others(void);
328*18eb7a2dSCharles.Forsyth char*	chcopy(char*, char*);
329*18eb7a2dSCharles.Forsyth char*	writem(int*);
330*18eb7a2dSCharles.Forsyth char*	symnam(int);
331*18eb7a2dSCharles.Forsyth void	summary(void);
332*18eb7a2dSCharles.Forsyth void	error(char*, ...);
333*18eb7a2dSCharles.Forsyth void	aryfil(int*, int, int);
334*18eb7a2dSCharles.Forsyth int	setunion(int*, int*);
335*18eb7a2dSCharles.Forsyth void	prlook(Lkset*);
336*18eb7a2dSCharles.Forsyth void	cpres(void);
337*18eb7a2dSCharles.Forsyth void	cpfir(void);
338*18eb7a2dSCharles.Forsyth int	state(int);
339*18eb7a2dSCharles.Forsyth void	putitem(int*, Lkset*);
340*18eb7a2dSCharles.Forsyth void	cempty(void);
341*18eb7a2dSCharles.Forsyth void	stagen(void);
342*18eb7a2dSCharles.Forsyth void	closure(int);
343*18eb7a2dSCharles.Forsyth Lkset*	flset(Lkset*);
344*18eb7a2dSCharles.Forsyth void	cleantmp(void);
345*18eb7a2dSCharles.Forsyth void	intr(void);
346*18eb7a2dSCharles.Forsyth void	setup(int, char**);
347*18eb7a2dSCharles.Forsyth void	finact(void);
348*18eb7a2dSCharles.Forsyth int	defin(int, char*);
349*18eb7a2dSCharles.Forsyth void	defout(int);
350*18eb7a2dSCharles.Forsyth char*	cstash(char*);
351*18eb7a2dSCharles.Forsyth long	gettok(void);
352*18eb7a2dSCharles.Forsyth int	fdtype(int);
353*18eb7a2dSCharles.Forsyth int	chfind(int, char*);
354*18eb7a2dSCharles.Forsyth void	cpyunion(void);
355*18eb7a2dSCharles.Forsyth void	cpycode(void);
356*18eb7a2dSCharles.Forsyth int	skipcom(void);
357*18eb7a2dSCharles.Forsyth void	cpyact(int);
358*18eb7a2dSCharles.Forsyth void	openup(char*, int, int, int, char*);
359*18eb7a2dSCharles.Forsyth void	output(void);
360*18eb7a2dSCharles.Forsyth int	apack(int*, int);
361*18eb7a2dSCharles.Forsyth void	go2out(void);
362*18eb7a2dSCharles.Forsyth void	go2gen(int);
363*18eb7a2dSCharles.Forsyth void	precftn(int, int, int);
364*18eb7a2dSCharles.Forsyth void	wract(int);
365*18eb7a2dSCharles.Forsyth void	wrstate(int);
366*18eb7a2dSCharles.Forsyth void	warray(char*, int*, int);
367*18eb7a2dSCharles.Forsyth void	hideprod(void);
368*18eb7a2dSCharles.Forsyth void	callopt(void);
369*18eb7a2dSCharles.Forsyth void	gin(int);
370*18eb7a2dSCharles.Forsyth void	stin(int);
371*18eb7a2dSCharles.Forsyth int	nxti(void);
372*18eb7a2dSCharles.Forsyth void	osummary(void);
373*18eb7a2dSCharles.Forsyth void	aoutput(void);
374*18eb7a2dSCharles.Forsyth void	arout(char*, int*, int);
375*18eb7a2dSCharles.Forsyth int	gtnm(void);
376*18eb7a2dSCharles.Forsyth 
377*18eb7a2dSCharles.Forsyth void
main(int argc,char * argv[])378*18eb7a2dSCharles.Forsyth main(int argc, char *argv[])
379*18eb7a2dSCharles.Forsyth {
380*18eb7a2dSCharles.Forsyth 
381*18eb7a2dSCharles.Forsyth 	setup(argc, argv);	/* initialize and read productions */
382*18eb7a2dSCharles.Forsyth 	tbitset = NWORDS(ntokens);
383*18eb7a2dSCharles.Forsyth 	cpres();		/* make table of which productions yield a given nonterminal */
384*18eb7a2dSCharles.Forsyth 	cempty();		/* make a table of which nonterminals can match the empty string */
385*18eb7a2dSCharles.Forsyth 	cpfir();		/* make a table of firsts of nonterminals */
386*18eb7a2dSCharles.Forsyth 	stagen();		/* generate the states */
387*18eb7a2dSCharles.Forsyth 	output();		/* write the states and the tables */
388*18eb7a2dSCharles.Forsyth 	go2out();
389*18eb7a2dSCharles.Forsyth 	hideprod();
390*18eb7a2dSCharles.Forsyth 	summary();
391*18eb7a2dSCharles.Forsyth 	callopt();
392*18eb7a2dSCharles.Forsyth 	others();
393*18eb7a2dSCharles.Forsyth 	exits(0);
394*18eb7a2dSCharles.Forsyth }
395*18eb7a2dSCharles.Forsyth 
396*18eb7a2dSCharles.Forsyth /*
397*18eb7a2dSCharles.Forsyth  * put out other arrays, copy the parsers
398*18eb7a2dSCharles.Forsyth  */
399*18eb7a2dSCharles.Forsyth void
others(void)400*18eb7a2dSCharles.Forsyth others(void)
401*18eb7a2dSCharles.Forsyth {
402*18eb7a2dSCharles.Forsyth 	int c, i, j;
403*18eb7a2dSCharles.Forsyth 
404*18eb7a2dSCharles.Forsyth 	finput = Bopen(parser, OREAD);
405*18eb7a2dSCharles.Forsyth 	if(finput == 0)
406*18eb7a2dSCharles.Forsyth 		error("cannot find parser %s", parser);
407*18eb7a2dSCharles.Forsyth 	warray("yyr1", levprd, nprod);
408*18eb7a2dSCharles.Forsyth 	aryfil(temp1, nprod, 0);
409*18eb7a2dSCharles.Forsyth 	PLOOP(1, i)
410*18eb7a2dSCharles.Forsyth 		temp1[i] = prdptr[i+1]-prdptr[i]-2;
411*18eb7a2dSCharles.Forsyth 	warray("yyr2", temp1, nprod);
412*18eb7a2dSCharles.Forsyth 
413*18eb7a2dSCharles.Forsyth 	aryfil(temp1, nstate, -1000);
414*18eb7a2dSCharles.Forsyth 	TLOOP(i)
415*18eb7a2dSCharles.Forsyth 		for(j=tstates[i]; j!=0; j=mstates[j])
416*18eb7a2dSCharles.Forsyth 			temp1[j] = i;
417*18eb7a2dSCharles.Forsyth 	NTLOOP(i)
418*18eb7a2dSCharles.Forsyth 		for(j=ntstates[i]; j!=0; j=mstates[j])
419*18eb7a2dSCharles.Forsyth 			temp1[j] = -i;
420*18eb7a2dSCharles.Forsyth 	warray("yychk", temp1, nstate);
421*18eb7a2dSCharles.Forsyth 	warray("yydef", defact, nstate);
422*18eb7a2dSCharles.Forsyth 
423*18eb7a2dSCharles.Forsyth 	/* put out token translation tables */
424*18eb7a2dSCharles.Forsyth 	/* table 1 has 0-256 */
425*18eb7a2dSCharles.Forsyth 	aryfil(temp1, 256, 0);
426*18eb7a2dSCharles.Forsyth 	c = 0;
427*18eb7a2dSCharles.Forsyth 	TLOOP(i) {
428*18eb7a2dSCharles.Forsyth 		j = tokset[i].value;
429*18eb7a2dSCharles.Forsyth 		if(j >= 0 && j < 256) {
430*18eb7a2dSCharles.Forsyth 			if(temp1[j]) {
431*18eb7a2dSCharles.Forsyth 				print("yacc bug -- cant have 2 different Ts with same value\n");
432*18eb7a2dSCharles.Forsyth 				print("	%s and %s\n", tokset[i].name, tokset[temp1[j]].name);
433*18eb7a2dSCharles.Forsyth 				nerrors++;
434*18eb7a2dSCharles.Forsyth 			}
435*18eb7a2dSCharles.Forsyth 			temp1[j] = i;
436*18eb7a2dSCharles.Forsyth 			if(j > c)
437*18eb7a2dSCharles.Forsyth 				c = j;
438*18eb7a2dSCharles.Forsyth 		}
439*18eb7a2dSCharles.Forsyth 	}
440*18eb7a2dSCharles.Forsyth 	warray("yytok1", temp1, c+1);
441*18eb7a2dSCharles.Forsyth 
442*18eb7a2dSCharles.Forsyth 	/* table 2 has PRIVATE-PRIVATE+256 */
443*18eb7a2dSCharles.Forsyth 	aryfil(temp1, 256, 0);
444*18eb7a2dSCharles.Forsyth 	c = 0;
445*18eb7a2dSCharles.Forsyth 	TLOOP(i) {
446*18eb7a2dSCharles.Forsyth 		j = tokset[i].value - PRIVATE;
447*18eb7a2dSCharles.Forsyth 		if(j >= 0 && j < 256) {
448*18eb7a2dSCharles.Forsyth 			if(temp1[j]) {
449*18eb7a2dSCharles.Forsyth 				print("yacc bug -- cant have 2 different Ts with same value\n");
450*18eb7a2dSCharles.Forsyth 				print("	%s and %s\n", tokset[i].name, tokset[temp1[j]].name);
451*18eb7a2dSCharles.Forsyth 				nerrors++;
452*18eb7a2dSCharles.Forsyth 			}
453*18eb7a2dSCharles.Forsyth 			temp1[j] = i;
454*18eb7a2dSCharles.Forsyth 			if(j > c)
455*18eb7a2dSCharles.Forsyth 				c = j;
456*18eb7a2dSCharles.Forsyth 		}
457*18eb7a2dSCharles.Forsyth 	}
458*18eb7a2dSCharles.Forsyth 	warray("yytok2", temp1, c+1);
459*18eb7a2dSCharles.Forsyth 
460*18eb7a2dSCharles.Forsyth 	/* table 3 has everything else */
461*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "long	yytok3[] =\n{\n");
462*18eb7a2dSCharles.Forsyth 	c = 0;
463*18eb7a2dSCharles.Forsyth 	TLOOP(i) {
464*18eb7a2dSCharles.Forsyth 		j = tokset[i].value;
465*18eb7a2dSCharles.Forsyth 		if(j >= 0 && j < 256)
466*18eb7a2dSCharles.Forsyth 			continue;
467*18eb7a2dSCharles.Forsyth 		if(j >= PRIVATE && j < 256+PRIVATE)
468*18eb7a2dSCharles.Forsyth 			continue;
469*18eb7a2dSCharles.Forsyth 
470*18eb7a2dSCharles.Forsyth 		Bprint(ftable, "%4d,%4d,", j, i);
471*18eb7a2dSCharles.Forsyth 		c++;
472*18eb7a2dSCharles.Forsyth 		if(c%5 == 0)
473*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "\n");
474*18eb7a2dSCharles.Forsyth 	}
475*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "%4d\n};\n", 0);
476*18eb7a2dSCharles.Forsyth 
477*18eb7a2dSCharles.Forsyth 	/* copy parser text */
478*18eb7a2dSCharles.Forsyth 	while((c=Bgetrune(finput)) != Beof) {
479*18eb7a2dSCharles.Forsyth 		if(c == '$') {
480*18eb7a2dSCharles.Forsyth 			if((c = Bgetrune(finput)) != 'A')
481*18eb7a2dSCharles.Forsyth 				Bputrune(ftable, '$');
482*18eb7a2dSCharles.Forsyth 			else { /* copy actions */
483*18eb7a2dSCharles.Forsyth 				faction = Bopen(actname, OREAD);
484*18eb7a2dSCharles.Forsyth 				if(faction == 0)
485*18eb7a2dSCharles.Forsyth 					error("cannot reopen action tempfile");
486*18eb7a2dSCharles.Forsyth 				while((c=Bgetrune(faction)) != Beof)
487*18eb7a2dSCharles.Forsyth 					Bputrune(ftable, c);
488*18eb7a2dSCharles.Forsyth 				Bterm(faction);
489*18eb7a2dSCharles.Forsyth 				ZAPFILE(actname);
490*18eb7a2dSCharles.Forsyth 				c = Bgetrune(finput);
491*18eb7a2dSCharles.Forsyth 			}
492*18eb7a2dSCharles.Forsyth 		}
493*18eb7a2dSCharles.Forsyth 		Bputrune(ftable, c);
494*18eb7a2dSCharles.Forsyth 	}
495*18eb7a2dSCharles.Forsyth 	Bterm(ftable);
496*18eb7a2dSCharles.Forsyth }
497*18eb7a2dSCharles.Forsyth 
498*18eb7a2dSCharles.Forsyth /*
499*18eb7a2dSCharles.Forsyth  * copies string q into p, returning next free char ptr
500*18eb7a2dSCharles.Forsyth  */
501*18eb7a2dSCharles.Forsyth char*
chcopy(char * p,char * q)502*18eb7a2dSCharles.Forsyth chcopy(char* p, char* q)
503*18eb7a2dSCharles.Forsyth {
504*18eb7a2dSCharles.Forsyth 	int c;
505*18eb7a2dSCharles.Forsyth 
506*18eb7a2dSCharles.Forsyth 	while(c = *q) {
507*18eb7a2dSCharles.Forsyth 		if(c == '"')
508*18eb7a2dSCharles.Forsyth 			*p++ = '\\';
509*18eb7a2dSCharles.Forsyth 		*p++ = c;
510*18eb7a2dSCharles.Forsyth 		q++;
511*18eb7a2dSCharles.Forsyth 	}
512*18eb7a2dSCharles.Forsyth 	*p = 0;
513*18eb7a2dSCharles.Forsyth 	return p;
514*18eb7a2dSCharles.Forsyth }
515*18eb7a2dSCharles.Forsyth 
516*18eb7a2dSCharles.Forsyth /*
517*18eb7a2dSCharles.Forsyth  * creates output string for item pointed to by pp
518*18eb7a2dSCharles.Forsyth  */
519*18eb7a2dSCharles.Forsyth char*
writem(int * pp)520*18eb7a2dSCharles.Forsyth writem(int *pp)
521*18eb7a2dSCharles.Forsyth {
522*18eb7a2dSCharles.Forsyth 	int i,*p;
523*18eb7a2dSCharles.Forsyth 	static char sarr[ISIZE];
524*18eb7a2dSCharles.Forsyth 	char* q;
525*18eb7a2dSCharles.Forsyth 
526*18eb7a2dSCharles.Forsyth 	for(p=pp; *p>0; p++)
527*18eb7a2dSCharles.Forsyth 		;
528*18eb7a2dSCharles.Forsyth 	p = prdptr[-*p];
529*18eb7a2dSCharles.Forsyth 	q = chcopy(sarr, nontrst[*p-NTBASE].name);
530*18eb7a2dSCharles.Forsyth 	q = chcopy(q, ": ");
531*18eb7a2dSCharles.Forsyth 	for(;;) {
532*18eb7a2dSCharles.Forsyth 		*q = ' ';
533*18eb7a2dSCharles.Forsyth 		p++;
534*18eb7a2dSCharles.Forsyth 		if(p == pp)
535*18eb7a2dSCharles.Forsyth 			*q = '.';
536*18eb7a2dSCharles.Forsyth 		q++;
537*18eb7a2dSCharles.Forsyth 		*q = '\0';
538*18eb7a2dSCharles.Forsyth 		i = *p;
539*18eb7a2dSCharles.Forsyth 		if(i <= 0)
540*18eb7a2dSCharles.Forsyth 			break;
541*18eb7a2dSCharles.Forsyth 		q = chcopy(q, symnam(i));
542*18eb7a2dSCharles.Forsyth 		if(q > &sarr[ISIZE-30])
543*18eb7a2dSCharles.Forsyth 			error("item too big");
544*18eb7a2dSCharles.Forsyth 	}
545*18eb7a2dSCharles.Forsyth 
546*18eb7a2dSCharles.Forsyth 	/* an item calling for a reduction */
547*18eb7a2dSCharles.Forsyth 	i = *pp;
548*18eb7a2dSCharles.Forsyth 	if(i < 0 ) {
549*18eb7a2dSCharles.Forsyth 		q = chcopy(q, "    (");
550*18eb7a2dSCharles.Forsyth 		sprint(q, "%d)", -i);
551*18eb7a2dSCharles.Forsyth 	}
552*18eb7a2dSCharles.Forsyth 	return sarr;
553*18eb7a2dSCharles.Forsyth }
554*18eb7a2dSCharles.Forsyth 
555*18eb7a2dSCharles.Forsyth /*
556*18eb7a2dSCharles.Forsyth  * return a pointer to the name of symbol i
557*18eb7a2dSCharles.Forsyth  */
558*18eb7a2dSCharles.Forsyth char*
symnam(int i)559*18eb7a2dSCharles.Forsyth symnam(int i)
560*18eb7a2dSCharles.Forsyth {
561*18eb7a2dSCharles.Forsyth 	char* cp;
562*18eb7a2dSCharles.Forsyth 
563*18eb7a2dSCharles.Forsyth 	cp = (i >= NTBASE)? nontrst[i-NTBASE].name: tokset[i].name;
564*18eb7a2dSCharles.Forsyth 	if(*cp == ' ')
565*18eb7a2dSCharles.Forsyth 		cp++;
566*18eb7a2dSCharles.Forsyth 	return cp;
567*18eb7a2dSCharles.Forsyth }
568*18eb7a2dSCharles.Forsyth 
569*18eb7a2dSCharles.Forsyth /*
570*18eb7a2dSCharles.Forsyth  * output the summary on y.output
571*18eb7a2dSCharles.Forsyth  */
572*18eb7a2dSCharles.Forsyth void
summary(void)573*18eb7a2dSCharles.Forsyth summary(void)
574*18eb7a2dSCharles.Forsyth {
575*18eb7a2dSCharles.Forsyth 
576*18eb7a2dSCharles.Forsyth 	if(foutput != 0) {
577*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "\n%d/%d terminals, %d/%d nonterminals\n",
578*18eb7a2dSCharles.Forsyth 			ntokens, NTERMS, nnonter, NNONTERM);
579*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "%d/%d grammar rules, %d/%d states\n",
580*18eb7a2dSCharles.Forsyth 			nprod, NPROD, nstate, NSTATES);
581*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n",
582*18eb7a2dSCharles.Forsyth 			zzsrconf, zzrrconf);
583*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "%d/%d working sets used\n",
584*18eb7a2dSCharles.Forsyth 			(int)(zzcwp-wsets), WSETSIZE);
585*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "memory: states,etc. %d/%d, parser %d/%d\n",
586*18eb7a2dSCharles.Forsyth 			(int)(zzmemsz-mem0), MEMSIZE, (int)(memp-amem), ACTSIZE);
587*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE);
588*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "%d extra closures\n", zzclose - 2*nstate);
589*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "%d shift entries, %d exceptions\n", zzacent, zzexcp);
590*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "%d goto entries\n", zzgoent);
591*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "%d entries saved by goto default\n", zzgobest);
592*18eb7a2dSCharles.Forsyth 	}
593*18eb7a2dSCharles.Forsyth 	if(zzsrconf != 0 || zzrrconf != 0) {
594*18eb7a2dSCharles.Forsyth 		print("\nconflicts: ");
595*18eb7a2dSCharles.Forsyth 		if(zzsrconf)
596*18eb7a2dSCharles.Forsyth 			print("%d shift/reduce", zzsrconf);
597*18eb7a2dSCharles.Forsyth 		if(zzsrconf && zzrrconf)
598*18eb7a2dSCharles.Forsyth 			print(", ");
599*18eb7a2dSCharles.Forsyth 		if(zzrrconf)
600*18eb7a2dSCharles.Forsyth 			print("%d reduce/reduce", zzrrconf);
601*18eb7a2dSCharles.Forsyth 		print("\n");
602*18eb7a2dSCharles.Forsyth 	}
603*18eb7a2dSCharles.Forsyth 	if(ftemp != 0) {
604*18eb7a2dSCharles.Forsyth 		Bterm(ftemp);
605*18eb7a2dSCharles.Forsyth 		ftemp = 0;
606*18eb7a2dSCharles.Forsyth 	}
607*18eb7a2dSCharles.Forsyth 	if(fdefine != 0) {
608*18eb7a2dSCharles.Forsyth 		Bterm(fdefine);
609*18eb7a2dSCharles.Forsyth 		fdefine = 0;
610*18eb7a2dSCharles.Forsyth 	}
611*18eb7a2dSCharles.Forsyth }
612*18eb7a2dSCharles.Forsyth 
613*18eb7a2dSCharles.Forsyth /*
614*18eb7a2dSCharles.Forsyth  * write out error comment -- NEEDS WORK
615*18eb7a2dSCharles.Forsyth  */
616*18eb7a2dSCharles.Forsyth void
error(char * s,...)617*18eb7a2dSCharles.Forsyth error(char *s, ...)
618*18eb7a2dSCharles.Forsyth {
619*18eb7a2dSCharles.Forsyth 
620*18eb7a2dSCharles.Forsyth 	nerrors++;
621*18eb7a2dSCharles.Forsyth 	fprint(2, "\n fatal error:");
622*18eb7a2dSCharles.Forsyth 	fprint(2, s, (&s)[1]);
623*18eb7a2dSCharles.Forsyth 	fprint(2, ", %s:%d\n", infile, lineno);
624*18eb7a2dSCharles.Forsyth 	if(!fatfl)
625*18eb7a2dSCharles.Forsyth 		return;
626*18eb7a2dSCharles.Forsyth 	summary();
627*18eb7a2dSCharles.Forsyth 	cleantmp();
628*18eb7a2dSCharles.Forsyth 	exits("error");
629*18eb7a2dSCharles.Forsyth }
630*18eb7a2dSCharles.Forsyth 
631*18eb7a2dSCharles.Forsyth /*
632*18eb7a2dSCharles.Forsyth  * set elements 0 through n-1 to c
633*18eb7a2dSCharles.Forsyth  */
634*18eb7a2dSCharles.Forsyth void
aryfil(int * v,int n,int c)635*18eb7a2dSCharles.Forsyth aryfil(int *v, int n, int c)
636*18eb7a2dSCharles.Forsyth {
637*18eb7a2dSCharles.Forsyth 	int i;
638*18eb7a2dSCharles.Forsyth 
639*18eb7a2dSCharles.Forsyth 	for(i=0; i<n; i++)
640*18eb7a2dSCharles.Forsyth 		v[i] = c;
641*18eb7a2dSCharles.Forsyth }
642*18eb7a2dSCharles.Forsyth 
643*18eb7a2dSCharles.Forsyth /*
644*18eb7a2dSCharles.Forsyth  * set a to the union of a and b
645*18eb7a2dSCharles.Forsyth  * return 1 if b is not a subset of a, 0 otherwise
646*18eb7a2dSCharles.Forsyth  */
647*18eb7a2dSCharles.Forsyth int
setunion(int * a,int * b)648*18eb7a2dSCharles.Forsyth setunion(int *a, int *b)
649*18eb7a2dSCharles.Forsyth {
650*18eb7a2dSCharles.Forsyth 	int i, x, sub;
651*18eb7a2dSCharles.Forsyth 
652*18eb7a2dSCharles.Forsyth 	sub = 0;
653*18eb7a2dSCharles.Forsyth 	SETLOOP(i) {
654*18eb7a2dSCharles.Forsyth 		x = *a;
655*18eb7a2dSCharles.Forsyth 		*a |= *b;
656*18eb7a2dSCharles.Forsyth 		if(*a != x)
657*18eb7a2dSCharles.Forsyth 			sub = 1;
658*18eb7a2dSCharles.Forsyth 		a++;
659*18eb7a2dSCharles.Forsyth 		b++;
660*18eb7a2dSCharles.Forsyth 	}
661*18eb7a2dSCharles.Forsyth 	return sub;
662*18eb7a2dSCharles.Forsyth }
663*18eb7a2dSCharles.Forsyth 
664*18eb7a2dSCharles.Forsyth void
prlook(Lkset * p)665*18eb7a2dSCharles.Forsyth prlook(Lkset* p)
666*18eb7a2dSCharles.Forsyth {
667*18eb7a2dSCharles.Forsyth 	int j, *pp;
668*18eb7a2dSCharles.Forsyth 
669*18eb7a2dSCharles.Forsyth 	pp = p->lset;
670*18eb7a2dSCharles.Forsyth 	if(pp == 0)
671*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "\tNULL");
672*18eb7a2dSCharles.Forsyth 	else {
673*18eb7a2dSCharles.Forsyth 		Bprint(foutput, " { ");
674*18eb7a2dSCharles.Forsyth 		TLOOP(j)
675*18eb7a2dSCharles.Forsyth 			if(BIT(pp,j))
676*18eb7a2dSCharles.Forsyth 				Bprint(foutput, "%s ", symnam(j));
677*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "}");
678*18eb7a2dSCharles.Forsyth 	}
679*18eb7a2dSCharles.Forsyth }
680*18eb7a2dSCharles.Forsyth 
681*18eb7a2dSCharles.Forsyth /*
682*18eb7a2dSCharles.Forsyth  * compute an array with the beginnings of  productions yielding given nonterminals
683*18eb7a2dSCharles.Forsyth  * The array pres points to these lists
684*18eb7a2dSCharles.Forsyth  * the array pyield has the lists: the total size is only NPROD+1
685*18eb7a2dSCharles.Forsyth  */
686*18eb7a2dSCharles.Forsyth void
cpres(void)687*18eb7a2dSCharles.Forsyth cpres(void)
688*18eb7a2dSCharles.Forsyth {
689*18eb7a2dSCharles.Forsyth 	int c, j, i, **pmem;
690*18eb7a2dSCharles.Forsyth 	static int *pyield[NPROD];
691*18eb7a2dSCharles.Forsyth 
692*18eb7a2dSCharles.Forsyth 	pmem = pyield;
693*18eb7a2dSCharles.Forsyth 	NTLOOP(i) {
694*18eb7a2dSCharles.Forsyth 		c = i+NTBASE;
695*18eb7a2dSCharles.Forsyth 		pres[i] = pmem;
696*18eb7a2dSCharles.Forsyth 		fatfl = 0;  	/* make undefined  symbols  nonfatal */
697*18eb7a2dSCharles.Forsyth 		PLOOP(0, j)
698*18eb7a2dSCharles.Forsyth 			if(*prdptr[j] == c)
699*18eb7a2dSCharles.Forsyth 				*pmem++ =  prdptr[j]+1;
700*18eb7a2dSCharles.Forsyth 		if(pres[i] == pmem)
701*18eb7a2dSCharles.Forsyth 			error("nonterminal %s not defined!", nontrst[i].name);
702*18eb7a2dSCharles.Forsyth 	}
703*18eb7a2dSCharles.Forsyth 	pres[i] = pmem;
704*18eb7a2dSCharles.Forsyth 	fatfl = 1;
705*18eb7a2dSCharles.Forsyth 	if(nerrors) {
706*18eb7a2dSCharles.Forsyth 		summary();
707*18eb7a2dSCharles.Forsyth 		cleantmp();
708*18eb7a2dSCharles.Forsyth 		exits("error");
709*18eb7a2dSCharles.Forsyth 	}
710*18eb7a2dSCharles.Forsyth 	if(pmem != &pyield[nprod])
711*18eb7a2dSCharles.Forsyth 		error("internal Yacc error: pyield %d", pmem-&pyield[nprod]);
712*18eb7a2dSCharles.Forsyth }
713*18eb7a2dSCharles.Forsyth 
714*18eb7a2dSCharles.Forsyth /*
715*18eb7a2dSCharles.Forsyth  * compute an array with the first of nonterminals
716*18eb7a2dSCharles.Forsyth  */
717*18eb7a2dSCharles.Forsyth void
cpfir(void)718*18eb7a2dSCharles.Forsyth cpfir(void)
719*18eb7a2dSCharles.Forsyth {
720*18eb7a2dSCharles.Forsyth 	int *p, **s, i, **t, ch, changes;
721*18eb7a2dSCharles.Forsyth 
722*18eb7a2dSCharles.Forsyth 	zzcwp = &wsets[nnonter];
723*18eb7a2dSCharles.Forsyth 	NTLOOP(i) {
724*18eb7a2dSCharles.Forsyth 		aryfil(wsets[i].ws.lset, tbitset, 0);
725*18eb7a2dSCharles.Forsyth 		t = pres[i+1];
726*18eb7a2dSCharles.Forsyth 		/* initially fill the sets */
727*18eb7a2dSCharles.Forsyth 		for(s=pres[i]; s<t; ++s)
728*18eb7a2dSCharles.Forsyth 			for(p = *s; (ch = *p) > 0; ++p) {
729*18eb7a2dSCharles.Forsyth 				if(ch < NTBASE) {
730*18eb7a2dSCharles.Forsyth 					SETBIT(wsets[i].ws.lset, ch);
731*18eb7a2dSCharles.Forsyth 					break;
732*18eb7a2dSCharles.Forsyth 				}
733*18eb7a2dSCharles.Forsyth 				if(!pempty[ch-NTBASE])
734*18eb7a2dSCharles.Forsyth 					break;
735*18eb7a2dSCharles.Forsyth 			}
736*18eb7a2dSCharles.Forsyth 	}
737*18eb7a2dSCharles.Forsyth 
738*18eb7a2dSCharles.Forsyth 	/* now, reflect transitivity */
739*18eb7a2dSCharles.Forsyth 	changes = 1;
740*18eb7a2dSCharles.Forsyth 	while(changes) {
741*18eb7a2dSCharles.Forsyth 		changes = 0;
742*18eb7a2dSCharles.Forsyth 		NTLOOP(i) {
743*18eb7a2dSCharles.Forsyth 			t = pres[i+1];
744*18eb7a2dSCharles.Forsyth 			for(s = pres[i]; s < t; ++s)
745*18eb7a2dSCharles.Forsyth 				for(p = *s; (ch = (*p-NTBASE)) >= 0; ++p) {
746*18eb7a2dSCharles.Forsyth 					changes |= setunion(wsets[i].ws.lset, wsets[ch].ws.lset);
747*18eb7a2dSCharles.Forsyth 					if(!pempty[ch])
748*18eb7a2dSCharles.Forsyth 						break;
749*18eb7a2dSCharles.Forsyth 				}
750*18eb7a2dSCharles.Forsyth 		}
751*18eb7a2dSCharles.Forsyth 	}
752*18eb7a2dSCharles.Forsyth 
753*18eb7a2dSCharles.Forsyth 	NTLOOP(i)
754*18eb7a2dSCharles.Forsyth 		pfirst[i] = flset(&wsets[i].ws);
755*18eb7a2dSCharles.Forsyth 	if(!indebug)
756*18eb7a2dSCharles.Forsyth 		return;
757*18eb7a2dSCharles.Forsyth 	if(foutput != 0)
758*18eb7a2dSCharles.Forsyth 		NTLOOP(i) {
759*18eb7a2dSCharles.Forsyth 			Bprint(foutput, "\n%s: ", nontrst[i].name);
760*18eb7a2dSCharles.Forsyth 			prlook(pfirst[i]);
761*18eb7a2dSCharles.Forsyth 			Bprint(foutput, " %d\n", pempty[i]);
762*18eb7a2dSCharles.Forsyth 		}
763*18eb7a2dSCharles.Forsyth }
764*18eb7a2dSCharles.Forsyth 
765*18eb7a2dSCharles.Forsyth /*
766*18eb7a2dSCharles.Forsyth  * sorts last state,and sees if it equals earlier ones. returns state number
767*18eb7a2dSCharles.Forsyth  */
768*18eb7a2dSCharles.Forsyth int
state(int c)769*18eb7a2dSCharles.Forsyth state(int c)
770*18eb7a2dSCharles.Forsyth {
771*18eb7a2dSCharles.Forsyth 	Item *p1, *p2, *k, *l, *q1, *q2;
772*18eb7a2dSCharles.Forsyth 	int size1, size2, i;
773*18eb7a2dSCharles.Forsyth 
774*18eb7a2dSCharles.Forsyth 	p1 = pstate[nstate];
775*18eb7a2dSCharles.Forsyth 	p2 = pstate[nstate+1];
776*18eb7a2dSCharles.Forsyth 	if(p1 == p2)
777*18eb7a2dSCharles.Forsyth 		return 0;	/* null state */
778*18eb7a2dSCharles.Forsyth 	/* sort the items */
779*18eb7a2dSCharles.Forsyth 	for(k = p2-1; k > p1; k--)	/* make k the biggest */
780*18eb7a2dSCharles.Forsyth 		for(l = k-1; l >= p1; --l)
781*18eb7a2dSCharles.Forsyth 			if(l->pitem > k->pitem) {
782*18eb7a2dSCharles.Forsyth 				int *s;
783*18eb7a2dSCharles.Forsyth 				Lkset *ss;
784*18eb7a2dSCharles.Forsyth 
785*18eb7a2dSCharles.Forsyth 				s = k->pitem;
786*18eb7a2dSCharles.Forsyth 				k->pitem = l->pitem;
787*18eb7a2dSCharles.Forsyth 				l->pitem = s;
788*18eb7a2dSCharles.Forsyth 				ss = k->look;
789*18eb7a2dSCharles.Forsyth 				k->look = l->look;
790*18eb7a2dSCharles.Forsyth 				l->look = ss;
791*18eb7a2dSCharles.Forsyth 			}
792*18eb7a2dSCharles.Forsyth 	size1 = p2 - p1;	/* size of state */
793*18eb7a2dSCharles.Forsyth 
794*18eb7a2dSCharles.Forsyth 	for(i = (c>=NTBASE)? ntstates[c-NTBASE]: tstates[c]; i != 0; i = mstates[i]) {
795*18eb7a2dSCharles.Forsyth 		/* get ith state */
796*18eb7a2dSCharles.Forsyth 		q1 = pstate[i];
797*18eb7a2dSCharles.Forsyth 		q2 = pstate[i+1];
798*18eb7a2dSCharles.Forsyth 		size2 = q2 - q1;
799*18eb7a2dSCharles.Forsyth 		if(size1 != size2)
800*18eb7a2dSCharles.Forsyth 			continue;
801*18eb7a2dSCharles.Forsyth 		k = p1;
802*18eb7a2dSCharles.Forsyth 		for(l = q1; l < q2; l++) {
803*18eb7a2dSCharles.Forsyth 			if(l->pitem != k->pitem)
804*18eb7a2dSCharles.Forsyth 				break;
805*18eb7a2dSCharles.Forsyth 			k++;
806*18eb7a2dSCharles.Forsyth 		}
807*18eb7a2dSCharles.Forsyth 		if(l != q2)
808*18eb7a2dSCharles.Forsyth 			continue;
809*18eb7a2dSCharles.Forsyth 		/* found it */
810*18eb7a2dSCharles.Forsyth 		pstate[nstate+1] = pstate[nstate];	/* delete last state */
811*18eb7a2dSCharles.Forsyth 		/* fix up lookaheads */
812*18eb7a2dSCharles.Forsyth 		if(nolook)
813*18eb7a2dSCharles.Forsyth 			return i;
814*18eb7a2dSCharles.Forsyth 		for(l = q1, k = p1; l < q2; ++l, ++k ) {
815*18eb7a2dSCharles.Forsyth 			int s;
816*18eb7a2dSCharles.Forsyth 
817*18eb7a2dSCharles.Forsyth 			SETLOOP(s)
818*18eb7a2dSCharles.Forsyth 				clset.lset[s] = l->look->lset[s];
819*18eb7a2dSCharles.Forsyth 			if(setunion(clset.lset, k->look->lset)) {
820*18eb7a2dSCharles.Forsyth 				tystate[i] = MUSTDO;
821*18eb7a2dSCharles.Forsyth 				/* register the new set */
822*18eb7a2dSCharles.Forsyth 				l->look = flset( &clset );
823*18eb7a2dSCharles.Forsyth 			}
824*18eb7a2dSCharles.Forsyth 		}
825*18eb7a2dSCharles.Forsyth 		return i;
826*18eb7a2dSCharles.Forsyth 	}
827*18eb7a2dSCharles.Forsyth 	/* state is new */
828*18eb7a2dSCharles.Forsyth 	if(nolook)
829*18eb7a2dSCharles.Forsyth 		error("yacc state/nolook error");
830*18eb7a2dSCharles.Forsyth 	pstate[nstate+2] = p2;
831*18eb7a2dSCharles.Forsyth 	if(nstate+1 >= NSTATES)
832*18eb7a2dSCharles.Forsyth 		error("too many states");
833*18eb7a2dSCharles.Forsyth 	if(c >= NTBASE) {
834*18eb7a2dSCharles.Forsyth 		mstates[nstate] = ntstates[c-NTBASE];
835*18eb7a2dSCharles.Forsyth 		ntstates[c-NTBASE] = nstate;
836*18eb7a2dSCharles.Forsyth 	} else {
837*18eb7a2dSCharles.Forsyth 		mstates[nstate] = tstates[c];
838*18eb7a2dSCharles.Forsyth 		tstates[c] = nstate;
839*18eb7a2dSCharles.Forsyth 	}
840*18eb7a2dSCharles.Forsyth 	tystate[nstate] = MUSTDO;
841*18eb7a2dSCharles.Forsyth 	return nstate++;
842*18eb7a2dSCharles.Forsyth }
843*18eb7a2dSCharles.Forsyth 
844*18eb7a2dSCharles.Forsyth void
putitem(int * ptr,Lkset * lptr)845*18eb7a2dSCharles.Forsyth putitem(int *ptr, Lkset *lptr)
846*18eb7a2dSCharles.Forsyth {
847*18eb7a2dSCharles.Forsyth 	Item *j;
848*18eb7a2dSCharles.Forsyth 
849*18eb7a2dSCharles.Forsyth 	if(pidebug && foutput != 0)
850*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "putitem(%s), state %d\n", writem(ptr), nstate);
851*18eb7a2dSCharles.Forsyth 	j = pstate[nstate+1];
852*18eb7a2dSCharles.Forsyth 	j->pitem = ptr;
853*18eb7a2dSCharles.Forsyth 	if(!nolook)
854*18eb7a2dSCharles.Forsyth 		j->look = flset(lptr);
855*18eb7a2dSCharles.Forsyth 	pstate[nstate+1] = ++j;
856*18eb7a2dSCharles.Forsyth 	if((int*)j > zzmemsz) {
857*18eb7a2dSCharles.Forsyth 		zzmemsz = (int*)j;
858*18eb7a2dSCharles.Forsyth 		if(zzmemsz >=  &mem0[MEMSIZE])
859*18eb7a2dSCharles.Forsyth 			error("out of state space");
860*18eb7a2dSCharles.Forsyth 	}
861*18eb7a2dSCharles.Forsyth }
862*18eb7a2dSCharles.Forsyth 
863*18eb7a2dSCharles.Forsyth /*
864*18eb7a2dSCharles.Forsyth  * mark nonterminals which derive the empty string
865*18eb7a2dSCharles.Forsyth  * also, look for nonterminals which don't derive any token strings
866*18eb7a2dSCharles.Forsyth  */
867*18eb7a2dSCharles.Forsyth void
cempty(void)868*18eb7a2dSCharles.Forsyth cempty(void)
869*18eb7a2dSCharles.Forsyth {
870*18eb7a2dSCharles.Forsyth 
871*18eb7a2dSCharles.Forsyth 	int i, *p;
872*18eb7a2dSCharles.Forsyth 
873*18eb7a2dSCharles.Forsyth 	/* first, use the array pempty to detect productions that can never be reduced */
874*18eb7a2dSCharles.Forsyth 	/* set pempty to WHONOWS */
875*18eb7a2dSCharles.Forsyth 	aryfil(pempty, nnonter+1, WHOKNOWS);
876*18eb7a2dSCharles.Forsyth 
877*18eb7a2dSCharles.Forsyth 	/* now, look at productions, marking nonterminals which derive something */
878*18eb7a2dSCharles.Forsyth more:
879*18eb7a2dSCharles.Forsyth 	PLOOP(0, i) {
880*18eb7a2dSCharles.Forsyth 		if(pempty[*prdptr[i] - NTBASE])
881*18eb7a2dSCharles.Forsyth 			continue;
882*18eb7a2dSCharles.Forsyth 		for(p = prdptr[i]+1; *p >= 0; ++p)
883*18eb7a2dSCharles.Forsyth 			if(*p >= NTBASE && pempty[*p-NTBASE] == WHOKNOWS)
884*18eb7a2dSCharles.Forsyth 				break;
885*18eb7a2dSCharles.Forsyth 		/* production can be derived */
886*18eb7a2dSCharles.Forsyth 		if(*p < 0) {
887*18eb7a2dSCharles.Forsyth 			pempty[*prdptr[i]-NTBASE] = OK;
888*18eb7a2dSCharles.Forsyth 			goto more;
889*18eb7a2dSCharles.Forsyth 		}
890*18eb7a2dSCharles.Forsyth 	}
891*18eb7a2dSCharles.Forsyth 
892*18eb7a2dSCharles.Forsyth 	/* now, look at the nonterminals, to see if they are all OK */
893*18eb7a2dSCharles.Forsyth 	NTLOOP(i) {
894*18eb7a2dSCharles.Forsyth 		/* the added production rises or falls as the start symbol ... */
895*18eb7a2dSCharles.Forsyth 		if(i == 0)
896*18eb7a2dSCharles.Forsyth 			continue;
897*18eb7a2dSCharles.Forsyth 		if(pempty[i] != OK) {
898*18eb7a2dSCharles.Forsyth 			fatfl = 0;
899*18eb7a2dSCharles.Forsyth 			error("nonterminal %s never derives any token string", nontrst[i].name);
900*18eb7a2dSCharles.Forsyth 		}
901*18eb7a2dSCharles.Forsyth 	}
902*18eb7a2dSCharles.Forsyth 
903*18eb7a2dSCharles.Forsyth 	if(nerrors) {
904*18eb7a2dSCharles.Forsyth 		summary();
905*18eb7a2dSCharles.Forsyth 		cleantmp();
906*18eb7a2dSCharles.Forsyth 		exits("error");
907*18eb7a2dSCharles.Forsyth 	}
908*18eb7a2dSCharles.Forsyth 
909*18eb7a2dSCharles.Forsyth 	/* now, compute the pempty array, to see which nonterminals derive the empty string */
910*18eb7a2dSCharles.Forsyth 	/* set pempty to WHOKNOWS */
911*18eb7a2dSCharles.Forsyth 	aryfil( pempty, nnonter+1, WHOKNOWS);
912*18eb7a2dSCharles.Forsyth 
913*18eb7a2dSCharles.Forsyth 	/* loop as long as we keep finding empty nonterminals */
914*18eb7a2dSCharles.Forsyth 
915*18eb7a2dSCharles.Forsyth again:
916*18eb7a2dSCharles.Forsyth 	PLOOP(1, i) {
917*18eb7a2dSCharles.Forsyth 		/* not known to be empty */
918*18eb7a2dSCharles.Forsyth 		if(pempty[*prdptr[i]-NTBASE] == WHOKNOWS) {
919*18eb7a2dSCharles.Forsyth 			for(p = prdptr[i]+1; *p >= NTBASE && pempty[*p-NTBASE] == EMPTY ; ++p)
920*18eb7a2dSCharles.Forsyth 				;
921*18eb7a2dSCharles.Forsyth 			/* we have a nontrivially empty nonterminal */
922*18eb7a2dSCharles.Forsyth 			if(*p < 0) {
923*18eb7a2dSCharles.Forsyth 				pempty[*prdptr[i]-NTBASE] = EMPTY;
924*18eb7a2dSCharles.Forsyth 				/* got one ... try for another */
925*18eb7a2dSCharles.Forsyth 				goto again;
926*18eb7a2dSCharles.Forsyth 			}
927*18eb7a2dSCharles.Forsyth 		}
928*18eb7a2dSCharles.Forsyth 	}
929*18eb7a2dSCharles.Forsyth }
930*18eb7a2dSCharles.Forsyth 
931*18eb7a2dSCharles.Forsyth /*
932*18eb7a2dSCharles.Forsyth  * generate the states
933*18eb7a2dSCharles.Forsyth  */
934*18eb7a2dSCharles.Forsyth void
stagen(void)935*18eb7a2dSCharles.Forsyth stagen(void)
936*18eb7a2dSCharles.Forsyth {
937*18eb7a2dSCharles.Forsyth 
938*18eb7a2dSCharles.Forsyth 	int c, i, j, more;
939*18eb7a2dSCharles.Forsyth 	Wset *p, *q;
940*18eb7a2dSCharles.Forsyth 
941*18eb7a2dSCharles.Forsyth 	/* initialize */
942*18eb7a2dSCharles.Forsyth 	nstate = 0;
943*18eb7a2dSCharles.Forsyth 
944*18eb7a2dSCharles.Forsyth 	/* THIS IS FUNNY from the standpoint of portability
945*18eb7a2dSCharles.Forsyth 	 * it represents the magic moment when the mem0 array, which has
946*18eb7a2dSCharles.Forsyth 	 * been holding the productions, starts to hold item pointers, of a
947*18eb7a2dSCharles.Forsyth 	 * different type...
948*18eb7a2dSCharles.Forsyth 	 * someday, alloc should be used to allocate all this stuff... for now, we
949*18eb7a2dSCharles.Forsyth 	 * accept that if pointers don't fit in integers, there is a problem...
950*18eb7a2dSCharles.Forsyth 	 */
951*18eb7a2dSCharles.Forsyth 
952*18eb7a2dSCharles.Forsyth 	pstate[0] = pstate[1] = (Item*)mem;
953*18eb7a2dSCharles.Forsyth 	aryfil(clset.lset, tbitset, 0);
954*18eb7a2dSCharles.Forsyth 	putitem(prdptr[0]+1, &clset);
955*18eb7a2dSCharles.Forsyth 	tystate[0] = MUSTDO;
956*18eb7a2dSCharles.Forsyth 	nstate = 1;
957*18eb7a2dSCharles.Forsyth 	pstate[2] = pstate[1];
958*18eb7a2dSCharles.Forsyth 
959*18eb7a2dSCharles.Forsyth 	aryfil(amem, ACTSIZE, 0);
960*18eb7a2dSCharles.Forsyth 
961*18eb7a2dSCharles.Forsyth 	/* now, the main state generation loop */
962*18eb7a2dSCharles.Forsyth 	for(more=1; more;) {
963*18eb7a2dSCharles.Forsyth 		more = 0;
964*18eb7a2dSCharles.Forsyth 		SLOOP(i) {
965*18eb7a2dSCharles.Forsyth 			if(tystate[i] != MUSTDO)
966*18eb7a2dSCharles.Forsyth 				continue;
967*18eb7a2dSCharles.Forsyth 			tystate[i] = DONE;
968*18eb7a2dSCharles.Forsyth 			aryfil(temp1, nnonter+1, 0);
969*18eb7a2dSCharles.Forsyth 			/* take state i, close it, and do gotos */
970*18eb7a2dSCharles.Forsyth 			closure(i);
971*18eb7a2dSCharles.Forsyth 			/* generate goto's */
972*18eb7a2dSCharles.Forsyth 			WSLOOP(wsets, p) {
973*18eb7a2dSCharles.Forsyth 				if(p->flag)
974*18eb7a2dSCharles.Forsyth 					continue;
975*18eb7a2dSCharles.Forsyth 				p->flag = 1;
976*18eb7a2dSCharles.Forsyth 				c = *(p->pitem);
977*18eb7a2dSCharles.Forsyth 				if(c <= 1) {
978*18eb7a2dSCharles.Forsyth 					if(pstate[i+1]-pstate[i] <= p-wsets)
979*18eb7a2dSCharles.Forsyth 						tystate[i] = MUSTLOOKAHEAD;
980*18eb7a2dSCharles.Forsyth 					continue;
981*18eb7a2dSCharles.Forsyth 				}
982*18eb7a2dSCharles.Forsyth 				/* do a goto on c */
983*18eb7a2dSCharles.Forsyth 				WSLOOP(p, q)
984*18eb7a2dSCharles.Forsyth 					/* this item contributes to the goto */
985*18eb7a2dSCharles.Forsyth 					if(c == *(q->pitem)) {
986*18eb7a2dSCharles.Forsyth 						putitem(q->pitem+1, &q->ws);
987*18eb7a2dSCharles.Forsyth 						q->flag = 1;
988*18eb7a2dSCharles.Forsyth 					}
989*18eb7a2dSCharles.Forsyth 				if(c < NTBASE)
990*18eb7a2dSCharles.Forsyth 					state(c);	/* register new state */
991*18eb7a2dSCharles.Forsyth 				else
992*18eb7a2dSCharles.Forsyth 					temp1[c-NTBASE] = state(c);
993*18eb7a2dSCharles.Forsyth 			}
994*18eb7a2dSCharles.Forsyth 			if(gsdebug && foutput != 0) {
995*18eb7a2dSCharles.Forsyth 				Bprint(foutput, "%d: ", i);
996*18eb7a2dSCharles.Forsyth 				NTLOOP(j)
997*18eb7a2dSCharles.Forsyth 					if(temp1[j])
998*18eb7a2dSCharles.Forsyth 						Bprint(foutput, "%s %d, ",
999*18eb7a2dSCharles.Forsyth 						nontrst[j].name, temp1[j]);
1000*18eb7a2dSCharles.Forsyth 				Bprint(foutput, "\n");
1001*18eb7a2dSCharles.Forsyth 			}
1002*18eb7a2dSCharles.Forsyth 			indgo[i] = apack(&temp1[1], nnonter-1) - 1;
1003*18eb7a2dSCharles.Forsyth 			/* do some more */
1004*18eb7a2dSCharles.Forsyth 			more = 1;
1005*18eb7a2dSCharles.Forsyth 		}
1006*18eb7a2dSCharles.Forsyth 	}
1007*18eb7a2dSCharles.Forsyth }
1008*18eb7a2dSCharles.Forsyth 
1009*18eb7a2dSCharles.Forsyth /*
1010*18eb7a2dSCharles.Forsyth  * generate the closure of state i
1011*18eb7a2dSCharles.Forsyth  */
1012*18eb7a2dSCharles.Forsyth void
closure(int i)1013*18eb7a2dSCharles.Forsyth closure(int i)
1014*18eb7a2dSCharles.Forsyth {
1015*18eb7a2dSCharles.Forsyth 
1016*18eb7a2dSCharles.Forsyth 	Wset *u, *v;
1017*18eb7a2dSCharles.Forsyth 	Item *p, *q;
1018*18eb7a2dSCharles.Forsyth 	int c, ch, work, k, *pi, **s, **t;
1019*18eb7a2dSCharles.Forsyth 
1020*18eb7a2dSCharles.Forsyth 	zzclose++;
1021*18eb7a2dSCharles.Forsyth 
1022*18eb7a2dSCharles.Forsyth 	/* first, copy kernel of state i to wsets */
1023*18eb7a2dSCharles.Forsyth 	cwp = wsets;
1024*18eb7a2dSCharles.Forsyth 	ITMLOOP(i, p, q) {
1025*18eb7a2dSCharles.Forsyth 		cwp->pitem = p->pitem;
1026*18eb7a2dSCharles.Forsyth 		cwp->flag = 1;			/* this item must get closed */
1027*18eb7a2dSCharles.Forsyth 		SETLOOP(k)
1028*18eb7a2dSCharles.Forsyth 			cwp->ws.lset[k] = p->look->lset[k];
1029*18eb7a2dSCharles.Forsyth 		WSBUMP(cwp);
1030*18eb7a2dSCharles.Forsyth 	}
1031*18eb7a2dSCharles.Forsyth 
1032*18eb7a2dSCharles.Forsyth 	/* now, go through the loop, closing each item */
1033*18eb7a2dSCharles.Forsyth 	work = 1;
1034*18eb7a2dSCharles.Forsyth 	while(work) {
1035*18eb7a2dSCharles.Forsyth 		work = 0;
1036*18eb7a2dSCharles.Forsyth 		WSLOOP(wsets, u) {
1037*18eb7a2dSCharles.Forsyth 			if(u->flag == 0)
1038*18eb7a2dSCharles.Forsyth 				continue;
1039*18eb7a2dSCharles.Forsyth 			/* dot is before c */
1040*18eb7a2dSCharles.Forsyth 			c = *(u->pitem);
1041*18eb7a2dSCharles.Forsyth 			if(c < NTBASE) {
1042*18eb7a2dSCharles.Forsyth 				u->flag = 0;
1043*18eb7a2dSCharles.Forsyth 				/* only interesting case is where . is before nonterminal */
1044*18eb7a2dSCharles.Forsyth 				continue;
1045*18eb7a2dSCharles.Forsyth 			}
1046*18eb7a2dSCharles.Forsyth 
1047*18eb7a2dSCharles.Forsyth 			/* compute the lookahead */
1048*18eb7a2dSCharles.Forsyth 			aryfil(clset.lset, tbitset, 0);
1049*18eb7a2dSCharles.Forsyth 
1050*18eb7a2dSCharles.Forsyth 			/* find items involving c */
1051*18eb7a2dSCharles.Forsyth 			WSLOOP(u, v)
1052*18eb7a2dSCharles.Forsyth 				if(v->flag == 1 && *(pi=v->pitem) == c) {
1053*18eb7a2dSCharles.Forsyth 					v->flag = 0;
1054*18eb7a2dSCharles.Forsyth 					if(nolook)
1055*18eb7a2dSCharles.Forsyth 						continue;
1056*18eb7a2dSCharles.Forsyth 					while((ch = *++pi) > 0) {
1057*18eb7a2dSCharles.Forsyth 						/* terminal symbol */
1058*18eb7a2dSCharles.Forsyth 						if(ch < NTBASE) {
1059*18eb7a2dSCharles.Forsyth 							SETBIT(clset.lset, ch);
1060*18eb7a2dSCharles.Forsyth 							break;
1061*18eb7a2dSCharles.Forsyth 						}
1062*18eb7a2dSCharles.Forsyth 						/* nonterminal symbol */
1063*18eb7a2dSCharles.Forsyth 						setunion(clset.lset, pfirst[ch-NTBASE]->lset);
1064*18eb7a2dSCharles.Forsyth 						if(!pempty[ch-NTBASE])
1065*18eb7a2dSCharles.Forsyth 							break;
1066*18eb7a2dSCharles.Forsyth 					}
1067*18eb7a2dSCharles.Forsyth 					if(ch <= 0)
1068*18eb7a2dSCharles.Forsyth 						setunion(clset.lset, v->ws.lset);
1069*18eb7a2dSCharles.Forsyth 				}
1070*18eb7a2dSCharles.Forsyth 
1071*18eb7a2dSCharles.Forsyth 			/*
1072*18eb7a2dSCharles.Forsyth 			 * now loop over productions derived from c
1073*18eb7a2dSCharles.Forsyth 			 * c is now nonterminal number
1074*18eb7a2dSCharles.Forsyth 			 */
1075*18eb7a2dSCharles.Forsyth 			c -= NTBASE;
1076*18eb7a2dSCharles.Forsyth 			t = pres[c+1];
1077*18eb7a2dSCharles.Forsyth 			for(s = pres[c]; s < t; ++s) {
1078*18eb7a2dSCharles.Forsyth 				/*
1079*18eb7a2dSCharles.Forsyth 				 * put these items into the closure
1080*18eb7a2dSCharles.Forsyth 				 * is the item there
1081*18eb7a2dSCharles.Forsyth 				 */
1082*18eb7a2dSCharles.Forsyth 				WSLOOP(wsets, v)
1083*18eb7a2dSCharles.Forsyth 					/* yes, it is there */
1084*18eb7a2dSCharles.Forsyth 					if(v->pitem == *s) {
1085*18eb7a2dSCharles.Forsyth 						if(nolook)
1086*18eb7a2dSCharles.Forsyth 							goto nexts;
1087*18eb7a2dSCharles.Forsyth 						if(setunion(v->ws.lset, clset.lset))
1088*18eb7a2dSCharles.Forsyth 							v->flag = work = 1;
1089*18eb7a2dSCharles.Forsyth 						goto nexts;
1090*18eb7a2dSCharles.Forsyth 					}
1091*18eb7a2dSCharles.Forsyth 
1092*18eb7a2dSCharles.Forsyth 				/*  not there; make a new entry */
1093*18eb7a2dSCharles.Forsyth 				if(cwp-wsets+1 >= WSETSIZE)
1094*18eb7a2dSCharles.Forsyth 					error( "working set overflow");
1095*18eb7a2dSCharles.Forsyth 				cwp->pitem = *s;
1096*18eb7a2dSCharles.Forsyth 				cwp->flag = 1;
1097*18eb7a2dSCharles.Forsyth 				if(!nolook) {
1098*18eb7a2dSCharles.Forsyth 					work = 1;
1099*18eb7a2dSCharles.Forsyth 					SETLOOP(k) cwp->ws.lset[k] = clset.lset[k];
1100*18eb7a2dSCharles.Forsyth 				}
1101*18eb7a2dSCharles.Forsyth 				WSBUMP(cwp);
1102*18eb7a2dSCharles.Forsyth 
1103*18eb7a2dSCharles.Forsyth 			nexts:;
1104*18eb7a2dSCharles.Forsyth 			}
1105*18eb7a2dSCharles.Forsyth 		}
1106*18eb7a2dSCharles.Forsyth 	}
1107*18eb7a2dSCharles.Forsyth 
1108*18eb7a2dSCharles.Forsyth 	/* have computed closure; flags are reset; return */
1109*18eb7a2dSCharles.Forsyth 	if(cwp > zzcwp)
1110*18eb7a2dSCharles.Forsyth 		zzcwp = cwp;
1111*18eb7a2dSCharles.Forsyth 	if(cldebug && foutput != 0) {
1112*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "\nState %d, nolook = %d\n", i, nolook);
1113*18eb7a2dSCharles.Forsyth 		WSLOOP(wsets, u) {
1114*18eb7a2dSCharles.Forsyth 			if(u->flag)
1115*18eb7a2dSCharles.Forsyth 				Bprint(foutput, "flag set!\n");
1116*18eb7a2dSCharles.Forsyth 			u->flag = 0;
1117*18eb7a2dSCharles.Forsyth 			Bprint(foutput, "\t%s", writem(u->pitem));
1118*18eb7a2dSCharles.Forsyth 			prlook(&u->ws);
1119*18eb7a2dSCharles.Forsyth 			Bprint(foutput, "\n");
1120*18eb7a2dSCharles.Forsyth 		}
1121*18eb7a2dSCharles.Forsyth 	}
1122*18eb7a2dSCharles.Forsyth }
1123*18eb7a2dSCharles.Forsyth 
1124*18eb7a2dSCharles.Forsyth /*
1125*18eb7a2dSCharles.Forsyth  * decide if the lookahead set pointed to by p is known
1126*18eb7a2dSCharles.Forsyth  * return pointer to a perminent location for the set
1127*18eb7a2dSCharles.Forsyth  */
1128*18eb7a2dSCharles.Forsyth Lkset*
flset(Lkset * p)1129*18eb7a2dSCharles.Forsyth flset(Lkset *p)
1130*18eb7a2dSCharles.Forsyth {
1131*18eb7a2dSCharles.Forsyth 	Lkset *q;
1132*18eb7a2dSCharles.Forsyth 	int *u, *v, *w, j;
1133*18eb7a2dSCharles.Forsyth 
1134*18eb7a2dSCharles.Forsyth 	for(q = &lkst[nlset]; q-- > lkst;) {
1135*18eb7a2dSCharles.Forsyth 		u = p->lset;
1136*18eb7a2dSCharles.Forsyth 		v = q->lset;
1137*18eb7a2dSCharles.Forsyth 		w = &v[tbitset];
1138*18eb7a2dSCharles.Forsyth 		while(v < w)
1139*18eb7a2dSCharles.Forsyth 			if(*u++ != *v++)
1140*18eb7a2dSCharles.Forsyth 				goto more;
1141*18eb7a2dSCharles.Forsyth 		/* we have matched */
1142*18eb7a2dSCharles.Forsyth 		return q;
1143*18eb7a2dSCharles.Forsyth 	more:;
1144*18eb7a2dSCharles.Forsyth 	}
1145*18eb7a2dSCharles.Forsyth 	/* add a new one */
1146*18eb7a2dSCharles.Forsyth 	q = &lkst[nlset++];
1147*18eb7a2dSCharles.Forsyth 	if(nlset >= LSETSIZE)
1148*18eb7a2dSCharles.Forsyth 		error("too many lookahead sets");
1149*18eb7a2dSCharles.Forsyth 	SETLOOP(j)
1150*18eb7a2dSCharles.Forsyth 		q->lset[j] = p->lset[j];
1151*18eb7a2dSCharles.Forsyth 	return q;
1152*18eb7a2dSCharles.Forsyth }
1153*18eb7a2dSCharles.Forsyth 
1154*18eb7a2dSCharles.Forsyth void
cleantmp(void)1155*18eb7a2dSCharles.Forsyth cleantmp(void)
1156*18eb7a2dSCharles.Forsyth {
1157*18eb7a2dSCharles.Forsyth 	ZAPFILE(actname);
1158*18eb7a2dSCharles.Forsyth 	ZAPFILE(tempname);
1159*18eb7a2dSCharles.Forsyth }
1160*18eb7a2dSCharles.Forsyth 
1161*18eb7a2dSCharles.Forsyth void
intr(void)1162*18eb7a2dSCharles.Forsyth intr(void)
1163*18eb7a2dSCharles.Forsyth {
1164*18eb7a2dSCharles.Forsyth 	cleantmp();
1165*18eb7a2dSCharles.Forsyth 	exits("interrupted");
1166*18eb7a2dSCharles.Forsyth }
1167*18eb7a2dSCharles.Forsyth 
1168*18eb7a2dSCharles.Forsyth void
setup(int argc,char * argv[])1169*18eb7a2dSCharles.Forsyth setup(int argc, char *argv[])
1170*18eb7a2dSCharles.Forsyth {
1171*18eb7a2dSCharles.Forsyth 	long c, t;
1172*18eb7a2dSCharles.Forsyth 	int i, j, lev, ty, ytab, *p;
1173*18eb7a2dSCharles.Forsyth 	int vflag, dflag, stem;
1174*18eb7a2dSCharles.Forsyth 	char actnm[8], *stemc, *cp;
1175*18eb7a2dSCharles.Forsyth 
1176*18eb7a2dSCharles.Forsyth 	ytab = 0;
1177*18eb7a2dSCharles.Forsyth 	vflag = 0;
1178*18eb7a2dSCharles.Forsyth 	dflag = 0;
1179*18eb7a2dSCharles.Forsyth 	stem = 0;
1180*18eb7a2dSCharles.Forsyth 	stemc = "y";
1181*18eb7a2dSCharles.Forsyth 	foutput = 0;
1182*18eb7a2dSCharles.Forsyth 	fdefine = 0;
1183*18eb7a2dSCharles.Forsyth 	fdebug = 0;
1184*18eb7a2dSCharles.Forsyth 	ARGBEGIN{
1185*18eb7a2dSCharles.Forsyth 	case 'v':
1186*18eb7a2dSCharles.Forsyth 	case 'V':
1187*18eb7a2dSCharles.Forsyth 		vflag++;
1188*18eb7a2dSCharles.Forsyth 		break;
1189*18eb7a2dSCharles.Forsyth 	case 'D':
1190*18eb7a2dSCharles.Forsyth 		yydebug = ARGF();
1191*18eb7a2dSCharles.Forsyth 		break;
1192*18eb7a2dSCharles.Forsyth 	case 'd':
1193*18eb7a2dSCharles.Forsyth 		dflag++;
1194*18eb7a2dSCharles.Forsyth 		break;
1195*18eb7a2dSCharles.Forsyth 	case 'o':
1196*18eb7a2dSCharles.Forsyth 		ytab++;
1197*18eb7a2dSCharles.Forsyth 		ytabc = ARGF();
1198*18eb7a2dSCharles.Forsyth 		break;
1199*18eb7a2dSCharles.Forsyth 	case 's':
1200*18eb7a2dSCharles.Forsyth 		stem++;
1201*18eb7a2dSCharles.Forsyth 		stemc = ARGF();
1202*18eb7a2dSCharles.Forsyth 		break;
1203*18eb7a2dSCharles.Forsyth 	case 'S':
1204*18eb7a2dSCharles.Forsyth 		parser = PARSERS;
1205*18eb7a2dSCharles.Forsyth 		break;
1206*18eb7a2dSCharles.Forsyth 	default:
1207*18eb7a2dSCharles.Forsyth 		error("illegal option: %c", ARGC());
1208*18eb7a2dSCharles.Forsyth 	}ARGEND
1209*18eb7a2dSCharles.Forsyth 
1210*18eb7a2dSCharles.Forsyth 	cp = getenv("ROOT");
1211*18eb7a2dSCharles.Forsyth 	if(cp == 0)
1212*18eb7a2dSCharles.Forsyth 		cp = ROOT;
1213*18eb7a2dSCharles.Forsyth 	snprint(par, sizeof(par), "%s/utils/lib/%s", cp, parser);
1214*18eb7a2dSCharles.Forsyth 	parser = par;
1215*18eb7a2dSCharles.Forsyth 
1216*18eb7a2dSCharles.Forsyth 	openup(stemc, dflag, vflag, ytab, ytabc);
1217*18eb7a2dSCharles.Forsyth 
1218*18eb7a2dSCharles.Forsyth 	ftemp = Bopen(tempname = mktemp(ttempname), OWRITE);
1219*18eb7a2dSCharles.Forsyth 	faction = Bopen(actname = mktemp(tactname), OWRITE);
1220*18eb7a2dSCharles.Forsyth 	if(ftemp == 0 || faction == 0)
1221*18eb7a2dSCharles.Forsyth 		error("cannot open temp file");
1222*18eb7a2dSCharles.Forsyth 	if(argc < 1)
1223*18eb7a2dSCharles.Forsyth 		error("no input file");
1224*18eb7a2dSCharles.Forsyth 	infile = argv[0];
1225*18eb7a2dSCharles.Forsyth 	finput = Bopen(infile, OREAD);
1226*18eb7a2dSCharles.Forsyth 	if(finput == 0)
1227*18eb7a2dSCharles.Forsyth 		error("cannot open '%s'", argv[0]);
1228*18eb7a2dSCharles.Forsyth 	cnamp = cnames;
1229*18eb7a2dSCharles.Forsyth 
1230*18eb7a2dSCharles.Forsyth 	defin(0, "$end");
1231*18eb7a2dSCharles.Forsyth 	extval = PRIVATE;	/* tokens start in unicode 'private use' */
1232*18eb7a2dSCharles.Forsyth 	defin(0, "error");
1233*18eb7a2dSCharles.Forsyth 	defin(1, "$accept");
1234*18eb7a2dSCharles.Forsyth 	defin(0, "$unk");
1235*18eb7a2dSCharles.Forsyth 	mem = mem0;
1236*18eb7a2dSCharles.Forsyth 	i = 0;
1237*18eb7a2dSCharles.Forsyth 
1238*18eb7a2dSCharles.Forsyth 	for(t = gettok(); t != MARK && t != ENDFILE;)
1239*18eb7a2dSCharles.Forsyth 	switch(t) {
1240*18eb7a2dSCharles.Forsyth 	case ';':
1241*18eb7a2dSCharles.Forsyth 		t = gettok();
1242*18eb7a2dSCharles.Forsyth 		break;
1243*18eb7a2dSCharles.Forsyth 
1244*18eb7a2dSCharles.Forsyth 	case START:
1245*18eb7a2dSCharles.Forsyth 		if(gettok() != IDENTIFIER)
1246*18eb7a2dSCharles.Forsyth 			error("bad %%start construction");
1247*18eb7a2dSCharles.Forsyth 		start = chfind(1, tokname);
1248*18eb7a2dSCharles.Forsyth 		t = gettok();
1249*18eb7a2dSCharles.Forsyth 		continue;
1250*18eb7a2dSCharles.Forsyth 
1251*18eb7a2dSCharles.Forsyth 	case TYPEDEF:
1252*18eb7a2dSCharles.Forsyth 		if(gettok() != TYPENAME)
1253*18eb7a2dSCharles.Forsyth 			error("bad syntax in %%type");
1254*18eb7a2dSCharles.Forsyth 		ty = numbval;
1255*18eb7a2dSCharles.Forsyth 		for(;;) {
1256*18eb7a2dSCharles.Forsyth 			t = gettok();
1257*18eb7a2dSCharles.Forsyth 			switch(t) {
1258*18eb7a2dSCharles.Forsyth 			case IDENTIFIER:
1259*18eb7a2dSCharles.Forsyth 				if((t=chfind(1, tokname)) < NTBASE) {
1260*18eb7a2dSCharles.Forsyth 					j = TYPE(toklev[t]);
1261*18eb7a2dSCharles.Forsyth 					if(j != 0 && j != ty)
1262*18eb7a2dSCharles.Forsyth 						error("type redeclaration of token %s",
1263*18eb7a2dSCharles.Forsyth 							tokset[t].name);
1264*18eb7a2dSCharles.Forsyth 					else
1265*18eb7a2dSCharles.Forsyth 						SETTYPE(toklev[t], ty);
1266*18eb7a2dSCharles.Forsyth 				} else {
1267*18eb7a2dSCharles.Forsyth 					j = nontrst[t-NTBASE].value;
1268*18eb7a2dSCharles.Forsyth 					if(j != 0 && j != ty)
1269*18eb7a2dSCharles.Forsyth 						error("type redeclaration of nonterminal %s",
1270*18eb7a2dSCharles.Forsyth 							nontrst[t-NTBASE].name );
1271*18eb7a2dSCharles.Forsyth 					else
1272*18eb7a2dSCharles.Forsyth 						nontrst[t-NTBASE].value = ty;
1273*18eb7a2dSCharles.Forsyth 				}
1274*18eb7a2dSCharles.Forsyth 			case ',':
1275*18eb7a2dSCharles.Forsyth 				continue;
1276*18eb7a2dSCharles.Forsyth 			case ';':
1277*18eb7a2dSCharles.Forsyth 				t = gettok();
1278*18eb7a2dSCharles.Forsyth 			default:
1279*18eb7a2dSCharles.Forsyth 				break;
1280*18eb7a2dSCharles.Forsyth 			}
1281*18eb7a2dSCharles.Forsyth 			break;
1282*18eb7a2dSCharles.Forsyth 		}
1283*18eb7a2dSCharles.Forsyth 		continue;
1284*18eb7a2dSCharles.Forsyth 
1285*18eb7a2dSCharles.Forsyth 	case UNION:
1286*18eb7a2dSCharles.Forsyth 		/* copy the union declaration to the output */
1287*18eb7a2dSCharles.Forsyth 		cpyunion();
1288*18eb7a2dSCharles.Forsyth 		t = gettok();
1289*18eb7a2dSCharles.Forsyth 		continue;
1290*18eb7a2dSCharles.Forsyth 
1291*18eb7a2dSCharles.Forsyth 	case LEFT:
1292*18eb7a2dSCharles.Forsyth 	case BINARY:
1293*18eb7a2dSCharles.Forsyth 	case RIGHT:
1294*18eb7a2dSCharles.Forsyth 		i++;
1295*18eb7a2dSCharles.Forsyth 
1296*18eb7a2dSCharles.Forsyth 	case TERM:
1297*18eb7a2dSCharles.Forsyth 		/* nonzero means new prec. and assoc. */
1298*18eb7a2dSCharles.Forsyth 		lev = t-TERM;
1299*18eb7a2dSCharles.Forsyth 		ty = 0;
1300*18eb7a2dSCharles.Forsyth 
1301*18eb7a2dSCharles.Forsyth 		/* get identifiers so defined */
1302*18eb7a2dSCharles.Forsyth 		t = gettok();
1303*18eb7a2dSCharles.Forsyth 
1304*18eb7a2dSCharles.Forsyth 		/* there is a type defined */
1305*18eb7a2dSCharles.Forsyth 		if(t == TYPENAME) {
1306*18eb7a2dSCharles.Forsyth 			ty = numbval;
1307*18eb7a2dSCharles.Forsyth 			t = gettok();
1308*18eb7a2dSCharles.Forsyth 		}
1309*18eb7a2dSCharles.Forsyth 		for(;;) {
1310*18eb7a2dSCharles.Forsyth 			switch(t) {
1311*18eb7a2dSCharles.Forsyth 			case ',':
1312*18eb7a2dSCharles.Forsyth 				t = gettok();
1313*18eb7a2dSCharles.Forsyth 				continue;
1314*18eb7a2dSCharles.Forsyth 
1315*18eb7a2dSCharles.Forsyth 			case ';':
1316*18eb7a2dSCharles.Forsyth 				break;
1317*18eb7a2dSCharles.Forsyth 
1318*18eb7a2dSCharles.Forsyth 			case IDENTIFIER:
1319*18eb7a2dSCharles.Forsyth 				j = chfind(0, tokname);
1320*18eb7a2dSCharles.Forsyth 				if(j >= NTBASE)
1321*18eb7a2dSCharles.Forsyth 					error("%s defined earlier as nonterminal", tokname);
1322*18eb7a2dSCharles.Forsyth 				if(lev) {
1323*18eb7a2dSCharles.Forsyth 					if(ASSOC(toklev[j]))
1324*18eb7a2dSCharles.Forsyth 						error("redeclaration of precedence of %s", tokname);
1325*18eb7a2dSCharles.Forsyth 					SETASC(toklev[j], lev);
1326*18eb7a2dSCharles.Forsyth 					SETPLEV(toklev[j], i);
1327*18eb7a2dSCharles.Forsyth 				}
1328*18eb7a2dSCharles.Forsyth 				if(ty) {
1329*18eb7a2dSCharles.Forsyth 					if(TYPE(toklev[j]))
1330*18eb7a2dSCharles.Forsyth 						error("redeclaration of type of %s", tokname);
1331*18eb7a2dSCharles.Forsyth 					SETTYPE(toklev[j],ty);
1332*18eb7a2dSCharles.Forsyth 				}
1333*18eb7a2dSCharles.Forsyth 				t = gettok();
1334*18eb7a2dSCharles.Forsyth 				if(t == NUMBER) {
1335*18eb7a2dSCharles.Forsyth 					tokset[j].value = numbval;
1336*18eb7a2dSCharles.Forsyth 					if(j < ndefout && j > 3)
1337*18eb7a2dSCharles.Forsyth 						error("please define type number of %s earlier",
1338*18eb7a2dSCharles.Forsyth 							tokset[j].name);
1339*18eb7a2dSCharles.Forsyth 					t = gettok();
1340*18eb7a2dSCharles.Forsyth 				}
1341*18eb7a2dSCharles.Forsyth 				continue;
1342*18eb7a2dSCharles.Forsyth 			}
1343*18eb7a2dSCharles.Forsyth 			break;
1344*18eb7a2dSCharles.Forsyth 		}
1345*18eb7a2dSCharles.Forsyth 		continue;
1346*18eb7a2dSCharles.Forsyth 
1347*18eb7a2dSCharles.Forsyth 	case LCURLY:
1348*18eb7a2dSCharles.Forsyth 		defout(0);
1349*18eb7a2dSCharles.Forsyth 		cpycode();
1350*18eb7a2dSCharles.Forsyth 		t = gettok();
1351*18eb7a2dSCharles.Forsyth 		continue;
1352*18eb7a2dSCharles.Forsyth 
1353*18eb7a2dSCharles.Forsyth 	default:
1354*18eb7a2dSCharles.Forsyth 		error("syntax error");
1355*18eb7a2dSCharles.Forsyth 	}
1356*18eb7a2dSCharles.Forsyth 	if(t == ENDFILE)
1357*18eb7a2dSCharles.Forsyth 		error("unexpected EOF before %%");
1358*18eb7a2dSCharles.Forsyth 
1359*18eb7a2dSCharles.Forsyth 	/* t is MARK */
1360*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "extern	int	yyerrflag;\n");
1361*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "#ifndef	YYMAXDEPTH\n");
1362*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "#define	YYMAXDEPTH	150\n");
1363*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "#endif\n" );
1364*18eb7a2dSCharles.Forsyth 	if(!ntypes) {
1365*18eb7a2dSCharles.Forsyth 		Bprint(ftable, "#ifndef	YYSTYPE\n");
1366*18eb7a2dSCharles.Forsyth 		Bprint(ftable, "#define	YYSTYPE	int\n");
1367*18eb7a2dSCharles.Forsyth 		Bprint(ftable, "#endif\n");
1368*18eb7a2dSCharles.Forsyth 	}
1369*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "YYSTYPE	yylval;\n");
1370*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "YYSTYPE	yyval;\n");
1371*18eb7a2dSCharles.Forsyth 
1372*18eb7a2dSCharles.Forsyth 	prdptr[0] = mem;
1373*18eb7a2dSCharles.Forsyth 
1374*18eb7a2dSCharles.Forsyth 	/* added production */
1375*18eb7a2dSCharles.Forsyth 	*mem++ = NTBASE;
1376*18eb7a2dSCharles.Forsyth 
1377*18eb7a2dSCharles.Forsyth 	/* if start is 0, we will overwrite with the lhs of the first rule */
1378*18eb7a2dSCharles.Forsyth 	*mem++ = start;
1379*18eb7a2dSCharles.Forsyth 	*mem++ = 1;
1380*18eb7a2dSCharles.Forsyth 	*mem++ = 0;
1381*18eb7a2dSCharles.Forsyth 	prdptr[1] = mem;
1382*18eb7a2dSCharles.Forsyth 	while((t=gettok()) == LCURLY)
1383*18eb7a2dSCharles.Forsyth 		cpycode();
1384*18eb7a2dSCharles.Forsyth 	if(t != IDENTCOLON)
1385*18eb7a2dSCharles.Forsyth 		error("bad syntax on first rule");
1386*18eb7a2dSCharles.Forsyth 
1387*18eb7a2dSCharles.Forsyth 	if(!start)
1388*18eb7a2dSCharles.Forsyth 		prdptr[0][1] = chfind(1, tokname);
1389*18eb7a2dSCharles.Forsyth 
1390*18eb7a2dSCharles.Forsyth 	/* read rules */
1391*18eb7a2dSCharles.Forsyth 	while(t != MARK && t != ENDFILE) {
1392*18eb7a2dSCharles.Forsyth 		/* process a rule */
1393*18eb7a2dSCharles.Forsyth 		rlines[nprod] = lineno;
1394*18eb7a2dSCharles.Forsyth 		if(t == '|')
1395*18eb7a2dSCharles.Forsyth 			*mem++ = *prdptr[nprod-1];
1396*18eb7a2dSCharles.Forsyth 		else
1397*18eb7a2dSCharles.Forsyth 			if(t == IDENTCOLON) {
1398*18eb7a2dSCharles.Forsyth 				*mem = chfind(1, tokname);
1399*18eb7a2dSCharles.Forsyth 				if(*mem < NTBASE)
1400*18eb7a2dSCharles.Forsyth 					error("token illegal on LHS of grammar rule");
1401*18eb7a2dSCharles.Forsyth 				mem++;
1402*18eb7a2dSCharles.Forsyth 			} else
1403*18eb7a2dSCharles.Forsyth 				error("illegal rule: missing semicolon or | ?");
1404*18eb7a2dSCharles.Forsyth 		/* read rule body */
1405*18eb7a2dSCharles.Forsyth 		t = gettok();
1406*18eb7a2dSCharles.Forsyth 
1407*18eb7a2dSCharles.Forsyth 	more_rule:
1408*18eb7a2dSCharles.Forsyth 		while(t == IDENTIFIER) {
1409*18eb7a2dSCharles.Forsyth 			*mem = chfind(1, tokname);
1410*18eb7a2dSCharles.Forsyth 			if(*mem < NTBASE)
1411*18eb7a2dSCharles.Forsyth 				levprd[nprod] = toklev[*mem];
1412*18eb7a2dSCharles.Forsyth 			mem++;
1413*18eb7a2dSCharles.Forsyth 			t = gettok();
1414*18eb7a2dSCharles.Forsyth 		}
1415*18eb7a2dSCharles.Forsyth 		if(t == PREC) {
1416*18eb7a2dSCharles.Forsyth 			if(gettok() != IDENTIFIER)
1417*18eb7a2dSCharles.Forsyth 				error("illegal %%prec syntax");
1418*18eb7a2dSCharles.Forsyth 			j = chfind(2, tokname);
1419*18eb7a2dSCharles.Forsyth 			if(j >= NTBASE)
1420*18eb7a2dSCharles.Forsyth 				error("nonterminal %s illegal after %%prec",
1421*18eb7a2dSCharles.Forsyth 					nontrst[j-NTBASE].name);
1422*18eb7a2dSCharles.Forsyth 			levprd[nprod] = toklev[j];
1423*18eb7a2dSCharles.Forsyth 			t = gettok();
1424*18eb7a2dSCharles.Forsyth 		}
1425*18eb7a2dSCharles.Forsyth 		if(t == '=') {
1426*18eb7a2dSCharles.Forsyth 			levprd[nprod] |= ACTFLAG;
1427*18eb7a2dSCharles.Forsyth 			Bprint(faction, "\ncase %d:", nprod);
1428*18eb7a2dSCharles.Forsyth 			cpyact(mem-prdptr[nprod]-1);
1429*18eb7a2dSCharles.Forsyth 			Bprint(faction, " break;");
1430*18eb7a2dSCharles.Forsyth 			if((t=gettok()) == IDENTIFIER) {
1431*18eb7a2dSCharles.Forsyth 
1432*18eb7a2dSCharles.Forsyth 				/* action within rule... */
1433*18eb7a2dSCharles.Forsyth 				sprint(actnm, "$$%d", nprod);
1434*18eb7a2dSCharles.Forsyth 
1435*18eb7a2dSCharles.Forsyth 				/* make it a nonterminal */
1436*18eb7a2dSCharles.Forsyth 				j = chfind(1, actnm);
1437*18eb7a2dSCharles.Forsyth 
1438*18eb7a2dSCharles.Forsyth 				/*
1439*18eb7a2dSCharles.Forsyth 				 * the current rule will become rule number nprod+1
1440*18eb7a2dSCharles.Forsyth 				 * move the contents down, and make room for the null
1441*18eb7a2dSCharles.Forsyth 				 */
1442*18eb7a2dSCharles.Forsyth 				for(p = mem; p >= prdptr[nprod]; --p)
1443*18eb7a2dSCharles.Forsyth 					p[2] = *p;
1444*18eb7a2dSCharles.Forsyth 				mem += 2;
1445*18eb7a2dSCharles.Forsyth 
1446*18eb7a2dSCharles.Forsyth 				/* enter null production for action */
1447*18eb7a2dSCharles.Forsyth 				p = prdptr[nprod];
1448*18eb7a2dSCharles.Forsyth 				*p++ = j;
1449*18eb7a2dSCharles.Forsyth 				*p++ = -nprod;
1450*18eb7a2dSCharles.Forsyth 
1451*18eb7a2dSCharles.Forsyth 				/* update the production information */
1452*18eb7a2dSCharles.Forsyth 				levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
1453*18eb7a2dSCharles.Forsyth 				levprd[nprod] = ACTFLAG;
1454*18eb7a2dSCharles.Forsyth 				if(++nprod >= NPROD)
1455*18eb7a2dSCharles.Forsyth 					error("more than %d rules", NPROD);
1456*18eb7a2dSCharles.Forsyth 				prdptr[nprod] = p;
1457*18eb7a2dSCharles.Forsyth 
1458*18eb7a2dSCharles.Forsyth 				/* make the action appear in the original rule */
1459*18eb7a2dSCharles.Forsyth 				*mem++ = j;
1460*18eb7a2dSCharles.Forsyth 
1461*18eb7a2dSCharles.Forsyth 				/* get some more of the rule */
1462*18eb7a2dSCharles.Forsyth 				goto more_rule;
1463*18eb7a2dSCharles.Forsyth 			}
1464*18eb7a2dSCharles.Forsyth 		}
1465*18eb7a2dSCharles.Forsyth 
1466*18eb7a2dSCharles.Forsyth 		while(t == ';')
1467*18eb7a2dSCharles.Forsyth 			t = gettok();
1468*18eb7a2dSCharles.Forsyth 		*mem++ = -nprod;
1469*18eb7a2dSCharles.Forsyth 
1470*18eb7a2dSCharles.Forsyth 		/* check that default action is reasonable */
1471*18eb7a2dSCharles.Forsyth 		if(ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].value) {
1472*18eb7a2dSCharles.Forsyth 
1473*18eb7a2dSCharles.Forsyth 			/* no explicit action, LHS has value */
1474*18eb7a2dSCharles.Forsyth 			int tempty;
1475*18eb7a2dSCharles.Forsyth 
1476*18eb7a2dSCharles.Forsyth 			tempty = prdptr[nprod][1];
1477*18eb7a2dSCharles.Forsyth 			if(tempty < 0)
1478*18eb7a2dSCharles.Forsyth 				error("must return a value, since LHS has a type");
1479*18eb7a2dSCharles.Forsyth 			else
1480*18eb7a2dSCharles.Forsyth 				if(tempty >= NTBASE)
1481*18eb7a2dSCharles.Forsyth 					tempty = nontrst[tempty-NTBASE].value;
1482*18eb7a2dSCharles.Forsyth 				else
1483*18eb7a2dSCharles.Forsyth 					tempty = TYPE(toklev[tempty]);
1484*18eb7a2dSCharles.Forsyth 			if(tempty != nontrst[*prdptr[nprod]-NTBASE].value)
1485*18eb7a2dSCharles.Forsyth 				error("default action causes potential type clash");
1486*18eb7a2dSCharles.Forsyth 		}
1487*18eb7a2dSCharles.Forsyth 		nprod++;
1488*18eb7a2dSCharles.Forsyth 		if(nprod >= NPROD)
1489*18eb7a2dSCharles.Forsyth 			error("more than %d rules", NPROD);
1490*18eb7a2dSCharles.Forsyth 		prdptr[nprod] = mem;
1491*18eb7a2dSCharles.Forsyth 		levprd[nprod] = 0;
1492*18eb7a2dSCharles.Forsyth 	}
1493*18eb7a2dSCharles.Forsyth 
1494*18eb7a2dSCharles.Forsyth 	/* end of all rules */
1495*18eb7a2dSCharles.Forsyth 	defout(1);
1496*18eb7a2dSCharles.Forsyth 
1497*18eb7a2dSCharles.Forsyth 	finact();
1498*18eb7a2dSCharles.Forsyth 	if(t == MARK) {
1499*18eb7a2dSCharles.Forsyth 		Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
1500*18eb7a2dSCharles.Forsyth 		while((c=Bgetrune(finput)) != Beof)
1501*18eb7a2dSCharles.Forsyth 			Bputrune(ftable, c);
1502*18eb7a2dSCharles.Forsyth 	}
1503*18eb7a2dSCharles.Forsyth 	Bterm(finput);
1504*18eb7a2dSCharles.Forsyth }
1505*18eb7a2dSCharles.Forsyth 
1506*18eb7a2dSCharles.Forsyth /*
1507*18eb7a2dSCharles.Forsyth  * finish action routine
1508*18eb7a2dSCharles.Forsyth  */
1509*18eb7a2dSCharles.Forsyth void
finact(void)1510*18eb7a2dSCharles.Forsyth finact(void)
1511*18eb7a2dSCharles.Forsyth {
1512*18eb7a2dSCharles.Forsyth 
1513*18eb7a2dSCharles.Forsyth 	Bterm(faction);
1514*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "#define YYEOFCODE %d\n", 1);
1515*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "#define YYERRCODE %d\n", 2);
1516*18eb7a2dSCharles.Forsyth }
1517*18eb7a2dSCharles.Forsyth 
1518*18eb7a2dSCharles.Forsyth /*
1519*18eb7a2dSCharles.Forsyth  * define s to be a terminal if t=0
1520*18eb7a2dSCharles.Forsyth  * or a nonterminal if t=1
1521*18eb7a2dSCharles.Forsyth  */
1522*18eb7a2dSCharles.Forsyth int
defin(int nt,char * s)1523*18eb7a2dSCharles.Forsyth defin(int nt, char *s)
1524*18eb7a2dSCharles.Forsyth {
1525*18eb7a2dSCharles.Forsyth 	int val;
1526*18eb7a2dSCharles.Forsyth 	Rune rune;
1527*18eb7a2dSCharles.Forsyth 
1528*18eb7a2dSCharles.Forsyth 	val = 0;
1529*18eb7a2dSCharles.Forsyth 	if(nt) {
1530*18eb7a2dSCharles.Forsyth 		nnonter++;
1531*18eb7a2dSCharles.Forsyth 		if(nnonter >= NNONTERM)
1532*18eb7a2dSCharles.Forsyth 			error("too many nonterminals, limit %d",NNONTERM);
1533*18eb7a2dSCharles.Forsyth 		nontrst[nnonter].name = cstash(s);
1534*18eb7a2dSCharles.Forsyth 		return NTBASE + nnonter;
1535*18eb7a2dSCharles.Forsyth 	}
1536*18eb7a2dSCharles.Forsyth 
1537*18eb7a2dSCharles.Forsyth 	/* must be a token */
1538*18eb7a2dSCharles.Forsyth 	ntokens++;
1539*18eb7a2dSCharles.Forsyth 	if(ntokens >= NTERMS)
1540*18eb7a2dSCharles.Forsyth 		error("too many terminals, limit %d", NTERMS);
1541*18eb7a2dSCharles.Forsyth 	tokset[ntokens].name = cstash(s);
1542*18eb7a2dSCharles.Forsyth 
1543*18eb7a2dSCharles.Forsyth 	/* establish value for token */
1544*18eb7a2dSCharles.Forsyth 	/* single character literal */
1545*18eb7a2dSCharles.Forsyth 	if(s[0] == ' ') {
1546*18eb7a2dSCharles.Forsyth 		val = chartorune(&rune, &s[1]);
1547*18eb7a2dSCharles.Forsyth 		if(s[val+1] == 0) {
1548*18eb7a2dSCharles.Forsyth 			val = rune;
1549*18eb7a2dSCharles.Forsyth 			goto out;
1550*18eb7a2dSCharles.Forsyth 		}
1551*18eb7a2dSCharles.Forsyth 	}
1552*18eb7a2dSCharles.Forsyth 
1553*18eb7a2dSCharles.Forsyth 	/* escape sequence */
1554*18eb7a2dSCharles.Forsyth 	if(s[0] == ' ' && s[1] == '\\') {
1555*18eb7a2dSCharles.Forsyth 		if(s[3] == 0) {
1556*18eb7a2dSCharles.Forsyth 			/* single character escape sequence */
1557*18eb7a2dSCharles.Forsyth 			switch(s[2]) {
1558*18eb7a2dSCharles.Forsyth 			case 'n':	val = '\n'; break;
1559*18eb7a2dSCharles.Forsyth 			case 'r':	val = '\r'; break;
1560*18eb7a2dSCharles.Forsyth 			case 'b':	val = '\b'; break;
1561*18eb7a2dSCharles.Forsyth 			case 't':	val = '\t'; break;
1562*18eb7a2dSCharles.Forsyth 			case 'f':	val = '\f'; break;
1563*18eb7a2dSCharles.Forsyth 			case '\'':	val = '\''; break;
1564*18eb7a2dSCharles.Forsyth 			case '"':	val = '"'; break;
1565*18eb7a2dSCharles.Forsyth 			case '\\':	val = '\\'; break;
1566*18eb7a2dSCharles.Forsyth 			default:	error("invalid escape");
1567*18eb7a2dSCharles.Forsyth 			}
1568*18eb7a2dSCharles.Forsyth 			goto out;
1569*18eb7a2dSCharles.Forsyth 		}
1570*18eb7a2dSCharles.Forsyth 
1571*18eb7a2dSCharles.Forsyth 		/* \nnn sequence */
1572*18eb7a2dSCharles.Forsyth 		if(s[2] >= '0' && s[2] <= '7') {
1573*18eb7a2dSCharles.Forsyth 			if(s[3] < '0' ||
1574*18eb7a2dSCharles.Forsyth 			   s[3] > '7' ||
1575*18eb7a2dSCharles.Forsyth 			   s[4] < '0' ||
1576*18eb7a2dSCharles.Forsyth 			   s[4] > '7' ||
1577*18eb7a2dSCharles.Forsyth 			   s[5] != 0)
1578*18eb7a2dSCharles.Forsyth 				error("illegal \\nnn construction");
1579*18eb7a2dSCharles.Forsyth 			val = 64*s[2] + 8*s[3] + s[4] - 73*'0';
1580*18eb7a2dSCharles.Forsyth 			if(val == 0)
1581*18eb7a2dSCharles.Forsyth 				error("'\\000' is illegal");
1582*18eb7a2dSCharles.Forsyth 			goto out;
1583*18eb7a2dSCharles.Forsyth 		}
1584*18eb7a2dSCharles.Forsyth 		error("unknown escape");
1585*18eb7a2dSCharles.Forsyth 	}
1586*18eb7a2dSCharles.Forsyth 	val = extval++;
1587*18eb7a2dSCharles.Forsyth 
1588*18eb7a2dSCharles.Forsyth out:
1589*18eb7a2dSCharles.Forsyth 	tokset[ntokens].value = val;
1590*18eb7a2dSCharles.Forsyth 	toklev[ntokens] = 0;
1591*18eb7a2dSCharles.Forsyth 	return ntokens;
1592*18eb7a2dSCharles.Forsyth }
1593*18eb7a2dSCharles.Forsyth 
1594*18eb7a2dSCharles.Forsyth /*
1595*18eb7a2dSCharles.Forsyth  * write out the defines (at the end of the declaration section)
1596*18eb7a2dSCharles.Forsyth  */
1597*18eb7a2dSCharles.Forsyth void
defout(int last)1598*18eb7a2dSCharles.Forsyth defout(int last)
1599*18eb7a2dSCharles.Forsyth {
1600*18eb7a2dSCharles.Forsyth 	int i, c;
1601*18eb7a2dSCharles.Forsyth 	char sar[NAMESIZE+10];
1602*18eb7a2dSCharles.Forsyth 
1603*18eb7a2dSCharles.Forsyth 	for(i=ndefout; i<=ntokens; i++) {
1604*18eb7a2dSCharles.Forsyth 		/* non-literals */
1605*18eb7a2dSCharles.Forsyth 		c = tokset[i].name[0];
1606*18eb7a2dSCharles.Forsyth 		if(c != ' ' && c != '$') {
1607*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "#define	%s	%d\n",
1608*18eb7a2dSCharles.Forsyth 				tokset[i].name, tokset[i].value);
1609*18eb7a2dSCharles.Forsyth 			if(fdefine)
1610*18eb7a2dSCharles.Forsyth 				Bprint(fdefine, "#define\t%s\t%d\n",
1611*18eb7a2dSCharles.Forsyth 					tokset[i].name, tokset[i].value);
1612*18eb7a2dSCharles.Forsyth 		}
1613*18eb7a2dSCharles.Forsyth 	}
1614*18eb7a2dSCharles.Forsyth 	ndefout = ntokens+1;
1615*18eb7a2dSCharles.Forsyth 	if(last && fdebug) {
1616*18eb7a2dSCharles.Forsyth 		Bprint(fdebug, "char*	yytoknames[] =\n{\n");
1617*18eb7a2dSCharles.Forsyth 		TLOOP(i) {
1618*18eb7a2dSCharles.Forsyth 			if(tokset[i].name) {
1619*18eb7a2dSCharles.Forsyth 				chcopy(sar, tokset[i].name);
1620*18eb7a2dSCharles.Forsyth 				Bprint(fdebug, "\t\"%s\",\n", sar);
1621*18eb7a2dSCharles.Forsyth 				continue;
1622*18eb7a2dSCharles.Forsyth 			}
1623*18eb7a2dSCharles.Forsyth 			Bprint(fdebug, "\t0,\n");
1624*18eb7a2dSCharles.Forsyth 		}
1625*18eb7a2dSCharles.Forsyth 		Bprint(fdebug, "};\n");
1626*18eb7a2dSCharles.Forsyth 	}
1627*18eb7a2dSCharles.Forsyth }
1628*18eb7a2dSCharles.Forsyth 
1629*18eb7a2dSCharles.Forsyth char*
cstash(char * s)1630*18eb7a2dSCharles.Forsyth cstash(char *s)
1631*18eb7a2dSCharles.Forsyth {
1632*18eb7a2dSCharles.Forsyth 	char *temp;
1633*18eb7a2dSCharles.Forsyth 
1634*18eb7a2dSCharles.Forsyth 	temp = cnamp;
1635*18eb7a2dSCharles.Forsyth 	do {
1636*18eb7a2dSCharles.Forsyth 		if(cnamp >= &cnames[cnamsz])
1637*18eb7a2dSCharles.Forsyth 			error("too many characters in id's and literals");
1638*18eb7a2dSCharles.Forsyth 		else
1639*18eb7a2dSCharles.Forsyth 			*cnamp++ = *s;
1640*18eb7a2dSCharles.Forsyth 	} while(*s++);
1641*18eb7a2dSCharles.Forsyth 	return temp;
1642*18eb7a2dSCharles.Forsyth }
1643*18eb7a2dSCharles.Forsyth 
1644*18eb7a2dSCharles.Forsyth long
gettok(void)1645*18eb7a2dSCharles.Forsyth gettok(void)
1646*18eb7a2dSCharles.Forsyth {
1647*18eb7a2dSCharles.Forsyth 	long c;
1648*18eb7a2dSCharles.Forsyth 	Rune rune;
1649*18eb7a2dSCharles.Forsyth 	int i, base, match, reserve;
1650*18eb7a2dSCharles.Forsyth 	static int peekline;
1651*18eb7a2dSCharles.Forsyth 
1652*18eb7a2dSCharles.Forsyth begin:
1653*18eb7a2dSCharles.Forsyth 	reserve = 0;
1654*18eb7a2dSCharles.Forsyth 	lineno += peekline;
1655*18eb7a2dSCharles.Forsyth 	peekline = 0;
1656*18eb7a2dSCharles.Forsyth 	c = Bgetrune(finput);
1657*18eb7a2dSCharles.Forsyth 	while(c == ' ' || c == '\n' || c == '\t' || c == '\f' || c == '\r') {
1658*18eb7a2dSCharles.Forsyth 		if(c == '\n')
1659*18eb7a2dSCharles.Forsyth 			lineno++;
1660*18eb7a2dSCharles.Forsyth 		c = Bgetrune(finput);
1661*18eb7a2dSCharles.Forsyth 	}
1662*18eb7a2dSCharles.Forsyth 
1663*18eb7a2dSCharles.Forsyth 	/* skip comment */
1664*18eb7a2dSCharles.Forsyth 	if(c == '/') {
1665*18eb7a2dSCharles.Forsyth 		lineno += skipcom();
1666*18eb7a2dSCharles.Forsyth 		goto begin;
1667*18eb7a2dSCharles.Forsyth 	}
1668*18eb7a2dSCharles.Forsyth 	switch(c) {
1669*18eb7a2dSCharles.Forsyth 	case Beof:
1670*18eb7a2dSCharles.Forsyth 		return ENDFILE;
1671*18eb7a2dSCharles.Forsyth 
1672*18eb7a2dSCharles.Forsyth 	case '{':
1673*18eb7a2dSCharles.Forsyth 		Bungetrune(finput);
1674*18eb7a2dSCharles.Forsyth 		return '=';
1675*18eb7a2dSCharles.Forsyth 
1676*18eb7a2dSCharles.Forsyth 	case '<':
1677*18eb7a2dSCharles.Forsyth 		/* get, and look up, a type name (union member name) */
1678*18eb7a2dSCharles.Forsyth 		i = 0;
1679*18eb7a2dSCharles.Forsyth 		while((c=Bgetrune(finput)) != '>' && c >= 0 && c != '\n' && c != '\r') {
1680*18eb7a2dSCharles.Forsyth 			rune = c;
1681*18eb7a2dSCharles.Forsyth 			c = runetochar(&tokname[i], &rune);
1682*18eb7a2dSCharles.Forsyth 			if(i < NAMESIZE)
1683*18eb7a2dSCharles.Forsyth 				i += c;
1684*18eb7a2dSCharles.Forsyth 		}
1685*18eb7a2dSCharles.Forsyth 		if(c != '>')
1686*18eb7a2dSCharles.Forsyth 			error("unterminated < ... > clause");
1687*18eb7a2dSCharles.Forsyth 		tokname[i] = 0;
1688*18eb7a2dSCharles.Forsyth 		for(i=1; i<=ntypes; i++)
1689*18eb7a2dSCharles.Forsyth 			if(!strcmp(typeset[i], tokname)) {
1690*18eb7a2dSCharles.Forsyth 				numbval = i;
1691*18eb7a2dSCharles.Forsyth 				return TYPENAME;
1692*18eb7a2dSCharles.Forsyth 			}
1693*18eb7a2dSCharles.Forsyth 		ntypes++;
1694*18eb7a2dSCharles.Forsyth 		numbval = ntypes;
1695*18eb7a2dSCharles.Forsyth 		typeset[numbval] = cstash(tokname);
1696*18eb7a2dSCharles.Forsyth 		return TYPENAME;
1697*18eb7a2dSCharles.Forsyth 
1698*18eb7a2dSCharles.Forsyth 	case '"':
1699*18eb7a2dSCharles.Forsyth 	case '\'':
1700*18eb7a2dSCharles.Forsyth 		match = c;
1701*18eb7a2dSCharles.Forsyth 		tokname[0] = ' ';
1702*18eb7a2dSCharles.Forsyth 		i = 1;
1703*18eb7a2dSCharles.Forsyth 		for(;;) {
1704*18eb7a2dSCharles.Forsyth 			c = Bgetrune(finput);
1705*18eb7a2dSCharles.Forsyth 			if(c == '\n' || c == '\r' || c <= 0)
1706*18eb7a2dSCharles.Forsyth 				error("illegal or missing ' or \"" );
1707*18eb7a2dSCharles.Forsyth 			if(c == '\\') {
1708*18eb7a2dSCharles.Forsyth 				tokname[i] = '\\';
1709*18eb7a2dSCharles.Forsyth 				if(i < NAMESIZE)
1710*18eb7a2dSCharles.Forsyth 					i++;
1711*18eb7a2dSCharles.Forsyth 				c = Bgetrune(finput);
1712*18eb7a2dSCharles.Forsyth 			} else
1713*18eb7a2dSCharles.Forsyth 				if(c == match)
1714*18eb7a2dSCharles.Forsyth 					break;
1715*18eb7a2dSCharles.Forsyth 			rune = c;
1716*18eb7a2dSCharles.Forsyth 			c = runetochar(&tokname[i], &rune);
1717*18eb7a2dSCharles.Forsyth 			if(i < NAMESIZE)
1718*18eb7a2dSCharles.Forsyth 				i += c;
1719*18eb7a2dSCharles.Forsyth 		}
1720*18eb7a2dSCharles.Forsyth 		break;
1721*18eb7a2dSCharles.Forsyth 
1722*18eb7a2dSCharles.Forsyth 	case '%':
1723*18eb7a2dSCharles.Forsyth 	case '\\':
1724*18eb7a2dSCharles.Forsyth 		switch(c = Bgetrune(finput)) {
1725*18eb7a2dSCharles.Forsyth 		case '0':	return TERM;
1726*18eb7a2dSCharles.Forsyth 		case '<':	return LEFT;
1727*18eb7a2dSCharles.Forsyth 		case '2':	return BINARY;
1728*18eb7a2dSCharles.Forsyth 		case '>':	return RIGHT;
1729*18eb7a2dSCharles.Forsyth 		case '%':
1730*18eb7a2dSCharles.Forsyth 		case '\\':	return MARK;
1731*18eb7a2dSCharles.Forsyth 		case '=':	return PREC;
1732*18eb7a2dSCharles.Forsyth 		case '{':	return LCURLY;
1733*18eb7a2dSCharles.Forsyth 		default:	reserve = 1;
1734*18eb7a2dSCharles.Forsyth 		}
1735*18eb7a2dSCharles.Forsyth 
1736*18eb7a2dSCharles.Forsyth 	default:
1737*18eb7a2dSCharles.Forsyth 		/* number */
1738*18eb7a2dSCharles.Forsyth 		if(isdigit(c)) {
1739*18eb7a2dSCharles.Forsyth 			numbval = c-'0';
1740*18eb7a2dSCharles.Forsyth 			base = (c=='0')? 8: 10;
1741*18eb7a2dSCharles.Forsyth 			for(c = Bgetrune(finput); isdigit(c); c = Bgetrune(finput))
1742*18eb7a2dSCharles.Forsyth 				numbval = numbval*base + (c-'0');
1743*18eb7a2dSCharles.Forsyth 			Bungetrune(finput);
1744*18eb7a2dSCharles.Forsyth 			return NUMBER;
1745*18eb7a2dSCharles.Forsyth 		}
1746*18eb7a2dSCharles.Forsyth 		if(islower(c) || isupper(c) || c=='_' || c=='.' || c=='$')  {
1747*18eb7a2dSCharles.Forsyth 			i = 0;
1748*18eb7a2dSCharles.Forsyth 			while(islower(c) || isupper(c) || isdigit(c) ||
1749*18eb7a2dSCharles.Forsyth 			    c == '-' || c=='_' || c=='.' || c=='$') {
1750*18eb7a2dSCharles.Forsyth 				if(reserve && isupper(c))
1751*18eb7a2dSCharles.Forsyth 					c += 'a'-'A';
1752*18eb7a2dSCharles.Forsyth 				rune = c;
1753*18eb7a2dSCharles.Forsyth 				c = runetochar(&tokname[i], &rune);
1754*18eb7a2dSCharles.Forsyth 				if(i < NAMESIZE)
1755*18eb7a2dSCharles.Forsyth 					i += c;
1756*18eb7a2dSCharles.Forsyth 				c = Bgetrune(finput);
1757*18eb7a2dSCharles.Forsyth 			}
1758*18eb7a2dSCharles.Forsyth 		} else
1759*18eb7a2dSCharles.Forsyth 			return c;
1760*18eb7a2dSCharles.Forsyth 		Bungetrune(finput);
1761*18eb7a2dSCharles.Forsyth 	}
1762*18eb7a2dSCharles.Forsyth 	tokname[i] = 0;
1763*18eb7a2dSCharles.Forsyth 
1764*18eb7a2dSCharles.Forsyth 	/* find a reserved word */
1765*18eb7a2dSCharles.Forsyth 	if(reserve) {
1766*18eb7a2dSCharles.Forsyth 		for(c=0; resrv[c].name; c++)
1767*18eb7a2dSCharles.Forsyth 			if(strcmp(tokname, resrv[c].name) == 0)
1768*18eb7a2dSCharles.Forsyth 				return resrv[c].value;
1769*18eb7a2dSCharles.Forsyth 		error("invalid escape, or illegal reserved word: %s", tokname);
1770*18eb7a2dSCharles.Forsyth 	}
1771*18eb7a2dSCharles.Forsyth 
1772*18eb7a2dSCharles.Forsyth 	/* look ahead to distinguish IDENTIFIER from IDENTCOLON */
1773*18eb7a2dSCharles.Forsyth 	c = Bgetrune(finput);
1774*18eb7a2dSCharles.Forsyth 	while(c == ' ' || c == '\t'|| c == '\n' || c == '\r' || c == '\f' || c == '/') {
1775*18eb7a2dSCharles.Forsyth 		if(c == '\n')
1776*18eb7a2dSCharles.Forsyth 			peekline++;
1777*18eb7a2dSCharles.Forsyth 		/* look for comments */
1778*18eb7a2dSCharles.Forsyth 		if(c == '/')
1779*18eb7a2dSCharles.Forsyth 			peekline += skipcom();
1780*18eb7a2dSCharles.Forsyth 		c = Bgetrune(finput);
1781*18eb7a2dSCharles.Forsyth 	}
1782*18eb7a2dSCharles.Forsyth 	if(c == ':')
1783*18eb7a2dSCharles.Forsyth 		return IDENTCOLON;
1784*18eb7a2dSCharles.Forsyth 	Bungetrune(finput);
1785*18eb7a2dSCharles.Forsyth 	return IDENTIFIER;
1786*18eb7a2dSCharles.Forsyth }
1787*18eb7a2dSCharles.Forsyth 
1788*18eb7a2dSCharles.Forsyth /*
1789*18eb7a2dSCharles.Forsyth  * determine the type of a symbol
1790*18eb7a2dSCharles.Forsyth  */
1791*18eb7a2dSCharles.Forsyth int
fdtype(int t)1792*18eb7a2dSCharles.Forsyth fdtype(int t)
1793*18eb7a2dSCharles.Forsyth {
1794*18eb7a2dSCharles.Forsyth 	int v;
1795*18eb7a2dSCharles.Forsyth 
1796*18eb7a2dSCharles.Forsyth 	if(t >= NTBASE)
1797*18eb7a2dSCharles.Forsyth 		v = nontrst[t-NTBASE].value;
1798*18eb7a2dSCharles.Forsyth 	else
1799*18eb7a2dSCharles.Forsyth 		v = TYPE(toklev[t]);
1800*18eb7a2dSCharles.Forsyth 	if(v <= 0)
1801*18eb7a2dSCharles.Forsyth 		error("must specify type for %s", (t>=NTBASE)?
1802*18eb7a2dSCharles.Forsyth 			nontrst[t-NTBASE].name: tokset[t].name);
1803*18eb7a2dSCharles.Forsyth 	return v;
1804*18eb7a2dSCharles.Forsyth }
1805*18eb7a2dSCharles.Forsyth 
1806*18eb7a2dSCharles.Forsyth int
chfind(int t,char * s)1807*18eb7a2dSCharles.Forsyth chfind(int t, char *s)
1808*18eb7a2dSCharles.Forsyth {
1809*18eb7a2dSCharles.Forsyth 	int i;
1810*18eb7a2dSCharles.Forsyth 
1811*18eb7a2dSCharles.Forsyth 	if(s[0] == ' ')
1812*18eb7a2dSCharles.Forsyth 		t = 0;
1813*18eb7a2dSCharles.Forsyth 	TLOOP(i)
1814*18eb7a2dSCharles.Forsyth 		if(!strcmp(s, tokset[i].name))
1815*18eb7a2dSCharles.Forsyth 			return i;
1816*18eb7a2dSCharles.Forsyth 	NTLOOP(i)
1817*18eb7a2dSCharles.Forsyth 		if(!strcmp(s, nontrst[i].name))
1818*18eb7a2dSCharles.Forsyth 			return NTBASE+i;
1819*18eb7a2dSCharles.Forsyth 
1820*18eb7a2dSCharles.Forsyth 	/* cannot find name */
1821*18eb7a2dSCharles.Forsyth 	if(t > 1)
1822*18eb7a2dSCharles.Forsyth 		error("%s should have been defined earlier", s);
1823*18eb7a2dSCharles.Forsyth 	return defin(t, s);
1824*18eb7a2dSCharles.Forsyth }
1825*18eb7a2dSCharles.Forsyth 
1826*18eb7a2dSCharles.Forsyth /*
1827*18eb7a2dSCharles.Forsyth  * copy the union declaration to the output, and the define file if present
1828*18eb7a2dSCharles.Forsyth  */
1829*18eb7a2dSCharles.Forsyth void
cpyunion(void)1830*18eb7a2dSCharles.Forsyth cpyunion(void)
1831*18eb7a2dSCharles.Forsyth {
1832*18eb7a2dSCharles.Forsyth 	long c;
1833*18eb7a2dSCharles.Forsyth 	int level;
1834*18eb7a2dSCharles.Forsyth 
1835*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
1836*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "typedef union ");
1837*18eb7a2dSCharles.Forsyth 	if(fdefine != 0)
1838*18eb7a2dSCharles.Forsyth 		Bprint(fdefine, "\ntypedef union ");
1839*18eb7a2dSCharles.Forsyth 
1840*18eb7a2dSCharles.Forsyth 	level = 0;
1841*18eb7a2dSCharles.Forsyth 	for(;;) {
1842*18eb7a2dSCharles.Forsyth 		if((c=Bgetrune(finput)) == Beof)
1843*18eb7a2dSCharles.Forsyth 			error("EOF encountered while processing %%union");
1844*18eb7a2dSCharles.Forsyth 		Bputrune(ftable, c);
1845*18eb7a2dSCharles.Forsyth 		if(fdefine != 0)
1846*18eb7a2dSCharles.Forsyth 			Bputrune(fdefine, c);
1847*18eb7a2dSCharles.Forsyth 		switch(c) {
1848*18eb7a2dSCharles.Forsyth 		case '\n':
1849*18eb7a2dSCharles.Forsyth 			lineno++;
1850*18eb7a2dSCharles.Forsyth 			break;
1851*18eb7a2dSCharles.Forsyth 		case '{':
1852*18eb7a2dSCharles.Forsyth 			level++;
1853*18eb7a2dSCharles.Forsyth 			break;
1854*18eb7a2dSCharles.Forsyth 		case '}':
1855*18eb7a2dSCharles.Forsyth 			level--;
1856*18eb7a2dSCharles.Forsyth 
1857*18eb7a2dSCharles.Forsyth 			/* we are finished copying */
1858*18eb7a2dSCharles.Forsyth 			if(level == 0) {
1859*18eb7a2dSCharles.Forsyth 				Bprint(ftable, " YYSTYPE;\n");
1860*18eb7a2dSCharles.Forsyth 				if(fdefine != 0)
1861*18eb7a2dSCharles.Forsyth 					Bprint(fdefine, "\tYYSTYPE;\nextern\tYYSTYPE\tyylval;\n");
1862*18eb7a2dSCharles.Forsyth 				return;
1863*18eb7a2dSCharles.Forsyth 			}
1864*18eb7a2dSCharles.Forsyth 		}
1865*18eb7a2dSCharles.Forsyth 	}
1866*18eb7a2dSCharles.Forsyth }
1867*18eb7a2dSCharles.Forsyth 
1868*18eb7a2dSCharles.Forsyth /*
1869*18eb7a2dSCharles.Forsyth  * copies code between \{ and \}
1870*18eb7a2dSCharles.Forsyth  */
1871*18eb7a2dSCharles.Forsyth void
cpycode(void)1872*18eb7a2dSCharles.Forsyth cpycode(void)
1873*18eb7a2dSCharles.Forsyth {
1874*18eb7a2dSCharles.Forsyth 
1875*18eb7a2dSCharles.Forsyth 	long c;
1876*18eb7a2dSCharles.Forsyth 
1877*18eb7a2dSCharles.Forsyth 	c = Bgetrune(finput);
1878*18eb7a2dSCharles.Forsyth 	if(c == '\n') {
1879*18eb7a2dSCharles.Forsyth 		c = Bgetrune(finput);
1880*18eb7a2dSCharles.Forsyth 		lineno++;
1881*18eb7a2dSCharles.Forsyth 	}
1882*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
1883*18eb7a2dSCharles.Forsyth 	while(c != Beof) {
1884*18eb7a2dSCharles.Forsyth 		if(c == '\\') {
1885*18eb7a2dSCharles.Forsyth 			if((c=Bgetrune(finput)) == '}')
1886*18eb7a2dSCharles.Forsyth 				return;
1887*18eb7a2dSCharles.Forsyth 			Bputc(ftable, '\\');
1888*18eb7a2dSCharles.Forsyth 		}
1889*18eb7a2dSCharles.Forsyth 		if(c == '%') {
1890*18eb7a2dSCharles.Forsyth 			if((c=Bgetrune(finput)) == '}')
1891*18eb7a2dSCharles.Forsyth 				return;
1892*18eb7a2dSCharles.Forsyth 			Bputc(ftable, '%');
1893*18eb7a2dSCharles.Forsyth 		}
1894*18eb7a2dSCharles.Forsyth 		Bputrune(ftable, c);
1895*18eb7a2dSCharles.Forsyth 		if(c == '\n')
1896*18eb7a2dSCharles.Forsyth 			lineno++;
1897*18eb7a2dSCharles.Forsyth 		c = Bgetrune(finput);
1898*18eb7a2dSCharles.Forsyth 	}
1899*18eb7a2dSCharles.Forsyth 	error("eof before %%}");
1900*18eb7a2dSCharles.Forsyth }
1901*18eb7a2dSCharles.Forsyth 
1902*18eb7a2dSCharles.Forsyth /*
1903*18eb7a2dSCharles.Forsyth  * skip over comments
1904*18eb7a2dSCharles.Forsyth  * skipcom is called after reading a '/'
1905*18eb7a2dSCharles.Forsyth  */
1906*18eb7a2dSCharles.Forsyth int
skipcom(void)1907*18eb7a2dSCharles.Forsyth skipcom(void)
1908*18eb7a2dSCharles.Forsyth {
1909*18eb7a2dSCharles.Forsyth 	long c;
1910*18eb7a2dSCharles.Forsyth 	int i;
1911*18eb7a2dSCharles.Forsyth 
1912*18eb7a2dSCharles.Forsyth 	/* i is the number of lines skipped */
1913*18eb7a2dSCharles.Forsyth 	i = 0;
1914*18eb7a2dSCharles.Forsyth 	if(Bgetrune(finput) != '*')
1915*18eb7a2dSCharles.Forsyth 		error("illegal comment");
1916*18eb7a2dSCharles.Forsyth 	c = Bgetrune(finput);
1917*18eb7a2dSCharles.Forsyth 	while(c != Beof) {
1918*18eb7a2dSCharles.Forsyth 		while(c == '*')
1919*18eb7a2dSCharles.Forsyth 			if((c=Bgetrune(finput)) == '/')
1920*18eb7a2dSCharles.Forsyth 				return i;
1921*18eb7a2dSCharles.Forsyth 		if(c == '\n')
1922*18eb7a2dSCharles.Forsyth 			i++;
1923*18eb7a2dSCharles.Forsyth 		c = Bgetrune(finput);
1924*18eb7a2dSCharles.Forsyth 	}
1925*18eb7a2dSCharles.Forsyth 	error("EOF inside comment");
1926*18eb7a2dSCharles.Forsyth 	return 0;
1927*18eb7a2dSCharles.Forsyth }
1928*18eb7a2dSCharles.Forsyth 
1929*18eb7a2dSCharles.Forsyth /*
1930*18eb7a2dSCharles.Forsyth  * copy C action to the next ; or closing }
1931*18eb7a2dSCharles.Forsyth  */
1932*18eb7a2dSCharles.Forsyth void
cpyact(int offset)1933*18eb7a2dSCharles.Forsyth cpyact(int offset)
1934*18eb7a2dSCharles.Forsyth {
1935*18eb7a2dSCharles.Forsyth 	long c;
1936*18eb7a2dSCharles.Forsyth 	int brac, match, j, s, fnd, tok;
1937*18eb7a2dSCharles.Forsyth 
1938*18eb7a2dSCharles.Forsyth 	Bprint(faction, "\n#line\t%d\t\"%s\"\n", lineno, infile);
1939*18eb7a2dSCharles.Forsyth 	brac = 0;
1940*18eb7a2dSCharles.Forsyth 
1941*18eb7a2dSCharles.Forsyth loop:
1942*18eb7a2dSCharles.Forsyth 	c = Bgetrune(finput);
1943*18eb7a2dSCharles.Forsyth swt:
1944*18eb7a2dSCharles.Forsyth 	switch(c) {
1945*18eb7a2dSCharles.Forsyth 	case ';':
1946*18eb7a2dSCharles.Forsyth 		if(brac == 0) {
1947*18eb7a2dSCharles.Forsyth 			Bputrune(faction, c);
1948*18eb7a2dSCharles.Forsyth 			return;
1949*18eb7a2dSCharles.Forsyth 		}
1950*18eb7a2dSCharles.Forsyth 		goto lcopy;
1951*18eb7a2dSCharles.Forsyth 
1952*18eb7a2dSCharles.Forsyth 	case '{':
1953*18eb7a2dSCharles.Forsyth 		brac++;
1954*18eb7a2dSCharles.Forsyth 		goto lcopy;
1955*18eb7a2dSCharles.Forsyth 
1956*18eb7a2dSCharles.Forsyth 	case '$':
1957*18eb7a2dSCharles.Forsyth 		s = 1;
1958*18eb7a2dSCharles.Forsyth 		tok = -1;
1959*18eb7a2dSCharles.Forsyth 		c = Bgetrune(finput);
1960*18eb7a2dSCharles.Forsyth 
1961*18eb7a2dSCharles.Forsyth 		/* type description */
1962*18eb7a2dSCharles.Forsyth 		if(c == '<') {
1963*18eb7a2dSCharles.Forsyth 			Bungetrune(finput);
1964*18eb7a2dSCharles.Forsyth 			if(gettok() != TYPENAME)
1965*18eb7a2dSCharles.Forsyth 				error("bad syntax on $<ident> clause");
1966*18eb7a2dSCharles.Forsyth 			tok = numbval;
1967*18eb7a2dSCharles.Forsyth 			c = Bgetrune(finput);
1968*18eb7a2dSCharles.Forsyth 		}
1969*18eb7a2dSCharles.Forsyth 		if(c == '$') {
1970*18eb7a2dSCharles.Forsyth 			Bprint(faction, "yyval");
1971*18eb7a2dSCharles.Forsyth 
1972*18eb7a2dSCharles.Forsyth 			/* put out the proper tag... */
1973*18eb7a2dSCharles.Forsyth 			if(ntypes) {
1974*18eb7a2dSCharles.Forsyth 				if(tok < 0)
1975*18eb7a2dSCharles.Forsyth 					tok = fdtype(*prdptr[nprod]);
1976*18eb7a2dSCharles.Forsyth 				Bprint(faction, ".%s", typeset[tok]);
1977*18eb7a2dSCharles.Forsyth 			}
1978*18eb7a2dSCharles.Forsyth 			goto loop;
1979*18eb7a2dSCharles.Forsyth 		}
1980*18eb7a2dSCharles.Forsyth 		if(c == '-') {
1981*18eb7a2dSCharles.Forsyth 			s = -s;
1982*18eb7a2dSCharles.Forsyth 			c = Bgetrune(finput);
1983*18eb7a2dSCharles.Forsyth 		}
1984*18eb7a2dSCharles.Forsyth 		if(isdigit(c)) {
1985*18eb7a2dSCharles.Forsyth 			j = 0;
1986*18eb7a2dSCharles.Forsyth 			while(isdigit(c)) {
1987*18eb7a2dSCharles.Forsyth 				j = j*10 + (c-'0');
1988*18eb7a2dSCharles.Forsyth 				c = Bgetrune(finput);
1989*18eb7a2dSCharles.Forsyth 			}
1990*18eb7a2dSCharles.Forsyth 			Bungetrune(finput);
1991*18eb7a2dSCharles.Forsyth 			j = j*s - offset;
1992*18eb7a2dSCharles.Forsyth 			if(j > 0)
1993*18eb7a2dSCharles.Forsyth 				error("Illegal use of $%d", j+offset);
1994*18eb7a2dSCharles.Forsyth 
1995*18eb7a2dSCharles.Forsyth 		dollar:
1996*18eb7a2dSCharles.Forsyth 			Bprint(faction, "yypt[-%d].yyv", -j);
1997*18eb7a2dSCharles.Forsyth 
1998*18eb7a2dSCharles.Forsyth 			/* put out the proper tag */
1999*18eb7a2dSCharles.Forsyth 			if(ntypes) {
2000*18eb7a2dSCharles.Forsyth 				if(j+offset <= 0 && tok < 0)
2001*18eb7a2dSCharles.Forsyth 					error("must specify type of $%d", j+offset);
2002*18eb7a2dSCharles.Forsyth 				if(tok < 0)
2003*18eb7a2dSCharles.Forsyth 					tok = fdtype(prdptr[nprod][j+offset]);
2004*18eb7a2dSCharles.Forsyth 				Bprint(faction, ".%s", typeset[tok]);
2005*18eb7a2dSCharles.Forsyth 			}
2006*18eb7a2dSCharles.Forsyth 			goto loop;
2007*18eb7a2dSCharles.Forsyth 		}
2008*18eb7a2dSCharles.Forsyth 		if(isupper(c) || islower(c) || c == '_' || c == '.') {
2009*18eb7a2dSCharles.Forsyth 			int tok; /* tok used oustide for type info */
2010*18eb7a2dSCharles.Forsyth 
2011*18eb7a2dSCharles.Forsyth 			/* look for $name */
2012*18eb7a2dSCharles.Forsyth 			Bungetrune(finput);
2013*18eb7a2dSCharles.Forsyth 			if(gettok() != IDENTIFIER)
2014*18eb7a2dSCharles.Forsyth 				error("$ must be followed by an identifier");
2015*18eb7a2dSCharles.Forsyth 			tok = chfind(2, tokname);
2016*18eb7a2dSCharles.Forsyth 			if((c = Bgetrune(finput)) != '#') {
2017*18eb7a2dSCharles.Forsyth 				Bungetrune(finput);
2018*18eb7a2dSCharles.Forsyth 				fnd = -1;
2019*18eb7a2dSCharles.Forsyth 			} else
2020*18eb7a2dSCharles.Forsyth 				if(gettok() != NUMBER) {
2021*18eb7a2dSCharles.Forsyth 					error("# must be followed by number");
2022*18eb7a2dSCharles.Forsyth 					fnd = -1;
2023*18eb7a2dSCharles.Forsyth 				} else
2024*18eb7a2dSCharles.Forsyth 					fnd = numbval;
2025*18eb7a2dSCharles.Forsyth 			for(j=1; j<=offset; ++j)
2026*18eb7a2dSCharles.Forsyth 				if(tok == prdptr[nprod][j]) {
2027*18eb7a2dSCharles.Forsyth 					if(--fnd <= 0) {
2028*18eb7a2dSCharles.Forsyth 						j -= offset;
2029*18eb7a2dSCharles.Forsyth 						goto dollar;
2030*18eb7a2dSCharles.Forsyth 					}
2031*18eb7a2dSCharles.Forsyth 				}
2032*18eb7a2dSCharles.Forsyth 			error("$name or $name#number not found");
2033*18eb7a2dSCharles.Forsyth 		}
2034*18eb7a2dSCharles.Forsyth 		Bputc(faction, '$');
2035*18eb7a2dSCharles.Forsyth 		if(s < 0 )
2036*18eb7a2dSCharles.Forsyth 			Bputc(faction, '-');
2037*18eb7a2dSCharles.Forsyth 		goto swt;
2038*18eb7a2dSCharles.Forsyth 
2039*18eb7a2dSCharles.Forsyth 	case '}':
2040*18eb7a2dSCharles.Forsyth 		brac--;
2041*18eb7a2dSCharles.Forsyth 		if(brac)
2042*18eb7a2dSCharles.Forsyth 			goto lcopy;
2043*18eb7a2dSCharles.Forsyth 		Bputrune(faction, c);
2044*18eb7a2dSCharles.Forsyth 		return;
2045*18eb7a2dSCharles.Forsyth 
2046*18eb7a2dSCharles.Forsyth 	case '/':
2047*18eb7a2dSCharles.Forsyth 		/* look for comments */
2048*18eb7a2dSCharles.Forsyth 		Bputrune(faction, c);
2049*18eb7a2dSCharles.Forsyth 		c = Bgetrune(finput);
2050*18eb7a2dSCharles.Forsyth 		if(c != '*')
2051*18eb7a2dSCharles.Forsyth 			goto swt;
2052*18eb7a2dSCharles.Forsyth 
2053*18eb7a2dSCharles.Forsyth 		/* it really is a comment */
2054*18eb7a2dSCharles.Forsyth 		Bputrune(faction, c);
2055*18eb7a2dSCharles.Forsyth 		c = Bgetrune(finput);
2056*18eb7a2dSCharles.Forsyth 		while(c >= 0) {
2057*18eb7a2dSCharles.Forsyth 			while(c == '*') {
2058*18eb7a2dSCharles.Forsyth 				Bputrune(faction, c);
2059*18eb7a2dSCharles.Forsyth 				if((c=Bgetrune(finput)) == '/')
2060*18eb7a2dSCharles.Forsyth 					goto lcopy;
2061*18eb7a2dSCharles.Forsyth 			}
2062*18eb7a2dSCharles.Forsyth 			Bputrune(faction, c);
2063*18eb7a2dSCharles.Forsyth 			if(c == '\n')
2064*18eb7a2dSCharles.Forsyth 				lineno++;
2065*18eb7a2dSCharles.Forsyth 			c = Bgetrune(finput);
2066*18eb7a2dSCharles.Forsyth 		}
2067*18eb7a2dSCharles.Forsyth 		error("EOF inside comment");
2068*18eb7a2dSCharles.Forsyth 
2069*18eb7a2dSCharles.Forsyth 	case '\'':
2070*18eb7a2dSCharles.Forsyth 		/* character constant */
2071*18eb7a2dSCharles.Forsyth 		match = '\'';
2072*18eb7a2dSCharles.Forsyth 		goto string;
2073*18eb7a2dSCharles.Forsyth 
2074*18eb7a2dSCharles.Forsyth 	case '"':
2075*18eb7a2dSCharles.Forsyth 		/* character string */
2076*18eb7a2dSCharles.Forsyth 		match = '"';
2077*18eb7a2dSCharles.Forsyth 
2078*18eb7a2dSCharles.Forsyth 	string:
2079*18eb7a2dSCharles.Forsyth 		Bputrune(faction, c);
2080*18eb7a2dSCharles.Forsyth 		while(c = Bgetrune(finput)) {
2081*18eb7a2dSCharles.Forsyth 			if(c == '\\') {
2082*18eb7a2dSCharles.Forsyth 				Bputrune(faction, c);
2083*18eb7a2dSCharles.Forsyth 				c = Bgetrune(finput);
2084*18eb7a2dSCharles.Forsyth 				if(c == '\n')
2085*18eb7a2dSCharles.Forsyth 					lineno++;
2086*18eb7a2dSCharles.Forsyth 			} else
2087*18eb7a2dSCharles.Forsyth 				if(c == match)
2088*18eb7a2dSCharles.Forsyth 					goto lcopy;
2089*18eb7a2dSCharles.Forsyth 				if(c == '\n')
2090*18eb7a2dSCharles.Forsyth 					error("newline in string or char. const.");
2091*18eb7a2dSCharles.Forsyth 			Bputrune(faction, c);
2092*18eb7a2dSCharles.Forsyth 		}
2093*18eb7a2dSCharles.Forsyth 		error("EOF in string or character constant");
2094*18eb7a2dSCharles.Forsyth 
2095*18eb7a2dSCharles.Forsyth 	case Beof:
2096*18eb7a2dSCharles.Forsyth 		error("action does not terminate");
2097*18eb7a2dSCharles.Forsyth 
2098*18eb7a2dSCharles.Forsyth 	case '\n':
2099*18eb7a2dSCharles.Forsyth 		lineno++;
2100*18eb7a2dSCharles.Forsyth 		goto lcopy;
2101*18eb7a2dSCharles.Forsyth 	}
2102*18eb7a2dSCharles.Forsyth 
2103*18eb7a2dSCharles.Forsyth lcopy:
2104*18eb7a2dSCharles.Forsyth 	Bputrune(faction, c);
2105*18eb7a2dSCharles.Forsyth 	goto loop;
2106*18eb7a2dSCharles.Forsyth }
2107*18eb7a2dSCharles.Forsyth 
2108*18eb7a2dSCharles.Forsyth void
openup(char * stem,int dflag,int vflag,int ytab,char * ytabc)2109*18eb7a2dSCharles.Forsyth openup(char *stem, int dflag, int vflag, int ytab, char *ytabc)
2110*18eb7a2dSCharles.Forsyth {
2111*18eb7a2dSCharles.Forsyth 	char buf[256];
2112*18eb7a2dSCharles.Forsyth 
2113*18eb7a2dSCharles.Forsyth 	if(vflag) {
2114*18eb7a2dSCharles.Forsyth 		sprint(buf, "%s.%s", stem, FILEU);
2115*18eb7a2dSCharles.Forsyth 		foutput = Bopen(buf, OWRITE);
2116*18eb7a2dSCharles.Forsyth 		if(foutput == 0)
2117*18eb7a2dSCharles.Forsyth 			error("cannot open %s", buf);
2118*18eb7a2dSCharles.Forsyth 	}
2119*18eb7a2dSCharles.Forsyth 	if(yydebug) {
2120*18eb7a2dSCharles.Forsyth 		sprint(buf, "%s.%s", stem, FILEDEBUG);
2121*18eb7a2dSCharles.Forsyth 		if((fdebug = Bopen(buf, OWRITE)) == 0)
2122*18eb7a2dSCharles.Forsyth 			error("can't open %s", buf);
2123*18eb7a2dSCharles.Forsyth 	}
2124*18eb7a2dSCharles.Forsyth 	if(dflag) {
2125*18eb7a2dSCharles.Forsyth 		sprint(buf, "%s.%s", stem, FILED);
2126*18eb7a2dSCharles.Forsyth 		fdefine = Bopen(buf, OWRITE);
2127*18eb7a2dSCharles.Forsyth 		if(fdefine == 0)
2128*18eb7a2dSCharles.Forsyth 			error("can't create %s", buf);
2129*18eb7a2dSCharles.Forsyth 	}
2130*18eb7a2dSCharles.Forsyth 	if(ytab == 0)
2131*18eb7a2dSCharles.Forsyth 		sprint(buf, "%s.%s", stem, OFILE);
2132*18eb7a2dSCharles.Forsyth 	else
2133*18eb7a2dSCharles.Forsyth 		strcpy(buf, ytabc);
2134*18eb7a2dSCharles.Forsyth 	ftable = Bopen(buf, OWRITE);
2135*18eb7a2dSCharles.Forsyth 	if(ftable == 0)
2136*18eb7a2dSCharles.Forsyth 		error("cannot open table file %s", buf);
2137*18eb7a2dSCharles.Forsyth }
2138*18eb7a2dSCharles.Forsyth 
2139*18eb7a2dSCharles.Forsyth /*
2140*18eb7a2dSCharles.Forsyth  * print the output for the states
2141*18eb7a2dSCharles.Forsyth  */
2142*18eb7a2dSCharles.Forsyth void
output(void)2143*18eb7a2dSCharles.Forsyth output(void)
2144*18eb7a2dSCharles.Forsyth {
2145*18eb7a2dSCharles.Forsyth 	int i, k, c;
2146*18eb7a2dSCharles.Forsyth 	Wset *u, *v;
2147*18eb7a2dSCharles.Forsyth 
2148*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "short	yyexca[] =\n{");
2149*18eb7a2dSCharles.Forsyth 	if(fdebug)
2150*18eb7a2dSCharles.Forsyth 		Bprint(fdebug, "char*	yystates[] =\n{\n");
2151*18eb7a2dSCharles.Forsyth 
2152*18eb7a2dSCharles.Forsyth 	/* output the stuff for state i */
2153*18eb7a2dSCharles.Forsyth 	SLOOP(i) {
2154*18eb7a2dSCharles.Forsyth 		nolook = tystate[i]!=MUSTLOOKAHEAD;
2155*18eb7a2dSCharles.Forsyth 		closure(i);
2156*18eb7a2dSCharles.Forsyth 
2157*18eb7a2dSCharles.Forsyth 		/* output actions */
2158*18eb7a2dSCharles.Forsyth 		nolook = 1;
2159*18eb7a2dSCharles.Forsyth 		aryfil(temp1, ntokens+nnonter+1, 0);
2160*18eb7a2dSCharles.Forsyth 		WSLOOP(wsets, u) {
2161*18eb7a2dSCharles.Forsyth 			c = *(u->pitem);
2162*18eb7a2dSCharles.Forsyth 			if(c > 1 && c < NTBASE && temp1[c] == 0) {
2163*18eb7a2dSCharles.Forsyth 				WSLOOP(u, v)
2164*18eb7a2dSCharles.Forsyth 					if(c == *(v->pitem))
2165*18eb7a2dSCharles.Forsyth 						putitem(v->pitem+1, (Lkset*)0);
2166*18eb7a2dSCharles.Forsyth 				temp1[c] = state(c);
2167*18eb7a2dSCharles.Forsyth 			} else
2168*18eb7a2dSCharles.Forsyth 				if(c > NTBASE && temp1[(c -= NTBASE) + ntokens] == 0)
2169*18eb7a2dSCharles.Forsyth 					temp1[c+ntokens] = amem[indgo[i]+c];
2170*18eb7a2dSCharles.Forsyth 		}
2171*18eb7a2dSCharles.Forsyth 		if(i == 1)
2172*18eb7a2dSCharles.Forsyth 			temp1[1] = ACCEPTCODE;
2173*18eb7a2dSCharles.Forsyth 
2174*18eb7a2dSCharles.Forsyth 		/* now, we have the shifts; look at the reductions */
2175*18eb7a2dSCharles.Forsyth 		lastred = 0;
2176*18eb7a2dSCharles.Forsyth 		WSLOOP(wsets, u) {
2177*18eb7a2dSCharles.Forsyth 			c = *u->pitem;
2178*18eb7a2dSCharles.Forsyth 
2179*18eb7a2dSCharles.Forsyth 			/* reduction */
2180*18eb7a2dSCharles.Forsyth 			if(c <= 0) {
2181*18eb7a2dSCharles.Forsyth 				lastred = -c;
2182*18eb7a2dSCharles.Forsyth 				TLOOP(k)
2183*18eb7a2dSCharles.Forsyth 					if(BIT(u->ws.lset, k)) {
2184*18eb7a2dSCharles.Forsyth 						if(temp1[k] == 0)
2185*18eb7a2dSCharles.Forsyth 							temp1[k] = c;
2186*18eb7a2dSCharles.Forsyth 						else
2187*18eb7a2dSCharles.Forsyth 						if(temp1[k] < 0) { /* reduce/reduce conflict */
2188*18eb7a2dSCharles.Forsyth 							if(foutput)
2189*18eb7a2dSCharles.Forsyth 								Bprint(foutput,
2190*18eb7a2dSCharles.Forsyth 									"\n%d: reduce/reduce conflict"
2191*18eb7a2dSCharles.Forsyth 									" (red'ns %d and %d ) on %s",
2192*18eb7a2dSCharles.Forsyth 									i, -temp1[k], lastred,
2193*18eb7a2dSCharles.Forsyth 									symnam(k));
2194*18eb7a2dSCharles.Forsyth 							if(-temp1[k] > lastred)
2195*18eb7a2dSCharles.Forsyth 								temp1[k] = -lastred;
2196*18eb7a2dSCharles.Forsyth 							zzrrconf++;
2197*18eb7a2dSCharles.Forsyth 						} else
2198*18eb7a2dSCharles.Forsyth 							/* potential shift/reduce conflict */
2199*18eb7a2dSCharles.Forsyth 							precftn( lastred, k, i );
2200*18eb7a2dSCharles.Forsyth 					}
2201*18eb7a2dSCharles.Forsyth 				}
2202*18eb7a2dSCharles.Forsyth 		}
2203*18eb7a2dSCharles.Forsyth 		wract(i);
2204*18eb7a2dSCharles.Forsyth 	}
2205*18eb7a2dSCharles.Forsyth 
2206*18eb7a2dSCharles.Forsyth 	if(fdebug)
2207*18eb7a2dSCharles.Forsyth 		Bprint(fdebug, "};\n");
2208*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "};\n");
2209*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "#define	YYNPROD	%d\n", nprod);
2210*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "#define	YYPRIVATE %d\n", PRIVATE);
2211*18eb7a2dSCharles.Forsyth 	if(yydebug)
2212*18eb7a2dSCharles.Forsyth 		Bprint(ftable, "#define	yydebug	%s\n", yydebug);
2213*18eb7a2dSCharles.Forsyth }
2214*18eb7a2dSCharles.Forsyth 
2215*18eb7a2dSCharles.Forsyth /*
2216*18eb7a2dSCharles.Forsyth  * pack state i from temp1 into amem
2217*18eb7a2dSCharles.Forsyth  */
2218*18eb7a2dSCharles.Forsyth int
apack(int * p,int n)2219*18eb7a2dSCharles.Forsyth apack(int *p, int n)
2220*18eb7a2dSCharles.Forsyth {
2221*18eb7a2dSCharles.Forsyth 	int *pp, *qq, *rr, off, *q, *r;
2222*18eb7a2dSCharles.Forsyth 
2223*18eb7a2dSCharles.Forsyth 	/* we don't need to worry about checking because
2224*18eb7a2dSCharles.Forsyth 	 * we will only look at entries known to be there...
2225*18eb7a2dSCharles.Forsyth 	 * eliminate leading and trailing 0's
2226*18eb7a2dSCharles.Forsyth 	 */
2227*18eb7a2dSCharles.Forsyth 
2228*18eb7a2dSCharles.Forsyth 	q = p+n;
2229*18eb7a2dSCharles.Forsyth 	for(pp = p, off = 0; *pp == 0 && pp <= q; ++pp, --off)
2230*18eb7a2dSCharles.Forsyth 		;
2231*18eb7a2dSCharles.Forsyth  	/* no actions */
2232*18eb7a2dSCharles.Forsyth 	if(pp > q)
2233*18eb7a2dSCharles.Forsyth 		return 0;
2234*18eb7a2dSCharles.Forsyth 	p = pp;
2235*18eb7a2dSCharles.Forsyth 
2236*18eb7a2dSCharles.Forsyth 	/* now, find a place for the elements from p to q, inclusive */
2237*18eb7a2dSCharles.Forsyth 	r = &amem[ACTSIZE-1];
2238*18eb7a2dSCharles.Forsyth 	for(rr = amem; rr <= r; rr++, off++) {
2239*18eb7a2dSCharles.Forsyth 		for(qq = rr, pp = p; pp <= q; pp++, qq++)
2240*18eb7a2dSCharles.Forsyth 			if(*pp != 0)
2241*18eb7a2dSCharles.Forsyth 				if(*pp != *qq && *qq != 0)
2242*18eb7a2dSCharles.Forsyth 					goto nextk;
2243*18eb7a2dSCharles.Forsyth 
2244*18eb7a2dSCharles.Forsyth 		/* we have found an acceptable k */
2245*18eb7a2dSCharles.Forsyth 		if(pkdebug && foutput != 0)
2246*18eb7a2dSCharles.Forsyth 			Bprint(foutput, "off = %d, k = %d\n", off, (int)(rr-amem));
2247*18eb7a2dSCharles.Forsyth 		for(qq = rr, pp = p; pp <= q; pp++, qq++)
2248*18eb7a2dSCharles.Forsyth 			if(*pp) {
2249*18eb7a2dSCharles.Forsyth 				if(qq > r)
2250*18eb7a2dSCharles.Forsyth 					error("action table overflow");
2251*18eb7a2dSCharles.Forsyth 				if(qq > memp)
2252*18eb7a2dSCharles.Forsyth 					memp = qq;
2253*18eb7a2dSCharles.Forsyth 				*qq = *pp;
2254*18eb7a2dSCharles.Forsyth 			}
2255*18eb7a2dSCharles.Forsyth 		if(pkdebug && foutput != 0)
2256*18eb7a2dSCharles.Forsyth 			for(pp = amem; pp <= memp; pp += 10) {
2257*18eb7a2dSCharles.Forsyth 				Bprint(foutput, "\t");
2258*18eb7a2dSCharles.Forsyth 				for(qq = pp; qq <= pp+9; qq++)
2259*18eb7a2dSCharles.Forsyth 					Bprint(foutput, "%d ", *qq);
2260*18eb7a2dSCharles.Forsyth 				Bprint(foutput, "\n");
2261*18eb7a2dSCharles.Forsyth 			}
2262*18eb7a2dSCharles.Forsyth 		return(off);
2263*18eb7a2dSCharles.Forsyth 	nextk:;
2264*18eb7a2dSCharles.Forsyth 	}
2265*18eb7a2dSCharles.Forsyth 	error("no space in action table");
2266*18eb7a2dSCharles.Forsyth 	return 0;
2267*18eb7a2dSCharles.Forsyth }
2268*18eb7a2dSCharles.Forsyth 
2269*18eb7a2dSCharles.Forsyth /*
2270*18eb7a2dSCharles.Forsyth  * output the gotos for the nontermninals
2271*18eb7a2dSCharles.Forsyth  */
2272*18eb7a2dSCharles.Forsyth void
go2out(void)2273*18eb7a2dSCharles.Forsyth go2out(void)
2274*18eb7a2dSCharles.Forsyth {
2275*18eb7a2dSCharles.Forsyth 	int i, j, k, best, count, cbest, times;
2276*18eb7a2dSCharles.Forsyth 
2277*18eb7a2dSCharles.Forsyth 	/* mark begining of gotos */
2278*18eb7a2dSCharles.Forsyth 	Bprint(ftemp, "$\n");
2279*18eb7a2dSCharles.Forsyth 	for(i = 1; i <= nnonter; i++) {
2280*18eb7a2dSCharles.Forsyth 		go2gen(i);
2281*18eb7a2dSCharles.Forsyth 
2282*18eb7a2dSCharles.Forsyth 		/* find the best one to make default */
2283*18eb7a2dSCharles.Forsyth 		best = -1;
2284*18eb7a2dSCharles.Forsyth 		times = 0;
2285*18eb7a2dSCharles.Forsyth 
2286*18eb7a2dSCharles.Forsyth 		/* is j the most frequent */
2287*18eb7a2dSCharles.Forsyth 		for(j = 0; j <= nstate; j++) {
2288*18eb7a2dSCharles.Forsyth 			if(tystate[j] == 0)
2289*18eb7a2dSCharles.Forsyth 				continue;
2290*18eb7a2dSCharles.Forsyth 			if(tystate[j] == best)
2291*18eb7a2dSCharles.Forsyth 				continue;
2292*18eb7a2dSCharles.Forsyth 
2293*18eb7a2dSCharles.Forsyth 			/* is tystate[j] the most frequent */
2294*18eb7a2dSCharles.Forsyth 			count = 0;
2295*18eb7a2dSCharles.Forsyth 			cbest = tystate[j];
2296*18eb7a2dSCharles.Forsyth 			for(k = j; k <= nstate; k++)
2297*18eb7a2dSCharles.Forsyth 				if(tystate[k] == cbest)
2298*18eb7a2dSCharles.Forsyth 					count++;
2299*18eb7a2dSCharles.Forsyth 			if(count > times) {
2300*18eb7a2dSCharles.Forsyth 				best = cbest;
2301*18eb7a2dSCharles.Forsyth 				times = count;
2302*18eb7a2dSCharles.Forsyth 			}
2303*18eb7a2dSCharles.Forsyth 		}
2304*18eb7a2dSCharles.Forsyth 
2305*18eb7a2dSCharles.Forsyth 		/* best is now the default entry */
2306*18eb7a2dSCharles.Forsyth 		zzgobest += times-1;
2307*18eb7a2dSCharles.Forsyth 		for(j = 0; j <= nstate; j++)
2308*18eb7a2dSCharles.Forsyth 			if(tystate[j] != 0 && tystate[j] != best) {
2309*18eb7a2dSCharles.Forsyth 				Bprint(ftemp, "%d,%d,", j, tystate[j]);
2310*18eb7a2dSCharles.Forsyth 				zzgoent++;
2311*18eb7a2dSCharles.Forsyth 			}
2312*18eb7a2dSCharles.Forsyth 
2313*18eb7a2dSCharles.Forsyth 		/* now, the default */
2314*18eb7a2dSCharles.Forsyth 		if(best == -1)
2315*18eb7a2dSCharles.Forsyth 			best = 0;
2316*18eb7a2dSCharles.Forsyth 		zzgoent++;
2317*18eb7a2dSCharles.Forsyth 		Bprint(ftemp, "%d\n", best);
2318*18eb7a2dSCharles.Forsyth 	}
2319*18eb7a2dSCharles.Forsyth }
2320*18eb7a2dSCharles.Forsyth 
2321*18eb7a2dSCharles.Forsyth /*
2322*18eb7a2dSCharles.Forsyth  * output the gotos for nonterminal c
2323*18eb7a2dSCharles.Forsyth  */
2324*18eb7a2dSCharles.Forsyth void
go2gen(int c)2325*18eb7a2dSCharles.Forsyth go2gen(int c)
2326*18eb7a2dSCharles.Forsyth {
2327*18eb7a2dSCharles.Forsyth 	int i, work, cc;
2328*18eb7a2dSCharles.Forsyth 	Item *p, *q;
2329*18eb7a2dSCharles.Forsyth 
2330*18eb7a2dSCharles.Forsyth 
2331*18eb7a2dSCharles.Forsyth 	/* first, find nonterminals with gotos on c */
2332*18eb7a2dSCharles.Forsyth 	aryfil(temp1, nnonter+1, 0);
2333*18eb7a2dSCharles.Forsyth 	temp1[c] = 1;
2334*18eb7a2dSCharles.Forsyth 	work = 1;
2335*18eb7a2dSCharles.Forsyth 	while(work) {
2336*18eb7a2dSCharles.Forsyth 		work = 0;
2337*18eb7a2dSCharles.Forsyth 		PLOOP(0, i)
2338*18eb7a2dSCharles.Forsyth 
2339*18eb7a2dSCharles.Forsyth 			/* cc is a nonterminal */
2340*18eb7a2dSCharles.Forsyth 			if((cc=prdptr[i][1]-NTBASE) >= 0)
2341*18eb7a2dSCharles.Forsyth 				/* cc has a goto on c */
2342*18eb7a2dSCharles.Forsyth 				if(temp1[cc] != 0) {
2343*18eb7a2dSCharles.Forsyth 
2344*18eb7a2dSCharles.Forsyth 					/* thus, the left side of production i does too */
2345*18eb7a2dSCharles.Forsyth 					cc = *prdptr[i]-NTBASE;
2346*18eb7a2dSCharles.Forsyth 					if(temp1[cc] == 0) {
2347*18eb7a2dSCharles.Forsyth 						  work = 1;
2348*18eb7a2dSCharles.Forsyth 						  temp1[cc] = 1;
2349*18eb7a2dSCharles.Forsyth 					}
2350*18eb7a2dSCharles.Forsyth 				}
2351*18eb7a2dSCharles.Forsyth 	}
2352*18eb7a2dSCharles.Forsyth 
2353*18eb7a2dSCharles.Forsyth 	/* now, we have temp1[c] = 1 if a goto on c in closure of cc */
2354*18eb7a2dSCharles.Forsyth 	if(g2debug && foutput != 0) {
2355*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "%s: gotos on ", nontrst[c].name);
2356*18eb7a2dSCharles.Forsyth 		NTLOOP(i)
2357*18eb7a2dSCharles.Forsyth 			if(temp1[i])
2358*18eb7a2dSCharles.Forsyth 				Bprint(foutput, "%s ", nontrst[i].name);
2359*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "\n");
2360*18eb7a2dSCharles.Forsyth 	}
2361*18eb7a2dSCharles.Forsyth 
2362*18eb7a2dSCharles.Forsyth 	/* now, go through and put gotos into tystate */
2363*18eb7a2dSCharles.Forsyth 	aryfil(tystate, nstate, 0);
2364*18eb7a2dSCharles.Forsyth 	SLOOP(i)
2365*18eb7a2dSCharles.Forsyth 		ITMLOOP(i, p, q)
2366*18eb7a2dSCharles.Forsyth 			if((cc = *p->pitem) >= NTBASE)
2367*18eb7a2dSCharles.Forsyth 				/* goto on c is possible */
2368*18eb7a2dSCharles.Forsyth 				if(temp1[cc-NTBASE]) {
2369*18eb7a2dSCharles.Forsyth 					tystate[i] = amem[indgo[i]+c];
2370*18eb7a2dSCharles.Forsyth 					break;
2371*18eb7a2dSCharles.Forsyth 				}
2372*18eb7a2dSCharles.Forsyth }
2373*18eb7a2dSCharles.Forsyth 
2374*18eb7a2dSCharles.Forsyth /*
2375*18eb7a2dSCharles.Forsyth  * decide a shift/reduce conflict by precedence.
2376*18eb7a2dSCharles.Forsyth  * r is a rule number, t a token number
2377*18eb7a2dSCharles.Forsyth  * the conflict is in state s
2378*18eb7a2dSCharles.Forsyth  * temp1[t] is changed to reflect the action
2379*18eb7a2dSCharles.Forsyth  */
2380*18eb7a2dSCharles.Forsyth void
precftn(int r,int t,int s)2381*18eb7a2dSCharles.Forsyth precftn(int r, int t, int s)
2382*18eb7a2dSCharles.Forsyth {
2383*18eb7a2dSCharles.Forsyth 	int lp, lt, action;
2384*18eb7a2dSCharles.Forsyth 
2385*18eb7a2dSCharles.Forsyth 	lp = levprd[r];
2386*18eb7a2dSCharles.Forsyth 	lt = toklev[t];
2387*18eb7a2dSCharles.Forsyth 	if(PLEVEL(lt) == 0 || PLEVEL(lp) == 0) {
2388*18eb7a2dSCharles.Forsyth 
2389*18eb7a2dSCharles.Forsyth 		/* conflict */
2390*18eb7a2dSCharles.Forsyth 		if(foutput != 0)
2391*18eb7a2dSCharles.Forsyth 			Bprint(foutput,
2392*18eb7a2dSCharles.Forsyth 				"\n%d: shift/reduce conflict (shift %d(%d), red'n %d(%d)) on %s",
2393*18eb7a2dSCharles.Forsyth 				s, temp1[t], PLEVEL(lt), r, PLEVEL(lp), symnam(t));
2394*18eb7a2dSCharles.Forsyth 		zzsrconf++;
2395*18eb7a2dSCharles.Forsyth 		return;
2396*18eb7a2dSCharles.Forsyth 	}
2397*18eb7a2dSCharles.Forsyth 	if(PLEVEL(lt) == PLEVEL(lp))
2398*18eb7a2dSCharles.Forsyth 		action = ASSOC(lt);
2399*18eb7a2dSCharles.Forsyth 	else
2400*18eb7a2dSCharles.Forsyth 		if(PLEVEL(lt) > PLEVEL(lp))
2401*18eb7a2dSCharles.Forsyth 			action = RASC;  /* shift */
2402*18eb7a2dSCharles.Forsyth 		else
2403*18eb7a2dSCharles.Forsyth 			action = LASC;  /* reduce */
2404*18eb7a2dSCharles.Forsyth 	switch(action) {
2405*18eb7a2dSCharles.Forsyth 	case BASC:  /* error action */
2406*18eb7a2dSCharles.Forsyth 		temp1[t] = ERRCODE;
2407*18eb7a2dSCharles.Forsyth 		break;
2408*18eb7a2dSCharles.Forsyth 	case LASC:  /* reduce */
2409*18eb7a2dSCharles.Forsyth 		temp1[t] = -r;
2410*18eb7a2dSCharles.Forsyth 		break;
2411*18eb7a2dSCharles.Forsyth 	}
2412*18eb7a2dSCharles.Forsyth }
2413*18eb7a2dSCharles.Forsyth 
2414*18eb7a2dSCharles.Forsyth /*
2415*18eb7a2dSCharles.Forsyth  * output state i
2416*18eb7a2dSCharles.Forsyth  * temp1 has the actions, lastred the default
2417*18eb7a2dSCharles.Forsyth  */
2418*18eb7a2dSCharles.Forsyth void
wract(int i)2419*18eb7a2dSCharles.Forsyth wract(int i)
2420*18eb7a2dSCharles.Forsyth {
2421*18eb7a2dSCharles.Forsyth 	int p, p0, p1, ntimes, tred, count, j, flag;
2422*18eb7a2dSCharles.Forsyth 
2423*18eb7a2dSCharles.Forsyth 	/* find the best choice for lastred */
2424*18eb7a2dSCharles.Forsyth 	lastred = 0;
2425*18eb7a2dSCharles.Forsyth 	ntimes = 0;
2426*18eb7a2dSCharles.Forsyth 	TLOOP(j) {
2427*18eb7a2dSCharles.Forsyth 		if(temp1[j] >= 0)
2428*18eb7a2dSCharles.Forsyth 			continue;
2429*18eb7a2dSCharles.Forsyth 		if(temp1[j]+lastred == 0)
2430*18eb7a2dSCharles.Forsyth 			continue;
2431*18eb7a2dSCharles.Forsyth 		/* count the number of appearances of temp1[j] */
2432*18eb7a2dSCharles.Forsyth 		count = 0;
2433*18eb7a2dSCharles.Forsyth 		tred = -temp1[j];
2434*18eb7a2dSCharles.Forsyth 		levprd[tred] |= REDFLAG;
2435*18eb7a2dSCharles.Forsyth 		TLOOP(p)
2436*18eb7a2dSCharles.Forsyth 			if(temp1[p]+tred == 0)
2437*18eb7a2dSCharles.Forsyth 				count++;
2438*18eb7a2dSCharles.Forsyth 		if(count > ntimes) {
2439*18eb7a2dSCharles.Forsyth 			lastred = tred;
2440*18eb7a2dSCharles.Forsyth 			ntimes = count;
2441*18eb7a2dSCharles.Forsyth 		}
2442*18eb7a2dSCharles.Forsyth 	}
2443*18eb7a2dSCharles.Forsyth 
2444*18eb7a2dSCharles.Forsyth 	/*
2445*18eb7a2dSCharles.Forsyth 	 * for error recovery, arrange that, if there is a shift on the
2446*18eb7a2dSCharles.Forsyth 	 * error recovery token, `error', that the default be the error action
2447*18eb7a2dSCharles.Forsyth 	 */
2448*18eb7a2dSCharles.Forsyth 	if(temp1[2] > 0)
2449*18eb7a2dSCharles.Forsyth 		lastred = 0;
2450*18eb7a2dSCharles.Forsyth 
2451*18eb7a2dSCharles.Forsyth 	/* clear out entries in temp1 which equal lastred */
2452*18eb7a2dSCharles.Forsyth 	TLOOP(p)
2453*18eb7a2dSCharles.Forsyth 		if(temp1[p]+lastred == 0)
2454*18eb7a2dSCharles.Forsyth 			temp1[p] = 0;
2455*18eb7a2dSCharles.Forsyth 
2456*18eb7a2dSCharles.Forsyth 	wrstate(i);
2457*18eb7a2dSCharles.Forsyth 	defact[i] = lastred;
2458*18eb7a2dSCharles.Forsyth 	flag = 0;
2459*18eb7a2dSCharles.Forsyth 	TLOOP(p0)
2460*18eb7a2dSCharles.Forsyth 		if((p1=temp1[p0]) != 0) {
2461*18eb7a2dSCharles.Forsyth 			if(p1 < 0) {
2462*18eb7a2dSCharles.Forsyth 				p1 = -p1;
2463*18eb7a2dSCharles.Forsyth 				goto exc;
2464*18eb7a2dSCharles.Forsyth 			}
2465*18eb7a2dSCharles.Forsyth 			if(p1 == ACCEPTCODE) {
2466*18eb7a2dSCharles.Forsyth 				p1 = -1;
2467*18eb7a2dSCharles.Forsyth 				goto exc;
2468*18eb7a2dSCharles.Forsyth 			}
2469*18eb7a2dSCharles.Forsyth 			if(p1 == ERRCODE) {
2470*18eb7a2dSCharles.Forsyth 				p1 = 0;
2471*18eb7a2dSCharles.Forsyth 			exc:
2472*18eb7a2dSCharles.Forsyth 				if(flag++ == 0)
2473*18eb7a2dSCharles.Forsyth 					Bprint(ftable, "-1, %d,\n", i);
2474*18eb7a2dSCharles.Forsyth 				Bprint(ftable, "\t%d, %d,\n", p0, p1);
2475*18eb7a2dSCharles.Forsyth 				zzexcp++;
2476*18eb7a2dSCharles.Forsyth 				continue;
2477*18eb7a2dSCharles.Forsyth 			}
2478*18eb7a2dSCharles.Forsyth 			Bprint(ftemp, "%d,%d,", p0, p1);
2479*18eb7a2dSCharles.Forsyth 			zzacent++;
2480*18eb7a2dSCharles.Forsyth 		}
2481*18eb7a2dSCharles.Forsyth 	if(flag) {
2482*18eb7a2dSCharles.Forsyth 		defact[i] = -2;
2483*18eb7a2dSCharles.Forsyth 		Bprint(ftable, "\t-2, %d,\n", lastred);
2484*18eb7a2dSCharles.Forsyth 	}
2485*18eb7a2dSCharles.Forsyth 	Bprint(ftemp, "\n");
2486*18eb7a2dSCharles.Forsyth }
2487*18eb7a2dSCharles.Forsyth 
2488*18eb7a2dSCharles.Forsyth /*
2489*18eb7a2dSCharles.Forsyth  * writes state i
2490*18eb7a2dSCharles.Forsyth  */
2491*18eb7a2dSCharles.Forsyth void
wrstate(int i)2492*18eb7a2dSCharles.Forsyth wrstate(int i)
2493*18eb7a2dSCharles.Forsyth {
2494*18eb7a2dSCharles.Forsyth 	int j0, j1;
2495*18eb7a2dSCharles.Forsyth 	Item *pp, *qq;
2496*18eb7a2dSCharles.Forsyth 	Wset *u;
2497*18eb7a2dSCharles.Forsyth 
2498*18eb7a2dSCharles.Forsyth 	if(fdebug) {
2499*18eb7a2dSCharles.Forsyth 		if(lastred) {
2500*18eb7a2dSCharles.Forsyth 			Bprint(fdebug, "	0, /*%d*/\n", i);
2501*18eb7a2dSCharles.Forsyth 		} else {
2502*18eb7a2dSCharles.Forsyth 			Bprint(fdebug, "	\"");
2503*18eb7a2dSCharles.Forsyth 			ITMLOOP(i, pp, qq)
2504*18eb7a2dSCharles.Forsyth 				Bprint(fdebug, "%s\\n", writem(pp->pitem));
2505*18eb7a2dSCharles.Forsyth 			if(tystate[i] == MUSTLOOKAHEAD)
2506*18eb7a2dSCharles.Forsyth 				WSLOOP(wsets + (pstate[i+1] - pstate[i]), u)
2507*18eb7a2dSCharles.Forsyth 					if(*u->pitem < 0)
2508*18eb7a2dSCharles.Forsyth 						Bprint(fdebug, "%s\\n", writem(u->pitem));
2509*18eb7a2dSCharles.Forsyth 			Bprint(fdebug, "\", /*%d*/\n", i);
2510*18eb7a2dSCharles.Forsyth 		}
2511*18eb7a2dSCharles.Forsyth 	}
2512*18eb7a2dSCharles.Forsyth 	if(foutput == 0)
2513*18eb7a2dSCharles.Forsyth 		return;
2514*18eb7a2dSCharles.Forsyth 	Bprint(foutput, "\nstate %d\n", i);
2515*18eb7a2dSCharles.Forsyth 	ITMLOOP(i, pp, qq)
2516*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "\t%s\n", writem(pp->pitem));
2517*18eb7a2dSCharles.Forsyth 	if(tystate[i] == MUSTLOOKAHEAD)
2518*18eb7a2dSCharles.Forsyth 		/* print out empty productions in closure */
2519*18eb7a2dSCharles.Forsyth 		WSLOOP(wsets+(pstate[i+1]-pstate[i]), u)
2520*18eb7a2dSCharles.Forsyth 			if(*u->pitem < 0)
2521*18eb7a2dSCharles.Forsyth 				Bprint(foutput, "\t%s\n", writem(u->pitem));
2522*18eb7a2dSCharles.Forsyth 
2523*18eb7a2dSCharles.Forsyth 	/* check for state equal to another */
2524*18eb7a2dSCharles.Forsyth 	TLOOP(j0)
2525*18eb7a2dSCharles.Forsyth 		if((j1=temp1[j0]) != 0) {
2526*18eb7a2dSCharles.Forsyth 			Bprint(foutput, "\n\t%s  ", symnam(j0));
2527*18eb7a2dSCharles.Forsyth 			/* shift, error, or accept */
2528*18eb7a2dSCharles.Forsyth 			if(j1 > 0) {
2529*18eb7a2dSCharles.Forsyth 				if(j1 == ACCEPTCODE)
2530*18eb7a2dSCharles.Forsyth 					Bprint(foutput,  "accept");
2531*18eb7a2dSCharles.Forsyth 				else
2532*18eb7a2dSCharles.Forsyth 					if(j1 == ERRCODE)
2533*18eb7a2dSCharles.Forsyth 						Bprint(foutput, "error");
2534*18eb7a2dSCharles.Forsyth 					else
2535*18eb7a2dSCharles.Forsyth 						Bprint(foutput, "shift %d", j1);
2536*18eb7a2dSCharles.Forsyth 			} else
2537*18eb7a2dSCharles.Forsyth 				Bprint(foutput, "reduce %d (src line %d)", -j1, rlines[-j1]);
2538*18eb7a2dSCharles.Forsyth 		}
2539*18eb7a2dSCharles.Forsyth 
2540*18eb7a2dSCharles.Forsyth 	/* output the final production */
2541*18eb7a2dSCharles.Forsyth 	if(lastred)
2542*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "\n\t.  reduce %d (src line %d)\n\n",
2543*18eb7a2dSCharles.Forsyth 			lastred, rlines[lastred]);
2544*18eb7a2dSCharles.Forsyth 	else
2545*18eb7a2dSCharles.Forsyth 		Bprint(foutput, "\n\t.  error\n\n");
2546*18eb7a2dSCharles.Forsyth 
2547*18eb7a2dSCharles.Forsyth 	/* now, output nonterminal actions */
2548*18eb7a2dSCharles.Forsyth 	j1 = ntokens;
2549*18eb7a2dSCharles.Forsyth 	for(j0 = 1; j0 <= nnonter; j0++) {
2550*18eb7a2dSCharles.Forsyth 		j1++;
2551*18eb7a2dSCharles.Forsyth 		if(temp1[j1])
2552*18eb7a2dSCharles.Forsyth 			Bprint(foutput, "\t%s  goto %d\n", symnam(j0+NTBASE), temp1[j1]);
2553*18eb7a2dSCharles.Forsyth 	}
2554*18eb7a2dSCharles.Forsyth }
2555*18eb7a2dSCharles.Forsyth 
2556*18eb7a2dSCharles.Forsyth void
warray(char * s,int * v,int n)2557*18eb7a2dSCharles.Forsyth warray(char *s, int *v, int n)
2558*18eb7a2dSCharles.Forsyth {
2559*18eb7a2dSCharles.Forsyth 	int i;
2560*18eb7a2dSCharles.Forsyth 
2561*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "short	%s[] =\n{", s);
2562*18eb7a2dSCharles.Forsyth 	for(i=0;;) {
2563*18eb7a2dSCharles.Forsyth 		if(i%10 == 0)
2564*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "\n");
2565*18eb7a2dSCharles.Forsyth 		Bprint(ftable, "%4d", v[i]);
2566*18eb7a2dSCharles.Forsyth 		i++;
2567*18eb7a2dSCharles.Forsyth 		if(i >= n) {
2568*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "\n};\n");
2569*18eb7a2dSCharles.Forsyth 			break;
2570*18eb7a2dSCharles.Forsyth 		}
2571*18eb7a2dSCharles.Forsyth 		Bprint(ftable, ",");
2572*18eb7a2dSCharles.Forsyth 	}
2573*18eb7a2dSCharles.Forsyth }
2574*18eb7a2dSCharles.Forsyth 
2575*18eb7a2dSCharles.Forsyth /*
2576*18eb7a2dSCharles.Forsyth  * in order to free up the mem and amem arrays for the optimizer,
2577*18eb7a2dSCharles.Forsyth  * and still be able to output yyr1, etc., after the sizes of
2578*18eb7a2dSCharles.Forsyth  * the action array is known, we hide the nonterminals
2579*18eb7a2dSCharles.Forsyth  * derived by productions in levprd.
2580*18eb7a2dSCharles.Forsyth  */
2581*18eb7a2dSCharles.Forsyth 
2582*18eb7a2dSCharles.Forsyth void
hideprod(void)2583*18eb7a2dSCharles.Forsyth hideprod(void)
2584*18eb7a2dSCharles.Forsyth {
2585*18eb7a2dSCharles.Forsyth 	int i, j;
2586*18eb7a2dSCharles.Forsyth 
2587*18eb7a2dSCharles.Forsyth 	j = 0;
2588*18eb7a2dSCharles.Forsyth 	levprd[0] = 0;
2589*18eb7a2dSCharles.Forsyth 	PLOOP(1, i) {
2590*18eb7a2dSCharles.Forsyth 		if(!(levprd[i] & REDFLAG)) {
2591*18eb7a2dSCharles.Forsyth 			j++;
2592*18eb7a2dSCharles.Forsyth 			if(foutput != 0)
2593*18eb7a2dSCharles.Forsyth 				Bprint(foutput, "Rule not reduced:   %s\n", writem(prdptr[i]));
2594*18eb7a2dSCharles.Forsyth 		}
2595*18eb7a2dSCharles.Forsyth 		levprd[i] = *prdptr[i] - NTBASE;
2596*18eb7a2dSCharles.Forsyth 	}
2597*18eb7a2dSCharles.Forsyth 	if(j)
2598*18eb7a2dSCharles.Forsyth 		print("%d rules never reduced\n", j);
2599*18eb7a2dSCharles.Forsyth }
2600*18eb7a2dSCharles.Forsyth 
2601*18eb7a2dSCharles.Forsyth void
callopt(void)2602*18eb7a2dSCharles.Forsyth callopt(void)
2603*18eb7a2dSCharles.Forsyth {
2604*18eb7a2dSCharles.Forsyth 	int i, *p, j, k, *q;
2605*18eb7a2dSCharles.Forsyth 
2606*18eb7a2dSCharles.Forsyth 	/* read the arrays from tempfile and set parameters */
2607*18eb7a2dSCharles.Forsyth 	finput = Bopen(tempname, OREAD);
2608*18eb7a2dSCharles.Forsyth 	if(finput == 0)
2609*18eb7a2dSCharles.Forsyth 		error("optimizer cannot open tempfile");
2610*18eb7a2dSCharles.Forsyth 	pgo[0] = 0;
2611*18eb7a2dSCharles.Forsyth 	temp1[0] = 0;
2612*18eb7a2dSCharles.Forsyth 	nstate = 0;
2613*18eb7a2dSCharles.Forsyth 	nnonter = 0;
2614*18eb7a2dSCharles.Forsyth 	for(;;) {
2615*18eb7a2dSCharles.Forsyth 		switch(gtnm()) {
2616*18eb7a2dSCharles.Forsyth 		case '\n':
2617*18eb7a2dSCharles.Forsyth 			nstate++;
2618*18eb7a2dSCharles.Forsyth 			pmem--;
2619*18eb7a2dSCharles.Forsyth 			temp1[nstate] = pmem - mem0;
2620*18eb7a2dSCharles.Forsyth 		case ',':
2621*18eb7a2dSCharles.Forsyth 			continue;
2622*18eb7a2dSCharles.Forsyth 		case '$':
2623*18eb7a2dSCharles.Forsyth 			break;
2624*18eb7a2dSCharles.Forsyth 		default:
2625*18eb7a2dSCharles.Forsyth 			error("bad tempfile");
2626*18eb7a2dSCharles.Forsyth 		}
2627*18eb7a2dSCharles.Forsyth 		break;
2628*18eb7a2dSCharles.Forsyth 	}
2629*18eb7a2dSCharles.Forsyth 
2630*18eb7a2dSCharles.Forsyth 	pmem--;
2631*18eb7a2dSCharles.Forsyth 	temp1[nstate] = yypgo[0] = pmem - mem0;
2632*18eb7a2dSCharles.Forsyth 	for(;;) {
2633*18eb7a2dSCharles.Forsyth 		switch(gtnm()) {
2634*18eb7a2dSCharles.Forsyth 		case '\n':
2635*18eb7a2dSCharles.Forsyth 			nnonter++;
2636*18eb7a2dSCharles.Forsyth 			yypgo[nnonter] = pmem-mem0;
2637*18eb7a2dSCharles.Forsyth 		case ',':
2638*18eb7a2dSCharles.Forsyth 			continue;
2639*18eb7a2dSCharles.Forsyth 		case -1:
2640*18eb7a2dSCharles.Forsyth 			break;
2641*18eb7a2dSCharles.Forsyth 		default:
2642*18eb7a2dSCharles.Forsyth 			error("bad tempfile");
2643*18eb7a2dSCharles.Forsyth 		}
2644*18eb7a2dSCharles.Forsyth 		break;
2645*18eb7a2dSCharles.Forsyth 	}
2646*18eb7a2dSCharles.Forsyth 	pmem--;
2647*18eb7a2dSCharles.Forsyth 	yypgo[nnonter--] = pmem - mem0;
2648*18eb7a2dSCharles.Forsyth 	for(i = 0; i < nstate; i++) {
2649*18eb7a2dSCharles.Forsyth 		k = 32000;
2650*18eb7a2dSCharles.Forsyth 		j = 0;
2651*18eb7a2dSCharles.Forsyth 		q = mem0 + temp1[i+1];
2652*18eb7a2dSCharles.Forsyth 		for(p = mem0 + temp1[i]; p < q ; p += 2) {
2653*18eb7a2dSCharles.Forsyth 			if(*p > j)
2654*18eb7a2dSCharles.Forsyth 				j = *p;
2655*18eb7a2dSCharles.Forsyth 			if(*p < k)
2656*18eb7a2dSCharles.Forsyth 				k = *p;
2657*18eb7a2dSCharles.Forsyth 		}
2658*18eb7a2dSCharles.Forsyth 		/* nontrivial situation */
2659*18eb7a2dSCharles.Forsyth 		if(k <= j) {
2660*18eb7a2dSCharles.Forsyth 			/* j is now the range */
2661*18eb7a2dSCharles.Forsyth /*			j -= k;			/* call scj */
2662*18eb7a2dSCharles.Forsyth 			if(k > maxoff)
2663*18eb7a2dSCharles.Forsyth 				maxoff = k;
2664*18eb7a2dSCharles.Forsyth 		}
2665*18eb7a2dSCharles.Forsyth 		tystate[i] = (temp1[i+1]-temp1[i]) + 2*j;
2666*18eb7a2dSCharles.Forsyth 		if(j > maxspr)
2667*18eb7a2dSCharles.Forsyth 			maxspr = j;
2668*18eb7a2dSCharles.Forsyth 	}
2669*18eb7a2dSCharles.Forsyth 
2670*18eb7a2dSCharles.Forsyth 	/* initialize ggreed table */
2671*18eb7a2dSCharles.Forsyth 	for(i = 1; i <= nnonter; i++) {
2672*18eb7a2dSCharles.Forsyth 		ggreed[i] = 1;
2673*18eb7a2dSCharles.Forsyth 		j = 0;
2674*18eb7a2dSCharles.Forsyth 
2675*18eb7a2dSCharles.Forsyth 		/* minimum entry index is always 0 */
2676*18eb7a2dSCharles.Forsyth 		q = mem0 + yypgo[i+1] - 1;
2677*18eb7a2dSCharles.Forsyth 		for(p = mem0+yypgo[i]; p < q ; p += 2) {
2678*18eb7a2dSCharles.Forsyth 			ggreed[i] += 2;
2679*18eb7a2dSCharles.Forsyth 			if(*p > j)
2680*18eb7a2dSCharles.Forsyth 				j = *p;
2681*18eb7a2dSCharles.Forsyth 		}
2682*18eb7a2dSCharles.Forsyth 		ggreed[i] = ggreed[i] + 2*j;
2683*18eb7a2dSCharles.Forsyth 		if(j > maxoff)
2684*18eb7a2dSCharles.Forsyth 			maxoff = j;
2685*18eb7a2dSCharles.Forsyth 	}
2686*18eb7a2dSCharles.Forsyth 
2687*18eb7a2dSCharles.Forsyth 	/* now, prepare to put the shift actions into the amem array */
2688*18eb7a2dSCharles.Forsyth 	for(i = 0; i < ACTSIZE; i++)
2689*18eb7a2dSCharles.Forsyth 		amem[i] = 0;
2690*18eb7a2dSCharles.Forsyth 	maxa = amem;
2691*18eb7a2dSCharles.Forsyth 	for(i = 0; i < nstate; i++) {
2692*18eb7a2dSCharles.Forsyth 		if(tystate[i] == 0 && adb > 1)
2693*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "State %d: null\n", i);
2694*18eb7a2dSCharles.Forsyth 		indgo[i] = YYFLAG1;
2695*18eb7a2dSCharles.Forsyth 	}
2696*18eb7a2dSCharles.Forsyth 	while((i = nxti()) != NOMORE)
2697*18eb7a2dSCharles.Forsyth 		if(i >= 0)
2698*18eb7a2dSCharles.Forsyth 			stin(i);
2699*18eb7a2dSCharles.Forsyth 		else
2700*18eb7a2dSCharles.Forsyth 			gin(-i);
2701*18eb7a2dSCharles.Forsyth 
2702*18eb7a2dSCharles.Forsyth 	/* print amem array */
2703*18eb7a2dSCharles.Forsyth 	if(adb > 2 )
2704*18eb7a2dSCharles.Forsyth 		for(p = amem; p <= maxa; p += 10) {
2705*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "%4d  ", (int)(p-amem));
2706*18eb7a2dSCharles.Forsyth 			for(i = 0; i < 10; ++i)
2707*18eb7a2dSCharles.Forsyth 				Bprint(ftable, "%4d  ", p[i]);
2708*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "\n");
2709*18eb7a2dSCharles.Forsyth 		}
2710*18eb7a2dSCharles.Forsyth 
2711*18eb7a2dSCharles.Forsyth 	/* write out the output appropriate to the language */
2712*18eb7a2dSCharles.Forsyth 	aoutput();
2713*18eb7a2dSCharles.Forsyth 	osummary();
2714*18eb7a2dSCharles.Forsyth 	Bterm(finput);
2715*18eb7a2dSCharles.Forsyth 	ZAPFILE(tempname);
2716*18eb7a2dSCharles.Forsyth }
2717*18eb7a2dSCharles.Forsyth 
2718*18eb7a2dSCharles.Forsyth void
gin(int i)2719*18eb7a2dSCharles.Forsyth gin(int i)
2720*18eb7a2dSCharles.Forsyth {
2721*18eb7a2dSCharles.Forsyth 	int *p, *r, *s, *q1, *q2;
2722*18eb7a2dSCharles.Forsyth 
2723*18eb7a2dSCharles.Forsyth 	/* enter gotos on nonterminal i into array amem */
2724*18eb7a2dSCharles.Forsyth 	ggreed[i] = 0;
2725*18eb7a2dSCharles.Forsyth 
2726*18eb7a2dSCharles.Forsyth 	q2 = mem0+ yypgo[i+1] - 1;
2727*18eb7a2dSCharles.Forsyth 	q1 = mem0 + yypgo[i];
2728*18eb7a2dSCharles.Forsyth 
2729*18eb7a2dSCharles.Forsyth 	/* now, find amem place for it */
2730*18eb7a2dSCharles.Forsyth 	for(p = amem; p < &amem[ACTSIZE]; p++) {
2731*18eb7a2dSCharles.Forsyth 		if(*p)
2732*18eb7a2dSCharles.Forsyth 			continue;
2733*18eb7a2dSCharles.Forsyth 		for(r = q1; r < q2; r += 2) {
2734*18eb7a2dSCharles.Forsyth 			s = p + *r + 1;
2735*18eb7a2dSCharles.Forsyth 			if(*s)
2736*18eb7a2dSCharles.Forsyth 				goto nextgp;
2737*18eb7a2dSCharles.Forsyth 			if(s > maxa)
2738*18eb7a2dSCharles.Forsyth 				if((maxa = s) > &amem[ACTSIZE])
2739*18eb7a2dSCharles.Forsyth 					error("a array overflow");
2740*18eb7a2dSCharles.Forsyth 		}
2741*18eb7a2dSCharles.Forsyth 		/* we have found amem spot */
2742*18eb7a2dSCharles.Forsyth 		*p = *q2;
2743*18eb7a2dSCharles.Forsyth 		if(p > maxa)
2744*18eb7a2dSCharles.Forsyth 			if((maxa = p) > &amem[ACTSIZE])
2745*18eb7a2dSCharles.Forsyth 				error("a array overflow");
2746*18eb7a2dSCharles.Forsyth 		for(r = q1; r < q2; r += 2) {
2747*18eb7a2dSCharles.Forsyth 			s = p + *r + 1;
2748*18eb7a2dSCharles.Forsyth 			*s = r[1];
2749*18eb7a2dSCharles.Forsyth 		}
2750*18eb7a2dSCharles.Forsyth 		pgo[i] = p-amem;
2751*18eb7a2dSCharles.Forsyth 		if(adb > 1)
2752*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "Nonterminal %d, entry at %d\n", i, pgo[i]);
2753*18eb7a2dSCharles.Forsyth 		return;
2754*18eb7a2dSCharles.Forsyth 
2755*18eb7a2dSCharles.Forsyth 	nextgp:;
2756*18eb7a2dSCharles.Forsyth 	}
2757*18eb7a2dSCharles.Forsyth 	error("cannot place goto %d\n", i);
2758*18eb7a2dSCharles.Forsyth }
2759*18eb7a2dSCharles.Forsyth 
2760*18eb7a2dSCharles.Forsyth void
stin(int i)2761*18eb7a2dSCharles.Forsyth stin(int i)
2762*18eb7a2dSCharles.Forsyth {
2763*18eb7a2dSCharles.Forsyth 	int *r, *s, n, flag, j, *q1, *q2;
2764*18eb7a2dSCharles.Forsyth 
2765*18eb7a2dSCharles.Forsyth 	tystate[i] = 0;
2766*18eb7a2dSCharles.Forsyth 
2767*18eb7a2dSCharles.Forsyth 	/* enter state i into the amem array */
2768*18eb7a2dSCharles.Forsyth 	q2 = mem0+temp1[i+1];
2769*18eb7a2dSCharles.Forsyth 	q1 = mem0+temp1[i];
2770*18eb7a2dSCharles.Forsyth 	/* find an acceptable place */
2771*18eb7a2dSCharles.Forsyth 	for(n = -maxoff; n < ACTSIZE; n++) {
2772*18eb7a2dSCharles.Forsyth 		flag = 0;
2773*18eb7a2dSCharles.Forsyth 		for(r = q1; r < q2; r += 2) {
2774*18eb7a2dSCharles.Forsyth 			if((s = *r + n + amem) < amem)
2775*18eb7a2dSCharles.Forsyth 				goto nextn;
2776*18eb7a2dSCharles.Forsyth 			if(*s == 0)
2777*18eb7a2dSCharles.Forsyth 				flag++;
2778*18eb7a2dSCharles.Forsyth 			else
2779*18eb7a2dSCharles.Forsyth 				if(*s != r[1])
2780*18eb7a2dSCharles.Forsyth 					goto nextn;
2781*18eb7a2dSCharles.Forsyth 		}
2782*18eb7a2dSCharles.Forsyth 
2783*18eb7a2dSCharles.Forsyth 		/* check that the position equals another only if the states are identical */
2784*18eb7a2dSCharles.Forsyth 		for(j=0; j<nstate; j++) {
2785*18eb7a2dSCharles.Forsyth 			if(indgo[j] == n) {
2786*18eb7a2dSCharles.Forsyth 
2787*18eb7a2dSCharles.Forsyth 				/* we have some disagreement */
2788*18eb7a2dSCharles.Forsyth 				if(flag)
2789*18eb7a2dSCharles.Forsyth 					goto nextn;
2790*18eb7a2dSCharles.Forsyth 				if(temp1[j+1]+temp1[i] == temp1[j]+temp1[i+1]) {
2791*18eb7a2dSCharles.Forsyth 
2792*18eb7a2dSCharles.Forsyth 					/* states are equal */
2793*18eb7a2dSCharles.Forsyth 					indgo[i] = n;
2794*18eb7a2dSCharles.Forsyth 					if(adb > 1)
2795*18eb7a2dSCharles.Forsyth 						Bprint(ftable,
2796*18eb7a2dSCharles.Forsyth 						"State %d: entry at %d equals state %d\n",
2797*18eb7a2dSCharles.Forsyth 						i, n, j);
2798*18eb7a2dSCharles.Forsyth 					return;
2799*18eb7a2dSCharles.Forsyth 				}
2800*18eb7a2dSCharles.Forsyth 
2801*18eb7a2dSCharles.Forsyth 				/* we have some disagreement */
2802*18eb7a2dSCharles.Forsyth 				goto nextn;
2803*18eb7a2dSCharles.Forsyth 			}
2804*18eb7a2dSCharles.Forsyth 		}
2805*18eb7a2dSCharles.Forsyth 
2806*18eb7a2dSCharles.Forsyth 		for(r = q1; r < q2; r += 2) {
2807*18eb7a2dSCharles.Forsyth 			if((s = *r+n+amem) >= &amem[ACTSIZE])
2808*18eb7a2dSCharles.Forsyth 				error("out of space in optimizer a array");
2809*18eb7a2dSCharles.Forsyth 			if(s > maxa)
2810*18eb7a2dSCharles.Forsyth 				maxa = s;
2811*18eb7a2dSCharles.Forsyth 			if(*s != 0 && *s != r[1])
2812*18eb7a2dSCharles.Forsyth 				error("clobber of a array, pos'n %d, by %d", s-amem, r[1]);
2813*18eb7a2dSCharles.Forsyth 			*s = r[1];
2814*18eb7a2dSCharles.Forsyth 		}
2815*18eb7a2dSCharles.Forsyth 		indgo[i] = n;
2816*18eb7a2dSCharles.Forsyth 		if(adb > 1)
2817*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "State %d: entry at %d\n", i, indgo[i]);
2818*18eb7a2dSCharles.Forsyth 		return;
2819*18eb7a2dSCharles.Forsyth 	nextn:;
2820*18eb7a2dSCharles.Forsyth 	}
2821*18eb7a2dSCharles.Forsyth 	error("Error; failure to place state %d\n", i);
2822*18eb7a2dSCharles.Forsyth }
2823*18eb7a2dSCharles.Forsyth 
2824*18eb7a2dSCharles.Forsyth /*
2825*18eb7a2dSCharles.Forsyth  * finds the next i
2826*18eb7a2dSCharles.Forsyth  */
2827*18eb7a2dSCharles.Forsyth int
nxti(void)2828*18eb7a2dSCharles.Forsyth nxti(void)
2829*18eb7a2dSCharles.Forsyth {
2830*18eb7a2dSCharles.Forsyth 	int i, max, maxi;
2831*18eb7a2dSCharles.Forsyth 
2832*18eb7a2dSCharles.Forsyth 	max = 0;
2833*18eb7a2dSCharles.Forsyth 	maxi = 0;
2834*18eb7a2dSCharles.Forsyth 	for(i = 1; i <= nnonter; i++)
2835*18eb7a2dSCharles.Forsyth 		if(ggreed[i] >= max) {
2836*18eb7a2dSCharles.Forsyth 			max = ggreed[i];
2837*18eb7a2dSCharles.Forsyth 			maxi = -i;
2838*18eb7a2dSCharles.Forsyth 		}
2839*18eb7a2dSCharles.Forsyth 	for(i = 0; i < nstate; ++i)
2840*18eb7a2dSCharles.Forsyth 		if(tystate[i] >= max) {
2841*18eb7a2dSCharles.Forsyth 			max = tystate[i];
2842*18eb7a2dSCharles.Forsyth 			maxi = i;
2843*18eb7a2dSCharles.Forsyth 		}
2844*18eb7a2dSCharles.Forsyth 	if(nxdb)
2845*18eb7a2dSCharles.Forsyth 		Bprint(ftable, "nxti = %d, max = %d\n", maxi, max);
2846*18eb7a2dSCharles.Forsyth 	if(max == 0)
2847*18eb7a2dSCharles.Forsyth 		return NOMORE;
2848*18eb7a2dSCharles.Forsyth 	return maxi;
2849*18eb7a2dSCharles.Forsyth }
2850*18eb7a2dSCharles.Forsyth 
2851*18eb7a2dSCharles.Forsyth /*
2852*18eb7a2dSCharles.Forsyth  * write summary
2853*18eb7a2dSCharles.Forsyth  */
2854*18eb7a2dSCharles.Forsyth void
osummary(void)2855*18eb7a2dSCharles.Forsyth osummary(void)
2856*18eb7a2dSCharles.Forsyth {
2857*18eb7a2dSCharles.Forsyth 
2858*18eb7a2dSCharles.Forsyth 	int i, *p;
2859*18eb7a2dSCharles.Forsyth 
2860*18eb7a2dSCharles.Forsyth 	if(foutput == 0)
2861*18eb7a2dSCharles.Forsyth 		return;
2862*18eb7a2dSCharles.Forsyth 	i = 0;
2863*18eb7a2dSCharles.Forsyth 	for(p = maxa; p >= amem; p--)
2864*18eb7a2dSCharles.Forsyth 		if(*p == 0)
2865*18eb7a2dSCharles.Forsyth 			i++;
2866*18eb7a2dSCharles.Forsyth 
2867*18eb7a2dSCharles.Forsyth 	Bprint(foutput, "Optimizer space used: input %d/%d, output %d/%d\n",
2868*18eb7a2dSCharles.Forsyth 		(int)(pmem-mem0+1), MEMSIZE, (int)(maxa-amem+1), ACTSIZE);
2869*18eb7a2dSCharles.Forsyth 	Bprint(foutput, "%d table entries, %d zero\n", (int)(maxa-amem+1), i);
2870*18eb7a2dSCharles.Forsyth 	Bprint(foutput, "maximum spread: %d, maximum offset: %d\n", maxspr, maxoff);
2871*18eb7a2dSCharles.Forsyth }
2872*18eb7a2dSCharles.Forsyth 
2873*18eb7a2dSCharles.Forsyth /*
2874*18eb7a2dSCharles.Forsyth  * this version is for C
2875*18eb7a2dSCharles.Forsyth  * write out the optimized parser
2876*18eb7a2dSCharles.Forsyth  */
2877*18eb7a2dSCharles.Forsyth void
aoutput(void)2878*18eb7a2dSCharles.Forsyth aoutput(void)
2879*18eb7a2dSCharles.Forsyth {
2880*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "#define\tYYLAST\t%d\n", (int)(maxa-amem+1));
2881*18eb7a2dSCharles.Forsyth 	arout("yyact", amem, (maxa-amem)+1);
2882*18eb7a2dSCharles.Forsyth 	arout("yypact", indgo, nstate);
2883*18eb7a2dSCharles.Forsyth 	arout("yypgo", pgo, nnonter+1);
2884*18eb7a2dSCharles.Forsyth }
2885*18eb7a2dSCharles.Forsyth 
2886*18eb7a2dSCharles.Forsyth void
arout(char * s,int * v,int n)2887*18eb7a2dSCharles.Forsyth arout(char *s, int *v, int n)
2888*18eb7a2dSCharles.Forsyth {
2889*18eb7a2dSCharles.Forsyth 	int i;
2890*18eb7a2dSCharles.Forsyth 
2891*18eb7a2dSCharles.Forsyth 	Bprint(ftable, "short	%s[] =\n{", s);
2892*18eb7a2dSCharles.Forsyth 	for(i = 0; i < n;) {
2893*18eb7a2dSCharles.Forsyth 		if(i%10 == 0)
2894*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "\n");
2895*18eb7a2dSCharles.Forsyth 		Bprint(ftable, "%4d", v[i]);
2896*18eb7a2dSCharles.Forsyth 		i++;
2897*18eb7a2dSCharles.Forsyth 		if(i == n)
2898*18eb7a2dSCharles.Forsyth 			Bprint(ftable, "\n};\n");
2899*18eb7a2dSCharles.Forsyth 		else
2900*18eb7a2dSCharles.Forsyth 			Bprint(ftable, ",");
2901*18eb7a2dSCharles.Forsyth 	}
2902*18eb7a2dSCharles.Forsyth }
2903*18eb7a2dSCharles.Forsyth 
2904*18eb7a2dSCharles.Forsyth /*
2905*18eb7a2dSCharles.Forsyth  * read and convert an integer from the standard input
2906*18eb7a2dSCharles.Forsyth  * return the terminating character
2907*18eb7a2dSCharles.Forsyth  * blanks, tabs, and newlines are ignored
2908*18eb7a2dSCharles.Forsyth  */
2909*18eb7a2dSCharles.Forsyth int
gtnm(void)2910*18eb7a2dSCharles.Forsyth gtnm(void)
2911*18eb7a2dSCharles.Forsyth {
2912*18eb7a2dSCharles.Forsyth 	int sign, val, c;
2913*18eb7a2dSCharles.Forsyth 
2914*18eb7a2dSCharles.Forsyth 	sign = 0;
2915*18eb7a2dSCharles.Forsyth 	val = 0;
2916*18eb7a2dSCharles.Forsyth 	while((c=Bgetrune(finput)) != Beof) {
2917*18eb7a2dSCharles.Forsyth 		if(isdigit(c)) {
2918*18eb7a2dSCharles.Forsyth 			val = val*10 + c-'0';
2919*18eb7a2dSCharles.Forsyth 			continue;
2920*18eb7a2dSCharles.Forsyth 		}
2921*18eb7a2dSCharles.Forsyth 		if(c == '-') {
2922*18eb7a2dSCharles.Forsyth 			sign = 1;
2923*18eb7a2dSCharles.Forsyth 			continue;
2924*18eb7a2dSCharles.Forsyth 		}
2925*18eb7a2dSCharles.Forsyth 		break;
2926*18eb7a2dSCharles.Forsyth 	}
2927*18eb7a2dSCharles.Forsyth 	if(sign)
2928*18eb7a2dSCharles.Forsyth 		val = -val;
2929*18eb7a2dSCharles.Forsyth 	*pmem++ = val;
2930*18eb7a2dSCharles.Forsyth 	if(pmem >= &mem0[MEMSIZE])
2931*18eb7a2dSCharles.Forsyth 		error("out of space");
2932*18eb7a2dSCharles.Forsyth 	return c;
2933*18eb7a2dSCharles.Forsyth }
2934