xref: /plan9/sys/src/cmd/yacc.c (revision f8f814447ad79df616c586571506a210f98c48bc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier #include <ctype.h>
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier #define	Bungetrune	Bungetc		/* ok for now. */
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier /*
93e12c5d1SDavid du Colombier  * all these are 32 bit
103e12c5d1SDavid du Colombier  */
113e12c5d1SDavid du Colombier #define TBITSET		((32+NTERMS)/32)	/* BOTCH?? +31 */
123e12c5d1SDavid du Colombier #define BIT(a,i)	((a)[(i)>>5] & (1<<((i)&037)))
133e12c5d1SDavid du Colombier #define SETBIT(a,i)	((a)[(i)>>5] |= (1<<((i)&037)))
143e12c5d1SDavid du Colombier #define NWORDS(n)	(((n)+32)/32)
153e12c5d1SDavid du Colombier 
163e12c5d1SDavid du Colombier #define PARSER		"/sys/lib/yaccpar"
173e12c5d1SDavid du Colombier #define PARSERS		"/sys/lib/yaccpars"
183e12c5d1SDavid du Colombier #define TEMPNAME	"y.tmp.XXXXXX"
193e12c5d1SDavid du Colombier #define ACTNAME		"y.acts.XXXXXX"
203e12c5d1SDavid du Colombier #define OFILE		"tab.c"
213e12c5d1SDavid du Colombier #define FILEU		"output"
223e12c5d1SDavid du Colombier #define FILED		"tab.h"
233e12c5d1SDavid du Colombier #define FILEDEBUG	"debug"
243e12c5d1SDavid du Colombier 
253e12c5d1SDavid du Colombier enum
263e12c5d1SDavid du Colombier {
273e12c5d1SDavid du Colombier /*
283e12c5d1SDavid du Colombier  * the following are adjustable
293e12c5d1SDavid du Colombier  * according to memory size
303e12c5d1SDavid du Colombier  */
3180ee5cbfSDavid du Colombier 	ACTSIZE		= 40000,
3280ee5cbfSDavid du Colombier 	MEMSIZE		= 40000,
33bd389b36SDavid du Colombier 	NSTATES		= 2000,
3480ee5cbfSDavid du Colombier 	NTERMS		= 511,
3559cc4ca5SDavid du Colombier 	NPROD		= 1600,
3680ee5cbfSDavid du Colombier 	NNONTERM	= 600,
37bd389b36SDavid du Colombier 	TEMPSIZE	= 2000,
3880ee5cbfSDavid du Colombier 	CNAMSZ		= 10000,
397dd7cddfSDavid du Colombier 	LSETSIZE	= 2400,
403e12c5d1SDavid du Colombier 	WSETSIZE	= 350,
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	NAMESIZE	= 50,
433e12c5d1SDavid du Colombier 	NTYPES		= 63,
443e12c5d1SDavid du Colombier 	ISIZE		= 400,
453e12c5d1SDavid du Colombier 
463e12c5d1SDavid du Colombier 	PRIVATE		= 0xE000,	/* unicode private use */
473e12c5d1SDavid du Colombier 
483e12c5d1SDavid du Colombier 	/* relationships which must hold:
493e12c5d1SDavid du Colombier 		TBITSET ints must hold NTERMS+1 bits...
503e12c5d1SDavid du Colombier 		WSETSIZE >= NNONTERM
513e12c5d1SDavid du Colombier 		LSETSIZE >= NNONTERM
523e12c5d1SDavid du Colombier 		TEMPSIZE >= NTERMS + NNONTERM + 1
533e12c5d1SDavid du Colombier 		TEMPSIZE >= NSTATES
543e12c5d1SDavid du Colombier 	*/
553e12c5d1SDavid du Colombier 
563e12c5d1SDavid du Colombier 	NTBASE		= 010000,
573e12c5d1SDavid du Colombier 	ERRCODE		= 8190,
583e12c5d1SDavid du Colombier 	ACCEPTCODE	= 8191,
593e12c5d1SDavid du Colombier 
603e12c5d1SDavid du Colombier 	NOASC		= 0,	/* no assoc. */
613e12c5d1SDavid du Colombier 	LASC		= 1,	/* left assoc. */
623e12c5d1SDavid du Colombier 	RASC		= 2,	/* right assoc. */
633e12c5d1SDavid du Colombier 	BASC		= 3,	/* binary assoc. */
643e12c5d1SDavid du Colombier 
653e12c5d1SDavid du Colombier 	/* flags for state generation */
663e12c5d1SDavid du Colombier 
673e12c5d1SDavid du Colombier 	DONE		= 0,
683e12c5d1SDavid du Colombier 	MUSTDO		= 1,
693e12c5d1SDavid du Colombier 	MUSTLOOKAHEAD	= 2,
703e12c5d1SDavid du Colombier 
713e12c5d1SDavid du Colombier 	/* flags for a rule having an action, and being reduced */
723e12c5d1SDavid du Colombier 
733e12c5d1SDavid du Colombier 	ACTFLAG		= 04,
743e12c5d1SDavid du Colombier 	REDFLAG		= 010,
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier 	/* output parser flags */
773e12c5d1SDavid du Colombier 	YYFLAG1		= -1000,
783e12c5d1SDavid du Colombier 
793e12c5d1SDavid du Colombier 	/* parse tokens */
803e12c5d1SDavid du Colombier 	IDENTIFIER	= PRIVATE,
813e12c5d1SDavid du Colombier 	MARK,
823e12c5d1SDavid du Colombier 	TERM,
833e12c5d1SDavid du Colombier 	LEFT,
843e12c5d1SDavid du Colombier 	RIGHT,
853e12c5d1SDavid du Colombier 	BINARY,
863e12c5d1SDavid du Colombier 	PREC,
873e12c5d1SDavid du Colombier 	LCURLY,
883e12c5d1SDavid du Colombier 	IDENTCOLON,
893e12c5d1SDavid du Colombier 	NUMBER,
903e12c5d1SDavid du Colombier 	START,
913e12c5d1SDavid du Colombier 	TYPEDEF,
923e12c5d1SDavid du Colombier 	TYPENAME,
933e12c5d1SDavid du Colombier 	UNION,
943e12c5d1SDavid du Colombier 
953e12c5d1SDavid du Colombier 	ENDFILE		= 0,
963e12c5d1SDavid du Colombier 
973e12c5d1SDavid du Colombier 	EMPTY		= 1,
983e12c5d1SDavid du Colombier 	WHOKNOWS	= 0,
993e12c5d1SDavid du Colombier 	OK		= 1,
1003e12c5d1SDavid du Colombier 	NOMORE		= -1000,
1013e12c5d1SDavid du Colombier };
1023e12c5d1SDavid du Colombier 
1033e12c5d1SDavid du Colombier 	/* macros for getting associativity and precedence levels */
1043e12c5d1SDavid du Colombier 
1053e12c5d1SDavid du Colombier #define ASSOC(i)	((i)&03)
1063e12c5d1SDavid du Colombier #define PLEVEL(i)	(((i)>>4)&077)
1073e12c5d1SDavid du Colombier #define TYPE(i)		(((i)>>10)&077)
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier 	/* macros for setting associativity and precedence levels */
1103e12c5d1SDavid du Colombier 
1113e12c5d1SDavid du Colombier #define SETASC(i,j)	i |= j
1123e12c5d1SDavid du Colombier #define SETPLEV(i,j)	i |= (j<<4)
1133e12c5d1SDavid du Colombier #define SETTYPE(i,j)	i |= (j<<10)
1143e12c5d1SDavid du Colombier 
1153e12c5d1SDavid du Colombier 	/* looping macros */
1163e12c5d1SDavid du Colombier 
1173e12c5d1SDavid du Colombier #define TLOOP(i)	for(i=1; i<=ntokens; i++)
1183e12c5d1SDavid du Colombier #define NTLOOP(i)	for(i=0; i<=nnonter; i++)
1193e12c5d1SDavid du Colombier #define PLOOP(s,i)	for(i=s; i<nprod; i++)
1203e12c5d1SDavid du Colombier #define SLOOP(i)	for(i=0; i<nstate; i++)
1213e12c5d1SDavid du Colombier #define WSBUMP(x)	x++
1223e12c5d1SDavid du Colombier #define WSLOOP(s,j)	for(j=s; j<cwp; j++)
1233e12c5d1SDavid du Colombier #define ITMLOOP(i,p,q)	for(q=pstate[i+1], p=pstate[i]; p<q; p++)
1243e12c5d1SDavid du Colombier #define SETLOOP(i)	for(i=0; i<tbitset; i++)
1253e12c5d1SDavid du Colombier 
1263e12c5d1SDavid du Colombier 	/* command to clobber tempfiles after use */
1273e12c5d1SDavid du Colombier 
1283e12c5d1SDavid du Colombier #define	ZAPFILE(x)	if(x) remove(x)
1293e12c5d1SDavid du Colombier 
1303e12c5d1SDavid du Colombier 	/* I/O descriptors */
1313e12c5d1SDavid du Colombier 
1323e12c5d1SDavid du Colombier Biobuf*	faction;	/* file for saving actions */
1333e12c5d1SDavid du Colombier Biobuf*	fdefine;	/* file for #defines */
1343e12c5d1SDavid du Colombier Biobuf*	fdebug;		/* y.debug for strings for debugging */
1353e12c5d1SDavid du Colombier Biobuf*	ftable;		/* y.tab.c file */
1363e12c5d1SDavid du Colombier Biobuf*	ftemp;		/* tempfile to pass 2 */
1373e12c5d1SDavid du Colombier Biobuf*	finput;		/* input file */
1383e12c5d1SDavid du Colombier Biobuf*	foutput;	/* y.output file */
1393e12c5d1SDavid du Colombier 
1403e12c5d1SDavid du Colombier 	/* communication variables between various I/O routines */
1413e12c5d1SDavid du Colombier 
1423e12c5d1SDavid du Colombier char*	infile;			/* input file name */
1433e12c5d1SDavid du Colombier int	numbval;		/* value of an input number */
144*f8f81444SDavid du Colombier char	tokname[NAMESIZE+UTFmax+1]; /* input token name, slop for runes and 0 */
1453e12c5d1SDavid du Colombier 
1463e12c5d1SDavid du Colombier 	/* structure declarations */
1473e12c5d1SDavid du Colombier 
1483e12c5d1SDavid du Colombier typedef
1493e12c5d1SDavid du Colombier struct
1503e12c5d1SDavid du Colombier {
151219b2ee8SDavid du Colombier 	int	lset[TBITSET];
1523e12c5d1SDavid du Colombier } Lkset;
1533e12c5d1SDavid du Colombier 
1543e12c5d1SDavid du Colombier typedef
1553e12c5d1SDavid du Colombier struct
1563e12c5d1SDavid du Colombier {
1573e12c5d1SDavid du Colombier 	int*	pitem;
1583e12c5d1SDavid du Colombier 	Lkset*	look;
1593e12c5d1SDavid du Colombier } Item;
1603e12c5d1SDavid du Colombier 
1613e12c5d1SDavid du Colombier typedef
1623e12c5d1SDavid du Colombier struct
1633e12c5d1SDavid du Colombier {
1643e12c5d1SDavid du Colombier 	char*	name;
165219b2ee8SDavid du Colombier 	int	value;
1663e12c5d1SDavid du Colombier } Symb;
1673e12c5d1SDavid du Colombier 
1683e12c5d1SDavid du Colombier typedef
1693e12c5d1SDavid du Colombier struct
1703e12c5d1SDavid du Colombier {
1713e12c5d1SDavid du Colombier 	int*	pitem;
1723e12c5d1SDavid du Colombier 	int	flag;
1733e12c5d1SDavid du Colombier 	Lkset	ws;
1743e12c5d1SDavid du Colombier } Wset;
1753e12c5d1SDavid du Colombier 
1763e12c5d1SDavid du Colombier 	/* storage of names */
1773e12c5d1SDavid du Colombier 
1783e12c5d1SDavid du Colombier char	cnames[CNAMSZ];		/* place where token and nonterminal names are stored */
1793e12c5d1SDavid du Colombier int	cnamsz = CNAMSZ;	/* size of cnames */
1803e12c5d1SDavid du Colombier char*	cnamp = cnames;		/* place where next name is to be put in */
1813e12c5d1SDavid du Colombier int	ndefout = 4;		/* number of defined symbols output */
1823e12c5d1SDavid du Colombier char*	tempname;
1833e12c5d1SDavid du Colombier char*	actname;
1843e12c5d1SDavid du Colombier char	ttempname[] = TEMPNAME;
1853e12c5d1SDavid du Colombier char	tactname[] = ACTNAME;
1863e12c5d1SDavid du Colombier char*	parser = PARSER;
1873e12c5d1SDavid du Colombier char*	yydebug;
1883e12c5d1SDavid du Colombier 
1893e12c5d1SDavid du Colombier 	/* storage of types */
1903e12c5d1SDavid du Colombier int	ntypes;			/* number of types defined */
1913e12c5d1SDavid du Colombier char*	typeset[NTYPES];	/* pointers to type tags */
1923e12c5d1SDavid du Colombier 
1933e12c5d1SDavid du Colombier 	/* token information */
1943e12c5d1SDavid du Colombier 
1953e12c5d1SDavid du Colombier int	ntokens = 0 ;		/* number of tokens */
1963e12c5d1SDavid du Colombier Symb	tokset[NTERMS];
1973e12c5d1SDavid du Colombier int	toklev[NTERMS];		/* vector with the precedence of the terminals */
1983e12c5d1SDavid du Colombier 
1993e12c5d1SDavid du Colombier 	/* nonterminal information */
2003e12c5d1SDavid du Colombier 
2013e12c5d1SDavid du Colombier int	nnonter = -1;		/* the number of nonterminals */
2023e12c5d1SDavid du Colombier Symb	nontrst[NNONTERM];
2033e12c5d1SDavid du Colombier int	start;			/* start symbol */
2043e12c5d1SDavid du Colombier 
2053e12c5d1SDavid du Colombier 	/* assigned token type values */
2063e12c5d1SDavid du Colombier int	extval = 0;
2073e12c5d1SDavid du Colombier 
2083e12c5d1SDavid du Colombier char*	ytabc = OFILE;	/* name of y.tab.c */
2093e12c5d1SDavid du Colombier 
2103e12c5d1SDavid du Colombier 	/* grammar rule information */
2113e12c5d1SDavid du Colombier 
2123e12c5d1SDavid du Colombier int	mem0[MEMSIZE] ;		/* production storage */
2133e12c5d1SDavid du Colombier int*	mem = mem0;
2143e12c5d1SDavid du Colombier int	nprod = 1;		/* number of productions */
2153e12c5d1SDavid du Colombier int*	prdptr[NPROD];		/* pointers to descriptions of productions */
2163e12c5d1SDavid du Colombier int	levprd[NPROD];		/* precedence levels for the productions */
2173e12c5d1SDavid du Colombier int	rlines[NPROD];		/* line number for this rule */
2183e12c5d1SDavid du Colombier 
2193e12c5d1SDavid du Colombier 	/* state information */
2203e12c5d1SDavid du Colombier 
2213e12c5d1SDavid du Colombier int	nstate = 0;		/* number of states */
2223e12c5d1SDavid du Colombier Item*	pstate[NSTATES+2];	/* pointers to the descriptions of the states */
2233e12c5d1SDavid du Colombier int	tystate[NSTATES];	/* contains type information about the states */
2243e12c5d1SDavid du Colombier int	defact[NSTATES];	/* the default actions of states */
2253e12c5d1SDavid du Colombier int	tstates[NTERMS];	/* states generated by terminal gotos */
2263e12c5d1SDavid du Colombier int	ntstates[NNONTERM]; 	/* states generated by nonterminal gotos */
2273e12c5d1SDavid du Colombier int	mstates[NSTATES];	/* chain of overflows of term/nonterm generation lists  */
2283e12c5d1SDavid du Colombier int	lastred; 		/* the number of the last reduction of a state */
2293e12c5d1SDavid du Colombier 
2303e12c5d1SDavid du Colombier 	/* lookahead set information */
2313e12c5d1SDavid du Colombier 
2323e12c5d1SDavid du Colombier Lkset	lkst[LSETSIZE];
2333e12c5d1SDavid du Colombier int	nolook;			/* flag to turn off lookahead computations */
2343e12c5d1SDavid du Colombier int	tbitset;		/* size of lookahead sets */
2353e12c5d1SDavid du Colombier int	nlset = 0;		/* next lookahead set index */
2363e12c5d1SDavid du Colombier int	nolook = 0;		/* flag to suppress lookahead computations */
2373e12c5d1SDavid du Colombier Lkset	clset;  		/* temporary storage for lookahead computations */
2383e12c5d1SDavid du Colombier 
2393e12c5d1SDavid du Colombier 	/* working set information */
2403e12c5d1SDavid du Colombier 
2413e12c5d1SDavid du Colombier Wset	wsets[WSETSIZE];
2423e12c5d1SDavid du Colombier Wset*	cwp;
2433e12c5d1SDavid du Colombier 
2443e12c5d1SDavid du Colombier 	/* storage for action table */
2453e12c5d1SDavid du Colombier 
2463e12c5d1SDavid du Colombier int	amem[ACTSIZE];		/* action table storage */
2473e12c5d1SDavid du Colombier int*	memp = amem;		/* next free action table position */
2483e12c5d1SDavid du Colombier int	indgo[NSTATES];		/* index to the stored goto table */
2493e12c5d1SDavid du Colombier 
2503e12c5d1SDavid du Colombier 	/* temporary vector, indexable by states, terms, or ntokens */
2513e12c5d1SDavid du Colombier 
2523e12c5d1SDavid du Colombier int	temp1[TEMPSIZE];	/* temporary storage, indexed by terms + ntokens or states */
2533e12c5d1SDavid du Colombier int	lineno = 1;		/* current input line number */
2543e12c5d1SDavid du Colombier int	fatfl = 1;  		/* if on, error is fatal */
2553e12c5d1SDavid du Colombier int	nerrors = 0;		/* number of errors */
2563e12c5d1SDavid du Colombier 
2573e12c5d1SDavid du Colombier 	/* statistics collection variables */
2583e12c5d1SDavid du Colombier 
2593e12c5d1SDavid du Colombier int	zzgoent;
2603e12c5d1SDavid du Colombier int	zzgobest;
2613e12c5d1SDavid du Colombier int	zzacent;
2623e12c5d1SDavid du Colombier int	zzexcp;
2633e12c5d1SDavid du Colombier int	zzclose;
2643e12c5d1SDavid du Colombier int	zzrrconf;
2653e12c5d1SDavid du Colombier int	zzsrconf;
2663e12c5d1SDavid du Colombier 
2673e12c5d1SDavid du Colombier int*	ggreed = lkst[0].lset;
2683e12c5d1SDavid du Colombier int*	pgo = wsets[0].ws.lset;
2693e12c5d1SDavid du Colombier int*	yypgo = &nontrst[0].value;
2703e12c5d1SDavid du Colombier 
2713e12c5d1SDavid du Colombier int	maxspr = 0;  		/* maximum spread of any entry */
2723e12c5d1SDavid du Colombier int	maxoff = 0;  		/* maximum offset into a array */
2733e12c5d1SDavid du Colombier int*	pmem = mem0;
2743e12c5d1SDavid du Colombier int*	maxa;
2753e12c5d1SDavid du Colombier int	nxdb = 0;
2763e12c5d1SDavid du Colombier int	adb = 0;
2773e12c5d1SDavid du Colombier 
2783e12c5d1SDavid du Colombier 
2793e12c5d1SDavid du Colombier 	/* storage for information about the nonterminals */
2803e12c5d1SDavid du Colombier 
2813e12c5d1SDavid du Colombier int**	pres[NNONTERM+2];  	/* vector of pointers to productions yielding each nonterminal */
2823e12c5d1SDavid du Colombier Lkset*	pfirst[NNONTERM+2];	/* vector of pointers to first sets for each nonterminal */
2833e12c5d1SDavid du Colombier int	pempty[NNONTERM+1];	/* vector of nonterminals nontrivially deriving e */
2843e12c5d1SDavid du Colombier 
2853e12c5d1SDavid du Colombier 	/* random stuff picked out from between functions */
2863e12c5d1SDavid du Colombier 
2873e12c5d1SDavid du Colombier int	indebug = 0;
2883e12c5d1SDavid du Colombier Wset*	zzcwp = wsets;
2893e12c5d1SDavid du Colombier int	zzgoent = 0;
2903e12c5d1SDavid du Colombier int	zzgobest = 0;
2913e12c5d1SDavid du Colombier int	zzacent = 0;
2923e12c5d1SDavid du Colombier int	zzexcp = 0;
2933e12c5d1SDavid du Colombier int	zzclose = 0;
2943e12c5d1SDavid du Colombier int	zzsrconf = 0;
2953e12c5d1SDavid du Colombier int*	zzmemsz = mem0;
2963e12c5d1SDavid du Colombier int	zzrrconf = 0;
2973e12c5d1SDavid du Colombier int	pidebug = 0;		/* debugging flag for putitem */
2983e12c5d1SDavid du Colombier int	gsdebug = 0;
2993e12c5d1SDavid du Colombier int	cldebug = 0;		/* debugging flag for closure */
3003e12c5d1SDavid du Colombier int	pkdebug = 0;
3013e12c5d1SDavid du Colombier int	g2debug = 0;
3023e12c5d1SDavid du Colombier 
3033e12c5d1SDavid du Colombier struct
3043e12c5d1SDavid du Colombier {
3053e12c5d1SDavid du Colombier 	char*	name;
3063e12c5d1SDavid du Colombier 	long	value;
3073e12c5d1SDavid du Colombier } resrv[] =
3083e12c5d1SDavid du Colombier {
3093e12c5d1SDavid du Colombier 	"binary",	BINARY,
3103e12c5d1SDavid du Colombier 	"left",		LEFT,
3113e12c5d1SDavid du Colombier 	"nonassoc",	BINARY,
3123e12c5d1SDavid du Colombier 	"prec",		PREC,
3133e12c5d1SDavid du Colombier 	"right",	RIGHT,
3143e12c5d1SDavid du Colombier 	"start",	START,
3153e12c5d1SDavid du Colombier 	"term",		TERM,
3163e12c5d1SDavid du Colombier 	"token",	TERM,
3173e12c5d1SDavid du Colombier 	"type",		TYPEDEF,
3183e12c5d1SDavid du Colombier 	"union",	UNION,
3193e12c5d1SDavid du Colombier 	0,
3203e12c5d1SDavid du Colombier };
3213e12c5d1SDavid du Colombier 
3223e12c5d1SDavid du Colombier 	/* define functions */
3233e12c5d1SDavid du Colombier 
3243e12c5d1SDavid du Colombier void	main(int, char**);
3253e12c5d1SDavid du Colombier void	others(void);
3263e12c5d1SDavid du Colombier char*	chcopy(char*, char*);
3273e12c5d1SDavid du Colombier char*	writem(int*);
3283e12c5d1SDavid du Colombier char*	symnam(int);
3293e12c5d1SDavid du Colombier void	summary(void);
3303e12c5d1SDavid du Colombier void	error(char*, ...);
3313e12c5d1SDavid du Colombier void	aryfil(int*, int, int);
3323e12c5d1SDavid du Colombier int	setunion(int*, int*);
3333e12c5d1SDavid du Colombier void	prlook(Lkset*);
3343e12c5d1SDavid du Colombier void	cpres(void);
3353e12c5d1SDavid du Colombier void	cpfir(void);
3363e12c5d1SDavid du Colombier int	state(int);
3373e12c5d1SDavid du Colombier void	putitem(int*, Lkset*);
3383e12c5d1SDavid du Colombier void	cempty(void);
3393e12c5d1SDavid du Colombier void	stagen(void);
3403e12c5d1SDavid du Colombier void	closure(int);
3413e12c5d1SDavid du Colombier Lkset*	flset(Lkset*);
3423e12c5d1SDavid du Colombier void	cleantmp(void);
3433e12c5d1SDavid du Colombier void	intr(void);
3443e12c5d1SDavid du Colombier void	setup(int, char**);
3453e12c5d1SDavid du Colombier void	finact(void);
3463e12c5d1SDavid du Colombier int	defin(int, char*);
3473e12c5d1SDavid du Colombier void	defout(int);
3483e12c5d1SDavid du Colombier char*	cstash(char*);
3493e12c5d1SDavid du Colombier long	gettok(void);
3503e12c5d1SDavid du Colombier int	fdtype(int);
3513e12c5d1SDavid du Colombier int	chfind(int, char*);
3523e12c5d1SDavid du Colombier void	cpyunion(void);
3533e12c5d1SDavid du Colombier void	cpycode(void);
3543e12c5d1SDavid du Colombier int	skipcom(void);
3553e12c5d1SDavid du Colombier void	cpyact(int);
3563e12c5d1SDavid du Colombier void	openup(char*, int, int, int, char*);
3573e12c5d1SDavid du Colombier void	output(void);
3583e12c5d1SDavid du Colombier int	apack(int*, int);
3593e12c5d1SDavid du Colombier void	go2out(void);
3603e12c5d1SDavid du Colombier void	go2gen(int);
3613e12c5d1SDavid du Colombier void	precftn(int, int, int);
3623e12c5d1SDavid du Colombier void	wract(int);
3633e12c5d1SDavid du Colombier void	wrstate(int);
3643e12c5d1SDavid du Colombier void	warray(char*, int*, int);
3653e12c5d1SDavid du Colombier void	hideprod(void);
3663e12c5d1SDavid du Colombier void	callopt(void);
3673e12c5d1SDavid du Colombier void	gin(int);
3683e12c5d1SDavid du Colombier void	stin(int);
3693e12c5d1SDavid du Colombier int	nxti(void);
3703e12c5d1SDavid du Colombier void	osummary(void);
3713e12c5d1SDavid du Colombier void	aoutput(void);
3723e12c5d1SDavid du Colombier void	arout(char*, int*, int);
3733e12c5d1SDavid du Colombier int	gtnm(void);
3743e12c5d1SDavid du Colombier 
3753e12c5d1SDavid du Colombier void
main(int argc,char * argv[])3763e12c5d1SDavid du Colombier main(int argc, char *argv[])
3773e12c5d1SDavid du Colombier {
3783e12c5d1SDavid du Colombier 
3793e12c5d1SDavid du Colombier 	setup(argc, argv);	/* initialize and read productions */
3803e12c5d1SDavid du Colombier 	tbitset = NWORDS(ntokens);
3813e12c5d1SDavid du Colombier 	cpres();		/* make table of which productions yield a given nonterminal */
3823e12c5d1SDavid du Colombier 	cempty();		/* make a table of which nonterminals can match the empty string */
3833e12c5d1SDavid du Colombier 	cpfir();		/* make a table of firsts of nonterminals */
3843e12c5d1SDavid du Colombier 	stagen();		/* generate the states */
3853e12c5d1SDavid du Colombier 	output();		/* write the states and the tables */
3863e12c5d1SDavid du Colombier 	go2out();
3873e12c5d1SDavid du Colombier 	hideprod();
3883e12c5d1SDavid du Colombier 	summary();
3893e12c5d1SDavid du Colombier 	callopt();
3903e12c5d1SDavid du Colombier 	others();
3913e12c5d1SDavid du Colombier 	exits(0);
3923e12c5d1SDavid du Colombier }
3933e12c5d1SDavid du Colombier 
3943e12c5d1SDavid du Colombier /*
3953e12c5d1SDavid du Colombier  * put out other arrays, copy the parsers
3963e12c5d1SDavid du Colombier  */
3973e12c5d1SDavid du Colombier void
others(void)3983e12c5d1SDavid du Colombier others(void)
3993e12c5d1SDavid du Colombier {
4003e12c5d1SDavid du Colombier 	int c, i, j;
4013e12c5d1SDavid du Colombier 
4023e12c5d1SDavid du Colombier 	finput = Bopen(parser, OREAD);
4033e12c5d1SDavid du Colombier 	if(finput == 0)
4043e12c5d1SDavid du Colombier 		error("cannot find parser %s", parser);
4053e12c5d1SDavid du Colombier 	warray("yyr1", levprd, nprod);
4063e12c5d1SDavid du Colombier 	aryfil(temp1, nprod, 0);
4073e12c5d1SDavid du Colombier 	PLOOP(1, i)
4083e12c5d1SDavid du Colombier 		temp1[i] = prdptr[i+1]-prdptr[i]-2;
4093e12c5d1SDavid du Colombier 	warray("yyr2", temp1, nprod);
4103e12c5d1SDavid du Colombier 
4113e12c5d1SDavid du Colombier 	aryfil(temp1, nstate, -1000);
4123e12c5d1SDavid du Colombier 	TLOOP(i)
4133e12c5d1SDavid du Colombier 		for(j=tstates[i]; j!=0; j=mstates[j])
4143e12c5d1SDavid du Colombier 			temp1[j] = i;
4153e12c5d1SDavid du Colombier 	NTLOOP(i)
4163e12c5d1SDavid du Colombier 		for(j=ntstates[i]; j!=0; j=mstates[j])
4173e12c5d1SDavid du Colombier 			temp1[j] = -i;
4183e12c5d1SDavid du Colombier 	warray("yychk", temp1, nstate);
4193e12c5d1SDavid du Colombier 	warray("yydef", defact, nstate);
4203e12c5d1SDavid du Colombier 
4213e12c5d1SDavid du Colombier 	/* put out token translation tables */
4223e12c5d1SDavid du Colombier 	/* table 1 has 0-256 */
4233e12c5d1SDavid du Colombier 	aryfil(temp1, 256, 0);
4243e12c5d1SDavid du Colombier 	c = 0;
4253e12c5d1SDavid du Colombier 	TLOOP(i) {
4263e12c5d1SDavid du Colombier 		j = tokset[i].value;
4273e12c5d1SDavid du Colombier 		if(j >= 0 && j < 256) {
428219b2ee8SDavid du Colombier 			if(temp1[j]) {
429219b2ee8SDavid du Colombier 				print("yacc bug -- cant have 2 different Ts with same value\n");
430219b2ee8SDavid du Colombier 				print("	%s and %s\n", tokset[i].name, tokset[temp1[j]].name);
431219b2ee8SDavid du Colombier 				nerrors++;
432219b2ee8SDavid du Colombier 			}
4333e12c5d1SDavid du Colombier 			temp1[j] = i;
4343e12c5d1SDavid du Colombier 			if(j > c)
4353e12c5d1SDavid du Colombier 				c = j;
4363e12c5d1SDavid du Colombier 		}
4373e12c5d1SDavid du Colombier 	}
4383e12c5d1SDavid du Colombier 	warray("yytok1", temp1, c+1);
4393e12c5d1SDavid du Colombier 
4403e12c5d1SDavid du Colombier 	/* table 2 has PRIVATE-PRIVATE+256 */
4413e12c5d1SDavid du Colombier 	aryfil(temp1, 256, 0);
4423e12c5d1SDavid du Colombier 	c = 0;
4433e12c5d1SDavid du Colombier 	TLOOP(i) {
4443e12c5d1SDavid du Colombier 		j = tokset[i].value - PRIVATE;
4453e12c5d1SDavid du Colombier 		if(j >= 0 && j < 256) {
446219b2ee8SDavid du Colombier 			if(temp1[j]) {
447219b2ee8SDavid du Colombier 				print("yacc bug -- cant have 2 different Ts with same value\n");
448219b2ee8SDavid du Colombier 				print("	%s and %s\n", tokset[i].name, tokset[temp1[j]].name);
449219b2ee8SDavid du Colombier 				nerrors++;
450219b2ee8SDavid du Colombier 			}
4513e12c5d1SDavid du Colombier 			temp1[j] = i;
4523e12c5d1SDavid du Colombier 			if(j > c)
4533e12c5d1SDavid du Colombier 				c = j;
4543e12c5d1SDavid du Colombier 		}
4553e12c5d1SDavid du Colombier 	}
4563e12c5d1SDavid du Colombier 	warray("yytok2", temp1, c+1);
4573e12c5d1SDavid du Colombier 
4583e12c5d1SDavid du Colombier 	/* table 3 has everything else */
4593e12c5d1SDavid du Colombier 	Bprint(ftable, "long	yytok3[] =\n{\n");
4603e12c5d1SDavid du Colombier 	c = 0;
4613e12c5d1SDavid du Colombier 	TLOOP(i) {
4623e12c5d1SDavid du Colombier 		j = tokset[i].value;
4633e12c5d1SDavid du Colombier 		if(j >= 0 && j < 256)
4643e12c5d1SDavid du Colombier 			continue;
4653e12c5d1SDavid du Colombier 		if(j >= PRIVATE && j < 256+PRIVATE)
4663e12c5d1SDavid du Colombier 			continue;
4673e12c5d1SDavid du Colombier 
4683e12c5d1SDavid du Colombier 		Bprint(ftable, "%4d,%4d,", j, i);
4693e12c5d1SDavid du Colombier 		c++;
4703e12c5d1SDavid du Colombier 		if(c%5 == 0)
4713e12c5d1SDavid du Colombier 			Bprint(ftable, "\n");
4723e12c5d1SDavid du Colombier 	}
4733e12c5d1SDavid du Colombier 	Bprint(ftable, "%4d\n};\n", 0);
4743e12c5d1SDavid du Colombier 
4753e12c5d1SDavid du Colombier 	/* copy parser text */
4763e12c5d1SDavid du Colombier 	while((c=Bgetrune(finput)) != Beof) {
4773e12c5d1SDavid du Colombier 		if(c == '$') {
4783e12c5d1SDavid du Colombier 			if((c = Bgetrune(finput)) != 'A')
4793e12c5d1SDavid du Colombier 				Bputrune(ftable, '$');
4803e12c5d1SDavid du Colombier 			else { /* copy actions */
4813e12c5d1SDavid du Colombier 				faction = Bopen(actname, OREAD);
4823e12c5d1SDavid du Colombier 				if(faction == 0)
4833e12c5d1SDavid du Colombier 					error("cannot reopen action tempfile");
4843e12c5d1SDavid du Colombier 				while((c=Bgetrune(faction)) != Beof)
4853e12c5d1SDavid du Colombier 					Bputrune(ftable, c);
486219b2ee8SDavid du Colombier 				Bterm(faction);
4873e12c5d1SDavid du Colombier 				ZAPFILE(actname);
4883e12c5d1SDavid du Colombier 				c = Bgetrune(finput);
4893e12c5d1SDavid du Colombier 			}
4903e12c5d1SDavid du Colombier 		}
4913e12c5d1SDavid du Colombier 		Bputrune(ftable, c);
4923e12c5d1SDavid du Colombier 	}
493219b2ee8SDavid du Colombier 	Bterm(ftable);
4943e12c5d1SDavid du Colombier }
4953e12c5d1SDavid du Colombier 
4963e12c5d1SDavid du Colombier /*
4973e12c5d1SDavid du Colombier  * copies string q into p, returning next free char ptr
4983e12c5d1SDavid du Colombier  */
4993e12c5d1SDavid du Colombier char*
chcopy(char * p,char * q)5003e12c5d1SDavid du Colombier chcopy(char* p, char* q)
5013e12c5d1SDavid du Colombier {
5023e12c5d1SDavid du Colombier 	int c;
5033e12c5d1SDavid du Colombier 
5043e12c5d1SDavid du Colombier 	while(c = *q) {
5053e12c5d1SDavid du Colombier 		if(c == '"')
5063e12c5d1SDavid du Colombier 			*p++ = '\\';
5073e12c5d1SDavid du Colombier 		*p++ = c;
5083e12c5d1SDavid du Colombier 		q++;
5093e12c5d1SDavid du Colombier 	}
5103e12c5d1SDavid du Colombier 	*p = 0;
5113e12c5d1SDavid du Colombier 	return p;
5123e12c5d1SDavid du Colombier }
5133e12c5d1SDavid du Colombier 
5143e12c5d1SDavid du Colombier /*
5153e12c5d1SDavid du Colombier  * creates output string for item pointed to by pp
5163e12c5d1SDavid du Colombier  */
5173e12c5d1SDavid du Colombier char*
writem(int * pp)5183e12c5d1SDavid du Colombier writem(int *pp)
5193e12c5d1SDavid du Colombier {
5203e12c5d1SDavid du Colombier 	int i,*p;
5213e12c5d1SDavid du Colombier 	static char sarr[ISIZE];
5223e12c5d1SDavid du Colombier 	char* q;
5233e12c5d1SDavid du Colombier 
5243e12c5d1SDavid du Colombier 	for(p=pp; *p>0; p++)
5253e12c5d1SDavid du Colombier 		;
5263e12c5d1SDavid du Colombier 	p = prdptr[-*p];
5273e12c5d1SDavid du Colombier 	q = chcopy(sarr, nontrst[*p-NTBASE].name);
5283e12c5d1SDavid du Colombier 	q = chcopy(q, ": ");
5293e12c5d1SDavid du Colombier 	for(;;) {
5303e12c5d1SDavid du Colombier 		*q = ' ';
5313e12c5d1SDavid du Colombier 		p++;
5323e12c5d1SDavid du Colombier 		if(p == pp)
5333e12c5d1SDavid du Colombier 			*q = '.';
5343e12c5d1SDavid du Colombier 		q++;
5353e12c5d1SDavid du Colombier 		*q = '\0';
5363e12c5d1SDavid du Colombier 		i = *p;
5373e12c5d1SDavid du Colombier 		if(i <= 0)
5383e12c5d1SDavid du Colombier 			break;
5393e12c5d1SDavid du Colombier 		q = chcopy(q, symnam(i));
5403e12c5d1SDavid du Colombier 		if(q > &sarr[ISIZE-30])
5413e12c5d1SDavid du Colombier 			error("item too big");
5423e12c5d1SDavid du Colombier 	}
5433e12c5d1SDavid du Colombier 
5443e12c5d1SDavid du Colombier 	/* an item calling for a reduction */
5453e12c5d1SDavid du Colombier 	i = *pp;
5463e12c5d1SDavid du Colombier 	if(i < 0 ) {
5473e12c5d1SDavid du Colombier 		q = chcopy(q, "    (");
5483e12c5d1SDavid du Colombier 		sprint(q, "%d)", -i);
5493e12c5d1SDavid du Colombier 	}
5503e12c5d1SDavid du Colombier 	return sarr;
5513e12c5d1SDavid du Colombier }
5523e12c5d1SDavid du Colombier 
5533e12c5d1SDavid du Colombier /*
5543e12c5d1SDavid du Colombier  * return a pointer to the name of symbol i
5553e12c5d1SDavid du Colombier  */
5563e12c5d1SDavid du Colombier char*
symnam(int i)5573e12c5d1SDavid du Colombier symnam(int i)
5583e12c5d1SDavid du Colombier {
5593e12c5d1SDavid du Colombier 	char* cp;
5603e12c5d1SDavid du Colombier 
5613e12c5d1SDavid du Colombier 	cp = (i >= NTBASE)? nontrst[i-NTBASE].name: tokset[i].name;
5623e12c5d1SDavid du Colombier 	if(*cp == ' ')
5633e12c5d1SDavid du Colombier 		cp++;
5643e12c5d1SDavid du Colombier 	return cp;
5653e12c5d1SDavid du Colombier }
5663e12c5d1SDavid du Colombier 
5673e12c5d1SDavid du Colombier /*
5683e12c5d1SDavid du Colombier  * output the summary on y.output
5693e12c5d1SDavid du Colombier  */
5703e12c5d1SDavid du Colombier void
summary(void)5713e12c5d1SDavid du Colombier summary(void)
5723e12c5d1SDavid du Colombier {
5733e12c5d1SDavid du Colombier 
5743e12c5d1SDavid du Colombier 	if(foutput != 0) {
5753e12c5d1SDavid du Colombier 		Bprint(foutput, "\n%d/%d terminals, %d/%d nonterminals\n",
5763e12c5d1SDavid du Colombier 			ntokens, NTERMS, nnonter, NNONTERM);
5773e12c5d1SDavid du Colombier 		Bprint(foutput, "%d/%d grammar rules, %d/%d states\n",
5783e12c5d1SDavid du Colombier 			nprod, NPROD, nstate, NSTATES);
5793e12c5d1SDavid du Colombier 		Bprint(foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n",
5803e12c5d1SDavid du Colombier 			zzsrconf, zzrrconf);
5813e12c5d1SDavid du Colombier 		Bprint(foutput, "%d/%d working sets used\n",
5827dd7cddfSDavid du Colombier 			(int)(zzcwp-wsets), WSETSIZE);
5833e12c5d1SDavid du Colombier 		Bprint(foutput, "memory: states,etc. %d/%d, parser %d/%d\n",
5847dd7cddfSDavid du Colombier 			(int)(zzmemsz-mem0), MEMSIZE, (int)(memp-amem), ACTSIZE);
5853e12c5d1SDavid du Colombier 		Bprint(foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE);
5863e12c5d1SDavid du Colombier 		Bprint(foutput, "%d extra closures\n", zzclose - 2*nstate);
5873e12c5d1SDavid du Colombier 		Bprint(foutput, "%d shift entries, %d exceptions\n", zzacent, zzexcp);
5883e12c5d1SDavid du Colombier 		Bprint(foutput, "%d goto entries\n", zzgoent);
5893e12c5d1SDavid du Colombier 		Bprint(foutput, "%d entries saved by goto default\n", zzgobest);
5903e12c5d1SDavid du Colombier 	}
5913e12c5d1SDavid du Colombier 	if(zzsrconf != 0 || zzrrconf != 0) {
5923e12c5d1SDavid du Colombier 		print("\nconflicts: ");
5933e12c5d1SDavid du Colombier 		if(zzsrconf)
5943e12c5d1SDavid du Colombier 			print("%d shift/reduce", zzsrconf);
5953e12c5d1SDavid du Colombier 		if(zzsrconf && zzrrconf)
5963e12c5d1SDavid du Colombier 			print(", ");
5973e12c5d1SDavid du Colombier 		if(zzrrconf)
5983e12c5d1SDavid du Colombier 			print("%d reduce/reduce", zzrrconf);
5993e12c5d1SDavid du Colombier 		print("\n");
6003e12c5d1SDavid du Colombier 	}
6017dd7cddfSDavid du Colombier 	if(ftemp != 0) {
602219b2ee8SDavid du Colombier 		Bterm(ftemp);
6037dd7cddfSDavid du Colombier 		ftemp = 0;
6047dd7cddfSDavid du Colombier 	}
6057dd7cddfSDavid du Colombier 	if(fdefine != 0) {
606219b2ee8SDavid du Colombier 		Bterm(fdefine);
6077dd7cddfSDavid du Colombier 		fdefine = 0;
6087dd7cddfSDavid du Colombier 	}
6093e12c5d1SDavid du Colombier }
6103e12c5d1SDavid du Colombier 
6113e12c5d1SDavid du Colombier /*
6123e12c5d1SDavid du Colombier  * write out error comment -- NEEDS WORK
6133e12c5d1SDavid du Colombier  */
6143e12c5d1SDavid du Colombier void
error(char * s,...)6153e12c5d1SDavid du Colombier error(char *s, ...)
6163e12c5d1SDavid du Colombier {
6173e12c5d1SDavid du Colombier 
6183e12c5d1SDavid du Colombier 	nerrors++;
6193e12c5d1SDavid du Colombier 	fprint(2, "\n fatal error:");
6203e12c5d1SDavid du Colombier 	fprint(2, s, (&s)[1]);
621219b2ee8SDavid du Colombier 	fprint(2, ", %s:%d\n", infile, lineno);
6223e12c5d1SDavid du Colombier 	if(!fatfl)
6233e12c5d1SDavid du Colombier 		return;
6243e12c5d1SDavid du Colombier 	summary();
6253e12c5d1SDavid du Colombier 	cleantmp();
6263e12c5d1SDavid du Colombier 	exits("error");
6273e12c5d1SDavid du Colombier }
6283e12c5d1SDavid du Colombier 
6293e12c5d1SDavid du Colombier /*
6303e12c5d1SDavid du Colombier  * set elements 0 through n-1 to c
6313e12c5d1SDavid du Colombier  */
6323e12c5d1SDavid du Colombier void
aryfil(int * v,int n,int c)6333e12c5d1SDavid du Colombier aryfil(int *v, int n, int c)
6343e12c5d1SDavid du Colombier {
6353e12c5d1SDavid du Colombier 	int i;
6363e12c5d1SDavid du Colombier 
6373e12c5d1SDavid du Colombier 	for(i=0; i<n; i++)
6383e12c5d1SDavid du Colombier 		v[i] = c;
6393e12c5d1SDavid du Colombier }
6403e12c5d1SDavid du Colombier 
6413e12c5d1SDavid du Colombier /*
6423e12c5d1SDavid du Colombier  * set a to the union of a and b
6433e12c5d1SDavid du Colombier  * return 1 if b is not a subset of a, 0 otherwise
6443e12c5d1SDavid du Colombier  */
6453e12c5d1SDavid du Colombier int
setunion(int * a,int * b)6463e12c5d1SDavid du Colombier setunion(int *a, int *b)
6473e12c5d1SDavid du Colombier {
6483e12c5d1SDavid du Colombier 	int i, x, sub;
6493e12c5d1SDavid du Colombier 
6503e12c5d1SDavid du Colombier 	sub = 0;
6513e12c5d1SDavid du Colombier 	SETLOOP(i) {
6523e12c5d1SDavid du Colombier 		x = *a;
6533e12c5d1SDavid du Colombier 		*a |= *b;
6543e12c5d1SDavid du Colombier 		if(*a != x)
6553e12c5d1SDavid du Colombier 			sub = 1;
6563e12c5d1SDavid du Colombier 		a++;
6573e12c5d1SDavid du Colombier 		b++;
6583e12c5d1SDavid du Colombier 	}
6593e12c5d1SDavid du Colombier 	return sub;
6603e12c5d1SDavid du Colombier }
6613e12c5d1SDavid du Colombier 
6623e12c5d1SDavid du Colombier void
prlook(Lkset * p)6633e12c5d1SDavid du Colombier prlook(Lkset* p)
6643e12c5d1SDavid du Colombier {
6653e12c5d1SDavid du Colombier 	int j, *pp;
6663e12c5d1SDavid du Colombier 
6673e12c5d1SDavid du Colombier 	pp = p->lset;
6683e12c5d1SDavid du Colombier 	if(pp == 0)
6693e12c5d1SDavid du Colombier 		Bprint(foutput, "\tNULL");
6703e12c5d1SDavid du Colombier 	else {
6713e12c5d1SDavid du Colombier 		Bprint(foutput, " { ");
6723e12c5d1SDavid du Colombier 		TLOOP(j)
6733e12c5d1SDavid du Colombier 			if(BIT(pp,j))
6743e12c5d1SDavid du Colombier 				Bprint(foutput, "%s ", symnam(j));
6753e12c5d1SDavid du Colombier 		Bprint(foutput, "}");
6763e12c5d1SDavid du Colombier 	}
6773e12c5d1SDavid du Colombier }
6783e12c5d1SDavid du Colombier 
6793e12c5d1SDavid du Colombier /*
6803e12c5d1SDavid du Colombier  * compute an array with the beginnings of  productions yielding given nonterminals
6813e12c5d1SDavid du Colombier  * The array pres points to these lists
6823e12c5d1SDavid du Colombier  * the array pyield has the lists: the total size is only NPROD+1
6833e12c5d1SDavid du Colombier  */
6843e12c5d1SDavid du Colombier void
cpres(void)6853e12c5d1SDavid du Colombier cpres(void)
6863e12c5d1SDavid du Colombier {
6873e12c5d1SDavid du Colombier 	int c, j, i, **pmem;
6883e12c5d1SDavid du Colombier 	static int *pyield[NPROD];
6893e12c5d1SDavid du Colombier 
6903e12c5d1SDavid du Colombier 	pmem = pyield;
6913e12c5d1SDavid du Colombier 	NTLOOP(i) {
6923e12c5d1SDavid du Colombier 		c = i+NTBASE;
6933e12c5d1SDavid du Colombier 		pres[i] = pmem;
6943e12c5d1SDavid du Colombier 		fatfl = 0;  	/* make undefined  symbols  nonfatal */
6953e12c5d1SDavid du Colombier 		PLOOP(0, j)
6963e12c5d1SDavid du Colombier 			if(*prdptr[j] == c)
6973e12c5d1SDavid du Colombier 				*pmem++ =  prdptr[j]+1;
6983e12c5d1SDavid du Colombier 		if(pres[i] == pmem)
6993e12c5d1SDavid du Colombier 			error("nonterminal %s not defined!", nontrst[i].name);
7003e12c5d1SDavid du Colombier 	}
7013e12c5d1SDavid du Colombier 	pres[i] = pmem;
7023e12c5d1SDavid du Colombier 	fatfl = 1;
7033e12c5d1SDavid du Colombier 	if(nerrors) {
7043e12c5d1SDavid du Colombier 		summary();
7053e12c5d1SDavid du Colombier 		cleantmp();
7063e12c5d1SDavid du Colombier 		exits("error");
7073e12c5d1SDavid du Colombier 	}
7083e12c5d1SDavid du Colombier 	if(pmem != &pyield[nprod])
7093e12c5d1SDavid du Colombier 		error("internal Yacc error: pyield %d", pmem-&pyield[nprod]);
7103e12c5d1SDavid du Colombier }
7113e12c5d1SDavid du Colombier 
7123e12c5d1SDavid du Colombier /*
7133e12c5d1SDavid du Colombier  * compute an array with the first of nonterminals
7143e12c5d1SDavid du Colombier  */
7153e12c5d1SDavid du Colombier void
cpfir(void)7163e12c5d1SDavid du Colombier cpfir(void)
7173e12c5d1SDavid du Colombier {
7183e12c5d1SDavid du Colombier 	int *p, **s, i, **t, ch, changes;
7193e12c5d1SDavid du Colombier 
7203e12c5d1SDavid du Colombier 	zzcwp = &wsets[nnonter];
7213e12c5d1SDavid du Colombier 	NTLOOP(i) {
7223e12c5d1SDavid du Colombier 		aryfil(wsets[i].ws.lset, tbitset, 0);
7233e12c5d1SDavid du Colombier 		t = pres[i+1];
7243e12c5d1SDavid du Colombier 		/* initially fill the sets */
7253e12c5d1SDavid du Colombier 		for(s=pres[i]; s<t; ++s)
7263e12c5d1SDavid du Colombier 			for(p = *s; (ch = *p) > 0; ++p) {
7273e12c5d1SDavid du Colombier 				if(ch < NTBASE) {
7283e12c5d1SDavid du Colombier 					SETBIT(wsets[i].ws.lset, ch);
7293e12c5d1SDavid du Colombier 					break;
7303e12c5d1SDavid du Colombier 				}
7313e12c5d1SDavid du Colombier 				if(!pempty[ch-NTBASE])
7323e12c5d1SDavid du Colombier 					break;
7333e12c5d1SDavid du Colombier 			}
7343e12c5d1SDavid du Colombier 	}
7353e12c5d1SDavid du Colombier 
7363e12c5d1SDavid du Colombier 	/* now, reflect transitivity */
7373e12c5d1SDavid du Colombier 	changes = 1;
7383e12c5d1SDavid du Colombier 	while(changes) {
7393e12c5d1SDavid du Colombier 		changes = 0;
7403e12c5d1SDavid du Colombier 		NTLOOP(i) {
7413e12c5d1SDavid du Colombier 			t = pres[i+1];
7423e12c5d1SDavid du Colombier 			for(s = pres[i]; s < t; ++s)
7433e12c5d1SDavid du Colombier 				for(p = *s; (ch = (*p-NTBASE)) >= 0; ++p) {
7443e12c5d1SDavid du Colombier 					changes |= setunion(wsets[i].ws.lset, wsets[ch].ws.lset);
7453e12c5d1SDavid du Colombier 					if(!pempty[ch])
7463e12c5d1SDavid du Colombier 						break;
7473e12c5d1SDavid du Colombier 				}
7483e12c5d1SDavid du Colombier 		}
7493e12c5d1SDavid du Colombier 	}
7503e12c5d1SDavid du Colombier 
7513e12c5d1SDavid du Colombier 	NTLOOP(i)
7523e12c5d1SDavid du Colombier 		pfirst[i] = flset(&wsets[i].ws);
7533e12c5d1SDavid du Colombier 	if(!indebug)
7543e12c5d1SDavid du Colombier 		return;
7553e12c5d1SDavid du Colombier 	if(foutput != 0)
7563e12c5d1SDavid du Colombier 		NTLOOP(i) {
7573e12c5d1SDavid du Colombier 			Bprint(foutput, "\n%s: ", nontrst[i].name);
7583e12c5d1SDavid du Colombier 			prlook(pfirst[i]);
7593e12c5d1SDavid du Colombier 			Bprint(foutput, " %d\n", pempty[i]);
7603e12c5d1SDavid du Colombier 		}
7613e12c5d1SDavid du Colombier }
7623e12c5d1SDavid du Colombier 
7633e12c5d1SDavid du Colombier /*
7643e12c5d1SDavid du Colombier  * sorts last state,and sees if it equals earlier ones. returns state number
7653e12c5d1SDavid du Colombier  */
7663e12c5d1SDavid du Colombier int
state(int c)7673e12c5d1SDavid du Colombier state(int c)
7683e12c5d1SDavid du Colombier {
7693e12c5d1SDavid du Colombier 	Item *p1, *p2, *k, *l, *q1, *q2;
7703e12c5d1SDavid du Colombier 	int size1, size2, i;
7713e12c5d1SDavid du Colombier 
7723e12c5d1SDavid du Colombier 	p1 = pstate[nstate];
7733e12c5d1SDavid du Colombier 	p2 = pstate[nstate+1];
7743e12c5d1SDavid du Colombier 	if(p1 == p2)
7753e12c5d1SDavid du Colombier 		return 0;	/* null state */
7763e12c5d1SDavid du Colombier 	/* sort the items */
7773e12c5d1SDavid du Colombier 	for(k = p2-1; k > p1; k--)	/* make k the biggest */
7783e12c5d1SDavid du Colombier 		for(l = k-1; l >= p1; --l)
7793e12c5d1SDavid du Colombier 			if(l->pitem > k->pitem) {
7803e12c5d1SDavid du Colombier 				int *s;
7813e12c5d1SDavid du Colombier 				Lkset *ss;
7823e12c5d1SDavid du Colombier 
7833e12c5d1SDavid du Colombier 				s = k->pitem;
7843e12c5d1SDavid du Colombier 				k->pitem = l->pitem;
7853e12c5d1SDavid du Colombier 				l->pitem = s;
7863e12c5d1SDavid du Colombier 				ss = k->look;
7873e12c5d1SDavid du Colombier 				k->look = l->look;
7883e12c5d1SDavid du Colombier 				l->look = ss;
7893e12c5d1SDavid du Colombier 			}
7903e12c5d1SDavid du Colombier 	size1 = p2 - p1;	/* size of state */
7913e12c5d1SDavid du Colombier 
7923e12c5d1SDavid du Colombier 	for(i = (c>=NTBASE)? ntstates[c-NTBASE]: tstates[c]; i != 0; i = mstates[i]) {
7933e12c5d1SDavid du Colombier 		/* get ith state */
7943e12c5d1SDavid du Colombier 		q1 = pstate[i];
7953e12c5d1SDavid du Colombier 		q2 = pstate[i+1];
7963e12c5d1SDavid du Colombier 		size2 = q2 - q1;
7973e12c5d1SDavid du Colombier 		if(size1 != size2)
7983e12c5d1SDavid du Colombier 			continue;
7993e12c5d1SDavid du Colombier 		k = p1;
8003e12c5d1SDavid du Colombier 		for(l = q1; l < q2; l++) {
8013e12c5d1SDavid du Colombier 			if(l->pitem != k->pitem)
8023e12c5d1SDavid du Colombier 				break;
8033e12c5d1SDavid du Colombier 			k++;
8043e12c5d1SDavid du Colombier 		}
8053e12c5d1SDavid du Colombier 		if(l != q2)
8063e12c5d1SDavid du Colombier 			continue;
8073e12c5d1SDavid du Colombier 		/* found it */
8083e12c5d1SDavid du Colombier 		pstate[nstate+1] = pstate[nstate];	/* delete last state */
8093e12c5d1SDavid du Colombier 		/* fix up lookaheads */
8103e12c5d1SDavid du Colombier 		if(nolook)
8113e12c5d1SDavid du Colombier 			return i;
8123e12c5d1SDavid du Colombier 		for(l = q1, k = p1; l < q2; ++l, ++k ) {
8133e12c5d1SDavid du Colombier 			int s;
8143e12c5d1SDavid du Colombier 
8153e12c5d1SDavid du Colombier 			SETLOOP(s)
8163e12c5d1SDavid du Colombier 				clset.lset[s] = l->look->lset[s];
8173e12c5d1SDavid du Colombier 			if(setunion(clset.lset, k->look->lset)) {
8183e12c5d1SDavid du Colombier 				tystate[i] = MUSTDO;
8193e12c5d1SDavid du Colombier 				/* register the new set */
8203e12c5d1SDavid du Colombier 				l->look = flset( &clset );
8213e12c5d1SDavid du Colombier 			}
8223e12c5d1SDavid du Colombier 		}
8233e12c5d1SDavid du Colombier 		return i;
8243e12c5d1SDavid du Colombier 	}
8253e12c5d1SDavid du Colombier 	/* state is new */
8263e12c5d1SDavid du Colombier 	if(nolook)
8273e12c5d1SDavid du Colombier 		error("yacc state/nolook error");
8283e12c5d1SDavid du Colombier 	pstate[nstate+2] = p2;
8293e12c5d1SDavid du Colombier 	if(nstate+1 >= NSTATES)
8303e12c5d1SDavid du Colombier 		error("too many states");
8313e12c5d1SDavid du Colombier 	if(c >= NTBASE) {
8323e12c5d1SDavid du Colombier 		mstates[nstate] = ntstates[c-NTBASE];
8333e12c5d1SDavid du Colombier 		ntstates[c-NTBASE] = nstate;
8343e12c5d1SDavid du Colombier 	} else {
8353e12c5d1SDavid du Colombier 		mstates[nstate] = tstates[c];
8363e12c5d1SDavid du Colombier 		tstates[c] = nstate;
8373e12c5d1SDavid du Colombier 	}
8383e12c5d1SDavid du Colombier 	tystate[nstate] = MUSTDO;
8393e12c5d1SDavid du Colombier 	return nstate++;
8403e12c5d1SDavid du Colombier }
8413e12c5d1SDavid du Colombier 
8423e12c5d1SDavid du Colombier void
putitem(int * ptr,Lkset * lptr)8433e12c5d1SDavid du Colombier putitem(int *ptr, Lkset *lptr)
8443e12c5d1SDavid du Colombier {
8453e12c5d1SDavid du Colombier 	Item *j;
8463e12c5d1SDavid du Colombier 
8473e12c5d1SDavid du Colombier 	if(pidebug && foutput != 0)
8483e12c5d1SDavid du Colombier 		Bprint(foutput, "putitem(%s), state %d\n", writem(ptr), nstate);
8493e12c5d1SDavid du Colombier 	j = pstate[nstate+1];
8503e12c5d1SDavid du Colombier 	j->pitem = ptr;
8513e12c5d1SDavid du Colombier 	if(!nolook)
8523e12c5d1SDavid du Colombier 		j->look = flset(lptr);
8533e12c5d1SDavid du Colombier 	pstate[nstate+1] = ++j;
8543e12c5d1SDavid du Colombier 	if((int*)j > zzmemsz) {
8553e12c5d1SDavid du Colombier 		zzmemsz = (int*)j;
8563e12c5d1SDavid du Colombier 		if(zzmemsz >=  &mem0[MEMSIZE])
8573e12c5d1SDavid du Colombier 			error("out of state space");
8583e12c5d1SDavid du Colombier 	}
8593e12c5d1SDavid du Colombier }
8603e12c5d1SDavid du Colombier 
8613e12c5d1SDavid du Colombier /*
8623e12c5d1SDavid du Colombier  * mark nonterminals which derive the empty string
8633e12c5d1SDavid du Colombier  * also, look for nonterminals which don't derive any token strings
8643e12c5d1SDavid du Colombier  */
8653e12c5d1SDavid du Colombier void
cempty(void)8663e12c5d1SDavid du Colombier cempty(void)
8673e12c5d1SDavid du Colombier {
8683e12c5d1SDavid du Colombier 
8693e12c5d1SDavid du Colombier 	int i, *p;
8703e12c5d1SDavid du Colombier 
8713e12c5d1SDavid du Colombier 	/* first, use the array pempty to detect productions that can never be reduced */
8723e12c5d1SDavid du Colombier 	/* set pempty to WHONOWS */
8733e12c5d1SDavid du Colombier 	aryfil(pempty, nnonter+1, WHOKNOWS);
8743e12c5d1SDavid du Colombier 
8753e12c5d1SDavid du Colombier 	/* now, look at productions, marking nonterminals which derive something */
8763e12c5d1SDavid du Colombier more:
8773e12c5d1SDavid du Colombier 	PLOOP(0, i) {
8783e12c5d1SDavid du Colombier 		if(pempty[*prdptr[i] - NTBASE])
8793e12c5d1SDavid du Colombier 			continue;
8803e12c5d1SDavid du Colombier 		for(p = prdptr[i]+1; *p >= 0; ++p)
8813e12c5d1SDavid du Colombier 			if(*p >= NTBASE && pempty[*p-NTBASE] == WHOKNOWS)
8823e12c5d1SDavid du Colombier 				break;
8833e12c5d1SDavid du Colombier 		/* production can be derived */
8843e12c5d1SDavid du Colombier 		if(*p < 0) {
8853e12c5d1SDavid du Colombier 			pempty[*prdptr[i]-NTBASE] = OK;
8863e12c5d1SDavid du Colombier 			goto more;
8873e12c5d1SDavid du Colombier 		}
8883e12c5d1SDavid du Colombier 	}
8893e12c5d1SDavid du Colombier 
8903e12c5d1SDavid du Colombier 	/* now, look at the nonterminals, to see if they are all OK */
8913e12c5d1SDavid du Colombier 	NTLOOP(i) {
8923e12c5d1SDavid du Colombier 		/* the added production rises or falls as the start symbol ... */
8933e12c5d1SDavid du Colombier 		if(i == 0)
8943e12c5d1SDavid du Colombier 			continue;
8953e12c5d1SDavid du Colombier 		if(pempty[i] != OK) {
8963e12c5d1SDavid du Colombier 			fatfl = 0;
8973e12c5d1SDavid du Colombier 			error("nonterminal %s never derives any token string", nontrst[i].name);
8983e12c5d1SDavid du Colombier 		}
8993e12c5d1SDavid du Colombier 	}
9003e12c5d1SDavid du Colombier 
9013e12c5d1SDavid du Colombier 	if(nerrors) {
9023e12c5d1SDavid du Colombier 		summary();
9033e12c5d1SDavid du Colombier 		cleantmp();
9043e12c5d1SDavid du Colombier 		exits("error");
9053e12c5d1SDavid du Colombier 	}
9063e12c5d1SDavid du Colombier 
9073e12c5d1SDavid du Colombier 	/* now, compute the pempty array, to see which nonterminals derive the empty string */
9083e12c5d1SDavid du Colombier 	/* set pempty to WHOKNOWS */
9093e12c5d1SDavid du Colombier 	aryfil( pempty, nnonter+1, WHOKNOWS);
9103e12c5d1SDavid du Colombier 
9113e12c5d1SDavid du Colombier 	/* loop as long as we keep finding empty nonterminals */
9123e12c5d1SDavid du Colombier 
9133e12c5d1SDavid du Colombier again:
9143e12c5d1SDavid du Colombier 	PLOOP(1, i) {
9153e12c5d1SDavid du Colombier 		/* not known to be empty */
9163e12c5d1SDavid du Colombier 		if(pempty[*prdptr[i]-NTBASE] == WHOKNOWS) {
9173e12c5d1SDavid du Colombier 			for(p = prdptr[i]+1; *p >= NTBASE && pempty[*p-NTBASE] == EMPTY ; ++p)
9183e12c5d1SDavid du Colombier 				;
9193e12c5d1SDavid du Colombier 			/* we have a nontrivially empty nonterminal */
9203e12c5d1SDavid du Colombier 			if(*p < 0) {
9213e12c5d1SDavid du Colombier 				pempty[*prdptr[i]-NTBASE] = EMPTY;
9223e12c5d1SDavid du Colombier 				/* got one ... try for another */
9233e12c5d1SDavid du Colombier 				goto again;
9243e12c5d1SDavid du Colombier 			}
9253e12c5d1SDavid du Colombier 		}
9263e12c5d1SDavid du Colombier 	}
9273e12c5d1SDavid du Colombier }
9283e12c5d1SDavid du Colombier 
9293e12c5d1SDavid du Colombier /*
9303e12c5d1SDavid du Colombier  * generate the states
9313e12c5d1SDavid du Colombier  */
9323e12c5d1SDavid du Colombier void
stagen(void)9333e12c5d1SDavid du Colombier stagen(void)
9343e12c5d1SDavid du Colombier {
9353e12c5d1SDavid du Colombier 
9367dd7cddfSDavid du Colombier 	int c, i, j, more;
9373e12c5d1SDavid du Colombier 	Wset *p, *q;
9383e12c5d1SDavid du Colombier 
9393e12c5d1SDavid du Colombier 	/* initialize */
9403e12c5d1SDavid du Colombier 	nstate = 0;
9413e12c5d1SDavid du Colombier 
9423e12c5d1SDavid du Colombier 	/* THIS IS FUNNY from the standpoint of portability
9433e12c5d1SDavid du Colombier 	 * it represents the magic moment when the mem0 array, which has
9443e12c5d1SDavid du Colombier 	 * been holding the productions, starts to hold item pointers, of a
9453e12c5d1SDavid du Colombier 	 * different type...
9463e12c5d1SDavid du Colombier 	 * someday, alloc should be used to allocate all this stuff... for now, we
9473e12c5d1SDavid du Colombier 	 * accept that if pointers don't fit in integers, there is a problem...
9483e12c5d1SDavid du Colombier 	 */
9493e12c5d1SDavid du Colombier 
9503e12c5d1SDavid du Colombier 	pstate[0] = pstate[1] = (Item*)mem;
9513e12c5d1SDavid du Colombier 	aryfil(clset.lset, tbitset, 0);
9523e12c5d1SDavid du Colombier 	putitem(prdptr[0]+1, &clset);
9533e12c5d1SDavid du Colombier 	tystate[0] = MUSTDO;
9543e12c5d1SDavid du Colombier 	nstate = 1;
9553e12c5d1SDavid du Colombier 	pstate[2] = pstate[1];
9563e12c5d1SDavid du Colombier 
9573e12c5d1SDavid du Colombier 	aryfil(amem, ACTSIZE, 0);
9583e12c5d1SDavid du Colombier 
9593e12c5d1SDavid du Colombier 	/* now, the main state generation loop */
9607dd7cddfSDavid du Colombier 	for(more=1; more;) {
9617dd7cddfSDavid du Colombier 		more = 0;
9623e12c5d1SDavid du Colombier 		SLOOP(i) {
9633e12c5d1SDavid du Colombier 			if(tystate[i] != MUSTDO)
9643e12c5d1SDavid du Colombier 				continue;
9653e12c5d1SDavid du Colombier 			tystate[i] = DONE;
9663e12c5d1SDavid du Colombier 			aryfil(temp1, nnonter+1, 0);
9673e12c5d1SDavid du Colombier 			/* take state i, close it, and do gotos */
9683e12c5d1SDavid du Colombier 			closure(i);
9693e12c5d1SDavid du Colombier 			/* generate goto's */
9703e12c5d1SDavid du Colombier 			WSLOOP(wsets, p) {
9713e12c5d1SDavid du Colombier 				if(p->flag)
9723e12c5d1SDavid du Colombier 					continue;
9733e12c5d1SDavid du Colombier 				p->flag = 1;
9743e12c5d1SDavid du Colombier 				c = *(p->pitem);
9753e12c5d1SDavid du Colombier 				if(c <= 1) {
9763e12c5d1SDavid du Colombier 					if(pstate[i+1]-pstate[i] <= p-wsets)
9773e12c5d1SDavid du Colombier 						tystate[i] = MUSTLOOKAHEAD;
9783e12c5d1SDavid du Colombier 					continue;
9793e12c5d1SDavid du Colombier 				}
9803e12c5d1SDavid du Colombier 				/* do a goto on c */
9813e12c5d1SDavid du Colombier 				WSLOOP(p, q)
9823e12c5d1SDavid du Colombier 					/* this item contributes to the goto */
9833e12c5d1SDavid du Colombier 					if(c == *(q->pitem)) {
9843e12c5d1SDavid du Colombier 						putitem(q->pitem+1, &q->ws);
9853e12c5d1SDavid du Colombier 						q->flag = 1;
9863e12c5d1SDavid du Colombier 					}
9873e12c5d1SDavid du Colombier 				if(c < NTBASE)
9883e12c5d1SDavid du Colombier 					state(c);	/* register new state */
9893e12c5d1SDavid du Colombier 				else
9903e12c5d1SDavid du Colombier 					temp1[c-NTBASE] = state(c);
9913e12c5d1SDavid du Colombier 			}
9923e12c5d1SDavid du Colombier 			if(gsdebug && foutput != 0) {
9933e12c5d1SDavid du Colombier 				Bprint(foutput, "%d: ", i);
9943e12c5d1SDavid du Colombier 				NTLOOP(j)
9953e12c5d1SDavid du Colombier 					if(temp1[j])
9967dd7cddfSDavid du Colombier 						Bprint(foutput, "%s %d, ",
9977dd7cddfSDavid du Colombier 						nontrst[j].name, temp1[j]);
9983e12c5d1SDavid du Colombier 				Bprint(foutput, "\n");
9993e12c5d1SDavid du Colombier 			}
10003e12c5d1SDavid du Colombier 			indgo[i] = apack(&temp1[1], nnonter-1) - 1;
10017dd7cddfSDavid du Colombier 			/* do some more */
10027dd7cddfSDavid du Colombier 			more = 1;
10033e12c5d1SDavid du Colombier 		}
10047dd7cddfSDavid du Colombier 	}
10053e12c5d1SDavid du Colombier }
10063e12c5d1SDavid du Colombier 
10073e12c5d1SDavid du Colombier /*
10083e12c5d1SDavid du Colombier  * generate the closure of state i
10093e12c5d1SDavid du Colombier  */
10103e12c5d1SDavid du Colombier void
closure(int i)10113e12c5d1SDavid du Colombier closure(int i)
10123e12c5d1SDavid du Colombier {
10133e12c5d1SDavid du Colombier 
10143e12c5d1SDavid du Colombier 	Wset *u, *v;
10153e12c5d1SDavid du Colombier 	Item *p, *q;
10163e12c5d1SDavid du Colombier 	int c, ch, work, k, *pi, **s, **t;
10173e12c5d1SDavid du Colombier 
10183e12c5d1SDavid du Colombier 	zzclose++;
10193e12c5d1SDavid du Colombier 
10203e12c5d1SDavid du Colombier 	/* first, copy kernel of state i to wsets */
10213e12c5d1SDavid du Colombier 	cwp = wsets;
10223e12c5d1SDavid du Colombier 	ITMLOOP(i, p, q) {
10233e12c5d1SDavid du Colombier 		cwp->pitem = p->pitem;
10243e12c5d1SDavid du Colombier 		cwp->flag = 1;			/* this item must get closed */
10253e12c5d1SDavid du Colombier 		SETLOOP(k)
10263e12c5d1SDavid du Colombier 			cwp->ws.lset[k] = p->look->lset[k];
10273e12c5d1SDavid du Colombier 		WSBUMP(cwp);
10283e12c5d1SDavid du Colombier 	}
10293e12c5d1SDavid du Colombier 
10303e12c5d1SDavid du Colombier 	/* now, go through the loop, closing each item */
10313e12c5d1SDavid du Colombier 	work = 1;
10323e12c5d1SDavid du Colombier 	while(work) {
10333e12c5d1SDavid du Colombier 		work = 0;
10343e12c5d1SDavid du Colombier 		WSLOOP(wsets, u) {
10353e12c5d1SDavid du Colombier 			if(u->flag == 0)
10363e12c5d1SDavid du Colombier 				continue;
10373e12c5d1SDavid du Colombier 			/* dot is before c */
10383e12c5d1SDavid du Colombier 			c = *(u->pitem);
10393e12c5d1SDavid du Colombier 			if(c < NTBASE) {
10403e12c5d1SDavid du Colombier 				u->flag = 0;
10413e12c5d1SDavid du Colombier 				/* only interesting case is where . is before nonterminal */
10423e12c5d1SDavid du Colombier 				continue;
10433e12c5d1SDavid du Colombier 			}
10443e12c5d1SDavid du Colombier 
10453e12c5d1SDavid du Colombier 			/* compute the lookahead */
10463e12c5d1SDavid du Colombier 			aryfil(clset.lset, tbitset, 0);
10473e12c5d1SDavid du Colombier 
10483e12c5d1SDavid du Colombier 			/* find items involving c */
10493e12c5d1SDavid du Colombier 			WSLOOP(u, v)
10503e12c5d1SDavid du Colombier 				if(v->flag == 1 && *(pi=v->pitem) == c) {
10513e12c5d1SDavid du Colombier 					v->flag = 0;
10523e12c5d1SDavid du Colombier 					if(nolook)
10533e12c5d1SDavid du Colombier 						continue;
10543e12c5d1SDavid du Colombier 					while((ch = *++pi) > 0) {
10553e12c5d1SDavid du Colombier 						/* terminal symbol */
10563e12c5d1SDavid du Colombier 						if(ch < NTBASE) {
10573e12c5d1SDavid du Colombier 							SETBIT(clset.lset, ch);
10583e12c5d1SDavid du Colombier 							break;
10593e12c5d1SDavid du Colombier 						}
10603e12c5d1SDavid du Colombier 						/* nonterminal symbol */
10613e12c5d1SDavid du Colombier 						setunion(clset.lset, pfirst[ch-NTBASE]->lset);
10623e12c5d1SDavid du Colombier 						if(!pempty[ch-NTBASE])
10633e12c5d1SDavid du Colombier 							break;
10643e12c5d1SDavid du Colombier 					}
10653e12c5d1SDavid du Colombier 					if(ch <= 0)
10663e12c5d1SDavid du Colombier 						setunion(clset.lset, v->ws.lset);
10673e12c5d1SDavid du Colombier 				}
10683e12c5d1SDavid du Colombier 
10693e12c5d1SDavid du Colombier 			/*
10703e12c5d1SDavid du Colombier 			 * now loop over productions derived from c
10713e12c5d1SDavid du Colombier 			 * c is now nonterminal number
10723e12c5d1SDavid du Colombier 			 */
10733e12c5d1SDavid du Colombier 			c -= NTBASE;
10743e12c5d1SDavid du Colombier 			t = pres[c+1];
10753e12c5d1SDavid du Colombier 			for(s = pres[c]; s < t; ++s) {
10763e12c5d1SDavid du Colombier 				/*
10773e12c5d1SDavid du Colombier 				 * put these items into the closure
10783e12c5d1SDavid du Colombier 				 * is the item there
10793e12c5d1SDavid du Colombier 				 */
10803e12c5d1SDavid du Colombier 				WSLOOP(wsets, v)
10813e12c5d1SDavid du Colombier 					/* yes, it is there */
10823e12c5d1SDavid du Colombier 					if(v->pitem == *s) {
10833e12c5d1SDavid du Colombier 						if(nolook)
10843e12c5d1SDavid du Colombier 							goto nexts;
10853e12c5d1SDavid du Colombier 						if(setunion(v->ws.lset, clset.lset))
10863e12c5d1SDavid du Colombier 							v->flag = work = 1;
10873e12c5d1SDavid du Colombier 						goto nexts;
10883e12c5d1SDavid du Colombier 					}
10893e12c5d1SDavid du Colombier 
10903e12c5d1SDavid du Colombier 				/*  not there; make a new entry */
10913e12c5d1SDavid du Colombier 				if(cwp-wsets+1 >= WSETSIZE)
10923e12c5d1SDavid du Colombier 					error( "working set overflow");
10933e12c5d1SDavid du Colombier 				cwp->pitem = *s;
10943e12c5d1SDavid du Colombier 				cwp->flag = 1;
10953e12c5d1SDavid du Colombier 				if(!nolook) {
10963e12c5d1SDavid du Colombier 					work = 1;
10973e12c5d1SDavid du Colombier 					SETLOOP(k) cwp->ws.lset[k] = clset.lset[k];
10983e12c5d1SDavid du Colombier 				}
10993e12c5d1SDavid du Colombier 				WSBUMP(cwp);
11003e12c5d1SDavid du Colombier 
11013e12c5d1SDavid du Colombier 			nexts:;
11023e12c5d1SDavid du Colombier 			}
11033e12c5d1SDavid du Colombier 		}
11043e12c5d1SDavid du Colombier 	}
11053e12c5d1SDavid du Colombier 
11063e12c5d1SDavid du Colombier 	/* have computed closure; flags are reset; return */
11073e12c5d1SDavid du Colombier 	if(cwp > zzcwp)
11083e12c5d1SDavid du Colombier 		zzcwp = cwp;
11093e12c5d1SDavid du Colombier 	if(cldebug && foutput != 0) {
11103e12c5d1SDavid du Colombier 		Bprint(foutput, "\nState %d, nolook = %d\n", i, nolook);
11113e12c5d1SDavid du Colombier 		WSLOOP(wsets, u) {
11123e12c5d1SDavid du Colombier 			if(u->flag)
11133e12c5d1SDavid du Colombier 				Bprint(foutput, "flag set!\n");
11143e12c5d1SDavid du Colombier 			u->flag = 0;
11153e12c5d1SDavid du Colombier 			Bprint(foutput, "\t%s", writem(u->pitem));
11163e12c5d1SDavid du Colombier 			prlook(&u->ws);
11173e12c5d1SDavid du Colombier 			Bprint(foutput, "\n");
11183e12c5d1SDavid du Colombier 		}
11193e12c5d1SDavid du Colombier 	}
11203e12c5d1SDavid du Colombier }
11213e12c5d1SDavid du Colombier 
11223e12c5d1SDavid du Colombier /*
11233e12c5d1SDavid du Colombier  * decide if the lookahead set pointed to by p is known
11243e12c5d1SDavid du Colombier  * return pointer to a perminent location for the set
11253e12c5d1SDavid du Colombier  */
11263e12c5d1SDavid du Colombier Lkset*
flset(Lkset * p)11273e12c5d1SDavid du Colombier flset(Lkset *p)
11283e12c5d1SDavid du Colombier {
11293e12c5d1SDavid du Colombier 	Lkset *q;
11303e12c5d1SDavid du Colombier 	int *u, *v, *w, j;
11313e12c5d1SDavid du Colombier 
11323e12c5d1SDavid du Colombier 	for(q = &lkst[nlset]; q-- > lkst;) {
11333e12c5d1SDavid du Colombier 		u = p->lset;
11343e12c5d1SDavid du Colombier 		v = q->lset;
11353e12c5d1SDavid du Colombier 		w = &v[tbitset];
11363e12c5d1SDavid du Colombier 		while(v < w)
11373e12c5d1SDavid du Colombier 			if(*u++ != *v++)
11383e12c5d1SDavid du Colombier 				goto more;
11393e12c5d1SDavid du Colombier 		/* we have matched */
11403e12c5d1SDavid du Colombier 		return q;
11413e12c5d1SDavid du Colombier 	more:;
11423e12c5d1SDavid du Colombier 	}
11433e12c5d1SDavid du Colombier 	/* add a new one */
11443e12c5d1SDavid du Colombier 	q = &lkst[nlset++];
11453e12c5d1SDavid du Colombier 	if(nlset >= LSETSIZE)
11463e12c5d1SDavid du Colombier 		error("too many lookahead sets");
11473e12c5d1SDavid du Colombier 	SETLOOP(j)
11483e12c5d1SDavid du Colombier 		q->lset[j] = p->lset[j];
11493e12c5d1SDavid du Colombier 	return q;
11503e12c5d1SDavid du Colombier }
11513e12c5d1SDavid du Colombier 
11523e12c5d1SDavid du Colombier void
cleantmp(void)11533e12c5d1SDavid du Colombier cleantmp(void)
11543e12c5d1SDavid du Colombier {
11553e12c5d1SDavid du Colombier 	ZAPFILE(actname);
11563e12c5d1SDavid du Colombier 	ZAPFILE(tempname);
11573e12c5d1SDavid du Colombier }
11583e12c5d1SDavid du Colombier 
11593e12c5d1SDavid du Colombier void
intr(void)11603e12c5d1SDavid du Colombier intr(void)
11613e12c5d1SDavid du Colombier {
11623e12c5d1SDavid du Colombier 	cleantmp();
11633e12c5d1SDavid du Colombier 	exits("interrupted");
11643e12c5d1SDavid du Colombier }
11653e12c5d1SDavid du Colombier 
11663e12c5d1SDavid du Colombier void
usage(void)1167de8abbc9SDavid du Colombier usage(void)
1168de8abbc9SDavid du Colombier {
1169de8abbc9SDavid du Colombier 	fprint(2, "usage: yacc [-Dn] [-vdS] [-o outputfile] [-s stem] grammar\n");
1170de8abbc9SDavid du Colombier 	exits("usage");
1171de8abbc9SDavid du Colombier }
1172de8abbc9SDavid du Colombier 
1173de8abbc9SDavid du Colombier void
setup(int argc,char * argv[])11743e12c5d1SDavid du Colombier setup(int argc, char *argv[])
11753e12c5d1SDavid du Colombier {
11763e12c5d1SDavid du Colombier 	long c, t;
11773e12c5d1SDavid du Colombier 	int i, j, lev, ty, ytab, *p;
11783e12c5d1SDavid du Colombier 	int vflag, dflag, stem;
11797dd7cddfSDavid du Colombier 	char actnm[8], *stemc, *s, dirbuf[128];
11803e12c5d1SDavid du Colombier 
11813e12c5d1SDavid du Colombier 	ytab = 0;
11823e12c5d1SDavid du Colombier 	vflag = 0;
11833e12c5d1SDavid du Colombier 	dflag = 0;
11843e12c5d1SDavid du Colombier 	stem = 0;
11853e12c5d1SDavid du Colombier 	stemc = "y";
11863e12c5d1SDavid du Colombier 	foutput = 0;
11873e12c5d1SDavid du Colombier 	fdefine = 0;
11883e12c5d1SDavid du Colombier 	fdebug = 0;
11893e12c5d1SDavid du Colombier 	ARGBEGIN{
11903e12c5d1SDavid du Colombier 	case 'v':
11913e12c5d1SDavid du Colombier 	case 'V':
11923e12c5d1SDavid du Colombier 		vflag++;
11933e12c5d1SDavid du Colombier 		break;
11943e12c5d1SDavid du Colombier 	case 'D':
1195de8abbc9SDavid du Colombier 		yydebug = EARGF(usage());
11963e12c5d1SDavid du Colombier 		break;
11973e12c5d1SDavid du Colombier 	case 'd':
11983e12c5d1SDavid du Colombier 		dflag++;
11993e12c5d1SDavid du Colombier 		break;
12003e12c5d1SDavid du Colombier 	case 'o':
12013e12c5d1SDavid du Colombier 		ytab++;
1202de8abbc9SDavid du Colombier 		ytabc = EARGF(usage());
12033e12c5d1SDavid du Colombier 		break;
12043e12c5d1SDavid du Colombier 	case 's':
12053e12c5d1SDavid du Colombier 		stem++;
12063e12c5d1SDavid du Colombier 		stemc = ARGF();
12073e12c5d1SDavid du Colombier 		break;
12083e12c5d1SDavid du Colombier 	case 'S':
12093e12c5d1SDavid du Colombier 		parser = PARSERS;
12103e12c5d1SDavid du Colombier 		break;
12113e12c5d1SDavid du Colombier 	default:
12123e12c5d1SDavid du Colombier 		error("illegal option: %c", ARGC());
12133e12c5d1SDavid du Colombier 	}ARGEND
12143e12c5d1SDavid du Colombier 	openup(stemc, dflag, vflag, ytab, ytabc);
12153e12c5d1SDavid du Colombier 
12163e12c5d1SDavid du Colombier 	ftemp = Bopen(tempname = mktemp(ttempname), OWRITE);
12173e12c5d1SDavid du Colombier 	faction = Bopen(actname = mktemp(tactname), OWRITE);
12183e12c5d1SDavid du Colombier 	if(ftemp == 0 || faction == 0)
12193e12c5d1SDavid du Colombier 		error("cannot open temp file");
12203e12c5d1SDavid du Colombier 	if(argc < 1)
12213e12c5d1SDavid du Colombier 		error("no input file");
12223e12c5d1SDavid du Colombier 	infile = argv[0];
12237dd7cddfSDavid du Colombier 	if(infile[0] != '/' && getwd(dirbuf, sizeof dirbuf)!=nil){
122459cc4ca5SDavid du Colombier 		i = strlen(infile)+1+strlen(dirbuf)+1+10;
12257dd7cddfSDavid du Colombier 		s = malloc(i);
12267dd7cddfSDavid du Colombier 		if(s != nil){
12277dd7cddfSDavid du Colombier 			snprint(s, i, "%s/%s", dirbuf, infile);
12287dd7cddfSDavid du Colombier 			cleanname(s);
12297dd7cddfSDavid du Colombier 			infile = s;
12307dd7cddfSDavid du Colombier 		}
12317dd7cddfSDavid du Colombier 	}
12323e12c5d1SDavid du Colombier 	finput = Bopen(infile, OREAD);
12333e12c5d1SDavid du Colombier 	if(finput == 0)
12343e12c5d1SDavid du Colombier 		error("cannot open '%s'", argv[0]);
12353e12c5d1SDavid du Colombier 	cnamp = cnames;
12363e12c5d1SDavid du Colombier 
12373e12c5d1SDavid du Colombier 	defin(0, "$end");
12383e12c5d1SDavid du Colombier 	extval = PRIVATE;	/* tokens start in unicode 'private use' */
12393e12c5d1SDavid du Colombier 	defin(0, "error");
12403e12c5d1SDavid du Colombier 	defin(1, "$accept");
12413e12c5d1SDavid du Colombier 	defin(0, "$unk");
12423e12c5d1SDavid du Colombier 	mem = mem0;
12433e12c5d1SDavid du Colombier 	i = 0;
12443e12c5d1SDavid du Colombier 
12453e12c5d1SDavid du Colombier 	for(t = gettok(); t != MARK && t != ENDFILE;)
12463e12c5d1SDavid du Colombier 	switch(t) {
12473e12c5d1SDavid du Colombier 	case ';':
12483e12c5d1SDavid du Colombier 		t = gettok();
12493e12c5d1SDavid du Colombier 		break;
12503e12c5d1SDavid du Colombier 
12513e12c5d1SDavid du Colombier 	case START:
12523e12c5d1SDavid du Colombier 		if(gettok() != IDENTIFIER)
12533e12c5d1SDavid du Colombier 			error("bad %%start construction");
12543e12c5d1SDavid du Colombier 		start = chfind(1, tokname);
12553e12c5d1SDavid du Colombier 		t = gettok();
12563e12c5d1SDavid du Colombier 		continue;
12573e12c5d1SDavid du Colombier 
12583e12c5d1SDavid du Colombier 	case TYPEDEF:
12593e12c5d1SDavid du Colombier 		if(gettok() != TYPENAME)
12603e12c5d1SDavid du Colombier 			error("bad syntax in %%type");
12613e12c5d1SDavid du Colombier 		ty = numbval;
12623e12c5d1SDavid du Colombier 		for(;;) {
12633e12c5d1SDavid du Colombier 			t = gettok();
12643e12c5d1SDavid du Colombier 			switch(t) {
12653e12c5d1SDavid du Colombier 			case IDENTIFIER:
12663e12c5d1SDavid du Colombier 				if((t=chfind(1, tokname)) < NTBASE) {
12673e12c5d1SDavid du Colombier 					j = TYPE(toklev[t]);
12683e12c5d1SDavid du Colombier 					if(j != 0 && j != ty)
12693e12c5d1SDavid du Colombier 						error("type redeclaration of token %s",
12703e12c5d1SDavid du Colombier 							tokset[t].name);
12713e12c5d1SDavid du Colombier 					else
12723e12c5d1SDavid du Colombier 						SETTYPE(toklev[t], ty);
12733e12c5d1SDavid du Colombier 				} else {
12743e12c5d1SDavid du Colombier 					j = nontrst[t-NTBASE].value;
12753e12c5d1SDavid du Colombier 					if(j != 0 && j != ty)
12763e12c5d1SDavid du Colombier 						error("type redeclaration of nonterminal %s",
12773e12c5d1SDavid du Colombier 							nontrst[t-NTBASE].name );
12783e12c5d1SDavid du Colombier 					else
12793e12c5d1SDavid du Colombier 						nontrst[t-NTBASE].value = ty;
12803e12c5d1SDavid du Colombier 				}
12813e12c5d1SDavid du Colombier 			case ',':
12823e12c5d1SDavid du Colombier 				continue;
12833e12c5d1SDavid du Colombier 			case ';':
12843e12c5d1SDavid du Colombier 				t = gettok();
12853e12c5d1SDavid du Colombier 			default:
12863e12c5d1SDavid du Colombier 				break;
12873e12c5d1SDavid du Colombier 			}
12883e12c5d1SDavid du Colombier 			break;
12893e12c5d1SDavid du Colombier 		}
12903e12c5d1SDavid du Colombier 		continue;
12913e12c5d1SDavid du Colombier 
12923e12c5d1SDavid du Colombier 	case UNION:
12933e12c5d1SDavid du Colombier 		/* copy the union declaration to the output */
12943e12c5d1SDavid du Colombier 		cpyunion();
12953e12c5d1SDavid du Colombier 		t = gettok();
12963e12c5d1SDavid du Colombier 		continue;
12973e12c5d1SDavid du Colombier 
12983e12c5d1SDavid du Colombier 	case LEFT:
12993e12c5d1SDavid du Colombier 	case BINARY:
13003e12c5d1SDavid du Colombier 	case RIGHT:
13013e12c5d1SDavid du Colombier 		i++;
13023e12c5d1SDavid du Colombier 
13033e12c5d1SDavid du Colombier 	case TERM:
13043e12c5d1SDavid du Colombier 		/* nonzero means new prec. and assoc. */
13053e12c5d1SDavid du Colombier 		lev = t-TERM;
13063e12c5d1SDavid du Colombier 		ty = 0;
13073e12c5d1SDavid du Colombier 
13083e12c5d1SDavid du Colombier 		/* get identifiers so defined */
13093e12c5d1SDavid du Colombier 		t = gettok();
13103e12c5d1SDavid du Colombier 
13113e12c5d1SDavid du Colombier 		/* there is a type defined */
13123e12c5d1SDavid du Colombier 		if(t == TYPENAME) {
13133e12c5d1SDavid du Colombier 			ty = numbval;
13143e12c5d1SDavid du Colombier 			t = gettok();
13153e12c5d1SDavid du Colombier 		}
13163e12c5d1SDavid du Colombier 		for(;;) {
13173e12c5d1SDavid du Colombier 			switch(t) {
13183e12c5d1SDavid du Colombier 			case ',':
13193e12c5d1SDavid du Colombier 				t = gettok();
13203e12c5d1SDavid du Colombier 				continue;
13213e12c5d1SDavid du Colombier 
13223e12c5d1SDavid du Colombier 			case ';':
13233e12c5d1SDavid du Colombier 				break;
13243e12c5d1SDavid du Colombier 
13253e12c5d1SDavid du Colombier 			case IDENTIFIER:
13263e12c5d1SDavid du Colombier 				j = chfind(0, tokname);
13273e12c5d1SDavid du Colombier 				if(j >= NTBASE)
13283e12c5d1SDavid du Colombier 					error("%s defined earlier as nonterminal", tokname);
13293e12c5d1SDavid du Colombier 				if(lev) {
13303e12c5d1SDavid du Colombier 					if(ASSOC(toklev[j]))
13313e12c5d1SDavid du Colombier 						error("redeclaration of precedence of %s", tokname);
13323e12c5d1SDavid du Colombier 					SETASC(toklev[j], lev);
13333e12c5d1SDavid du Colombier 					SETPLEV(toklev[j], i);
13343e12c5d1SDavid du Colombier 				}
13353e12c5d1SDavid du Colombier 				if(ty) {
13363e12c5d1SDavid du Colombier 					if(TYPE(toklev[j]))
13373e12c5d1SDavid du Colombier 						error("redeclaration of type of %s", tokname);
13383e12c5d1SDavid du Colombier 					SETTYPE(toklev[j],ty);
13393e12c5d1SDavid du Colombier 				}
13403e12c5d1SDavid du Colombier 				t = gettok();
13413e12c5d1SDavid du Colombier 				if(t == NUMBER) {
13423e12c5d1SDavid du Colombier 					tokset[j].value = numbval;
13433e12c5d1SDavid du Colombier 					if(j < ndefout && j > 3)
13443e12c5d1SDavid du Colombier 						error("please define type number of %s earlier",
13453e12c5d1SDavid du Colombier 							tokset[j].name);
13463e12c5d1SDavid du Colombier 					t = gettok();
13473e12c5d1SDavid du Colombier 				}
13483e12c5d1SDavid du Colombier 				continue;
13493e12c5d1SDavid du Colombier 			}
13503e12c5d1SDavid du Colombier 			break;
13513e12c5d1SDavid du Colombier 		}
13523e12c5d1SDavid du Colombier 		continue;
13533e12c5d1SDavid du Colombier 
13543e12c5d1SDavid du Colombier 	case LCURLY:
13553e12c5d1SDavid du Colombier 		defout(0);
13563e12c5d1SDavid du Colombier 		cpycode();
13573e12c5d1SDavid du Colombier 		t = gettok();
13583e12c5d1SDavid du Colombier 		continue;
13593e12c5d1SDavid du Colombier 
13603e12c5d1SDavid du Colombier 	default:
13613e12c5d1SDavid du Colombier 		error("syntax error");
13623e12c5d1SDavid du Colombier 	}
13633e12c5d1SDavid du Colombier 	if(t == ENDFILE)
13643e12c5d1SDavid du Colombier 		error("unexpected EOF before %%");
13653e12c5d1SDavid du Colombier 
13663e12c5d1SDavid du Colombier 	/* t is MARK */
13673e12c5d1SDavid du Colombier 	Bprint(ftable, "extern	int	yyerrflag;\n");
13683e12c5d1SDavid du Colombier 	Bprint(ftable, "#ifndef	YYMAXDEPTH\n");
13693e12c5d1SDavid du Colombier 	Bprint(ftable, "#define	YYMAXDEPTH	150\n");
13703e12c5d1SDavid du Colombier 	Bprint(ftable, "#endif\n" );
13713e12c5d1SDavid du Colombier 	if(!ntypes) {
13723e12c5d1SDavid du Colombier 		Bprint(ftable, "#ifndef	YYSTYPE\n");
13733e12c5d1SDavid du Colombier 		Bprint(ftable, "#define	YYSTYPE	int\n");
13743e12c5d1SDavid du Colombier 		Bprint(ftable, "#endif\n");
13753e12c5d1SDavid du Colombier 	}
13763e12c5d1SDavid du Colombier 	Bprint(ftable, "YYSTYPE	yylval;\n");
13773e12c5d1SDavid du Colombier 	Bprint(ftable, "YYSTYPE	yyval;\n");
13783e12c5d1SDavid du Colombier 
13793e12c5d1SDavid du Colombier 	prdptr[0] = mem;
13803e12c5d1SDavid du Colombier 
13813e12c5d1SDavid du Colombier 	/* added production */
13823e12c5d1SDavid du Colombier 	*mem++ = NTBASE;
13833e12c5d1SDavid du Colombier 
13843e12c5d1SDavid du Colombier 	/* if start is 0, we will overwrite with the lhs of the first rule */
13853e12c5d1SDavid du Colombier 	*mem++ = start;
13863e12c5d1SDavid du Colombier 	*mem++ = 1;
13873e12c5d1SDavid du Colombier 	*mem++ = 0;
13883e12c5d1SDavid du Colombier 	prdptr[1] = mem;
13893e12c5d1SDavid du Colombier 	while((t=gettok()) == LCURLY)
13903e12c5d1SDavid du Colombier 		cpycode();
13913e12c5d1SDavid du Colombier 	if(t != IDENTCOLON)
13923e12c5d1SDavid du Colombier 		error("bad syntax on first rule");
13933e12c5d1SDavid du Colombier 
13943e12c5d1SDavid du Colombier 	if(!start)
13953e12c5d1SDavid du Colombier 		prdptr[0][1] = chfind(1, tokname);
13963e12c5d1SDavid du Colombier 
13973e12c5d1SDavid du Colombier 	/* read rules */
13983e12c5d1SDavid du Colombier 	while(t != MARK && t != ENDFILE) {
13993e12c5d1SDavid du Colombier 		/* process a rule */
14003e12c5d1SDavid du Colombier 		rlines[nprod] = lineno;
14013e12c5d1SDavid du Colombier 		if(t == '|')
14023e12c5d1SDavid du Colombier 			*mem++ = *prdptr[nprod-1];
14033e12c5d1SDavid du Colombier 		else
14043e12c5d1SDavid du Colombier 			if(t == IDENTCOLON) {
14053e12c5d1SDavid du Colombier 				*mem = chfind(1, tokname);
14063e12c5d1SDavid du Colombier 				if(*mem < NTBASE)
14073e12c5d1SDavid du Colombier 					error("token illegal on LHS of grammar rule");
14083e12c5d1SDavid du Colombier 				mem++;
14093e12c5d1SDavid du Colombier 			} else
14103e12c5d1SDavid du Colombier 				error("illegal rule: missing semicolon or | ?");
14113e12c5d1SDavid du Colombier 		/* read rule body */
14123e12c5d1SDavid du Colombier 		t = gettok();
14133e12c5d1SDavid du Colombier 
14143e12c5d1SDavid du Colombier 	more_rule:
14153e12c5d1SDavid du Colombier 		while(t == IDENTIFIER) {
14163e12c5d1SDavid du Colombier 			*mem = chfind(1, tokname);
14173e12c5d1SDavid du Colombier 			if(*mem < NTBASE)
14183e12c5d1SDavid du Colombier 				levprd[nprod] = toklev[*mem];
14193e12c5d1SDavid du Colombier 			mem++;
14203e12c5d1SDavid du Colombier 			t = gettok();
14213e12c5d1SDavid du Colombier 		}
14223e12c5d1SDavid du Colombier 		if(t == PREC) {
14233e12c5d1SDavid du Colombier 			if(gettok() != IDENTIFIER)
14243e12c5d1SDavid du Colombier 				error("illegal %%prec syntax");
14253e12c5d1SDavid du Colombier 			j = chfind(2, tokname);
14263e12c5d1SDavid du Colombier 			if(j >= NTBASE)
14273e12c5d1SDavid du Colombier 				error("nonterminal %s illegal after %%prec",
14283e12c5d1SDavid du Colombier 					nontrst[j-NTBASE].name);
14293e12c5d1SDavid du Colombier 			levprd[nprod] = toklev[j];
14303e12c5d1SDavid du Colombier 			t = gettok();
14313e12c5d1SDavid du Colombier 		}
14323e12c5d1SDavid du Colombier 		if(t == '=') {
14333e12c5d1SDavid du Colombier 			levprd[nprod] |= ACTFLAG;
14343e12c5d1SDavid du Colombier 			Bprint(faction, "\ncase %d:", nprod);
14353e12c5d1SDavid du Colombier 			cpyact(mem-prdptr[nprod]-1);
14363e12c5d1SDavid du Colombier 			Bprint(faction, " break;");
14373e12c5d1SDavid du Colombier 			if((t=gettok()) == IDENTIFIER) {
14383e12c5d1SDavid du Colombier 
14393e12c5d1SDavid du Colombier 				/* action within rule... */
14403e12c5d1SDavid du Colombier 				sprint(actnm, "$$%d", nprod);
14413e12c5d1SDavid du Colombier 
14423e12c5d1SDavid du Colombier 				/* make it a nonterminal */
14433e12c5d1SDavid du Colombier 				j = chfind(1, actnm);
14443e12c5d1SDavid du Colombier 
14453e12c5d1SDavid du Colombier 				/*
14463e12c5d1SDavid du Colombier 				 * the current rule will become rule number nprod+1
14473e12c5d1SDavid du Colombier 				 * move the contents down, and make room for the null
14483e12c5d1SDavid du Colombier 				 */
14493e12c5d1SDavid du Colombier 				for(p = mem; p >= prdptr[nprod]; --p)
14503e12c5d1SDavid du Colombier 					p[2] = *p;
14513e12c5d1SDavid du Colombier 				mem += 2;
14523e12c5d1SDavid du Colombier 
14533e12c5d1SDavid du Colombier 				/* enter null production for action */
14543e12c5d1SDavid du Colombier 				p = prdptr[nprod];
14553e12c5d1SDavid du Colombier 				*p++ = j;
14563e12c5d1SDavid du Colombier 				*p++ = -nprod;
14573e12c5d1SDavid du Colombier 
14583e12c5d1SDavid du Colombier 				/* update the production information */
14593e12c5d1SDavid du Colombier 				levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
14603e12c5d1SDavid du Colombier 				levprd[nprod] = ACTFLAG;
14613e12c5d1SDavid du Colombier 				if(++nprod >= NPROD)
14623e12c5d1SDavid du Colombier 					error("more than %d rules", NPROD);
14633e12c5d1SDavid du Colombier 				prdptr[nprod] = p;
14643e12c5d1SDavid du Colombier 
14653e12c5d1SDavid du Colombier 				/* make the action appear in the original rule */
14663e12c5d1SDavid du Colombier 				*mem++ = j;
14673e12c5d1SDavid du Colombier 
14683e12c5d1SDavid du Colombier 				/* get some more of the rule */
14693e12c5d1SDavid du Colombier 				goto more_rule;
14703e12c5d1SDavid du Colombier 			}
14713e12c5d1SDavid du Colombier 		}
14723e12c5d1SDavid du Colombier 
14733e12c5d1SDavid du Colombier 		while(t == ';')
14743e12c5d1SDavid du Colombier 			t = gettok();
14753e12c5d1SDavid du Colombier 		*mem++ = -nprod;
14763e12c5d1SDavid du Colombier 
14773e12c5d1SDavid du Colombier 		/* check that default action is reasonable */
14783e12c5d1SDavid du Colombier 		if(ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].value) {
14793e12c5d1SDavid du Colombier 
14803e12c5d1SDavid du Colombier 			/* no explicit action, LHS has value */
14813e12c5d1SDavid du Colombier 			int tempty;
14823e12c5d1SDavid du Colombier 
14833e12c5d1SDavid du Colombier 			tempty = prdptr[nprod][1];
14843e12c5d1SDavid du Colombier 			if(tempty < 0)
14853e12c5d1SDavid du Colombier 				error("must return a value, since LHS has a type");
14863e12c5d1SDavid du Colombier 			else
14873e12c5d1SDavid du Colombier 				if(tempty >= NTBASE)
14883e12c5d1SDavid du Colombier 					tempty = nontrst[tempty-NTBASE].value;
14893e12c5d1SDavid du Colombier 				else
14903e12c5d1SDavid du Colombier 					tempty = TYPE(toklev[tempty]);
14913e12c5d1SDavid du Colombier 			if(tempty != nontrst[*prdptr[nprod]-NTBASE].value)
14923e12c5d1SDavid du Colombier 				error("default action causes potential type clash");
14933e12c5d1SDavid du Colombier 		}
14943e12c5d1SDavid du Colombier 		nprod++;
14953e12c5d1SDavid du Colombier 		if(nprod >= NPROD)
14963e12c5d1SDavid du Colombier 			error("more than %d rules", NPROD);
14973e12c5d1SDavid du Colombier 		prdptr[nprod] = mem;
14983e12c5d1SDavid du Colombier 		levprd[nprod] = 0;
14993e12c5d1SDavid du Colombier 	}
15003e12c5d1SDavid du Colombier 
15013e12c5d1SDavid du Colombier 	/* end of all rules */
15023e12c5d1SDavid du Colombier 	defout(1);
15033e12c5d1SDavid du Colombier 
15043e12c5d1SDavid du Colombier 	finact();
15053e12c5d1SDavid du Colombier 	if(t == MARK) {
15063e12c5d1SDavid du Colombier 		Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
15073e12c5d1SDavid du Colombier 		while((c=Bgetrune(finput)) != Beof)
15083e12c5d1SDavid du Colombier 			Bputrune(ftable, c);
15093e12c5d1SDavid du Colombier 	}
1510219b2ee8SDavid du Colombier 	Bterm(finput);
15113e12c5d1SDavid du Colombier }
15123e12c5d1SDavid du Colombier 
15133e12c5d1SDavid du Colombier /*
15143e12c5d1SDavid du Colombier  * finish action routine
15153e12c5d1SDavid du Colombier  */
15163e12c5d1SDavid du Colombier void
finact(void)15173e12c5d1SDavid du Colombier finact(void)
15183e12c5d1SDavid du Colombier {
15193e12c5d1SDavid du Colombier 
1520219b2ee8SDavid du Colombier 	Bterm(faction);
1521bd389b36SDavid du Colombier 	Bprint(ftable, "#define YYEOFCODE %d\n", 1);
1522bd389b36SDavid du Colombier 	Bprint(ftable, "#define YYERRCODE %d\n", 2);
15233e12c5d1SDavid du Colombier }
15243e12c5d1SDavid du Colombier 
15253e12c5d1SDavid du Colombier /*
15263e12c5d1SDavid du Colombier  * define s to be a terminal if t=0
15273e12c5d1SDavid du Colombier  * or a nonterminal if t=1
15283e12c5d1SDavid du Colombier  */
15293e12c5d1SDavid du Colombier int
defin(int nt,char * s)15303e12c5d1SDavid du Colombier defin(int nt, char *s)
15313e12c5d1SDavid du Colombier {
15323e12c5d1SDavid du Colombier 	int val;
15333e12c5d1SDavid du Colombier 	Rune rune;
15343e12c5d1SDavid du Colombier 
15353e12c5d1SDavid du Colombier 	val = 0;
15363e12c5d1SDavid du Colombier 	if(nt) {
15373e12c5d1SDavid du Colombier 		nnonter++;
15383e12c5d1SDavid du Colombier 		if(nnonter >= NNONTERM)
15393e12c5d1SDavid du Colombier 			error("too many nonterminals, limit %d",NNONTERM);
15403e12c5d1SDavid du Colombier 		nontrst[nnonter].name = cstash(s);
15413e12c5d1SDavid du Colombier 		return NTBASE + nnonter;
15423e12c5d1SDavid du Colombier 	}
15433e12c5d1SDavid du Colombier 
15443e12c5d1SDavid du Colombier 	/* must be a token */
15453e12c5d1SDavid du Colombier 	ntokens++;
15463e12c5d1SDavid du Colombier 	if(ntokens >= NTERMS)
15473e12c5d1SDavid du Colombier 		error("too many terminals, limit %d", NTERMS);
15483e12c5d1SDavid du Colombier 	tokset[ntokens].name = cstash(s);
15493e12c5d1SDavid du Colombier 
15503e12c5d1SDavid du Colombier 	/* establish value for token */
15513e12c5d1SDavid du Colombier 	/* single character literal */
15523e12c5d1SDavid du Colombier 	if(s[0] == ' ') {
15533e12c5d1SDavid du Colombier 		val = chartorune(&rune, &s[1]);
15543e12c5d1SDavid du Colombier 		if(s[val+1] == 0) {
15553e12c5d1SDavid du Colombier 			val = rune;
15563e12c5d1SDavid du Colombier 			goto out;
15573e12c5d1SDavid du Colombier 		}
15583e12c5d1SDavid du Colombier 	}
15593e12c5d1SDavid du Colombier 
15603e12c5d1SDavid du Colombier 	/* escape sequence */
1561bd389b36SDavid du Colombier 	if(s[0] == ' ' && s[1] == '\\') {
1562bd389b36SDavid du Colombier 		if(s[3] == 0) {
15633e12c5d1SDavid du Colombier 			/* single character escape sequence */
15643e12c5d1SDavid du Colombier 			switch(s[2]) {
15653e12c5d1SDavid du Colombier 			case 'n':	val = '\n'; break;
15663e12c5d1SDavid du Colombier 			case 'r':	val = '\r'; break;
15673e12c5d1SDavid du Colombier 			case 'b':	val = '\b'; break;
15683e12c5d1SDavid du Colombier 			case 't':	val = '\t'; break;
15693e12c5d1SDavid du Colombier 			case 'f':	val = '\f'; break;
15703e12c5d1SDavid du Colombier 			case '\'':	val = '\''; break;
15713e12c5d1SDavid du Colombier 			case '"':	val = '"'; break;
15723e12c5d1SDavid du Colombier 			case '\\':	val = '\\'; break;
15733e12c5d1SDavid du Colombier 			default:	error("invalid escape");
15743e12c5d1SDavid du Colombier 			}
15753e12c5d1SDavid du Colombier 			goto out;
15763e12c5d1SDavid du Colombier 		}
15773e12c5d1SDavid du Colombier 
15783e12c5d1SDavid du Colombier 		/* \nnn sequence */
15793e12c5d1SDavid du Colombier 		if(s[2] >= '0' && s[2] <= '7') {
15803e12c5d1SDavid du Colombier 			if(s[3] < '0' ||
15813e12c5d1SDavid du Colombier 			   s[3] > '7' ||
15823e12c5d1SDavid du Colombier 			   s[4] < '0' ||
15833e12c5d1SDavid du Colombier 			   s[4] > '7' ||
15843e12c5d1SDavid du Colombier 			   s[5] != 0)
15853e12c5d1SDavid du Colombier 				error("illegal \\nnn construction");
15863e12c5d1SDavid du Colombier 			val = 64*s[2] + 8*s[3] + s[4] - 73*'0';
15873e12c5d1SDavid du Colombier 			if(val == 0)
15883e12c5d1SDavid du Colombier 				error("'\\000' is illegal");
15893e12c5d1SDavid du Colombier 			goto out;
15903e12c5d1SDavid du Colombier 		}
1591bd389b36SDavid du Colombier 		error("unknown escape");
1592bd389b36SDavid du Colombier 	}
15933e12c5d1SDavid du Colombier 	val = extval++;
15943e12c5d1SDavid du Colombier 
15953e12c5d1SDavid du Colombier out:
15963e12c5d1SDavid du Colombier 	tokset[ntokens].value = val;
15973e12c5d1SDavid du Colombier 	toklev[ntokens] = 0;
15983e12c5d1SDavid du Colombier 	return ntokens;
15993e12c5d1SDavid du Colombier }
16003e12c5d1SDavid du Colombier 
16013e12c5d1SDavid du Colombier /*
16023e12c5d1SDavid du Colombier  * write out the defines (at the end of the declaration section)
16033e12c5d1SDavid du Colombier  */
16043e12c5d1SDavid du Colombier void
defout(int last)16053e12c5d1SDavid du Colombier defout(int last)
16063e12c5d1SDavid du Colombier {
16073e12c5d1SDavid du Colombier 	int i, c;
16083e12c5d1SDavid du Colombier 	char sar[NAMESIZE+10];
16093e12c5d1SDavid du Colombier 
16103e12c5d1SDavid du Colombier 	for(i=ndefout; i<=ntokens; i++) {
16113e12c5d1SDavid du Colombier 		/* non-literals */
16123e12c5d1SDavid du Colombier 		c = tokset[i].name[0];
16133e12c5d1SDavid du Colombier 		if(c != ' ' && c != '$') {
16143e12c5d1SDavid du Colombier 			Bprint(ftable, "#define	%s	%d\n",
16153e12c5d1SDavid du Colombier 				tokset[i].name, tokset[i].value);
16163e12c5d1SDavid du Colombier 			if(fdefine)
16173e12c5d1SDavid du Colombier 				Bprint(fdefine, "#define\t%s\t%d\n",
16183e12c5d1SDavid du Colombier 					tokset[i].name, tokset[i].value);
16193e12c5d1SDavid du Colombier 		}
16203e12c5d1SDavid du Colombier 	}
16213e12c5d1SDavid du Colombier 	ndefout = ntokens+1;
16223e12c5d1SDavid du Colombier 	if(last && fdebug) {
16233e12c5d1SDavid du Colombier 		Bprint(fdebug, "char*	yytoknames[] =\n{\n");
16243e12c5d1SDavid du Colombier 		TLOOP(i) {
16253e12c5d1SDavid du Colombier 			if(tokset[i].name) {
16263e12c5d1SDavid du Colombier 				chcopy(sar, tokset[i].name);
16273e12c5d1SDavid du Colombier 				Bprint(fdebug, "\t\"%s\",\n", sar);
16283e12c5d1SDavid du Colombier 				continue;
16293e12c5d1SDavid du Colombier 			}
16303e12c5d1SDavid du Colombier 			Bprint(fdebug, "\t0,\n");
16313e12c5d1SDavid du Colombier 		}
16323e12c5d1SDavid du Colombier 		Bprint(fdebug, "};\n");
16333e12c5d1SDavid du Colombier 	}
16343e12c5d1SDavid du Colombier }
16353e12c5d1SDavid du Colombier 
16363e12c5d1SDavid du Colombier char*
cstash(char * s)16373e12c5d1SDavid du Colombier cstash(char *s)
16383e12c5d1SDavid du Colombier {
16393e12c5d1SDavid du Colombier 	char *temp;
16403e12c5d1SDavid du Colombier 
16413e12c5d1SDavid du Colombier 	temp = cnamp;
16423e12c5d1SDavid du Colombier 	do {
16433e12c5d1SDavid du Colombier 		if(cnamp >= &cnames[cnamsz])
16443e12c5d1SDavid du Colombier 			error("too many characters in id's and literals");
16453e12c5d1SDavid du Colombier 		else
16463e12c5d1SDavid du Colombier 			*cnamp++ = *s;
16473e12c5d1SDavid du Colombier 	} while(*s++);
16483e12c5d1SDavid du Colombier 	return temp;
16493e12c5d1SDavid du Colombier }
16503e12c5d1SDavid du Colombier 
16513e12c5d1SDavid du Colombier long
gettok(void)16523e12c5d1SDavid du Colombier gettok(void)
16533e12c5d1SDavid du Colombier {
16543e12c5d1SDavid du Colombier 	long c;
16553e12c5d1SDavid du Colombier 	Rune rune;
16563e12c5d1SDavid du Colombier 	int i, base, match, reserve;
16573e12c5d1SDavid du Colombier 	static int peekline;
16583e12c5d1SDavid du Colombier 
16593e12c5d1SDavid du Colombier begin:
16603e12c5d1SDavid du Colombier 	reserve = 0;
16613e12c5d1SDavid du Colombier 	lineno += peekline;
16623e12c5d1SDavid du Colombier 	peekline = 0;
16633e12c5d1SDavid du Colombier 	c = Bgetrune(finput);
16643e12c5d1SDavid du Colombier 	while(c == ' ' || c == '\n' || c == '\t' || c == '\f') {
16653e12c5d1SDavid du Colombier 		if(c == '\n')
16663e12c5d1SDavid du Colombier 			lineno++;
16673e12c5d1SDavid du Colombier 		c = Bgetrune(finput);
16683e12c5d1SDavid du Colombier 	}
16693e12c5d1SDavid du Colombier 
16703e12c5d1SDavid du Colombier 	/* skip comment */
16713e12c5d1SDavid du Colombier 	if(c == '/') {
16723e12c5d1SDavid du Colombier 		lineno += skipcom();
16733e12c5d1SDavid du Colombier 		goto begin;
16743e12c5d1SDavid du Colombier 	}
16753e12c5d1SDavid du Colombier 	switch(c) {
16763e12c5d1SDavid du Colombier 	case Beof:
16773e12c5d1SDavid du Colombier 		return ENDFILE;
16783e12c5d1SDavid du Colombier 
16793e12c5d1SDavid du Colombier 	case '{':
16803e12c5d1SDavid du Colombier 		Bungetrune(finput);
16813e12c5d1SDavid du Colombier 		return '=';
16823e12c5d1SDavid du Colombier 
16833e12c5d1SDavid du Colombier 	case '<':
16843e12c5d1SDavid du Colombier 		/* get, and look up, a type name (union member name) */
16853e12c5d1SDavid du Colombier 		i = 0;
16863e12c5d1SDavid du Colombier 		while((c=Bgetrune(finput)) != '>' && c >= 0 && c != '\n') {
16873e12c5d1SDavid du Colombier 			rune = c;
16883e12c5d1SDavid du Colombier 			c = runetochar(&tokname[i], &rune);
16893e12c5d1SDavid du Colombier 			if(i < NAMESIZE)
16903e12c5d1SDavid du Colombier 				i += c;
16913e12c5d1SDavid du Colombier 		}
16923e12c5d1SDavid du Colombier 		if(c != '>')
16933e12c5d1SDavid du Colombier 			error("unterminated < ... > clause");
16943e12c5d1SDavid du Colombier 		tokname[i] = 0;
16953e12c5d1SDavid du Colombier 		for(i=1; i<=ntypes; i++)
16963e12c5d1SDavid du Colombier 			if(!strcmp(typeset[i], tokname)) {
16973e12c5d1SDavid du Colombier 				numbval = i;
16983e12c5d1SDavid du Colombier 				return TYPENAME;
16993e12c5d1SDavid du Colombier 			}
17003e12c5d1SDavid du Colombier 		ntypes++;
17013e12c5d1SDavid du Colombier 		numbval = ntypes;
17023e12c5d1SDavid du Colombier 		typeset[numbval] = cstash(tokname);
17033e12c5d1SDavid du Colombier 		return TYPENAME;
17043e12c5d1SDavid du Colombier 
17053e12c5d1SDavid du Colombier 	case '"':
17063e12c5d1SDavid du Colombier 	case '\'':
17073e12c5d1SDavid du Colombier 		match = c;
17083e12c5d1SDavid du Colombier 		tokname[0] = ' ';
17093e12c5d1SDavid du Colombier 		i = 1;
17103e12c5d1SDavid du Colombier 		for(;;) {
17113e12c5d1SDavid du Colombier 			c = Bgetrune(finput);
17123e12c5d1SDavid du Colombier 			if(c == '\n' || c <= 0)
17133e12c5d1SDavid du Colombier 				error("illegal or missing ' or \"" );
17143e12c5d1SDavid du Colombier 			if(c == '\\') {
17153e12c5d1SDavid du Colombier 				tokname[i] = '\\';
17163e12c5d1SDavid du Colombier 				if(i < NAMESIZE)
17173e12c5d1SDavid du Colombier 					i++;
17183e12c5d1SDavid du Colombier 				c = Bgetrune(finput);
17193e12c5d1SDavid du Colombier 			} else
17203e12c5d1SDavid du Colombier 				if(c == match)
17213e12c5d1SDavid du Colombier 					break;
17223e12c5d1SDavid du Colombier 			rune = c;
17233e12c5d1SDavid du Colombier 			c = runetochar(&tokname[i], &rune);
17243e12c5d1SDavid du Colombier 			if(i < NAMESIZE)
17253e12c5d1SDavid du Colombier 				i += c;
17263e12c5d1SDavid du Colombier 		}
17273e12c5d1SDavid du Colombier 		break;
17283e12c5d1SDavid du Colombier 
17293e12c5d1SDavid du Colombier 	case '%':
17303e12c5d1SDavid du Colombier 	case '\\':
17313e12c5d1SDavid du Colombier 		switch(c = Bgetrune(finput)) {
17323e12c5d1SDavid du Colombier 		case '0':	return TERM;
17333e12c5d1SDavid du Colombier 		case '<':	return LEFT;
17343e12c5d1SDavid du Colombier 		case '2':	return BINARY;
17353e12c5d1SDavid du Colombier 		case '>':	return RIGHT;
17363e12c5d1SDavid du Colombier 		case '%':
17373e12c5d1SDavid du Colombier 		case '\\':	return MARK;
17383e12c5d1SDavid du Colombier 		case '=':	return PREC;
17393e12c5d1SDavid du Colombier 		case '{':	return LCURLY;
17403e12c5d1SDavid du Colombier 		default:	reserve = 1;
17413e12c5d1SDavid du Colombier 		}
17423e12c5d1SDavid du Colombier 
17433e12c5d1SDavid du Colombier 	default:
17443e12c5d1SDavid du Colombier 		/* number */
17453e12c5d1SDavid du Colombier 		if(isdigit(c)) {
17463e12c5d1SDavid du Colombier 			numbval = c-'0';
17473e12c5d1SDavid du Colombier 			base = (c=='0')? 8: 10;
17483e12c5d1SDavid du Colombier 			for(c = Bgetrune(finput); isdigit(c); c = Bgetrune(finput))
17493e12c5d1SDavid du Colombier 				numbval = numbval*base + (c-'0');
17503e12c5d1SDavid du Colombier 			Bungetrune(finput);
17513e12c5d1SDavid du Colombier 			return NUMBER;
17523e12c5d1SDavid du Colombier 		}
17533e12c5d1SDavid du Colombier 		if(islower(c) || isupper(c) || c=='_' || c=='.' || c=='$')  {
17543e12c5d1SDavid du Colombier 			i = 0;
17553e12c5d1SDavid du Colombier 			while(islower(c) || isupper(c) || isdigit(c) ||
17563e12c5d1SDavid du Colombier 			    c == '-' || c=='_' || c=='.' || c=='$') {
17573e12c5d1SDavid du Colombier 				if(reserve && isupper(c))
17583e12c5d1SDavid du Colombier 					c += 'a'-'A';
17593e12c5d1SDavid du Colombier 				rune = c;
17603e12c5d1SDavid du Colombier 				c = runetochar(&tokname[i], &rune);
17613e12c5d1SDavid du Colombier 				if(i < NAMESIZE)
17623e12c5d1SDavid du Colombier 					i += c;
17633e12c5d1SDavid du Colombier 				c = Bgetrune(finput);
17643e12c5d1SDavid du Colombier 			}
17653e12c5d1SDavid du Colombier 		} else
17663e12c5d1SDavid du Colombier 			return c;
17673e12c5d1SDavid du Colombier 		Bungetrune(finput);
17683e12c5d1SDavid du Colombier 	}
17693e12c5d1SDavid du Colombier 	tokname[i] = 0;
17703e12c5d1SDavid du Colombier 
17713e12c5d1SDavid du Colombier 	/* find a reserved word */
17723e12c5d1SDavid du Colombier 	if(reserve) {
17733e12c5d1SDavid du Colombier 		for(c=0; resrv[c].name; c++)
17743e12c5d1SDavid du Colombier 			if(strcmp(tokname, resrv[c].name) == 0)
17753e12c5d1SDavid du Colombier 				return resrv[c].value;
17763e12c5d1SDavid du Colombier 		error("invalid escape, or illegal reserved word: %s", tokname);
17773e12c5d1SDavid du Colombier 	}
17783e12c5d1SDavid du Colombier 
17793e12c5d1SDavid du Colombier 	/* look ahead to distinguish IDENTIFIER from IDENTCOLON */
17803e12c5d1SDavid du Colombier 	c = Bgetrune(finput);
17813e12c5d1SDavid du Colombier 	while(c == ' ' || c == '\t'|| c == '\n' || c == '\f' || c == '/') {
17823e12c5d1SDavid du Colombier 		if(c == '\n')
17833e12c5d1SDavid du Colombier 			peekline++;
17843e12c5d1SDavid du Colombier 		/* look for comments */
17853e12c5d1SDavid du Colombier 		if(c == '/')
17863e12c5d1SDavid du Colombier 			peekline += skipcom();
17873e12c5d1SDavid du Colombier 		c = Bgetrune(finput);
17883e12c5d1SDavid du Colombier 	}
17893e12c5d1SDavid du Colombier 	if(c == ':')
17903e12c5d1SDavid du Colombier 		return IDENTCOLON;
17913e12c5d1SDavid du Colombier 	Bungetrune(finput);
17923e12c5d1SDavid du Colombier 	return IDENTIFIER;
17933e12c5d1SDavid du Colombier }
17943e12c5d1SDavid du Colombier 
17953e12c5d1SDavid du Colombier /*
17963e12c5d1SDavid du Colombier  * determine the type of a symbol
17973e12c5d1SDavid du Colombier  */
17983e12c5d1SDavid du Colombier int
fdtype(int t)17993e12c5d1SDavid du Colombier fdtype(int t)
18003e12c5d1SDavid du Colombier {
18013e12c5d1SDavid du Colombier 	int v;
18023e12c5d1SDavid du Colombier 
18033e12c5d1SDavid du Colombier 	if(t >= NTBASE)
18043e12c5d1SDavid du Colombier 		v = nontrst[t-NTBASE].value;
18053e12c5d1SDavid du Colombier 	else
18063e12c5d1SDavid du Colombier 		v = TYPE(toklev[t]);
18073e12c5d1SDavid du Colombier 	if(v <= 0)
18083e12c5d1SDavid du Colombier 		error("must specify type for %s", (t>=NTBASE)?
18093e12c5d1SDavid du Colombier 			nontrst[t-NTBASE].name: tokset[t].name);
18103e12c5d1SDavid du Colombier 	return v;
18113e12c5d1SDavid du Colombier }
18123e12c5d1SDavid du Colombier 
18133e12c5d1SDavid du Colombier int
chfind(int t,char * s)18143e12c5d1SDavid du Colombier chfind(int t, char *s)
18153e12c5d1SDavid du Colombier {
18163e12c5d1SDavid du Colombier 	int i;
18173e12c5d1SDavid du Colombier 
18183e12c5d1SDavid du Colombier 	if(s[0] == ' ')
18193e12c5d1SDavid du Colombier 		t = 0;
18203e12c5d1SDavid du Colombier 	TLOOP(i)
18213e12c5d1SDavid du Colombier 		if(!strcmp(s, tokset[i].name))
18223e12c5d1SDavid du Colombier 			return i;
18233e12c5d1SDavid du Colombier 	NTLOOP(i)
18243e12c5d1SDavid du Colombier 		if(!strcmp(s, nontrst[i].name))
18253e12c5d1SDavid du Colombier 			return NTBASE+i;
18263e12c5d1SDavid du Colombier 
18273e12c5d1SDavid du Colombier 	/* cannot find name */
18283e12c5d1SDavid du Colombier 	if(t > 1)
18293e12c5d1SDavid du Colombier 		error("%s should have been defined earlier", s);
18303e12c5d1SDavid du Colombier 	return defin(t, s);
18313e12c5d1SDavid du Colombier }
18323e12c5d1SDavid du Colombier 
18333e12c5d1SDavid du Colombier /*
18343e12c5d1SDavid du Colombier  * copy the union declaration to the output, and the define file if present
18353e12c5d1SDavid du Colombier  */
18363e12c5d1SDavid du Colombier void
cpyunion(void)18373e12c5d1SDavid du Colombier cpyunion(void)
18383e12c5d1SDavid du Colombier {
18393e12c5d1SDavid du Colombier 	long c;
18403e12c5d1SDavid du Colombier 	int level;
18413e12c5d1SDavid du Colombier 
18423e12c5d1SDavid du Colombier 	Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
18433e12c5d1SDavid du Colombier 	Bprint(ftable, "typedef union ");
18443e12c5d1SDavid du Colombier 	if(fdefine != 0)
18453e12c5d1SDavid du Colombier 		Bprint(fdefine, "\ntypedef union ");
18463e12c5d1SDavid du Colombier 
18473e12c5d1SDavid du Colombier 	level = 0;
18483e12c5d1SDavid du Colombier 	for(;;) {
18493e12c5d1SDavid du Colombier 		if((c=Bgetrune(finput)) == Beof)
18503e12c5d1SDavid du Colombier 			error("EOF encountered while processing %%union");
18513e12c5d1SDavid du Colombier 		Bputrune(ftable, c);
18523e12c5d1SDavid du Colombier 		if(fdefine != 0)
18533e12c5d1SDavid du Colombier 			Bputrune(fdefine, c);
18543e12c5d1SDavid du Colombier 		switch(c) {
18553e12c5d1SDavid du Colombier 		case '\n':
18563e12c5d1SDavid du Colombier 			lineno++;
18573e12c5d1SDavid du Colombier 			break;
18583e12c5d1SDavid du Colombier 		case '{':
18593e12c5d1SDavid du Colombier 			level++;
18603e12c5d1SDavid du Colombier 			break;
18613e12c5d1SDavid du Colombier 		case '}':
18623e12c5d1SDavid du Colombier 			level--;
18633e12c5d1SDavid du Colombier 
18643e12c5d1SDavid du Colombier 			/* we are finished copying */
18653e12c5d1SDavid du Colombier 			if(level == 0) {
18663e12c5d1SDavid du Colombier 				Bprint(ftable, " YYSTYPE;\n");
18673e12c5d1SDavid du Colombier 				if(fdefine != 0)
18683e12c5d1SDavid du Colombier 					Bprint(fdefine, "\tYYSTYPE;\nextern\tYYSTYPE\tyylval;\n");
18693e12c5d1SDavid du Colombier 				return;
18703e12c5d1SDavid du Colombier 			}
18713e12c5d1SDavid du Colombier 		}
18723e12c5d1SDavid du Colombier 	}
18733e12c5d1SDavid du Colombier }
18743e12c5d1SDavid du Colombier 
18753e12c5d1SDavid du Colombier /*
18763e12c5d1SDavid du Colombier  * copies code between \{ and \}
18773e12c5d1SDavid du Colombier  */
18783e12c5d1SDavid du Colombier void
cpycode(void)18793e12c5d1SDavid du Colombier cpycode(void)
18803e12c5d1SDavid du Colombier {
18813e12c5d1SDavid du Colombier 
18823e12c5d1SDavid du Colombier 	long c;
18833e12c5d1SDavid du Colombier 
18843e12c5d1SDavid du Colombier 	c = Bgetrune(finput);
18853e12c5d1SDavid du Colombier 	if(c == '\n') {
18863e12c5d1SDavid du Colombier 		c = Bgetrune(finput);
18873e12c5d1SDavid du Colombier 		lineno++;
18883e12c5d1SDavid du Colombier 	}
18893e12c5d1SDavid du Colombier 	Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
18903e12c5d1SDavid du Colombier 	while(c != Beof) {
18913e12c5d1SDavid du Colombier 		if(c == '\\') {
18923e12c5d1SDavid du Colombier 			if((c=Bgetrune(finput)) == '}')
18933e12c5d1SDavid du Colombier 				return;
18943e12c5d1SDavid du Colombier 			Bputc(ftable, '\\');
18953e12c5d1SDavid du Colombier 		}
18963e12c5d1SDavid du Colombier 		if(c == '%') {
18973e12c5d1SDavid du Colombier 			if((c=Bgetrune(finput)) == '}')
18983e12c5d1SDavid du Colombier 				return;
18993e12c5d1SDavid du Colombier 			Bputc(ftable, '%');
19003e12c5d1SDavid du Colombier 		}
19013e12c5d1SDavid du Colombier 		Bputrune(ftable, c);
19023e12c5d1SDavid du Colombier 		if(c == '\n')
19033e12c5d1SDavid du Colombier 			lineno++;
19043e12c5d1SDavid du Colombier 		c = Bgetrune(finput);
19053e12c5d1SDavid du Colombier 	}
19063e12c5d1SDavid du Colombier 	error("eof before %%}");
19073e12c5d1SDavid du Colombier }
19083e12c5d1SDavid du Colombier 
19093e12c5d1SDavid du Colombier /*
19103e12c5d1SDavid du Colombier  * skip over comments
19113e12c5d1SDavid du Colombier  * skipcom is called after reading a '/'
19123e12c5d1SDavid du Colombier  */
19133e12c5d1SDavid du Colombier int
skipcom(void)19143e12c5d1SDavid du Colombier skipcom(void)
19153e12c5d1SDavid du Colombier {
19163e12c5d1SDavid du Colombier 	long c;
19173e12c5d1SDavid du Colombier 	int i;
19183e12c5d1SDavid du Colombier 
19193e12c5d1SDavid du Colombier 	/* i is the number of lines skipped */
19203e12c5d1SDavid du Colombier 	i = 0;
19213e12c5d1SDavid du Colombier 	c = Bgetrune(finput);
192243aadf5eSDavid du Colombier 	if(c == '/'){			/* C++ //: skip to end of line */
192343aadf5eSDavid du Colombier 		while((c = Bgetrune(finput)) != Beof)
192443aadf5eSDavid du Colombier 			if(c == '\n')
192543aadf5eSDavid du Colombier 				return 1;
192643aadf5eSDavid du Colombier 	}else if(c == '*'){		/* normal C comment */
192743aadf5eSDavid du Colombier 		while((c = Bgetrune(finput)) != Beof) {
19283e12c5d1SDavid du Colombier 			while(c == '*')
19293e12c5d1SDavid du Colombier 				if((c = Bgetrune(finput)) == '/')
19303e12c5d1SDavid du Colombier 					return i;
19313e12c5d1SDavid du Colombier 			if(c == '\n')
19323e12c5d1SDavid du Colombier 				i++;
19333e12c5d1SDavid du Colombier 		}
193443aadf5eSDavid du Colombier 	}else
193543aadf5eSDavid du Colombier 		error("illegal comment");
193643aadf5eSDavid du Colombier 
19373e12c5d1SDavid du Colombier 	error("EOF inside comment");
19383e12c5d1SDavid du Colombier 	return 0;
19393e12c5d1SDavid du Colombier }
19403e12c5d1SDavid du Colombier 
19413e12c5d1SDavid du Colombier /*
19423e12c5d1SDavid du Colombier  * copy C action to the next ; or closing }
19433e12c5d1SDavid du Colombier  */
19443e12c5d1SDavid du Colombier void
cpyact(int offset)19453e12c5d1SDavid du Colombier cpyact(int offset)
19463e12c5d1SDavid du Colombier {
19473e12c5d1SDavid du Colombier 	long c;
19483e12c5d1SDavid du Colombier 	int brac, match, j, s, fnd, tok;
19493e12c5d1SDavid du Colombier 
19503e12c5d1SDavid du Colombier 	Bprint(faction, "\n#line\t%d\t\"%s\"\n", lineno, infile);
19513e12c5d1SDavid du Colombier 	brac = 0;
19523e12c5d1SDavid du Colombier 
19533e12c5d1SDavid du Colombier loop:
19543e12c5d1SDavid du Colombier 	c = Bgetrune(finput);
19553e12c5d1SDavid du Colombier swt:
19563e12c5d1SDavid du Colombier 	switch(c) {
19573e12c5d1SDavid du Colombier 	case ';':
19583e12c5d1SDavid du Colombier 		if(brac == 0) {
19593e12c5d1SDavid du Colombier 			Bputrune(faction, c);
19603e12c5d1SDavid du Colombier 			return;
19613e12c5d1SDavid du Colombier 		}
19623e12c5d1SDavid du Colombier 		goto lcopy;
19633e12c5d1SDavid du Colombier 
19643e12c5d1SDavid du Colombier 	case '{':
19653e12c5d1SDavid du Colombier 		brac++;
19663e12c5d1SDavid du Colombier 		goto lcopy;
19673e12c5d1SDavid du Colombier 
19683e12c5d1SDavid du Colombier 	case '$':
19693e12c5d1SDavid du Colombier 		s = 1;
19703e12c5d1SDavid du Colombier 		tok = -1;
19713e12c5d1SDavid du Colombier 		c = Bgetrune(finput);
19723e12c5d1SDavid du Colombier 
19733e12c5d1SDavid du Colombier 		/* type description */
19743e12c5d1SDavid du Colombier 		if(c == '<') {
19753e12c5d1SDavid du Colombier 			Bungetrune(finput);
19763e12c5d1SDavid du Colombier 			if(gettok() != TYPENAME)
19773e12c5d1SDavid du Colombier 				error("bad syntax on $<ident> clause");
19783e12c5d1SDavid du Colombier 			tok = numbval;
19793e12c5d1SDavid du Colombier 			c = Bgetrune(finput);
19803e12c5d1SDavid du Colombier 		}
19813e12c5d1SDavid du Colombier 		if(c == '$') {
19823e12c5d1SDavid du Colombier 			Bprint(faction, "yyval");
19833e12c5d1SDavid du Colombier 
19843e12c5d1SDavid du Colombier 			/* put out the proper tag... */
19853e12c5d1SDavid du Colombier 			if(ntypes) {
19863e12c5d1SDavid du Colombier 				if(tok < 0)
19873e12c5d1SDavid du Colombier 					tok = fdtype(*prdptr[nprod]);
19883e12c5d1SDavid du Colombier 				Bprint(faction, ".%s", typeset[tok]);
19893e12c5d1SDavid du Colombier 			}
19903e12c5d1SDavid du Colombier 			goto loop;
19913e12c5d1SDavid du Colombier 		}
19923e12c5d1SDavid du Colombier 		if(c == '-') {
19933e12c5d1SDavid du Colombier 			s = -s;
19943e12c5d1SDavid du Colombier 			c = Bgetrune(finput);
19953e12c5d1SDavid du Colombier 		}
19963e12c5d1SDavid du Colombier 		if(isdigit(c)) {
19973e12c5d1SDavid du Colombier 			j = 0;
19983e12c5d1SDavid du Colombier 			while(isdigit(c)) {
19993e12c5d1SDavid du Colombier 				j = j*10 + (c-'0');
20003e12c5d1SDavid du Colombier 				c = Bgetrune(finput);
20013e12c5d1SDavid du Colombier 			}
20023e12c5d1SDavid du Colombier 			Bungetrune(finput);
20033e12c5d1SDavid du Colombier 			j = j*s - offset;
20043e12c5d1SDavid du Colombier 			if(j > 0)
20053e12c5d1SDavid du Colombier 				error("Illegal use of $%d", j+offset);
20063e12c5d1SDavid du Colombier 
20073e12c5d1SDavid du Colombier 		dollar:
20083e12c5d1SDavid du Colombier 			Bprint(faction, "yypt[-%d].yyv", -j);
20093e12c5d1SDavid du Colombier 
20103e12c5d1SDavid du Colombier 			/* put out the proper tag */
20113e12c5d1SDavid du Colombier 			if(ntypes) {
20123e12c5d1SDavid du Colombier 				if(j+offset <= 0 && tok < 0)
20133e12c5d1SDavid du Colombier 					error("must specify type of $%d", j+offset);
20143e12c5d1SDavid du Colombier 				if(tok < 0)
20153e12c5d1SDavid du Colombier 					tok = fdtype(prdptr[nprod][j+offset]);
20163e12c5d1SDavid du Colombier 				Bprint(faction, ".%s", typeset[tok]);
20173e12c5d1SDavid du Colombier 			}
20183e12c5d1SDavid du Colombier 			goto loop;
20193e12c5d1SDavid du Colombier 		}
20203e12c5d1SDavid du Colombier 		if(isupper(c) || islower(c) || c == '_' || c == '.') {
20213e12c5d1SDavid du Colombier 			int tok; /* tok used oustide for type info */
20223e12c5d1SDavid du Colombier 
20233e12c5d1SDavid du Colombier 			/* look for $name */
20243e12c5d1SDavid du Colombier 			Bungetrune(finput);
20253e12c5d1SDavid du Colombier 			if(gettok() != IDENTIFIER)
20263e12c5d1SDavid du Colombier 				error("$ must be followed by an identifier");
20273e12c5d1SDavid du Colombier 			tok = chfind(2, tokname);
20283e12c5d1SDavid du Colombier 			if((c = Bgetrune(finput)) != '#') {
20293e12c5d1SDavid du Colombier 				Bungetrune(finput);
20303e12c5d1SDavid du Colombier 				fnd = -1;
20313e12c5d1SDavid du Colombier 			} else
20323e12c5d1SDavid du Colombier 				if(gettok() != NUMBER) {
20333e12c5d1SDavid du Colombier 					error("# must be followed by number");
20343e12c5d1SDavid du Colombier 					fnd = -1;
20353e12c5d1SDavid du Colombier 				} else
20363e12c5d1SDavid du Colombier 					fnd = numbval;
20373e12c5d1SDavid du Colombier 			for(j=1; j<=offset; ++j)
20383e12c5d1SDavid du Colombier 				if(tok == prdptr[nprod][j]) {
20393e12c5d1SDavid du Colombier 					if(--fnd <= 0) {
20403e12c5d1SDavid du Colombier 						j -= offset;
20413e12c5d1SDavid du Colombier 						goto dollar;
20423e12c5d1SDavid du Colombier 					}
20433e12c5d1SDavid du Colombier 				}
20443e12c5d1SDavid du Colombier 			error("$name or $name#number not found");
20453e12c5d1SDavid du Colombier 		}
20463e12c5d1SDavid du Colombier 		Bputc(faction, '$');
20473e12c5d1SDavid du Colombier 		if(s < 0 )
20483e12c5d1SDavid du Colombier 			Bputc(faction, '-');
20493e12c5d1SDavid du Colombier 		goto swt;
20503e12c5d1SDavid du Colombier 
20513e12c5d1SDavid du Colombier 	case '}':
20523e12c5d1SDavid du Colombier 		brac--;
20533e12c5d1SDavid du Colombier 		if(brac)
20543e12c5d1SDavid du Colombier 			goto lcopy;
20553e12c5d1SDavid du Colombier 		Bputrune(faction, c);
20563e12c5d1SDavid du Colombier 		return;
20573e12c5d1SDavid du Colombier 
20583e12c5d1SDavid du Colombier 	case '/':
20593e12c5d1SDavid du Colombier 		/* look for comments */
20603e12c5d1SDavid du Colombier 		Bputrune(faction, c);
20613e12c5d1SDavid du Colombier 		c = Bgetrune(finput);
20623e12c5d1SDavid du Colombier 		if(c != '*')
20633e12c5d1SDavid du Colombier 			goto swt;
20643e12c5d1SDavid du Colombier 
2065889a2622SDavid du Colombier 		/* it really is a comment; copy it */
20663e12c5d1SDavid du Colombier 		Bputrune(faction, c);
20673e12c5d1SDavid du Colombier 		c = Bgetrune(finput);
20683e12c5d1SDavid du Colombier 		while(c >= 0) {
20693e12c5d1SDavid du Colombier 			while(c == '*') {
20703e12c5d1SDavid du Colombier 				Bputrune(faction, c);
20713e12c5d1SDavid du Colombier 				if((c=Bgetrune(finput)) == '/')
20723e12c5d1SDavid du Colombier 					goto lcopy;
20733e12c5d1SDavid du Colombier 			}
20743e12c5d1SDavid du Colombier 			Bputrune(faction, c);
20753e12c5d1SDavid du Colombier 			if(c == '\n')
20763e12c5d1SDavid du Colombier 				lineno++;
20773e12c5d1SDavid du Colombier 			c = Bgetrune(finput);
20783e12c5d1SDavid du Colombier 		}
20793e12c5d1SDavid du Colombier 		error("EOF inside comment");
20803e12c5d1SDavid du Colombier 
20813e12c5d1SDavid du Colombier 	case '\'':
20823e12c5d1SDavid du Colombier 		/* character constant */
20833e12c5d1SDavid du Colombier 		match = '\'';
20843e12c5d1SDavid du Colombier 		goto string;
20853e12c5d1SDavid du Colombier 
20863e12c5d1SDavid du Colombier 	case '"':
20873e12c5d1SDavid du Colombier 		/* character string */
20883e12c5d1SDavid du Colombier 		match = '"';
20893e12c5d1SDavid du Colombier 
20903e12c5d1SDavid du Colombier 	string:
20913e12c5d1SDavid du Colombier 		Bputrune(faction, c);
20923e12c5d1SDavid du Colombier 		while(c = Bgetrune(finput)) {
20933e12c5d1SDavid du Colombier 			if(c == '\\') {
20943e12c5d1SDavid du Colombier 				Bputrune(faction, c);
20953e12c5d1SDavid du Colombier 				c = Bgetrune(finput);
20963e12c5d1SDavid du Colombier 				if(c == '\n')
20973e12c5d1SDavid du Colombier 					lineno++;
20983e12c5d1SDavid du Colombier 			} else
20993e12c5d1SDavid du Colombier 				if(c == match)
21003e12c5d1SDavid du Colombier 					goto lcopy;
21013e12c5d1SDavid du Colombier 				if(c == '\n')
21023e12c5d1SDavid du Colombier 					error("newline in string or char. const.");
21033e12c5d1SDavid du Colombier 			Bputrune(faction, c);
21043e12c5d1SDavid du Colombier 		}
21053e12c5d1SDavid du Colombier 		error("EOF in string or character constant");
21063e12c5d1SDavid du Colombier 
21073e12c5d1SDavid du Colombier 	case Beof:
21083e12c5d1SDavid du Colombier 		error("action does not terminate");
21093e12c5d1SDavid du Colombier 
21103e12c5d1SDavid du Colombier 	case '\n':
21113e12c5d1SDavid du Colombier 		lineno++;
21123e12c5d1SDavid du Colombier 		goto lcopy;
21133e12c5d1SDavid du Colombier 	}
21143e12c5d1SDavid du Colombier 
21153e12c5d1SDavid du Colombier lcopy:
21163e12c5d1SDavid du Colombier 	Bputrune(faction, c);
21173e12c5d1SDavid du Colombier 	goto loop;
21183e12c5d1SDavid du Colombier }
21193e12c5d1SDavid du Colombier 
21203e12c5d1SDavid du Colombier void
openup(char * stem,int dflag,int vflag,int ytab,char * ytabc)21213e12c5d1SDavid du Colombier openup(char *stem, int dflag, int vflag, int ytab, char *ytabc)
21223e12c5d1SDavid du Colombier {
21233e12c5d1SDavid du Colombier 	char buf[256];
21243e12c5d1SDavid du Colombier 
21253e12c5d1SDavid du Colombier 	if(vflag) {
21264d44ba9bSDavid du Colombier 		snprint(buf, sizeof buf, "%s.%s", stem, FILEU);
21273e12c5d1SDavid du Colombier 		foutput = Bopen(buf, OWRITE);
21283e12c5d1SDavid du Colombier 		if(foutput == 0)
21293e12c5d1SDavid du Colombier 			error("cannot open %s", buf);
21303e12c5d1SDavid du Colombier 	}
21313e12c5d1SDavid du Colombier 	if(yydebug) {
21324d44ba9bSDavid du Colombier 		snprint(buf, sizeof buf, "%s.%s", stem, FILEDEBUG);
21333e12c5d1SDavid du Colombier 		if((fdebug = Bopen(buf, OWRITE)) == 0)
21343e12c5d1SDavid du Colombier 			error("can't open %s", buf);
21353e12c5d1SDavid du Colombier 	}
21363e12c5d1SDavid du Colombier 	if(dflag) {
21374d44ba9bSDavid du Colombier 		snprint(buf, sizeof buf, "%s.%s", stem, FILED);
21383e12c5d1SDavid du Colombier 		fdefine = Bopen(buf, OWRITE);
21393e12c5d1SDavid du Colombier 		if(fdefine == 0)
21403e12c5d1SDavid du Colombier 			error("can't create %s", buf);
21413e12c5d1SDavid du Colombier 	}
21423e12c5d1SDavid du Colombier 	if(ytab == 0)
21434d44ba9bSDavid du Colombier 		snprint(buf, sizeof buf, "%s.%s", stem, OFILE);
21443e12c5d1SDavid du Colombier 	else
21454d44ba9bSDavid du Colombier 		strecpy(buf, buf+sizeof buf, ytabc);
21463e12c5d1SDavid du Colombier 	ftable = Bopen(buf, OWRITE);
21473e12c5d1SDavid du Colombier 	if(ftable == 0)
21483e12c5d1SDavid du Colombier 		error("cannot open table file %s", buf);
21493e12c5d1SDavid du Colombier }
21503e12c5d1SDavid du Colombier 
21513e12c5d1SDavid du Colombier /*
21523e12c5d1SDavid du Colombier  * print the output for the states
21533e12c5d1SDavid du Colombier  */
21543e12c5d1SDavid du Colombier void
output(void)21553e12c5d1SDavid du Colombier output(void)
21563e12c5d1SDavid du Colombier {
21573e12c5d1SDavid du Colombier 	int i, k, c;
21583e12c5d1SDavid du Colombier 	Wset *u, *v;
21593e12c5d1SDavid du Colombier 
21603e12c5d1SDavid du Colombier 	Bprint(ftable, "short	yyexca[] =\n{");
21613e12c5d1SDavid du Colombier 	if(fdebug)
21623e12c5d1SDavid du Colombier 		Bprint(fdebug, "char*	yystates[] =\n{\n");
21633e12c5d1SDavid du Colombier 
21643e12c5d1SDavid du Colombier 	/* output the stuff for state i */
21653e12c5d1SDavid du Colombier 	SLOOP(i) {
21663e12c5d1SDavid du Colombier 		nolook = tystate[i]!=MUSTLOOKAHEAD;
21673e12c5d1SDavid du Colombier 		closure(i);
21683e12c5d1SDavid du Colombier 
21693e12c5d1SDavid du Colombier 		/* output actions */
21703e12c5d1SDavid du Colombier 		nolook = 1;
21713e12c5d1SDavid du Colombier 		aryfil(temp1, ntokens+nnonter+1, 0);
21723e12c5d1SDavid du Colombier 		WSLOOP(wsets, u) {
21733e12c5d1SDavid du Colombier 			c = *(u->pitem);
21743e12c5d1SDavid du Colombier 			if(c > 1 && c < NTBASE && temp1[c] == 0) {
21753e12c5d1SDavid du Colombier 				WSLOOP(u, v)
21763e12c5d1SDavid du Colombier 					if(c == *(v->pitem))
21773e12c5d1SDavid du Colombier 						putitem(v->pitem+1, (Lkset*)0);
21783e12c5d1SDavid du Colombier 				temp1[c] = state(c);
21793e12c5d1SDavid du Colombier 			} else
21803e12c5d1SDavid du Colombier 				if(c > NTBASE && temp1[(c -= NTBASE) + ntokens] == 0)
21813e12c5d1SDavid du Colombier 					temp1[c+ntokens] = amem[indgo[i]+c];
21823e12c5d1SDavid du Colombier 		}
21833e12c5d1SDavid du Colombier 		if(i == 1)
21843e12c5d1SDavid du Colombier 			temp1[1] = ACCEPTCODE;
21853e12c5d1SDavid du Colombier 
21863e12c5d1SDavid du Colombier 		/* now, we have the shifts; look at the reductions */
21873e12c5d1SDavid du Colombier 		lastred = 0;
21883e12c5d1SDavid du Colombier 		WSLOOP(wsets, u) {
21893e12c5d1SDavid du Colombier 			c = *u->pitem;
21903e12c5d1SDavid du Colombier 
21913e12c5d1SDavid du Colombier 			/* reduction */
21923e12c5d1SDavid du Colombier 			if(c <= 0) {
21933e12c5d1SDavid du Colombier 				lastred = -c;
21943e12c5d1SDavid du Colombier 				TLOOP(k)
21953e12c5d1SDavid du Colombier 					if(BIT(u->ws.lset, k)) {
21963e12c5d1SDavid du Colombier 						if(temp1[k] == 0)
21973e12c5d1SDavid du Colombier 							temp1[k] = c;
21983e12c5d1SDavid du Colombier 						else
21993e12c5d1SDavid du Colombier 						if(temp1[k] < 0) { /* reduce/reduce conflict */
22003e12c5d1SDavid du Colombier 							if(foutput)
22013e12c5d1SDavid du Colombier 								Bprint(foutput,
22023e12c5d1SDavid du Colombier 									"\n%d: reduce/reduce conflict"
22033e12c5d1SDavid du Colombier 									" (red'ns %d and %d ) on %s",
22043e12c5d1SDavid du Colombier 									i, -temp1[k], lastred,
22053e12c5d1SDavid du Colombier 									symnam(k));
22063e12c5d1SDavid du Colombier 							if(-temp1[k] > lastred)
22073e12c5d1SDavid du Colombier 								temp1[k] = -lastred;
22083e12c5d1SDavid du Colombier 							zzrrconf++;
22093e12c5d1SDavid du Colombier 						} else
22103e12c5d1SDavid du Colombier 							/* potential shift/reduce conflict */
22113e12c5d1SDavid du Colombier 							precftn( lastred, k, i );
22123e12c5d1SDavid du Colombier 					}
22133e12c5d1SDavid du Colombier 				}
22143e12c5d1SDavid du Colombier 		}
22153e12c5d1SDavid du Colombier 		wract(i);
22163e12c5d1SDavid du Colombier 	}
22173e12c5d1SDavid du Colombier 
22183e12c5d1SDavid du Colombier 	if(fdebug)
22193e12c5d1SDavid du Colombier 		Bprint(fdebug, "};\n");
22203e12c5d1SDavid du Colombier 	Bprint(ftable, "};\n");
22213e12c5d1SDavid du Colombier 	Bprint(ftable, "#define	YYNPROD	%d\n", nprod);
22223e12c5d1SDavid du Colombier 	Bprint(ftable, "#define	YYPRIVATE %d\n", PRIVATE);
22233e12c5d1SDavid du Colombier 	if(yydebug)
22243e12c5d1SDavid du Colombier 		Bprint(ftable, "#define	yydebug	%s\n", yydebug);
22253e12c5d1SDavid du Colombier }
22263e12c5d1SDavid du Colombier 
22273e12c5d1SDavid du Colombier /*
22283e12c5d1SDavid du Colombier  * pack state i from temp1 into amem
22293e12c5d1SDavid du Colombier  */
22303e12c5d1SDavid du Colombier int
apack(int * p,int n)22313e12c5d1SDavid du Colombier apack(int *p, int n)
22323e12c5d1SDavid du Colombier {
22333e12c5d1SDavid du Colombier 	int *pp, *qq, *rr, off, *q, *r;
22343e12c5d1SDavid du Colombier 
22353e12c5d1SDavid du Colombier 	/* we don't need to worry about checking because
22363e12c5d1SDavid du Colombier 	 * we will only look at entries known to be there...
22373e12c5d1SDavid du Colombier 	 * eliminate leading and trailing 0's
22383e12c5d1SDavid du Colombier 	 */
22393e12c5d1SDavid du Colombier 
22403e12c5d1SDavid du Colombier 	q = p+n;
22413e12c5d1SDavid du Colombier 	for(pp = p, off = 0; *pp == 0 && pp <= q; ++pp, --off)
22423e12c5d1SDavid du Colombier 		;
22433e12c5d1SDavid du Colombier  	/* no actions */
22443e12c5d1SDavid du Colombier 	if(pp > q)
22453e12c5d1SDavid du Colombier 		return 0;
22463e12c5d1SDavid du Colombier 	p = pp;
22473e12c5d1SDavid du Colombier 
22483e12c5d1SDavid du Colombier 	/* now, find a place for the elements from p to q, inclusive */
22493e12c5d1SDavid du Colombier 	r = &amem[ACTSIZE-1];
22503e12c5d1SDavid du Colombier 	for(rr = amem; rr <= r; rr++, off++) {
22513e12c5d1SDavid du Colombier 		for(qq = rr, pp = p; pp <= q; pp++, qq++)
22523e12c5d1SDavid du Colombier 			if(*pp != 0)
22533e12c5d1SDavid du Colombier 				if(*pp != *qq && *qq != 0)
22543e12c5d1SDavid du Colombier 					goto nextk;
22553e12c5d1SDavid du Colombier 
22563e12c5d1SDavid du Colombier 		/* we have found an acceptable k */
22573e12c5d1SDavid du Colombier 		if(pkdebug && foutput != 0)
22587dd7cddfSDavid du Colombier 			Bprint(foutput, "off = %d, k = %d\n", off, (int)(rr-amem));
22593e12c5d1SDavid du Colombier 		for(qq = rr, pp = p; pp <= q; pp++, qq++)
22603e12c5d1SDavid du Colombier 			if(*pp) {
22613e12c5d1SDavid du Colombier 				if(qq > r)
22623e12c5d1SDavid du Colombier 					error("action table overflow");
22633e12c5d1SDavid du Colombier 				if(qq > memp)
22643e12c5d1SDavid du Colombier 					memp = qq;
22653e12c5d1SDavid du Colombier 				*qq = *pp;
22663e12c5d1SDavid du Colombier 			}
22673e12c5d1SDavid du Colombier 		if(pkdebug && foutput != 0)
22683e12c5d1SDavid du Colombier 			for(pp = amem; pp <= memp; pp += 10) {
22693e12c5d1SDavid du Colombier 				Bprint(foutput, "\t");
22703e12c5d1SDavid du Colombier 				for(qq = pp; qq <= pp+9; qq++)
22713e12c5d1SDavid du Colombier 					Bprint(foutput, "%d ", *qq);
22723e12c5d1SDavid du Colombier 				Bprint(foutput, "\n");
22733e12c5d1SDavid du Colombier 			}
22743e12c5d1SDavid du Colombier 		return(off);
22753e12c5d1SDavid du Colombier 	nextk:;
22763e12c5d1SDavid du Colombier 	}
22773e12c5d1SDavid du Colombier 	error("no space in action table");
22783e12c5d1SDavid du Colombier 	return 0;
22793e12c5d1SDavid du Colombier }
22803e12c5d1SDavid du Colombier 
22813e12c5d1SDavid du Colombier /*
22823e12c5d1SDavid du Colombier  * output the gotos for the nontermninals
22833e12c5d1SDavid du Colombier  */
22843e12c5d1SDavid du Colombier void
go2out(void)22853e12c5d1SDavid du Colombier go2out(void)
22863e12c5d1SDavid du Colombier {
22873e12c5d1SDavid du Colombier 	int i, j, k, best, count, cbest, times;
22883e12c5d1SDavid du Colombier 
22893e12c5d1SDavid du Colombier 	/* mark begining of gotos */
22903e12c5d1SDavid du Colombier 	Bprint(ftemp, "$\n");
22913e12c5d1SDavid du Colombier 	for(i = 1; i <= nnonter; i++) {
22923e12c5d1SDavid du Colombier 		go2gen(i);
22933e12c5d1SDavid du Colombier 
22943e12c5d1SDavid du Colombier 		/* find the best one to make default */
22953e12c5d1SDavid du Colombier 		best = -1;
22963e12c5d1SDavid du Colombier 		times = 0;
22973e12c5d1SDavid du Colombier 
22983e12c5d1SDavid du Colombier 		/* is j the most frequent */
22993e12c5d1SDavid du Colombier 		for(j = 0; j <= nstate; j++) {
23003e12c5d1SDavid du Colombier 			if(tystate[j] == 0)
23013e12c5d1SDavid du Colombier 				continue;
23023e12c5d1SDavid du Colombier 			if(tystate[j] == best)
23033e12c5d1SDavid du Colombier 				continue;
23043e12c5d1SDavid du Colombier 
23053e12c5d1SDavid du Colombier 			/* is tystate[j] the most frequent */
23063e12c5d1SDavid du Colombier 			count = 0;
23073e12c5d1SDavid du Colombier 			cbest = tystate[j];
23083e12c5d1SDavid du Colombier 			for(k = j; k <= nstate; k++)
23093e12c5d1SDavid du Colombier 				if(tystate[k] == cbest)
23103e12c5d1SDavid du Colombier 					count++;
23113e12c5d1SDavid du Colombier 			if(count > times) {
23123e12c5d1SDavid du Colombier 				best = cbest;
23133e12c5d1SDavid du Colombier 				times = count;
23143e12c5d1SDavid du Colombier 			}
23153e12c5d1SDavid du Colombier 		}
23163e12c5d1SDavid du Colombier 
23173e12c5d1SDavid du Colombier 		/* best is now the default entry */
23183e12c5d1SDavid du Colombier 		zzgobest += times-1;
23193e12c5d1SDavid du Colombier 		for(j = 0; j <= nstate; j++)
23203e12c5d1SDavid du Colombier 			if(tystate[j] != 0 && tystate[j] != best) {
23213e12c5d1SDavid du Colombier 				Bprint(ftemp, "%d,%d,", j, tystate[j]);
23223e12c5d1SDavid du Colombier 				zzgoent++;
23233e12c5d1SDavid du Colombier 			}
23243e12c5d1SDavid du Colombier 
23253e12c5d1SDavid du Colombier 		/* now, the default */
23267dd7cddfSDavid du Colombier 		if(best == -1)
23277dd7cddfSDavid du Colombier 			best = 0;
23283e12c5d1SDavid du Colombier 		zzgoent++;
23293e12c5d1SDavid du Colombier 		Bprint(ftemp, "%d\n", best);
23303e12c5d1SDavid du Colombier 	}
23313e12c5d1SDavid du Colombier }
23323e12c5d1SDavid du Colombier 
23333e12c5d1SDavid du Colombier /*
23343e12c5d1SDavid du Colombier  * output the gotos for nonterminal c
23353e12c5d1SDavid du Colombier  */
23363e12c5d1SDavid du Colombier void
go2gen(int c)23373e12c5d1SDavid du Colombier go2gen(int c)
23383e12c5d1SDavid du Colombier {
23393e12c5d1SDavid du Colombier 	int i, work, cc;
23403e12c5d1SDavid du Colombier 	Item *p, *q;
23413e12c5d1SDavid du Colombier 
23423e12c5d1SDavid du Colombier 
23433e12c5d1SDavid du Colombier 	/* first, find nonterminals with gotos on c */
23443e12c5d1SDavid du Colombier 	aryfil(temp1, nnonter+1, 0);
23453e12c5d1SDavid du Colombier 	temp1[c] = 1;
23463e12c5d1SDavid du Colombier 	work = 1;
23473e12c5d1SDavid du Colombier 	while(work) {
23483e12c5d1SDavid du Colombier 		work = 0;
23493e12c5d1SDavid du Colombier 		PLOOP(0, i)
23503e12c5d1SDavid du Colombier 
23513e12c5d1SDavid du Colombier 			/* cc is a nonterminal */
23523e12c5d1SDavid du Colombier 			if((cc=prdptr[i][1]-NTBASE) >= 0)
23533e12c5d1SDavid du Colombier 				/* cc has a goto on c */
23543e12c5d1SDavid du Colombier 				if(temp1[cc] != 0) {
23553e12c5d1SDavid du Colombier 
23563e12c5d1SDavid du Colombier 					/* thus, the left side of production i does too */
23573e12c5d1SDavid du Colombier 					cc = *prdptr[i]-NTBASE;
23583e12c5d1SDavid du Colombier 					if(temp1[cc] == 0) {
23593e12c5d1SDavid du Colombier 						  work = 1;
23603e12c5d1SDavid du Colombier 						  temp1[cc] = 1;
23613e12c5d1SDavid du Colombier 					}
23623e12c5d1SDavid du Colombier 				}
23633e12c5d1SDavid du Colombier 	}
23643e12c5d1SDavid du Colombier 
23653e12c5d1SDavid du Colombier 	/* now, we have temp1[c] = 1 if a goto on c in closure of cc */
23663e12c5d1SDavid du Colombier 	if(g2debug && foutput != 0) {
23673e12c5d1SDavid du Colombier 		Bprint(foutput, "%s: gotos on ", nontrst[c].name);
23683e12c5d1SDavid du Colombier 		NTLOOP(i)
23693e12c5d1SDavid du Colombier 			if(temp1[i])
23703e12c5d1SDavid du Colombier 				Bprint(foutput, "%s ", nontrst[i].name);
23713e12c5d1SDavid du Colombier 		Bprint(foutput, "\n");
23723e12c5d1SDavid du Colombier 	}
23733e12c5d1SDavid du Colombier 
23743e12c5d1SDavid du Colombier 	/* now, go through and put gotos into tystate */
23753e12c5d1SDavid du Colombier 	aryfil(tystate, nstate, 0);
23763e12c5d1SDavid du Colombier 	SLOOP(i)
23773e12c5d1SDavid du Colombier 		ITMLOOP(i, p, q)
23783e12c5d1SDavid du Colombier 			if((cc = *p->pitem) >= NTBASE)
23793e12c5d1SDavid du Colombier 				/* goto on c is possible */
23803e12c5d1SDavid du Colombier 				if(temp1[cc-NTBASE]) {
23813e12c5d1SDavid du Colombier 					tystate[i] = amem[indgo[i]+c];
23823e12c5d1SDavid du Colombier 					break;
23833e12c5d1SDavid du Colombier 				}
23843e12c5d1SDavid du Colombier }
23853e12c5d1SDavid du Colombier 
23863e12c5d1SDavid du Colombier /*
23873e12c5d1SDavid du Colombier  * decide a shift/reduce conflict by precedence.
23883e12c5d1SDavid du Colombier  * r is a rule number, t a token number
23893e12c5d1SDavid du Colombier  * the conflict is in state s
23903e12c5d1SDavid du Colombier  * temp1[t] is changed to reflect the action
23913e12c5d1SDavid du Colombier  */
23923e12c5d1SDavid du Colombier void
precftn(int r,int t,int s)23933e12c5d1SDavid du Colombier precftn(int r, int t, int s)
23943e12c5d1SDavid du Colombier {
23953e12c5d1SDavid du Colombier 	int lp, lt, action;
23963e12c5d1SDavid du Colombier 
23973e12c5d1SDavid du Colombier 	lp = levprd[r];
23983e12c5d1SDavid du Colombier 	lt = toklev[t];
23993e12c5d1SDavid du Colombier 	if(PLEVEL(lt) == 0 || PLEVEL(lp) == 0) {
24003e12c5d1SDavid du Colombier 
24013e12c5d1SDavid du Colombier 		/* conflict */
24023e12c5d1SDavid du Colombier 		if(foutput != 0)
24033e12c5d1SDavid du Colombier 			Bprint(foutput,
24043e12c5d1SDavid du Colombier 				"\n%d: shift/reduce conflict (shift %d(%d), red'n %d(%d)) on %s",
24053e12c5d1SDavid du Colombier 				s, temp1[t], PLEVEL(lt), r, PLEVEL(lp), symnam(t));
24063e12c5d1SDavid du Colombier 		zzsrconf++;
24073e12c5d1SDavid du Colombier 		return;
24083e12c5d1SDavid du Colombier 	}
24093e12c5d1SDavid du Colombier 	if(PLEVEL(lt) == PLEVEL(lp))
24103e12c5d1SDavid du Colombier 		action = ASSOC(lt);
24113e12c5d1SDavid du Colombier 	else
24123e12c5d1SDavid du Colombier 		if(PLEVEL(lt) > PLEVEL(lp))
24133e12c5d1SDavid du Colombier 			action = RASC;  /* shift */
24143e12c5d1SDavid du Colombier 		else
24153e12c5d1SDavid du Colombier 			action = LASC;  /* reduce */
24163e12c5d1SDavid du Colombier 	switch(action) {
24173e12c5d1SDavid du Colombier 	case BASC:  /* error action */
24183e12c5d1SDavid du Colombier 		temp1[t] = ERRCODE;
24193e12c5d1SDavid du Colombier 		break;
24203e12c5d1SDavid du Colombier 	case LASC:  /* reduce */
24213e12c5d1SDavid du Colombier 		temp1[t] = -r;
24223e12c5d1SDavid du Colombier 		break;
24233e12c5d1SDavid du Colombier 	}
24243e12c5d1SDavid du Colombier }
24253e12c5d1SDavid du Colombier 
24263e12c5d1SDavid du Colombier /*
24273e12c5d1SDavid du Colombier  * output state i
24283e12c5d1SDavid du Colombier  * temp1 has the actions, lastred the default
24293e12c5d1SDavid du Colombier  */
24303e12c5d1SDavid du Colombier void
wract(int i)24313e12c5d1SDavid du Colombier wract(int i)
24323e12c5d1SDavid du Colombier {
24333e12c5d1SDavid du Colombier 	int p, p0, p1, ntimes, tred, count, j, flag;
24343e12c5d1SDavid du Colombier 
24353e12c5d1SDavid du Colombier 	/* find the best choice for lastred */
24363e12c5d1SDavid du Colombier 	lastred = 0;
24373e12c5d1SDavid du Colombier 	ntimes = 0;
24383e12c5d1SDavid du Colombier 	TLOOP(j) {
24393e12c5d1SDavid du Colombier 		if(temp1[j] >= 0)
24403e12c5d1SDavid du Colombier 			continue;
24413e12c5d1SDavid du Colombier 		if(temp1[j]+lastred == 0)
24423e12c5d1SDavid du Colombier 			continue;
24433e12c5d1SDavid du Colombier 		/* count the number of appearances of temp1[j] */
24443e12c5d1SDavid du Colombier 		count = 0;
24453e12c5d1SDavid du Colombier 		tred = -temp1[j];
24463e12c5d1SDavid du Colombier 		levprd[tred] |= REDFLAG;
24473e12c5d1SDavid du Colombier 		TLOOP(p)
24483e12c5d1SDavid du Colombier 			if(temp1[p]+tred == 0)
24493e12c5d1SDavid du Colombier 				count++;
24503e12c5d1SDavid du Colombier 		if(count > ntimes) {
24513e12c5d1SDavid du Colombier 			lastred = tred;
24523e12c5d1SDavid du Colombier 			ntimes = count;
24533e12c5d1SDavid du Colombier 		}
24543e12c5d1SDavid du Colombier 	}
24553e12c5d1SDavid du Colombier 
24563e12c5d1SDavid du Colombier 	/*
24573e12c5d1SDavid du Colombier 	 * for error recovery, arrange that, if there is a shift on the
24583e12c5d1SDavid du Colombier 	 * error recovery token, `error', that the default be the error action
24593e12c5d1SDavid du Colombier 	 */
24603e12c5d1SDavid du Colombier 	if(temp1[2] > 0)
24613e12c5d1SDavid du Colombier 		lastred = 0;
24623e12c5d1SDavid du Colombier 
24633e12c5d1SDavid du Colombier 	/* clear out entries in temp1 which equal lastred */
24643e12c5d1SDavid du Colombier 	TLOOP(p)
24653e12c5d1SDavid du Colombier 		if(temp1[p]+lastred == 0)
24663e12c5d1SDavid du Colombier 			temp1[p] = 0;
24673e12c5d1SDavid du Colombier 
24683e12c5d1SDavid du Colombier 	wrstate(i);
24693e12c5d1SDavid du Colombier 	defact[i] = lastred;
24703e12c5d1SDavid du Colombier 	flag = 0;
24713e12c5d1SDavid du Colombier 	TLOOP(p0)
24723e12c5d1SDavid du Colombier 		if((p1=temp1[p0]) != 0) {
24733e12c5d1SDavid du Colombier 			if(p1 < 0) {
24743e12c5d1SDavid du Colombier 				p1 = -p1;
24753e12c5d1SDavid du Colombier 				goto exc;
24763e12c5d1SDavid du Colombier 			}
24773e12c5d1SDavid du Colombier 			if(p1 == ACCEPTCODE) {
24783e12c5d1SDavid du Colombier 				p1 = -1;
24793e12c5d1SDavid du Colombier 				goto exc;
24803e12c5d1SDavid du Colombier 			}
24813e12c5d1SDavid du Colombier 			if(p1 == ERRCODE) {
24823e12c5d1SDavid du Colombier 				p1 = 0;
24833e12c5d1SDavid du Colombier 			exc:
24843e12c5d1SDavid du Colombier 				if(flag++ == 0)
24853e12c5d1SDavid du Colombier 					Bprint(ftable, "-1, %d,\n", i);
24863e12c5d1SDavid du Colombier 				Bprint(ftable, "\t%d, %d,\n", p0, p1);
24873e12c5d1SDavid du Colombier 				zzexcp++;
24883e12c5d1SDavid du Colombier 				continue;
24893e12c5d1SDavid du Colombier 			}
24903e12c5d1SDavid du Colombier 			Bprint(ftemp, "%d,%d,", p0, p1);
24913e12c5d1SDavid du Colombier 			zzacent++;
24923e12c5d1SDavid du Colombier 		}
24933e12c5d1SDavid du Colombier 	if(flag) {
24943e12c5d1SDavid du Colombier 		defact[i] = -2;
24953e12c5d1SDavid du Colombier 		Bprint(ftable, "\t-2, %d,\n", lastred);
24963e12c5d1SDavid du Colombier 	}
24973e12c5d1SDavid du Colombier 	Bprint(ftemp, "\n");
24983e12c5d1SDavid du Colombier }
24993e12c5d1SDavid du Colombier 
25003e12c5d1SDavid du Colombier /*
25013e12c5d1SDavid du Colombier  * writes state i
25023e12c5d1SDavid du Colombier  */
25033e12c5d1SDavid du Colombier void
wrstate(int i)25043e12c5d1SDavid du Colombier wrstate(int i)
25053e12c5d1SDavid du Colombier {
25063e12c5d1SDavid du Colombier 	int j0, j1;
25073e12c5d1SDavid du Colombier 	Item *pp, *qq;
25083e12c5d1SDavid du Colombier 	Wset *u;
25093e12c5d1SDavid du Colombier 
25103e12c5d1SDavid du Colombier 	if(fdebug) {
25113e12c5d1SDavid du Colombier 		if(lastred) {
25123e12c5d1SDavid du Colombier 			Bprint(fdebug, "	0, /*%d*/\n", i);
25133e12c5d1SDavid du Colombier 		} else {
25143e12c5d1SDavid du Colombier 			Bprint(fdebug, "	\"");
25153e12c5d1SDavid du Colombier 			ITMLOOP(i, pp, qq)
25163e12c5d1SDavid du Colombier 				Bprint(fdebug, "%s\\n", writem(pp->pitem));
25173e12c5d1SDavid du Colombier 			if(tystate[i] == MUSTLOOKAHEAD)
25183e12c5d1SDavid du Colombier 				WSLOOP(wsets + (pstate[i+1] - pstate[i]), u)
25193e12c5d1SDavid du Colombier 					if(*u->pitem < 0)
25203e12c5d1SDavid du Colombier 						Bprint(fdebug, "%s\\n", writem(u->pitem));
25213e12c5d1SDavid du Colombier 			Bprint(fdebug, "\", /*%d*/\n", i);
25223e12c5d1SDavid du Colombier 		}
25233e12c5d1SDavid du Colombier 	}
25243e12c5d1SDavid du Colombier 	if(foutput == 0)
25253e12c5d1SDavid du Colombier 		return;
25263e12c5d1SDavid du Colombier 	Bprint(foutput, "\nstate %d\n", i);
25273e12c5d1SDavid du Colombier 	ITMLOOP(i, pp, qq)
25283e12c5d1SDavid du Colombier 		Bprint(foutput, "\t%s\n", writem(pp->pitem));
25293e12c5d1SDavid du Colombier 	if(tystate[i] == MUSTLOOKAHEAD)
25303e12c5d1SDavid du Colombier 		/* print out empty productions in closure */
25313e12c5d1SDavid du Colombier 		WSLOOP(wsets+(pstate[i+1]-pstate[i]), u)
25323e12c5d1SDavid du Colombier 			if(*u->pitem < 0)
25333e12c5d1SDavid du Colombier 				Bprint(foutput, "\t%s\n", writem(u->pitem));
25343e12c5d1SDavid du Colombier 
25353e12c5d1SDavid du Colombier 	/* check for state equal to another */
25363e12c5d1SDavid du Colombier 	TLOOP(j0)
25373e12c5d1SDavid du Colombier 		if((j1=temp1[j0]) != 0) {
25383e12c5d1SDavid du Colombier 			Bprint(foutput, "\n\t%s  ", symnam(j0));
25393e12c5d1SDavid du Colombier 			/* shift, error, or accept */
25403e12c5d1SDavid du Colombier 			if(j1 > 0) {
25413e12c5d1SDavid du Colombier 				if(j1 == ACCEPTCODE)
25423e12c5d1SDavid du Colombier 					Bprint(foutput,  "accept");
25433e12c5d1SDavid du Colombier 				else
25443e12c5d1SDavid du Colombier 					if(j1 == ERRCODE)
25453e12c5d1SDavid du Colombier 						Bprint(foutput, "error");
25463e12c5d1SDavid du Colombier 					else
25473e12c5d1SDavid du Colombier 						Bprint(foutput, "shift %d", j1);
25483e12c5d1SDavid du Colombier 			} else
25493e12c5d1SDavid du Colombier 				Bprint(foutput, "reduce %d (src line %d)", -j1, rlines[-j1]);
25503e12c5d1SDavid du Colombier 		}
25513e12c5d1SDavid du Colombier 
25523e12c5d1SDavid du Colombier 	/* output the final production */
25533e12c5d1SDavid du Colombier 	if(lastred)
25543e12c5d1SDavid du Colombier 		Bprint(foutput, "\n\t.  reduce %d (src line %d)\n\n",
25553e12c5d1SDavid du Colombier 			lastred, rlines[lastred]);
25563e12c5d1SDavid du Colombier 	else
25573e12c5d1SDavid du Colombier 		Bprint(foutput, "\n\t.  error\n\n");
25583e12c5d1SDavid du Colombier 
25593e12c5d1SDavid du Colombier 	/* now, output nonterminal actions */
25603e12c5d1SDavid du Colombier 	j1 = ntokens;
25613e12c5d1SDavid du Colombier 	for(j0 = 1; j0 <= nnonter; j0++) {
25623e12c5d1SDavid du Colombier 		j1++;
25633e12c5d1SDavid du Colombier 		if(temp1[j1])
25643e12c5d1SDavid du Colombier 			Bprint(foutput, "\t%s  goto %d\n", symnam(j0+NTBASE), temp1[j1]);
25653e12c5d1SDavid du Colombier 	}
25663e12c5d1SDavid du Colombier }
25673e12c5d1SDavid du Colombier 
25683e12c5d1SDavid du Colombier void
warray(char * s,int * v,int n)25693e12c5d1SDavid du Colombier warray(char *s, int *v, int n)
25703e12c5d1SDavid du Colombier {
25713e12c5d1SDavid du Colombier 	int i;
25723e12c5d1SDavid du Colombier 
25733e12c5d1SDavid du Colombier 	Bprint(ftable, "short	%s[] =\n{", s);
25743e12c5d1SDavid du Colombier 	for(i=0;;) {
25753e12c5d1SDavid du Colombier 		if(i%10 == 0)
25763e12c5d1SDavid du Colombier 			Bprint(ftable, "\n");
25773e12c5d1SDavid du Colombier 		Bprint(ftable, "%4d", v[i]);
25783e12c5d1SDavid du Colombier 		i++;
25793e12c5d1SDavid du Colombier 		if(i >= n) {
25803e12c5d1SDavid du Colombier 			Bprint(ftable, "\n};\n");
25813e12c5d1SDavid du Colombier 			break;
25823e12c5d1SDavid du Colombier 		}
25833e12c5d1SDavid du Colombier 		Bprint(ftable, ",");
25843e12c5d1SDavid du Colombier 	}
25853e12c5d1SDavid du Colombier }
25863e12c5d1SDavid du Colombier 
25873e12c5d1SDavid du Colombier /*
25883e12c5d1SDavid du Colombier  * in order to free up the mem and amem arrays for the optimizer,
25893e12c5d1SDavid du Colombier  * and still be able to output yyr1, etc., after the sizes of
25903e12c5d1SDavid du Colombier  * the action array is known, we hide the nonterminals
25913e12c5d1SDavid du Colombier  * derived by productions in levprd.
25923e12c5d1SDavid du Colombier  */
25933e12c5d1SDavid du Colombier 
25943e12c5d1SDavid du Colombier void
hideprod(void)25953e12c5d1SDavid du Colombier hideprod(void)
25963e12c5d1SDavid du Colombier {
25973e12c5d1SDavid du Colombier 	int i, j;
25983e12c5d1SDavid du Colombier 
25993e12c5d1SDavid du Colombier 	j = 0;
26003e12c5d1SDavid du Colombier 	levprd[0] = 0;
26013e12c5d1SDavid du Colombier 	PLOOP(1, i) {
26023e12c5d1SDavid du Colombier 		if(!(levprd[i] & REDFLAG)) {
26033e12c5d1SDavid du Colombier 			j++;
26043e12c5d1SDavid du Colombier 			if(foutput != 0)
26053e12c5d1SDavid du Colombier 				Bprint(foutput, "Rule not reduced:   %s\n", writem(prdptr[i]));
26063e12c5d1SDavid du Colombier 		}
26073e12c5d1SDavid du Colombier 		levprd[i] = *prdptr[i] - NTBASE;
26083e12c5d1SDavid du Colombier 	}
26093e12c5d1SDavid du Colombier 	if(j)
26103e12c5d1SDavid du Colombier 		print("%d rules never reduced\n", j);
26113e12c5d1SDavid du Colombier }
26123e12c5d1SDavid du Colombier 
26133e12c5d1SDavid du Colombier void
callopt(void)26143e12c5d1SDavid du Colombier callopt(void)
26153e12c5d1SDavid du Colombier {
26163e12c5d1SDavid du Colombier 	int i, *p, j, k, *q;
26173e12c5d1SDavid du Colombier 
26183e12c5d1SDavid du Colombier 	/* read the arrays from tempfile and set parameters */
26197dd7cddfSDavid du Colombier 	finput = Bopen(tempname, OREAD);
26207dd7cddfSDavid du Colombier 	if(finput == 0)
26213e12c5d1SDavid du Colombier 		error("optimizer cannot open tempfile");
26227dd7cddfSDavid du Colombier 
26233e12c5d1SDavid du Colombier 	pgo[0] = 0;
26243e12c5d1SDavid du Colombier 	temp1[0] = 0;
26253e12c5d1SDavid du Colombier 	nstate = 0;
26263e12c5d1SDavid du Colombier 	nnonter = 0;
26273e12c5d1SDavid du Colombier 	for(;;) {
26283e12c5d1SDavid du Colombier 		switch(gtnm()) {
26293e12c5d1SDavid du Colombier 		case '\n':
26303e12c5d1SDavid du Colombier 			nstate++;
26313e12c5d1SDavid du Colombier 			pmem--;
26323e12c5d1SDavid du Colombier 			temp1[nstate] = pmem - mem0;
26333e12c5d1SDavid du Colombier 		case ',':
26343e12c5d1SDavid du Colombier 			continue;
26353e12c5d1SDavid du Colombier 		case '$':
26363e12c5d1SDavid du Colombier 			break;
26373e12c5d1SDavid du Colombier 		default:
26383e12c5d1SDavid du Colombier 			error("bad tempfile");
26393e12c5d1SDavid du Colombier 		}
26403e12c5d1SDavid du Colombier 		break;
26413e12c5d1SDavid du Colombier 	}
26423e12c5d1SDavid du Colombier 
26433e12c5d1SDavid du Colombier 	pmem--;
26443e12c5d1SDavid du Colombier 	temp1[nstate] = yypgo[0] = pmem - mem0;
26453e12c5d1SDavid du Colombier 	for(;;) {
26463e12c5d1SDavid du Colombier 		switch(gtnm()) {
26473e12c5d1SDavid du Colombier 		case '\n':
26483e12c5d1SDavid du Colombier 			nnonter++;
26493e12c5d1SDavid du Colombier 			yypgo[nnonter] = pmem-mem0;
26503e12c5d1SDavid du Colombier 		case ',':
26513e12c5d1SDavid du Colombier 			continue;
26523e12c5d1SDavid du Colombier 		case -1:
26533e12c5d1SDavid du Colombier 			break;
26543e12c5d1SDavid du Colombier 		default:
26553e12c5d1SDavid du Colombier 			error("bad tempfile");
26563e12c5d1SDavid du Colombier 		}
26573e12c5d1SDavid du Colombier 		break;
26583e12c5d1SDavid du Colombier 	}
26593e12c5d1SDavid du Colombier 	pmem--;
26603e12c5d1SDavid du Colombier 	yypgo[nnonter--] = pmem - mem0;
26613e12c5d1SDavid du Colombier 	for(i = 0; i < nstate; i++) {
26623e12c5d1SDavid du Colombier 		k = 32000;
26633e12c5d1SDavid du Colombier 		j = 0;
26643e12c5d1SDavid du Colombier 		q = mem0 + temp1[i+1];
26653e12c5d1SDavid du Colombier 		for(p = mem0 + temp1[i]; p < q ; p += 2) {
26663e12c5d1SDavid du Colombier 			if(*p > j)
26673e12c5d1SDavid du Colombier 				j = *p;
26683e12c5d1SDavid du Colombier 			if(*p < k)
26693e12c5d1SDavid du Colombier 				k = *p;
26703e12c5d1SDavid du Colombier 		}
26713e12c5d1SDavid du Colombier 		/* nontrivial situation */
26723e12c5d1SDavid du Colombier 		if(k <= j) {
26733e12c5d1SDavid du Colombier 			/* j is now the range */
26743e12c5d1SDavid du Colombier /*			j -= k;			/* call scj */
26753e12c5d1SDavid du Colombier 			if(k > maxoff)
26763e12c5d1SDavid du Colombier 				maxoff = k;
26773e12c5d1SDavid du Colombier 		}
26783e12c5d1SDavid du Colombier 		tystate[i] = (temp1[i+1]-temp1[i]) + 2*j;
26793e12c5d1SDavid du Colombier 		if(j > maxspr)
26803e12c5d1SDavid du Colombier 			maxspr = j;
26813e12c5d1SDavid du Colombier 	}
26823e12c5d1SDavid du Colombier 
26833e12c5d1SDavid du Colombier 	/* initialize ggreed table */
26843e12c5d1SDavid du Colombier 	for(i = 1; i <= nnonter; i++) {
26853e12c5d1SDavid du Colombier 		ggreed[i] = 1;
26863e12c5d1SDavid du Colombier 		j = 0;
26873e12c5d1SDavid du Colombier 
26883e12c5d1SDavid du Colombier 		/* minimum entry index is always 0 */
26893e12c5d1SDavid du Colombier 		q = mem0 + yypgo[i+1] - 1;
26903e12c5d1SDavid du Colombier 		for(p = mem0+yypgo[i]; p < q ; p += 2) {
26913e12c5d1SDavid du Colombier 			ggreed[i] += 2;
26923e12c5d1SDavid du Colombier 			if(*p > j)
26933e12c5d1SDavid du Colombier 				j = *p;
26943e12c5d1SDavid du Colombier 		}
26953e12c5d1SDavid du Colombier 		ggreed[i] = ggreed[i] + 2*j;
26963e12c5d1SDavid du Colombier 		if(j > maxoff)
26973e12c5d1SDavid du Colombier 			maxoff = j;
26983e12c5d1SDavid du Colombier 	}
26993e12c5d1SDavid du Colombier 
27003e12c5d1SDavid du Colombier 	/* now, prepare to put the shift actions into the amem array */
27013e12c5d1SDavid du Colombier 	for(i = 0; i < ACTSIZE; i++)
27023e12c5d1SDavid du Colombier 		amem[i] = 0;
27033e12c5d1SDavid du Colombier 	maxa = amem;
27043e12c5d1SDavid du Colombier 	for(i = 0; i < nstate; i++) {
27053e12c5d1SDavid du Colombier 		if(tystate[i] == 0 && adb > 1)
27063e12c5d1SDavid du Colombier 			Bprint(ftable, "State %d: null\n", i);
27073e12c5d1SDavid du Colombier 		indgo[i] = YYFLAG1;
27083e12c5d1SDavid du Colombier 	}
27093e12c5d1SDavid du Colombier 	while((i = nxti()) != NOMORE)
27103e12c5d1SDavid du Colombier 		if(i >= 0)
27113e12c5d1SDavid du Colombier 			stin(i);
27123e12c5d1SDavid du Colombier 		else
27133e12c5d1SDavid du Colombier 			gin(-i);
27143e12c5d1SDavid du Colombier 
27153e12c5d1SDavid du Colombier 	/* print amem array */
27163e12c5d1SDavid du Colombier 	if(adb > 2 )
27173e12c5d1SDavid du Colombier 		for(p = amem; p <= maxa; p += 10) {
27187dd7cddfSDavid du Colombier 			Bprint(ftable, "%4d  ", (int)(p-amem));
27193e12c5d1SDavid du Colombier 			for(i = 0; i < 10; ++i)
27203e12c5d1SDavid du Colombier 				Bprint(ftable, "%4d  ", p[i]);
27213e12c5d1SDavid du Colombier 			Bprint(ftable, "\n");
27223e12c5d1SDavid du Colombier 		}
27233e12c5d1SDavid du Colombier 
27243e12c5d1SDavid du Colombier 	/* write out the output appropriate to the language */
27253e12c5d1SDavid du Colombier 	aoutput();
27263e12c5d1SDavid du Colombier 	osummary();
27273e12c5d1SDavid du Colombier 	ZAPFILE(tempname);
27283e12c5d1SDavid du Colombier }
27293e12c5d1SDavid du Colombier 
27303e12c5d1SDavid du Colombier void
gin(int i)27313e12c5d1SDavid du Colombier gin(int i)
27323e12c5d1SDavid du Colombier {
27333e12c5d1SDavid du Colombier 	int *p, *r, *s, *q1, *q2;
27343e12c5d1SDavid du Colombier 
27353e12c5d1SDavid du Colombier 	/* enter gotos on nonterminal i into array amem */
27363e12c5d1SDavid du Colombier 	ggreed[i] = 0;
27373e12c5d1SDavid du Colombier 
27383e12c5d1SDavid du Colombier 	q2 = mem0+ yypgo[i+1] - 1;
27393e12c5d1SDavid du Colombier 	q1 = mem0 + yypgo[i];
27403e12c5d1SDavid du Colombier 
27413e12c5d1SDavid du Colombier 	/* now, find amem place for it */
27423e12c5d1SDavid du Colombier 	for(p = amem; p < &amem[ACTSIZE]; p++) {
27433e12c5d1SDavid du Colombier 		if(*p)
27443e12c5d1SDavid du Colombier 			continue;
27453e12c5d1SDavid du Colombier 		for(r = q1; r < q2; r += 2) {
27463e12c5d1SDavid du Colombier 			s = p + *r + 1;
27473e12c5d1SDavid du Colombier 			if(*s)
27483e12c5d1SDavid du Colombier 				goto nextgp;
27493e12c5d1SDavid du Colombier 			if(s > maxa)
27503e12c5d1SDavid du Colombier 				if((maxa = s) > &amem[ACTSIZE])
27513e12c5d1SDavid du Colombier 					error("a array overflow");
27523e12c5d1SDavid du Colombier 		}
27533e12c5d1SDavid du Colombier 		/* we have found amem spot */
27543e12c5d1SDavid du Colombier 		*p = *q2;
27553e12c5d1SDavid du Colombier 		if(p > maxa)
27563e12c5d1SDavid du Colombier 			if((maxa = p) > &amem[ACTSIZE])
27573e12c5d1SDavid du Colombier 				error("a array overflow");
27583e12c5d1SDavid du Colombier 		for(r = q1; r < q2; r += 2) {
27593e12c5d1SDavid du Colombier 			s = p + *r + 1;
27603e12c5d1SDavid du Colombier 			*s = r[1];
27613e12c5d1SDavid du Colombier 		}
27623e12c5d1SDavid du Colombier 		pgo[i] = p-amem;
27633e12c5d1SDavid du Colombier 		if(adb > 1)
27643e12c5d1SDavid du Colombier 			Bprint(ftable, "Nonterminal %d, entry at %d\n", i, pgo[i]);
27653e12c5d1SDavid du Colombier 		return;
27663e12c5d1SDavid du Colombier 
27673e12c5d1SDavid du Colombier 	nextgp:;
27683e12c5d1SDavid du Colombier 	}
27693e12c5d1SDavid du Colombier 	error("cannot place goto %d\n", i);
27703e12c5d1SDavid du Colombier }
27713e12c5d1SDavid du Colombier 
27723e12c5d1SDavid du Colombier void
stin(int i)27733e12c5d1SDavid du Colombier stin(int i)
27743e12c5d1SDavid du Colombier {
27753e12c5d1SDavid du Colombier 	int *r, *s, n, flag, j, *q1, *q2;
27763e12c5d1SDavid du Colombier 
27773e12c5d1SDavid du Colombier 	tystate[i] = 0;
27783e12c5d1SDavid du Colombier 
27793e12c5d1SDavid du Colombier 	/* enter state i into the amem array */
27803e12c5d1SDavid du Colombier 	q2 = mem0+temp1[i+1];
27813e12c5d1SDavid du Colombier 	q1 = mem0+temp1[i];
27823e12c5d1SDavid du Colombier 	/* find an acceptable place */
27833e12c5d1SDavid du Colombier 	for(n = -maxoff; n < ACTSIZE; n++) {
27843e12c5d1SDavid du Colombier 		flag = 0;
27853e12c5d1SDavid du Colombier 		for(r = q1; r < q2; r += 2) {
27863e12c5d1SDavid du Colombier 			if((s = *r + n + amem) < amem)
27873e12c5d1SDavid du Colombier 				goto nextn;
27883e12c5d1SDavid du Colombier 			if(*s == 0)
27893e12c5d1SDavid du Colombier 				flag++;
27903e12c5d1SDavid du Colombier 			else
27913e12c5d1SDavid du Colombier 				if(*s != r[1])
27923e12c5d1SDavid du Colombier 					goto nextn;
27933e12c5d1SDavid du Colombier 		}
27943e12c5d1SDavid du Colombier 
27953e12c5d1SDavid du Colombier 		/* check that the position equals another only if the states are identical */
27963e12c5d1SDavid du Colombier 		for(j=0; j<nstate; j++) {
27973e12c5d1SDavid du Colombier 			if(indgo[j] == n) {
27983e12c5d1SDavid du Colombier 
27993e12c5d1SDavid du Colombier 				/* we have some disagreement */
28003e12c5d1SDavid du Colombier 				if(flag)
28013e12c5d1SDavid du Colombier 					goto nextn;
28023e12c5d1SDavid du Colombier 				if(temp1[j+1]+temp1[i] == temp1[j]+temp1[i+1]) {
28033e12c5d1SDavid du Colombier 
28043e12c5d1SDavid du Colombier 					/* states are equal */
28053e12c5d1SDavid du Colombier 					indgo[i] = n;
28063e12c5d1SDavid du Colombier 					if(adb > 1)
28073e12c5d1SDavid du Colombier 						Bprint(ftable,
28083e12c5d1SDavid du Colombier 						"State %d: entry at %d equals state %d\n",
28093e12c5d1SDavid du Colombier 						i, n, j);
28103e12c5d1SDavid du Colombier 					return;
28113e12c5d1SDavid du Colombier 				}
28123e12c5d1SDavid du Colombier 
28133e12c5d1SDavid du Colombier 				/* we have some disagreement */
28143e12c5d1SDavid du Colombier 				goto nextn;
28153e12c5d1SDavid du Colombier 			}
28163e12c5d1SDavid du Colombier 		}
28173e12c5d1SDavid du Colombier 
28183e12c5d1SDavid du Colombier 		for(r = q1; r < q2; r += 2) {
28193e12c5d1SDavid du Colombier 			if((s = *r+n+amem) >= &amem[ACTSIZE])
28203e12c5d1SDavid du Colombier 				error("out of space in optimizer a array");
28213e12c5d1SDavid du Colombier 			if(s > maxa)
28223e12c5d1SDavid du Colombier 				maxa = s;
28233e12c5d1SDavid du Colombier 			if(*s != 0 && *s != r[1])
28243e12c5d1SDavid du Colombier 				error("clobber of a array, pos'n %d, by %d", s-amem, r[1]);
28253e12c5d1SDavid du Colombier 			*s = r[1];
28263e12c5d1SDavid du Colombier 		}
28273e12c5d1SDavid du Colombier 		indgo[i] = n;
28283e12c5d1SDavid du Colombier 		if(adb > 1)
28293e12c5d1SDavid du Colombier 			Bprint(ftable, "State %d: entry at %d\n", i, indgo[i]);
28303e12c5d1SDavid du Colombier 		return;
28313e12c5d1SDavid du Colombier 	nextn:;
28323e12c5d1SDavid du Colombier 	}
28333e12c5d1SDavid du Colombier 	error("Error; failure to place state %d\n", i);
28343e12c5d1SDavid du Colombier }
28353e12c5d1SDavid du Colombier 
28363e12c5d1SDavid du Colombier /*
28373e12c5d1SDavid du Colombier  * finds the next i
28383e12c5d1SDavid du Colombier  */
28393e12c5d1SDavid du Colombier int
nxti(void)28403e12c5d1SDavid du Colombier nxti(void)
28413e12c5d1SDavid du Colombier {
28423e12c5d1SDavid du Colombier 	int i, max, maxi;
28433e12c5d1SDavid du Colombier 
28443e12c5d1SDavid du Colombier 	max = 0;
28453e12c5d1SDavid du Colombier 	maxi = 0;
28463e12c5d1SDavid du Colombier 	for(i = 1; i <= nnonter; i++)
28473e12c5d1SDavid du Colombier 		if(ggreed[i] >= max) {
28483e12c5d1SDavid du Colombier 			max = ggreed[i];
28493e12c5d1SDavid du Colombier 			maxi = -i;
28503e12c5d1SDavid du Colombier 		}
28513e12c5d1SDavid du Colombier 	for(i = 0; i < nstate; ++i)
28523e12c5d1SDavid du Colombier 		if(tystate[i] >= max) {
28533e12c5d1SDavid du Colombier 			max = tystate[i];
28543e12c5d1SDavid du Colombier 			maxi = i;
28553e12c5d1SDavid du Colombier 		}
28563e12c5d1SDavid du Colombier 	if(nxdb)
28573e12c5d1SDavid du Colombier 		Bprint(ftable, "nxti = %d, max = %d\n", maxi, max);
28583e12c5d1SDavid du Colombier 	if(max == 0)
28593e12c5d1SDavid du Colombier 		return NOMORE;
28603e12c5d1SDavid du Colombier 	return maxi;
28613e12c5d1SDavid du Colombier }
28623e12c5d1SDavid du Colombier 
28633e12c5d1SDavid du Colombier /*
28643e12c5d1SDavid du Colombier  * write summary
28653e12c5d1SDavid du Colombier  */
28663e12c5d1SDavid du Colombier void
osummary(void)28673e12c5d1SDavid du Colombier osummary(void)
28683e12c5d1SDavid du Colombier {
28693e12c5d1SDavid du Colombier 
28703e12c5d1SDavid du Colombier 	int i, *p;
28713e12c5d1SDavid du Colombier 
28723e12c5d1SDavid du Colombier 	if(foutput == 0)
28733e12c5d1SDavid du Colombier 		return;
28743e12c5d1SDavid du Colombier 	i = 0;
28753e12c5d1SDavid du Colombier 	for(p = maxa; p >= amem; p--)
28763e12c5d1SDavid du Colombier 		if(*p == 0)
28773e12c5d1SDavid du Colombier 			i++;
28783e12c5d1SDavid du Colombier 
28793e12c5d1SDavid du Colombier 	Bprint(foutput, "Optimizer space used: input %d/%d, output %d/%d\n",
28807dd7cddfSDavid du Colombier 		(int)(pmem-mem0+1), MEMSIZE, (int)(maxa-amem+1), ACTSIZE);
28817dd7cddfSDavid du Colombier 	Bprint(foutput, "%d table entries, %d zero\n", (int)(maxa-amem+1), i);
28823e12c5d1SDavid du Colombier 	Bprint(foutput, "maximum spread: %d, maximum offset: %d\n", maxspr, maxoff);
28833e12c5d1SDavid du Colombier }
28843e12c5d1SDavid du Colombier 
28853e12c5d1SDavid du Colombier /*
28863e12c5d1SDavid du Colombier  * this version is for C
28873e12c5d1SDavid du Colombier  * write out the optimized parser
28883e12c5d1SDavid du Colombier  */
28893e12c5d1SDavid du Colombier void
aoutput(void)28903e12c5d1SDavid du Colombier aoutput(void)
28913e12c5d1SDavid du Colombier {
28927dd7cddfSDavid du Colombier 	Bprint(ftable, "#define\tYYLAST\t%d\n", (int)(maxa-amem+1));
28933e12c5d1SDavid du Colombier 	arout("yyact", amem, (maxa-amem)+1);
28943e12c5d1SDavid du Colombier 	arout("yypact", indgo, nstate);
28953e12c5d1SDavid du Colombier 	arout("yypgo", pgo, nnonter+1);
28963e12c5d1SDavid du Colombier }
28973e12c5d1SDavid du Colombier 
28983e12c5d1SDavid du Colombier void
arout(char * s,int * v,int n)28993e12c5d1SDavid du Colombier arout(char *s, int *v, int n)
29003e12c5d1SDavid du Colombier {
29013e12c5d1SDavid du Colombier 	int i;
29023e12c5d1SDavid du Colombier 
29033e12c5d1SDavid du Colombier 	Bprint(ftable, "short	%s[] =\n{", s);
29043e12c5d1SDavid du Colombier 	for(i = 0; i < n;) {
29053e12c5d1SDavid du Colombier 		if(i%10 == 0)
29063e12c5d1SDavid du Colombier 			Bprint(ftable, "\n");
29073e12c5d1SDavid du Colombier 		Bprint(ftable, "%4d", v[i]);
29083e12c5d1SDavid du Colombier 		i++;
29093e12c5d1SDavid du Colombier 		if(i == n)
29103e12c5d1SDavid du Colombier 			Bprint(ftable, "\n};\n");
29113e12c5d1SDavid du Colombier 		else
29123e12c5d1SDavid du Colombier 			Bprint(ftable, ",");
29133e12c5d1SDavid du Colombier 	}
29143e12c5d1SDavid du Colombier }
29153e12c5d1SDavid du Colombier 
29163e12c5d1SDavid du Colombier /*
29173e12c5d1SDavid du Colombier  * read and convert an integer from the standard input
29183e12c5d1SDavid du Colombier  * return the terminating character
29193e12c5d1SDavid du Colombier  * blanks, tabs, and newlines are ignored
29203e12c5d1SDavid du Colombier  */
29213e12c5d1SDavid du Colombier int
gtnm(void)29223e12c5d1SDavid du Colombier gtnm(void)
29233e12c5d1SDavid du Colombier {
29247dd7cddfSDavid du Colombier 	int sign, val, c;
29253e12c5d1SDavid du Colombier 
29267dd7cddfSDavid du Colombier 	sign = 0;
29273e12c5d1SDavid du Colombier 	val = 0;
29283e12c5d1SDavid du Colombier 	while((c=Bgetrune(finput)) != Beof) {
29297dd7cddfSDavid du Colombier 		if(isdigit(c)) {
29303e12c5d1SDavid du Colombier 			val = val*10 + c-'0';
29317dd7cddfSDavid du Colombier 			continue;
29327dd7cddfSDavid du Colombier 		}
29337dd7cddfSDavid du Colombier 		if(c == '-') {
29347dd7cddfSDavid du Colombier 			sign = 1;
29357dd7cddfSDavid du Colombier 			continue;
29367dd7cddfSDavid du Colombier 		}
29373e12c5d1SDavid du Colombier 		break;
29383e12c5d1SDavid du Colombier 	}
29397dd7cddfSDavid du Colombier 	if(sign)
29407dd7cddfSDavid du Colombier 		val = -val;
29417dd7cddfSDavid du Colombier 	*pmem++ = val;
29427dd7cddfSDavid du Colombier 	if(pmem >= &mem0[MEMSIZE])
29433e12c5d1SDavid du Colombier 		error("out of space");
29443e12c5d1SDavid du Colombier 	return c;
29453e12c5d1SDavid du Colombier }
2946