/* 
 * Some grammar independent code.
 * This file is copied into Lpars.c.
 */

# ifndef lint
static char *rcsid = "$Header$";
# endif

# ifdef LL_DEBUG
# include <stdio.h>
# endif

int		LLsymb;
unsigned int	LLtcnt[LL_NTERMINALS];
unsigned int	LLscnt[LL_NSETS];
int		LLcsymb, LLsymb;
static int	LLlevel;

/* In this file are defined: */
extern		LLread();
extern int	LLskip();
extern int	LLnext();
extern		LLscan();
extern		LLerror();
# ifndef LLNOFIRSTS
extern int	LLfirst();
# endif
extern		LLnewlevel();
extern		LLoldlevel();

LLscan(t) {
	/*
	 * Check if the next symbol is equal to the parameter
	 */
	if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE;
	if (LLsymb == t) {
		return;
	}
	/*
	 * If we come here, an error has been detected
	 */
	LLerror(t);
}

LLread() {
	for (;;) {
		if ((LLsymb = LL_LEXI()) <= 0) LLsymb = EOFILE;
		if ((LLcsymb = LLindex[LLsymb]) >= 0) return;
		LLmessage(0);
	}
	/* NOTREACHED */
}

LLerror(t) {
	register int i;

#ifdef LL_NEWMESS
	if (t == EOFILE) {
		LLmessage(-1);
		while ((LLsymb = LL_LEXI()) > 0) /* nothing */ ;
		return;
	}
#endif
	if ((LLcsymb = LLindex[LLsymb]) < 0) {
		LLmessage(0);
		LLread();
	}
	i = LLindex[t];
	LLtcnt[i]++;
	if (LLskip()) /* nothing */;
	LLtcnt[i]--;
	if (LLsymb != t) LLmessage(t);
}

# ifndef LLNOFIRSTS
LLfirst(x, d) {
	register int i;

	return (i = LLindex[x]) >= 0 &&
		(LLsets[d + (i >> 3)] & (1 << (i & 07)));
}
# endif

LLnext(n) {

	if (LLskip()) /* nothing */;
	if (n <= 0) return (LLsets[(LLcsymb >> 3) - n] & (1 << (LLcsymb & 07)));
	return LLsymb == n;
}

LLskip() {
	register int i;
	int retval;
	int LLi, LLb;

	retval = 0;
	for (;;) {
		if (LLtcnt[LLcsymb] != 0) return retval;
		LLi = LLcsymb >> 3;
		LLb = 1 << (LLcsymb & 07);
		for (i = LL_NSETS - 1; i >= 0; i--) {
			if (LLscnt[i] != 0) {
				if (LLsets[LL_SSIZE*i+LLi] & LLb) return retval;
			}
		}
		retval = 1;
		LLmessage(0);
		LLread();
	}
	/* NOTREACHED */
}

LLnewlevel(LLsinfo) unsigned int *LLsinfo; {
	register int i;

	if (LLlevel++) {
		LLsinfo[LL_NSETS+LL_NTERMINALS] = (unsigned) LLsymb;
		LLsinfo[LL_NSETS+LL_NTERMINALS+1] = (unsigned) LLcsymb;
		for (i = LL_NTERMINALS - 1; i >= 0; i--) {
			LLsinfo[i] = LLtcnt[i];
			LLtcnt[i] = 0;
		}
		for (i = LL_NSETS - 1; i >= 0; i--) {
			LLsinfo[LL_NTERMINALS+i] = LLscnt[i];
			LLscnt[i] = 0;
		}
	}
	LLtincr(0);
}

LLoldlevel(LLsinfo) unsigned int *LLsinfo; {
	register int i;

	LLtdecr(0);
# ifdef LL_DEBUG
	for (i = 0; i < LL_NTERMINALS; i++) LL_assert(LLtcnt[i] == 0);
	for (i = 0; i < LL_NSETS; i++) LL_assert(LLscnt[i] == 0);
# endif
	if (--LLlevel) {
		for (i = LL_NSETS - 1; i >= 0; i--) {
			LLscnt[i] = LLsinfo[LL_NTERMINALS+i];
		}
		for (i = LL_NTERMINALS - 1; i >= 0; i--) {
			LLtcnt[i] = LLsinfo[i];
		}
		LLsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS];
		LLcsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS+1];
	}
}

# ifdef LL_DEBUG
LL_badassertion(asstr,file,line) char *asstr, *file; {

	fprintf(stderr,"Assertion \"%s\" failed %s(%d)\n",asstr,file,line);
	abort();
}
# endif
