#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	antlr.c
#	chk.c
#	err.c
#	fset.c
#	gen.c
#	lexhelp.c
#	main.c
#	makefile
#	parser.dlg
#	scan.c
#	set.c
#	set.h
#	struct.h
#	tokens.h
#	trax.c
# This archive created: Fri Mar 23 17:48:24 1990
# By:	CARP Research Group ()
export PATH; PATH=/bin:$PATH
if test -f 'antlr.c'
then
	echo shar: will not over-write existing file "'antlr.c'"
else
cat << \SHAR_EOF > 'antlr.c'
/*
 * A n t l r  T r a n s l a t i o n  H e a d e r
 *
 * This file translated from: antlr.g
 *
 * (c) 1989, 1990 by Terence Parr, Hank Dietz and Will Cohen
 * Purdue University Electrical Engineering
 * ANTLR Version 1.0B
 */
#include <stdio.h>
#define aError(a,b)    dfltError(a,b)
#include "set.h"
#include "struct.h"
#ifdef MEMCHK
#include "trax.h"
#endif
#include "dlgdef.h"
#include "attrib.h"
#include "tokens.h"
extern unsigned char err[][4];
extern char *tokens[];
#ifndef aStackSize
#define aStackSize 200
#endif
Attrib	aStack[aStackSize];
int		_asp=aStackSize;

#ifdef MPW
/*#pragma segment Antlr*/
#endif
static int newToken;	/* Was last token, new? */
static char tokStr[MaxTokenSize+1];
static int r=0,rf=0,fa=0;
grammar()
{
	RULEvars;
	BLKvars;
	int act=0,t,tl,rl=0;
	InitStrArray(ActStr);
	InitStrArray(ActStr2);
	InitStrArray(FailActionStr);
	InitRules(Rules);
	InitRuleFile(RuleFile);
	InitRuleLine(RuleLine);
	EnterBLK;
	EnterRule;
	Make0;
	{
	BLKvars;
	EnterBLK;
	switch ( Token )
	{
	case 7 : /* "#attrib" */
		Munch;
		if ( !lex(Action) ) { aError(Action,1); goto Fail; }
		AttribAction = aArg(2).atom.ptr.action;
		break;
	case Action :
	case Eof :
	case 9 : /* "#lex" */
	case NonTerminal :
	case 14 : /* "#token" */
		break;
	default : aError(&(err[0][0]),0); goto Fail;
	}
	ExitBLK;
	}
	Make0;
	{
	BLKvars;
	EnterBLK;
	do {
		switch ( Token )
		{
		case Action :
			Munch;
			extStrArray(ActStr, act);
			ActStr[act] = aArg(1).atom.ptr.action;
			break;
		case Eof :
		case 9 : /* "#lex" */
		case NonTerminal :
		case 14 : /* "#token" */
			goto _L0;
		default : aError(&(err[1][0]),0); goto Fail;
		}
		sREL;
	} while (1);
	_L0: ;
	ExitBLK;
	}
	/*extStrArray(ActStr, act); ActStr[act] = NULL;*/ 
	act=0; InitAlxFile(); 
	Make0; if (!lexStuff()) goto Fail;
	AlxSep(); t = CurFile; tl=lex_line;
	Make0;
	{
	BLKvars;
	EnterBLK;
	while ( Token==NonTerminal || Token==14 )
	{
		Make0; if (!rule()) goto Fail;
		if ( aArg(1).blk != NULL )
		{
			defRule(r, aArg(1).blk);
			defRuleFile(rf, t);
			defRuleLine(rl, tl);
			NumRules++;
		}
		t = CurFile; tl=lex_line;
		sREL;
	}
	if (!( Token==Action || Token==Eof || Token==9 )) {aError(&(err[2][0]),0); goto Fail;}
	ExitBLK;
	}
	defRule(r, NULL); 
	{	int new;
		EofToken = defTname("Eof", "\"@\"", &new );	/* Make sure EOF is defined */
		if ( new ) DmpAlxRule("\"@\"","Eof",EofToken,NULL);
	}
	AlxSep();
	Make0; if (!lexStuff()) goto Fail;
	Make0;
	{
	BLKvars;
	EnterBLK;
	while ( Token==Action )
	{
		Munch;
		extStrArray(ActStr2, act);
		ActStr2[act] = aArg(1).atom.ptr.action;
		sREL;
	}
	if (!( Token==Eof )) {aError(&(err[3][0]),0); goto Fail;}
	ExitBLK;
	}
	/*extStrArray(ActStr2, act); ActStr2[act] = NULL;*/ 
	if ( !lex(Eof) ) { aError(Eof,1); goto Fail; }
	CloseAlxFile(); 
	SUCCESS;
Fail: ;
	Terminate = 1; 
	FAILURE;
}

lexStuff()
{
	RULEvars;
	BLKvars;
	EnterBLK;
	EnterRule;
	Make0;
	{
	BLKvars;
	EnterBLK;
	do {
		switch ( Token )
		{
		case 9 : /* "#lex" */
			Munch;
			if ( !lex(10) ) { aError(10,1); goto Fail; }
			if ( !lex(Action) ) { aError(Action,1); goto Fail; }
			DmpAlxAction(aArg(3).atom.ptr.action, 0);
			free(aArg(3).atom.ptr.action);
			break;
		case Action :
		case Eof :
		case NonTerminal :
		case 14 : /* "#token" */
			goto _L1;
		default : aError(&(err[4][0]),0); goto Fail;
		}
		sREL;
	} while (1);
	_L1: ;
	ExitBLK;
	}
	SUCCESS;
Fail: ;
	FAILURE;
}

rule()
{
	RULEvars;
	BLKvars;
	int n,t,l; char *action; Atom **b=NULL; char *buf[MaxTokenSize+1];
	EnterBLK;
	EnterRule;
	if ( Token==NonTerminal ) {
		if ( !lex(NonTerminal) ) { aError(NonTerminal,1); goto Fail; }
		defRname(aArg(1).atom.ptr.rule); free(aArg(1).atom.ptr.rule);
		if ( !lex(12) ) { aError(12,1); goto Fail; }
		Make0; if (!block()) goto Fail;
		b=aArg(3).blk;
		if ( !lex(13) ) { aError(13,1); goto Fail; }
		extStrArray(FailActionStr, fa);
		Make0;
		{
		BLKvars;
		EnterBLK;
		switch ( Token )
		{
		case Action :
			Munch;
			FailActionStr[fa] = aArg(1).atom.ptr.action;
			break;
		case Eof :
		case 9 : /* "#lex" */
		case NonTerminal :
		case 14 : /* "#token" */
			break;
		default : aError(&(err[5][0]),0); goto Fail;
		}
		ExitBLK;
		}
		/*extStrArray(FailActionStr, fa); FailActionStr[fa--] = NULL;*/ 
		aArg(0).blk=aArg(3).blk;
	}
	else if ( Token==14 ) {
		Munch;
		Make0;
		{
		BLKvars;
		EnterBLK;
		if ( Token==TokenTerm ) {
			Munch;
			strncpy(buf,tokStr,MaxTokenSize); l = lex_line;
			Make0;
			{
			BLKvars;
			EnterBLK;
			switch ( Token )
			{
			case QuotedTerm :
				Munch;
				t=defTname(buf,tokStr,&n);
				break;
			case Action :
			case Eof :
			case 9 : /* "#lex" */
			case NonTerminal :
			case 14 : /* "#token" */
				t=defTname(buf, NULL, &n);
				break;
			default : aError(&(err[6][0]),0); goto Fail;
			}
			ExitBLK;
			}
			Make0;
			{
			BLKvars;
			action=NULL;
			EnterBLK;
			switch ( Token )
			{
			case Action :
				if ( !lex(Action) ) { aError(Action,1); goto Fail; }
				action=aArg(1).atom.ptr.action;
				break;
			case Eof :
			case 9 : /* "#lex" */
			case NonTerminal :
			case 14 : /* "#token" */
				break;
			default : aError(&(err[7][0]),0); goto Fail;
			}
			ExitBLK;
			}
			if ( RegExprStr[t] != NULL )
			DmpAlxRule(RegExprStr[t],TokenStr[t],t,action);
			if ( action != NULL ) free(action); 
		}
		else if ( Token==QuotedTerm ) {
			Munch;
			t = defTname(NULL, tokStr, &n);
			Make0;
			{
			BLKvars;
			action=NULL;
			EnterBLK;
			switch ( Token )
			{
			case Action :
				if ( !lex(Action) ) { aError(Action,1); goto Fail; }
				action=aArg(1).atom.ptr.action;
				break;
			case Eof :
			case 9 : /* "#lex" */
			case NonTerminal :
			case 14 : /* "#token" */
				break;
			default : aError(&(err[8][0]),0); goto Fail;
			}
			ExitBLK;
			}
			if ( n )
			{
				DmpAlxRule(RegExprStr[t],TokenStr[t],t,action);
				if ( action != NULL ) free(action);
			}
			else
			{
				warnFL( eMsg("token %s redefinition; ignored", tokStr),
				FileStr[CurFile], l ); 
			}
		}
		else {aError(&(err[9][0]),0); goto Fail;}
		ExitBLK;
		}
		aArg(0).blk = NULL;
	}
	else {aError(&(err[10][0]),0); goto Fail;}
	SUCCESS;
Fail: ;
	if ( b!=NULL ) freeBlk(b);
	FAILURE;
}

block()
{
	RULEvars;
	BLKvars;
	int i=0; Atom **b; InitBlock(b);
	EnterBLK;
	EnterRule;
	Make0; if (!alt()) goto Fail;
	defBlk(b,i, aArg(1).alt); defBlk(b,i,NULL); i--;
	Make0;
	{
	BLKvars;
	EnterBLK;
	while ( Token==17 )
	{
		Munch;
		Make0; if (!alt()) goto Fail;
		defBlk(b,i,aArg(2).alt); defBlk(b,i,NULL); i--; 
		sREL;
	}
	if (!( Token==13 || Token==20 || Token==23 )) {aError(&(err[11][0]),0); goto Fail;}
	ExitBLK;
	}
	aArg(0).blk = b; 
	SUCCESS;
Fail: ;
	freeBlk(b);
	FAILURE;
}

alt()
{
	RULEvars;
	BLKvars;
	int i=0; Atom *a; InitAlt(a); extAlt(a,i); a[i--].type = EOL;
	EnterBLK;
	EnterRule;
	Make0;
	{
	BLKvars;
	EnterBLK;
	do {
		switch ( Token )
		{
		case Action :
		case NonTerminal :
		case TokenTerm :
		case QuotedTerm :
		case 19 : /* "\(" */
		case 22 : /* "\{" */
			Make0; if (!element()) goto Fail;
			defAlt(a,i,aArg(1).atom);
			setParPtrs(&(a[i]));
			extAlt(a,i); a[i--].type = EOL;
			break;
		case 13 : /* ";" */
		case 17 : /* "\|" */
		case 20 : /* "\)" */
		case 23 : /* "\}" */
			goto _L2;
		default : aError(&(err[12][0]),0); goto Fail;
		}
		sREL;
	} while (1);
	_L2: ;
	ExitBLK;
	}
	aArg(0).alt = a; 
	SUCCESS;
Fail: ;
	freeAlt(a);
	FAILURE;
}

element()
{
	RULEvars;
	BLKvars;
	int type,t,l; Atom **b=NULL;
	EnterBLK;
	EnterRule;
	switch ( Token )
	{
	case QuotedTerm :
		if ( !lex(QuotedTerm) ) { aError(QuotedTerm,1); goto Fail; }
		t = defTname(NULL, tokStr, &newToken);
		if ( newToken )
		{
			DmpAlxRule(RegExprStr[t],TokenStr[t],t,NULL);
		}
		aArg(1).atom.token = t;
		aRet=aArg(1);
		break;
	case TokenTerm :
		Munch;
		aArg(1).atom.token=defTname(tokStr,NULL,&newToken);
		aRet=aArg(1);
		break;
	case NonTerminal :
		Munch;
		aRet=aArg(1);
		Make0;
		{
		BLKvars;
		EnterBLK;
		switch ( Token )
		{
		case Override :
			Munch;
			aRet.atom.inheritance = aArg(1).inh;
			break;
		case Action :
		case NonTerminal :
		case 13 : /* ";" */
		case TokenTerm :
		case QuotedTerm :
		case 17 : /* "\|" */
		case 19 : /* "\(" */
		case 20 : /* "\)" */
		case 22 : /* "\{" */
		case 23 : /* "\}" */
			break;
		default : aError(&(err[13][0]),0); goto Fail;
		}
		ExitBLK;
		}
		break;
	case 19 : /* "\(" */
		Munch;
		l=lex_line;
		Make0; if (!block()) goto Fail;
		b=aArg(2).blk;
		if ( !lex(20) ) { aError(20,1); goto Fail; }
		Make0;
		{
		BLKvars;
		type=aSubBLK;
		EnterBLK;
		switch ( Token )
		{
		case 21 : /* "\*" */
			if ( !lex(21) ) { aError(21,1); goto Fail; }
			type=aLoopBLK;
			break;
		case Action :
		case NonTerminal :
		case 13 : /* ";" */
		case TokenTerm :
		case QuotedTerm :
		case 17 : /* "\|" */
		case Override :
		case 19 : /* "\(" */
		case 20 : /* "\)" */
		case 22 : /* "\{" */
		case 23 : /* "\}" */
			break;
		default : aError(&(err[14][0]),0); goto Fail;
		}
		ExitBLK;
		}
		makeBlkAtom(aArg(0).atom,type,b,l);
		Make0;
		{
		BLKvars;
		EnterBLK;
		switch ( Token )
		{
		case Override :
			Munch;
			aRet.atom.inheritance = aArg(1).inh;
			break;
		case Action :
		case NonTerminal :
		case 13 : /* ";" */
		case TokenTerm :
		case QuotedTerm :
		case 17 : /* "\|" */
		case 19 : /* "\(" */
		case 20 : /* "\)" */
		case 22 : /* "\{" */
		case 23 : /* "\}" */
			break;
		default : aError(&(err[15][0]),0); goto Fail;
		}
		ExitBLK;
		}
		if ( emptyBlk(b) )
		warnFL( "warning: empty subblock; ignored",
		FileStr[CurFile], l ); 
		break;
	case 22 : /* "\{" */
		Munch;
		l=lex_line;
		Make0; if (!block()) goto Fail;
		b=aArg(2).blk;
		if ( !lex(23) ) { aError(23,1); goto Fail; }
		makeBlkAtom(aArg(0).atom,aOptBLK,b,l);
		Make0;
		{
		BLKvars;
		EnterBLK;
		switch ( Token )
		{
		case Override :
			Munch;
			aRet.atom.inheritance = aArg(1).inh;
			break;
		case Action :
		case NonTerminal :
		case 13 : /* ";" */
		case TokenTerm :
		case QuotedTerm :
		case 17 : /* "\|" */
		case 19 : /* "\(" */
		case 20 : /* "\)" */
		case 22 : /* "\{" */
		case 23 : /* "\}" */
			break;
		default : aError(&(err[16][0]),0); goto Fail;
		}
		ExitBLK;
		}
		if ( emptyBlk(b) )
		warnFL( "warning: empty subblock; ignored",
		FileStr[CurFile], l ); 
		break;
	case Action :
		Munch;
		aRet=aArg(1);
		break;
	default : aError(&(err[17][0]),0); goto Fail;
	}
	SUCCESS;
Fail: ;
	if (b!=NULL) freeBlk(b);
	FAILURE;
}

aCreate(attr)
Attrib *attr;
{
	char *action, *name;
	switch ( Token )
	{
		case QuotedTerm :
		case TokenTerm :
		attr->atom.type = aLeaf;
		attr->atom.line = lex_line;
		attr->atom.file = FileStr[CurFile];
		strncpy(tokStr, LexText, MaxTokenSize);
		break;
		case NonTerminal :
		name = malloc(strlen(LexText)+1);
		if ( name == NULL ) fatal("Can't Alloc Rule Name Space");
		strcpy(name, LexText);
		attr->atom.type = aRule;
		attr->atom.token = 0;
		attr->atom.line = lex_line;
		attr->atom.file = FileStr[CurFile];
		attr->atom.inheritance = NULL;
		attr->atom.ptr.rule = name;
		break;
		case Action :
		action = malloc(strlen(LexText)+1);
		if ( action == NULL ) fatal("Can't Alloc Action Space");
		strcpy(action, LexText);
		attr->atom.type = aAction;
		attr->atom.ptr.action = action;
		break;
		case Override :
		action = malloc(strlen(LexText)+1);
		if ( action == NULL ) fatal("Can't Alloc Override Parm Space");
		strcpy(action, LexText);
		attr->inh = action;
		break;
	}
}
/*
* Set every subrule in every alt of block pointed to by atom 'a' to
* point to 'a' itself.
*
* Recursively call this function to set subblock parents pointers
* of more deeply nested blocks.
*/
setParPtrs(a)
Atom *a;
{
	int alt, atm;
	Atom **blk;
	Atom *altern;
	if ( a->type != aSubBLK &&
	a->type != aOptBLK &&
	a->type != aLoopBLK )
	{
		return;
	}
	blk = a->ptr.block;
	for (alt=1; blk[alt]!=NULL; alt++)
	{
		altern = blk[alt];
		for (atm=1; altern[atm].type != EOL; atm++)
		{
			if ( altern[atm].type == aSubBLK ||
			altern[atm].type == aOptBLK ||
			altern[atm].type == aLoopBLK )
			{
				altern[atm].parent = a;
				setParPtrs( &(altern[atm]) );
			}
		}
	}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'chk.c'
then
	echo shar: will not over-write existing file "'chk.c'"
else
cat << \SHAR_EOF > 'chk.c'
/*
 * chk.c
 *
 * Check the grammar for errors, ambiguities etc...
 *
 * Forced variable names to be unique to 7 char for portability
 * Terence Parr -- March 1990
 */

#include <stdio.h>
#ifdef MEMCHK
#include "trax.h"
#endif
#include "set.h"
#include "struct.h"
#include "attrib.h"

/*
 * Compute firsts of all rules
 */
CheckRules(r)
Atom ***r;
{
	set *f,t;
	int i;
	
	for (i=1; r[i] != NULL; i++)
	{
		chkBlk(r[i], i);
		f = First(i);
		if ( PrintFi ) {
			printf("First(%s) is\n", RuleStr[i]);
			fset_pr( f );
		}
		ambigRule(f, i);
		freeFset(f);
		
		if ( PrintFo ) {
			t = Follow(i);
			printf("Follow(%s) is ", RuleStr[i]);
			set_prT(t);
			printf("\n\n");
			set_free(t);
		}
	}
}

/*
 * chkBblk()
 *
 * Check sub block for problems.
 */
static
chkBlk(b, rule)
Atom **b;
int rule;
{
	int alt, atm;

	for (alt=1; b[alt] != NULL; alt++)
	{
		for (atm=1; b[alt][atm].type != EOL; atm++)
		{
			chkAtom( &(b[alt][atm]), rule );
		}
	}
}

static
chkAtom( a, rule )
Atom *a;
int rule;
{
	set *f;

	switch ( a->type )
	{
		case aRule :
			break;
		case aSubBLK :
		case aOptBLK :
		case aLoopBLK :
			if ( a->ptr.block == NULL ) break;
			if ( emptyBlk(a->ptr.block) ) break;
			fAtom(a, rule, FALSE, &f);
			ambigSub(f, a, rule);
			if ( PrFirstSub && PrintFi )
			{
				printf("First[");
				dispAtom( *a, stdout );
				printf(" ] is\n");
				fset_pr( f );
			}
			chkBlk(a->ptr.block, rule);
			freeFset( f );
			break;
	}
}

ambiguous( f, t, a1, a2 )
set *f;
int *t, *a1, *a2;
{
	int alt, other;
	set g;

	*a1 = *a2 =0;
	for (alt = 0; f[alt].n != 0; alt++)	/* for each alt */
	{
		*a1 = alt;
		for (other=alt+1; f[other].n != 0; other++)
		{
			*a2 = other;
			g = set_and(f[alt], f[other]);
			if ( set_deg(g) > 0 )
			{
				*t = set_int(g);		/* Return 1st Ambiguity */
				set_free(g);
				return( TRUE );
			}
			set_free(g);
		}
	}
	return( FALSE );
}

ambigRule(f,r)
set *f;
int r;
{
	unsigned t, a1, a2, alt;

	if ( ambiguous( f, &t, &a1, &a2 ) )
	{
		if ( a2==0 )
		{
			warnFL( eMsg("warning: alt %d rule %s ambiguous upon %s",
					a1+1,RuleStr[r],TokenName(t)),
				FileStr[RuleFile[r]], RuleLine[r] );
		}
		else
		{
			warnFL( eMsg("warning: alts %d,%d rule %s ambiguous upon %s",
					a1+1,a2+1,RuleStr[r],TokenName(t)),
				FileStr[RuleFile[r]], RuleLine[r] );
		}
	}
	for (alt=0; f[alt].n != 0; alt++)
	{
		if ( set_el(EpToken, f[alt]) )
		{
			warnFL( eMsg("warning: alt %d rule %s empty follow set; assuming EOF",
						alt+1, RuleStr[r]),
					FileStr[RuleFile[r]], RuleLine[r] );
			set_rm(EpToken, f[alt]);
			set_orel(EofToken, &(f[alt]));
		}
	}
}

ambigSub(f, a, r)
set *f;
Atom *a;
unsigned r;
{
	unsigned t,a1,a2,alt;

	if ( ambiguous( f, &t, &a1, &a2 ) )
	{
		warnBlk( *a, eMsg(" [rule %s] ambiguous upon %s",
				RuleStr[r], TokenName(t)) );
	}
	for (alt=0; f[alt].n != 0; alt++)
	{
		if ( set_el(EpToken, f[alt]) )
		{
			warnBlk( *a, eMsg(" [rule %s] empty follow set; assuming EOF",
							RuleStr[r]) );
			set_rm(EpToken, f[alt]);
			set_orel(EofToken, &(f[alt]));
		}
	}
}

InhChk(rule)
Atom ***rule;
{
	register int r;
	
	for (r=1; rule[r] != NULL; r++)
	{
		InhChkBlk(rule[r], r);
	}
}

InhChkBlk(blk, r)
Atom **blk;
int r;
{
	register Atom *alt;
	register int a, atm;
	int t;
	
	for (a=1; blk[a] != NULL; a++)
	{
		alt = blk[a];
		for (atm=1; alt[atm].type != EOL; atm++)
		{
			switch ( alt[atm].type )
			{
				case aSubBLK :
				case aOptBLK :
				case aLoopBLK :
					InhChkBlk(alt[atm].ptr.block, r);
					break;
				case aRule :
					if ( (t=ruleNum(&(alt[atm]))) == 0 ) continue;
					/* Do rule cross reference */
					/* Check Inheritance override consistency */
					if ( alt[atm].inheritance != NULL )
					{
						if ( !set_el(t, RuleInh) && !set_nil( CrossRef[t]) )
						{
							warnFL(
								eMsg("warning: inheritance for rule %s used inconsistently in rule %s",
										 alt[atm].ptr.rule,
										 RuleStr[r]),
								FileStr[RuleFile[r]], RuleLine[r] );
						}
						set_orel(t, &RuleInh);
					}
					else
					{
						if ( set_el(t, RuleInh) )
						{
							warnFL(
								eMsg("warning: inheritance for rule %s used inconsistently in rule %s",
										 alt[atm].ptr.rule,
										 RuleStr[r]),
								FileStr[RuleFile[r]], RuleLine[r] );
						}
					}
					set_orel(r, &(CrossRef[t]));
					break;
			}
		}
	}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'err.c'
then
	echo shar: will not over-write existing file "'err.c'"
else
cat << \SHAR_EOF > 'err.c'
/*
 * A n t l r  E r r o r  T a b l e  H e a d e r
 *
 * Generated from: antlr.g
 *
 * (c) 1989, 1990 by Terence Parr, Hank Dietz and Will Cohen
 * Purdue University Electrical Engineering
 * ANTLR Version 1.0B
 */

#include <stdio.h>
#include "dlgdef.h"
#define nil ((unsigned)-1)
#ifdef MPW		/* Macintosh Programmer's Workshop */
#define ErrHdr "File \"%s\"; Line %d #"
#else
#define ErrHdr "\"%s\", line %d:"
#endif

extern char *tokens[];
char *aSourceFile = "stdin";	/* Set to current src filename */

unsigned *err_decode(p)
register unsigned char *p;
{
	static unsigned bitmask[] = {
		0x00000001, 0x00000002, 0x00000004, 0x00000008,
		0x00000010, 0x00000020, 0x00000040, 0x00000080,
	};
	extern unsigned *malloc();
	register unsigned char *endp = &(p[4]);
	register unsigned *q,*r,e= 0;

	r = q = (unsigned *) malloc(33*sizeof(unsigned));
	if ( q == 0 ) return( 0 );
	do {
		register unsigned t = *p;
		register unsigned *b = &(bitmask[0]);
		do {
			if ( t & *b ) *q++ = e;
			e++;
		} while (++b < &(bitmask[8]));
	} while (++p < endp);
	*q = nil;
	return( r );
}

err_print(e)
unsigned char *e;
{
	unsigned *p, *q;

	if ( (q=p=err_decode(e))==NULL ) return;
	fprintf(stderr, "{");
	while ( *p != nil )
	{
		fprintf(stderr, " %s", tokens[*p++]);
	}
	fprintf(stderr, " }");
	free(q);
}

dfltError(e, single)
union { unsigned char *eset; unsigned tok; } e;
int single;
{
	fprintf(stderr, ErrHdr, aSourceFile, lex_line);
	if ( single )
	{
		fprintf(stderr, " missing %s (Was \"%s\"(%s))\n",
						tokens[(int)e.tok],
						(tokens[Token][0]=='@')?"eof":LexText,
						tokens[Token]);
		return;
	}
	fprintf(stderr, " missing ");
	err_print(e.eset);
	fprintf(stderr, " (Was \"%s\"(%s))\n",
		(tokens[Token][0]=='@')?"eof":LexText, tokens[Token]);
}

char *tokens[24]={
	/* 00 */	"Invalid",
	/* 01 */	"[\t\ ]",
	/* 02 */	"[\n\r]",
	/* 03 */	"/\*",
	/* 04 */	"\*/",
	/* 05 */	"\>\>",
	/* 06 */	"Action",
	/* 07 */	"#attrib",
	/* 08 */	"Eof",
	/* 09 */	"#lex",
	/* 10 */	"action",
	/* 11 */	"NonTerminal",
	/* 12 */	":",
	/* 13 */	";",
	/* 14 */	"#token",
	/* 15 */	"TokenTerm",
	/* 16 */	"QuotedTerm",
	/* 17 */	"\|",
	/* 18 */	"Override",
	/* 19 */	"\(",
	/* 20 */	"\)",
	/* 21 */	"\*",
	/* 22 */	"\{",
	/* 23 */	"\}"
};
unsigned char err[][4]={
{ 0xc0, 0x4b, 0x00, 0x00 },
{ 0x40, 0x4b, 0x00, 0x00 },
{ 0x40, 0x4b, 0x00, 0x00 },
{ 0x40, 0x01, 0x00, 0x00 },
{ 0x40, 0x4b, 0x00, 0x00 },
{ 0x40, 0x4b, 0x00, 0x00 },
{ 0x40, 0x4b, 0x01, 0x00 },
{ 0x40, 0x4b, 0x00, 0x00 },
{ 0x40, 0x4b, 0x00, 0x00 },
{ 0x00, 0x80, 0x01, 0x00 },
{ 0x00, 0x48, 0x00, 0x00 },
{ 0x00, 0x20, 0x92, 0x00 },
{ 0x40, 0xa8, 0xdb, 0x00 },
{ 0x40, 0xa8, 0xdf, 0x00 },
{ 0x40, 0xa8, 0xff, 0x00 },
{ 0x40, 0xa8, 0xdf, 0x00 },
{ 0x40, 0xa8, 0xdf, 0x00 },
{ 0x40, 0x88, 0x49, 0x00 },
{ 0x00 }
};
SHAR_EOF
fi # end of overwriting check
if test -f 'fset.c'
then
	echo shar: will not over-write existing file "'fset.c'"
else
cat << \SHAR_EOF > 'fset.c'
/*
 * F s e t . c
 *
 * This file contains the grammar analysis section of antlr.
 *
 * Terence Parr
 * Purdue University
 * Summer 1989
 *
 * Forced variable names to be unique to 7 char for portability
 * Terence Parr -- March 1990
 */

#include <stdio.h>
#ifdef MEMCHK
#include "trax.h"
#endif
#include "set.h"
#include "struct.h"
#ifdef MPW
/*#pragma segment fset*/
#endif

/*
 * Sometimes the computation of a Follow set will be stopped before completion
 * due to infinite-recursion avoidance checks, namely:
 *		if ( set_el(rule, FoVisit) ) ...Don't Visit rule...
 * This implies that the follow set is incomplete and must be finished later.
 * Two sets are now used for each rule found in a grammar--follow and remainder.
 * The follow set is the current state of the follow computation.  The remainder
 * set is a set of rules (not tokens like the follow) and records the rules that
 * were required for a follow set, but that could not be completed due to infinite
 * recursion.
 *
 * Follow will look into the two tables of sets first to see if a partial solution
 * is known.  If nothing is there, the normal follow computation is initiated.
 * Else, the follow of each rule in the remainder set is attempted and combined
 * with the current follow set.
 *
 * Note that this is very different from the FIRST cache system.  No such complexity
 * is required there.
 *
 * This algorithm modification done January 1990
 * By Terence Parr
 */
static set	*FoCache,		/* Current follow set for a rule */
			*Remainder;		/* Remaining rules needed in follow computation */
static char *FoValid;		/* Is a follow set for a rule valid yet? */

static set **FiCache = NULL;


/*
 * Compute the first set of a rule.
 *
 * Notice that we leave "a trail of bread-crumbs" to detect infinite-recursion
 * (markFi and unMarkFi).
 */
set *
First(rule)
int rule;
{
	set *f;
	set t,u;
	int alt;

	DEBUG(2) {
		fprintf(stderr, "First(%s)\n", RuleStr[rule]);
	}
	f = fBlock(Rules[rule], rule, aRule);

	for (alt=0; f[alt].n != 0; alt++)
	{
		if ( set_el(EpToken, f[alt]) )	/* If optional alternative */
		{
			t = Follow(rule);
			/* Leave Epsilon if follow is empty */
			if ( set_deg(t) != 0 ) set_rm(EpToken, f[alt]);
			u = set_and(f[alt], t); 
			if ( !set_nil(u) )
			{
				warnFLNoCR( eMsg("alt %d rule %s ambiguous",
								alt+1, RuleStr[rule]),
						FileStr[RuleFile[rule]], RuleLine[rule] );
				fprintf(stderr, " upon ");
				if ( set_deg(u) > 1 ) set_fpT(stderr, u);
				else fprintf(stderr, "%s", TokenName(set_int(u)));
				fprintf(stderr, "\n");
			}
			set_orin(&(f[alt]), t);
			set_free( t );
			set_free(u);
		}
	}

	return( f );
}

/*
 * Compute the first set of a block of alternatives.  An array of sets
 * is returned.  set i is the first of alternative i.
 */
set *
fBlock(blk, rule, type)
Block blk;
int rule, type;
{
	set *f;
	int i;
	
	DEBUG(2) fprintf(stderr, "fBlock(%s)\n", RuleStr[rule]);
	/* If Block was cached, use it.  But, only rules are saved for now */
	if ( type == aRule && FiCache[rule] != NULL )	/* If in cache */
	{
		Save++;
		f = dupFset(FiCache[rule]);
	}
	else
	{
		if ( type == aRule ) markFi( rule );
		f = newFset();
		for (i=1; blk[i] != NULL; i++)
		{
			f[i-1] = fAlt(blk[i], rule);
		}
		if ( type == aRule )
		{
			FiCache[rule] = dupFset(f);
			unMarkFi( rule );
		}
	}
	return( f );
}

/*
 * Return the first set of an alternative starting from a
 * specified starting atom --> 'start'.
 *
 * Compute fAtom on each atom starting from 'start' while epsilon is
 * a member of the FIRST set.  In other words, the first of an alternative
 * is the set of all tokens that can possibly begin that alternative either
 * by appearing first or by following optional paths.
 *
 * When optional rule atoms are present, one must make sure that the combined
 * first sets are unique.  This means that one token cannot be accepted by
 * more than one place along the optional paths.
 */
set
fMidAlt(start, rule)
Atom *start;
int rule;
{
	set f, g, u;
	Atom *p;
	
	DEBUG(2) {
		fprintf(stderr, "fMidAlt(%s, @", RuleStr[rule]);
		dispAtom(*start, stderr);
		fprintf(stderr, ")\n");
	}
	p = start;
	skipActions(p);
	if ( p->type == EOL )	/* Epsilon Transfer (empty alternative)? */
	{
		return( set_of(EpToken) );
	}
	f = fAtom(p++, rule, TRUE);
	skipActions(p);
	while ( set_el(EpToken, f) && p->type != EOL )	/* Was atom optional? */
	{
		set_rm(EpToken, f);
		g = fAtom(p, rule, TRUE);
		u = set_and(f, g); 
		if ( !set_nil(u) )
		{
			warnFLNoCR( eMsg("alt of rule %s ambiguous", RuleStr[rule]),
					p->file, p->line );
			fprintf(stderr, " upon ");
			if ( set_deg(u) > 1 ) set_fpT(stderr, u);
			else fprintf(stderr, "%s", TokenName(set_int(u)));
			fprintf(stderr, " near");
			dispAtom( *p, stderr );
			fprintf(stderr, "\n");
		}
		p++;
		set_orin(&f, g);
		set_free(g);
		set_free(u);
		skipActions(p);
	}

	return( f );
}

/*
 * Return the first set of an alternative within a block.
 */
set
fAlt(alt, rule)
Alt alt;
int rule;
{
	return( fMidAlt(&(alt[1]), rule) );
}

/*
 * Compute the first set of an atom.
 * Return the set containing:
 *
 *		one atom			--> If leaf node
 *		First( nonTerm )	--> If atom is rule
 *		fBlock( subBlock )	-->	If atom is a subrule of any type
 *
 * If noAlts, compact f before returning it when subBlock.
 * If !noAlts, a pointer to an array of sets is returned
 *		else a pointer to a single set is returned.
 * If noAlts, then no blk follow is done.
 *
 * noAlts==FALSE only when generating code and you want an array of sets
 * to come back reflecting the FIRST of each alternative within that block.
 */
set
fAtom(atom, rule, noAlts, fset)
Atom *atom;
int rule, noAlts;
set **fset;		/* only used when !noAlts */
{
	int r,n;
	set *f, a;

	DEBUG(2) {
		fprintf(stderr, "fAtom(%s,", RuleStr[rule]);
		dispAtom(*atom, stderr );
		fprintf(stderr, ", %s)\n", noAlts ? "noAlts" : "Alts");
	}
	switch ( atom->type )
	{
		case aLeaf :
			return( set_of(atom->token) );
		case aRule :
			r = ruleNum(atom);
			if ( r == 0 )
			{
				warnFL( eMsg("rule %s undefined", atom->ptr.rule),
						atom->file, atom->line );
				return( empty );
			}
			if ( !set_el(r, FiVisit) )	/* Infinite recursion? */
			{
				f = fBlock(Rules[r], r, aRule);
				a = fCompact(f);
				freeFset(f);
				return( a );
			}
			if ( rule == r )
			{
				warnFL( eMsg("rule %s infinite left-recursion possible", RuleStr[r]),
						atom->file, atom->line );
			}
			else
			{
				warnFL(
					eMsg("rule %s indirect left-recursion to rule %s possible",
						RuleStr[rule], RuleStr[r]),
						atom->file, atom->line );
			}
			return( empty );
		case aSubBLK :
		case aOptBLK :
		case aLoopBLK :
			if ( atom->ptr.block == NULL ) return( set_of(EpToken) );
			if ( emptyBlk(atom->ptr.block) ) return( set_of(EpToken) );
			f = fBlock(atom->ptr.block, rule, atom->type);
			if ( atom->type != aSubBLK )	/* Add implicit Ep Transfer */
			{
				set_orel(EpToken, &(f[nextAlt(f)]));
			}
			if ( (n=multEpsilon(f)) > 1 )
			{
				warnBlk( *atom, eMsg(" [rule %s] has %d epsilon paths",
							RuleStr[rule], n) );
			}
			if ( !noAlts )
			{
				doBlkFollow(f, atom, rule);
				*fset = f;
				return( empty );	/* return value is ignored */
			}
			a = fCompact(f);
			freeFset(f);
			return( a );
	}
	return( empty );
}

/* Compute the follow of a block.  This is similar to the FOLLOW of a rule, but
 * blocks (subrules) can be referenced only in the rule that uses it.
 *
 * Each alternative in the array of sets passed in is checked for optionality
 * (contains epsilon).  If an alternative is optional, the FOLLOW of the subrule
 * computed and appended to the set for that alt.
 */
doBlkFollow(f, atom, rule)
set *f;
Atom *atom;
int rule;
{
	set t,s, fBlkFollow();
	int alt;

	DEBUG(2) {
		fprintf(stderr, "doBlkFollow(%s, @", RuleStr[rule]);
		dispAtom(*atom, stderr);
		fprintf(stderr, ")\n");
	}
	for (alt=0; f[alt].n != 0; alt++)
	{
		if ( set_el(EpToken, f[alt]) )
		{
			set u;
			
			set_rm(EpToken, f[alt]);
			t = fBlkFollow(atom, rule);
			u = set_and(f[alt], t); 
			if ( !set_nil(u) )
			{
				warnBlkNoCR( (*atom), eMsg(" alt %d ambiguous upon ", alt+1) );
				if ( set_deg(u) > 1 ) set_fpT(stderr, u);
				else fprintf(stderr, "%s", TokenName(set_int(u)));
				fprintf(stderr, "\n");
			}
			set_free( u );
			set_orin(&(f[alt]), t);
			/* If what follows can be bypassed til end of rule, do follow */
			/* If no follow, leave Epsilon Token in its place */
			if ( set_el(EpToken, t) )
			{
				s = Follow(rule);
				if ( set_deg(s) > 0 ) set_rm(EpToken, f[alt]);
				u = set_and(f[alt], s);
				if ( !set_nil(u) )
				{
					warnBlkNoCR( (*atom), eMsg(" alt %d ambiguous upon ", alt+1) );
					if ( set_deg(u) > 1 ) set_fpT(stderr, u);
					else fprintf(stderr, "%s", TokenName(set_int(u)));
					fprintf(stderr, "\n");
				}
				set_free( u );
				set_orin(&(f[alt]), s);
				set_free( s );
			}
			set_free( t );
		}
	}
}

/*
 * Do the actual computation for doBlkFollow() above.  This looks at the
 * tokens following the block passed in.
 *
 * When the edge of a subrule is found, the follow of the enclosing block
 * must also be considered.  The parent pointer, points to the subrule atom
 * of the (parent) inner-most enclosing subrule
 */
static set
fBlkFollow(blk, rule)
Atom *blk;
int rule;
{
	set f, t;
	
	DEBUG(2) {
		fprintf(stderr, "fBlkFollow(%s, after:", RuleStr[rule]);
		dispAtom(*blk, stderr);
		fprintf(stderr, ")\n");
	}
	f = fMidAlt(blk+1, rule);
	if ( set_el(EpToken, f) && blk->parent != NULL )
	{
		set_rm(EpToken, f);
		t = fBlkFollow(blk->parent, rule);
		set_orin(&f, t);
		set_free(t);
	}
	return( f );
}

/*
 * Compute the FOLLOW of 'frule'.
 *
 * First check to see if the follow has already been computed.  If so, simply
 * return the cached set.
 *
 * If the FOLLOW has not been totally computed, has it been partially computed?
 * If not, we must perform the FOLLOW--follow().
 *
 * If the FOLLOW set has been partially computed, append the FOLLOW of each
 * rule in the Partial[frule] set to FoCache[frule].  The FOLLOW always
 * be complete after this operation.  This is because the only way for a
 * partial set to arise is when cycles appear in the FOLLOW computation.
 * For example, FOLLOW of rule e requires FOLLOW of rule e2 which requires the
 * FOLLOW of rule e1 which requires FOLLOW of e.  Since we have already begun
 * the FOLLOW computation for rule e, we cannot ask for it again or infinite-
 * recursion will result.  So, the fact that the FOLLOW for rules e1 and e2
 * require FOLLOW rule e is recorded.  After FOLLOW rule e has completed, we
 * have the following information:
 *
 *	Rule	FoCache		Remainder
 *	[e] 	{A B T}
 *	[e1]	{A}			{e}
 *	[e2]	{A B}		{e}
 *
 * FOLLOW for rules e1 and e2 are obviously easy to compute:  Simply append
 * the FOLLOW of rule e to both of them.
 *
 *		a  : I e T s;
 *		e  : e1 {A e1} ;
 *		e1 : e2 {B e2} ; 
 *		e2 : C | D e ;
 */
set
Follow(frule)
int frule;
{
	unsigned *rem, *r;
	
	FoRequest++;				/* We have another follow request */
	DEBUG(2) fprintf(stderr, "Start of Follow(%s)\n", RuleStr[frule]);
	if ( !UseCache )
	{
		follow( frule );
		return( set_dup(FoCache[frule]) );
	}

	if ( FoValid[frule] )		/* If we have fully computed follow */
	{
		FoSave++;				/* Saved complete follow set computation */
		DEBUG(1) {
			fprintf(stderr, "Follow(%s) complete: ", RuleStr[frule]);
			set_fpT(stderr, FoCache[frule]);
			fprintf(stderr, "\n\n");
		}
		return( set_dup(FoCache[frule]) );
	}
	/* If invalid and empty, we have done nothing */
	if ( set_deg( Remainder[frule] ) == 0 )	/* We have to compute whole thing */
	{
		follow( frule );
		set_rm(frule, Remainder[frule]);	/* Make sure no follow of self */
		if ( set_deg(Remainder[frule]) == 0 ) FoValid[frule] = 1;
		DEBUG(1) {
			fprintf(stderr, "(No remainder was avail) after Follow(%s) calc\n", RuleStr[frule]);
			dumpFcache();
		}
		return( set_dup(FoCache[frule]) );
	}

	/* Else we have follows remaining to compute */
	FoPartial++;				/* Partial follow to compute */
	r = rem = set_pdq(Remainder[frule]);
	DEBUG(1) {
		fprintf(stderr,"For Follow(%s), we have these left to compute: ",
						RuleStr[frule]);
		set_fpR(stderr, Remainder[frule]);
		fprintf(stderr, "\n");
	}
	while ( *r != nil )
	{
		if ( !set_el(*r, FoVisit) )
		{
			/*
			 * if *r in remainder set and not in FoVisit this implies
			 * that FOLLOW(*r) is completed and in the cache.
			 */
			/* t = Follow( *r ); set_free( t ); */
			set_orin(&(FoCache[frule]), FoCache[*r]);
			set_orin(&(Remainder[frule]), Remainder[*r]);
			set_rm(*r, Remainder[frule]);
		}
		r++;
	}
	free( rem );
	if ( set_deg(Remainder[frule]) == 0 ) FoValid[frule] = 1;
	DEBUG(1) {
		fprintf(stderr, "(Remainder was avail) after Follow(%s) calc\n",
						RuleStr[frule]);
		dumpFcache();
	}
	return( set_dup(FoCache[frule]) );
}

/*
 * Include Epsilon if follow required and is empty
 * Do not do followBlk for rules that do not reference frule
*/
static
follow(frule)
int frule;
{
	int r;
	set t;
	
	FoCompute++;
	markFo( frule );
	for (r=1; Rules[r]!=NULL; r++)
	{
		if ( !set_el(r, CrossRef[frule]) ) continue;
		t = followBlk(Rules[r], frule, r, NULL);
		set_orin(&(FoCache[frule]), t);
		set_free(t);
		if ( set_el(EpToken, FoCache[frule]) )
		{
			set_rm(EpToken, FoCache[frule]);
			if ( set_el(r, FoVisit) )
			{
				set_orel( r, &(Remainder[frule]) );
			}
			else
			{
				t = Follow( r );
				set_free( t );
				set_orin(&(FoCache[frule]), FoCache[r]);
				set_orin(&(Remainder[frule]), Remainder[r]);
				if ( set_deg(FoCache[frule]) == 0 )
				{
					set_orel(EpToken, &(FoCache[frule]));
				}
			}
		}
	}
	unMarkFo( frule );
}

/*
 * We know that rule 'frule' is referenced in 'curRule' because of
 * CrossRef[].  Check this block for a reference to it.
 */
set
followBlk(blk,frule,curRule,parent)
Block blk;
Atom *parent;
int frule, curRule;
{
	int alt;
	set t, f;
	
	f = empty;
	for (alt=1; blk[alt]!=NULL; alt++)
	{
		t = followAlt(blk[alt], frule, curRule);
		set_orin(&(f), t);
		set_free( t );
		DEBUG(3) setMsg( eMsg("followAlt(%s) %d returns ",RuleStr[frule],alt), f );
	}
	if ( parent != NULL )	/* No parent => can't do fBlkFollow() */
	{
		if ( set_el(EpToken, f ) )	/* Follow past end of block? */
		{
			if ( parent->type == aLoopBLK )
			{
				/* Must include first of loop block ()* itself */
				t = fMidAlt(parent, curRule);
				set_orin(&(f), t);
				set_free( t );
			}
			set_rm(EpToken, f);
			t = fBlkFollow(parent, curRule);
			set_orin(&(f), t);
			set_free( t );
		}
	}
	DEBUG(3) setMsg( eMsg("followBlk(%s) returns",RuleStr[frule]), f );
	return( f );
}

/*
 * For each atom in an alternative, check subrules for references to 'frule'.
 * Also, if atom is a ref to 'frule', append FIRST of alt[atom+1] to the
 * FOLLOW of 'frule'.
 */
set
followAlt(alt,frule,curRule)
Atom *alt;
int frule, curRule;
{
	set t, f;
	int a,r;

	DEBUG(2) {
		fprintf(stderr,"followAlt(%s in %s @",RuleStr[frule],RuleStr[curRule]);
		dispAtom( alt[1], stderr );
		fprintf(stderr, ")\n");
	}
	f = empty;
	for (a=1; alt[a].type!=EOL; a++)
	{
		switch ( alt[a].type )
		{
			case aLeaf :
			case aAction :
				continue;
			case aSubBLK :
			case aOptBLK :
			case aLoopBLK :
				t = followBlk(alt[a].ptr.block,frule,curRule,&(alt[a]));
				set_orin(&(f), t);
				set_free( t );
				continue;
			case aRule :
				r = ruleNum(&(alt[a]));
				if ( r == 0 )
				{
					warnFL(eMsg("rule %s undefined", alt[a].ptr.rule),
							alt[a].file, alt[a].line);
					continue;
				}
				if ( frule != r ) continue;
				/* Found match. "following" rule is in this alternative */
				t = fMidAlt(&(alt[a+1]), curRule);
				set_orin(&(f), t);
				set_free( t );
				continue;
		}
	}
	return( f );
}

/* return number of epsilon paths in array of sets */
multEpsilon( f )
set *f;
{
	int found = 0;
	
	while ( f->n != 0 )
	{
		if ( set_el(EpToken, *f++) ) found++;
	}
	return( found );
}

ruleNum(a)
register Atom *a;
{
	if ( a->token != 0 || RuleStr[1] == 0 ) return( a->token );
	return( (a->token=strPos(RuleStr, a->ptr.rule)) );
}

/*
 * Compact f and place into set a.  i.e. a = OR(f[0]|..|f[n-1])
 */
set
fCompact( f )
set *f;
{
	set a;
	
	a = empty;
	while ( f->n != 0 )
	{
		set_orin(&a, *f++);
	}
	return( a );
}

/* return TRUE if block is empty (no rule elements other than actions */
emptyBlk(b)
Atom **b;
{
	Atom *p;
	int i=1;
	
	if ( b == NULL ) return(1);
	b++;	/* Move to 1st element in block */
	while ( *b != NULL )
	{
		p = (*b)+1;
		while ( p->type != EOL )
		{
			if (p->type != aAction) return(0);
			p++;
		}
		b++;
	}
	return(1);
}

fDump( f )
set *f;
{
	int i=0;

	while ( f->n != 0 )
	{
		setMsg( eMsg("[%d] ", i), *f);
		i++;
		f++;
	}
}

fset_pr(e)
set *e;
{
	unsigned i=0;

	while ( e->n != 0 )
	{
		printf("[%d] ", i++);
		set_prT(*e++);
		putchar('\n');
	}
}

set_fpR(f, e)
FILE *f;
set e;
{
	register unsigned *p;
	unsigned *q;

	if ( set_deg(e) == 0 ) return;
	if ( (q=p=set_pdq(e)) == NULL ) fatal("Can't alloc space for set_pdq");
	fprintf(f, "{");
	while ( *p != nil )
	{
		fprintf(f, " %s", RuleStr[*p++]);
	}
	fprintf(f, " }");
	free(q);
}

set_fpT(f, e)
FILE *f;
set e;
{
	register unsigned *p;
	unsigned *q;

	if ( set_deg(e) == 0 ) return;
	if ( (q=p=set_pdq(e)) == NULL ) fatal("Can't alloc space for set_pdq");
	fprintf(f, "{");
	while ( *p != nil )
	{
		fprintf(f, " %s", TokenName(*p++));
	}
	fprintf(f, " }");
	free(q);
}

set_prR(e)
set e;
{
	set_fpR(stdout, e);
}

set_prT(e)
set e;
{
	set_fpT(stdout, e);
}

set *
newFset()
{
	set *f;
	int i;
	
	f = (set *) calloc(MaxAlts+1, sizeof(set));
	if ( f==NULL ) fatal("Cannot allocate new fset\n");
	for (i=0; i<MaxAlts+1; i++) f[i] = empty;
	return( f );
}

/*
 * Duplicate an array of sets.  Return a pointer to it.
 */
set *
dupFset(f)
set *f;
{
	set *g, *p;
	
	p = g = newFset();
	while ( f->n != 0 ) *p++ = set_dup( *f++ );
	return( g );
}

void
freeFset(f)
set *f;
{
	set *p=f;
	
	if ( f == 0 ) return;
	while ( p->n != 0 )
	{
		set_free( *p );
		p++;
	}
	free( f );
}

/*
 * return the next empty set found in f.  f must hold an empty one or
 * this routine will fall off the edge of the world.
 */
nextAlt(f)
set *f;
{
	int i=0;
	
	while ( f->n != 0 ) {f++; i++;}
	return( i );
}

/* C a c h e  R o u t i n e s */

InitCache(n)
int n;			/* Number of rules */
{
	if ( n <= 0 ) return;
	FiCache = (set **) calloc(n, sizeof(set *));
	if ( FiCache == NULL ) fatal("Cannot allocate FIRST cache\n");
	FoCache = (set *) calloc(n, sizeof(set));
	if ( FoCache == NULL ) fatal("Cannot allocate FoCache\n");
	Remainder = (set *) calloc(n, sizeof(set));
	if ( Remainder == NULL ) fatal("Cannot allocate Remainder\n");
	FoValid = (char *) calloc(n, sizeof(char));
	if ( FoValid == NULL ) fatal("Cannot allocate FoValid\n");
}

KillCache(n)
int n;
{
	int r;

	if ( n <= 0 ) return;
	if ( FiCache != NULL )
	{
		register set **p;
		
		p = &(FiCache[n-1]);
		while ( p >= &(FiCache[1]) )
		{
			if ( *p != NULL ) freeFset( *p );
			--p;
		}
		free( FiCache );
	}
	if ( FoCache != NULL )
	{
		for (r=1; r<=NumRules; r++)
		{
			if ( FoCache[r].n != 0 ) set_free( FoCache[r] );
		}
		free( FoCache );
	}
	if ( Remainder != NULL )
	{
		for (r=1; r<=NumRules; r++)
		{
			if ( FoCache[r].n != 0 ) set_free( Remainder[r] );
		}
		free( Remainder );
	}
	if ( FoValid != NULL ) free( FoValid );
}

dumpFcache()
{
	int r;
	
	fprintf(stderr, "Follow cache state:\n");
	for (r=1; r<=NumRules; r++)
	{
		fprintf(stderr, "Follow[%s] = ", RuleStr[r]);
		set_fpT(stderr, FoCache[r]);
		if ( !FoValid[r] ) fprintf(stderr, "\txxx\n");
		else fprintf(stderr, "\n");
	}
	for (r=1; r<=NumRules; r++)
	{
		fprintf(stderr, "Remainder[%s] = ", RuleStr[r]);
		set_fpR(stderr, Remainder[r]);
		fprintf(stderr, "\n");
	}
	fprintf(stderr, "\n\n");
}

SHAR_EOF
fi # end of overwriting check
if test -f 'gen.c'
then
	echo shar: will not over-write existing file "'gen.c'"
else
cat << \SHAR_EOF > 'gen.c'
/*
 * ANTLR Code Generator
 *
 * Take the list of rules and generator code for each alt of every rule.
 *
 * Notes:
 *		ALX has been replaced by DLG (written by Will Cohen).  No names have
 *		been changed in ANTLR, however.
 */

#include <stdio.h>
#ifdef MEMCHK
#include "trax.h"
#endif
#include "set.h"
#include "struct.h"
#ifdef MPW
/*#pragma segment gen*/
#endif

#define MaxLabel		10
#define MaxFileName		30
#define TokFile			"tokens.h"
#define ErrFile			"err.c"
#define LexErrorString "Invalid token"
#define TokenOffset		1	/* Pass 0th position */

#define tabF(f, ta)	{register int i; for (i=1; i<=ta; i++) putc('\t', f);}
#define Tab			tabF(output, tabs)
#define PastWhiteSpace(s)	\
			while (*(s) == ' ' || *(s) == '\t' || *(s) == '\n') {s++;}

static FILE *output = stdout,
			*errtab = NULL;
static int	file=0;
static int	tabs, numErrSets=0;

#define NewLabel	sprintf(label, "_L%d", labelNum++);
static char	label[MaxLabel+1];
static int	labelNum=0;
static FILE *alx;	/* parser.alx output file */

#define NumAlts(b, m)	{register Atom **t=(b)+1; m=0; while ( *t++ != NULL ) {m++;}}
#define MaxDegInFset(f, max)							\
			{	register set *t=(f); unsigned m;		\
				max = 0;								\
				while ( t->n != 0 ) {					\
					m = set_deg(*t);					\
					if ( m > max ) max = m;				\
					t++;								\
				}										\
			}
#define TotalInFset(f, tot)								\
			{	register set *t=(f);					\
				tot = 0;								\
				while ( t->n != 0 ) {					\
					tot += set_deg(*t);					\
					t++;								\
				}										\
			}

int THRif = 3, THRexpr = 3;		/* Alt and First_Set thresholds */

char *StdErrMsg(), *outname(), *StripQuotes();

static
Gen(s,a1,a2,a3)
char *s;
long a1,a2,a3;
{
	Tab;
	fprintf(output, s, a1, a2, a3);
}

static
GenNT(s,a1,a2,a3)
char *s;
long a1,a2,a3;
{
	fprintf(output, s, a1, a2, a3);
}

GenRules(rules)
Atom ***rules;
{
	int r;
	set *f;
	
	errtab = fopen(ErrFile, "w");
	if ( errtab == NULL ) fatal("Can't open errtab file");
	GenErrHdr();
	file = -1;
	output = NULL;
	for (r=1; rules[r] != NULL; r++)
	{
		if ( RuleFile[r] != file )
		{
			if ( output != NULL ) fclose( output );
			output = fopen(outname(FileStr[RuleFile[r]]), "w");
			if ( output == NULL )
			{
				fatal("Can't open output file");
			}
			file = RuleFile[r];
			GenFileHdr();
			if ( r == 1 )
			{
				dmpActList(ActStr);
			}
		}
		f = First(r);
		ambigRule(f, r);
		GRule(rules[r], f, r);
		freeFset(f);
	}
	dmpActList(ActStr2);
	fclose( output );
	if ( numErrSets > 0 ) putc(',', errtab);	/* Put at least this 1 set in table */
	fprintf(errtab, "\n{ 0x%02x }", 0);
	fprintf(errtab, "\n};\n");
	fclose( errtab );
}

GRule(rule, f, r)
Atom **rule;
set *f;
int r;
{
	Atom blk;
	
	/* Create a dummy atom that happens to be a blk atom */
	blk.ptr.block=rule;
	blk.type = aRule;
	blk.parent=NULL;
	blk.inheritance=NULL;
	blk.file = FileStr[RuleFile[r]];
	blk.line = RuleLine[r];
	tabs=0;
	Gen("%s()\n", RuleStr[r]);
	GenBlk(&blk, f, r);
	Gen("\n");
}

GenBlk(atm, f, r)
Atom *atm;
set *f;
int r;
{
	Atom **blk = atm->ptr.block;
	set used;

	set_new(used, MaxToken);
	Gen("{\n");
	if ( atm->type == aRule )
	{
		tabs++;
		Gen("RULEvars;\n");
	}
	Gen("BLKvars;\n");
	if ( blk[1][1].type == aAction )
	{
		dumpAction( blk[1][1].ptr.action, output, tabs );
	}
	Gen("EnterBLK;\n");
	if ( atm->type == aRule ) Gen("EnterRule;\n");
	if ( MakeTrax && atm->type == aRule ) Gen("aTrax(\"%s\",LexText);\n", RuleStr[r]);
	switch ( atm->type )
	{
		case aRule :
		case aSubBLK :	GenSubBLK(atm, f, r, &used); break;
		case aOptBLK :	GenOptBLK(atm, f, r, &used); break;
		case aLoopBLK :	GenLoopBLK(atm, f, r, &used); break;
	}
	if ( atm->type == aRule )
	{
		Gen("SUCCESS;\n");
		--tabs;
		Gen("Fail: ;\n");
		tabs++;
		if ( FailActionStr[r] != NULL )
		{
			dumpAction( FailActionStr[r], output, tabs );
		}
		Gen("FAILURE;\n");
		--tabs;
	}
	else Gen("ExitBLK;\n");
	Gen("}\n");
	set_free( used );
}

/*
 * Some rules for generating optimized IF sequences:
 *
 *	SubBLK:
 *		if ( #alts == 1 ) don't generate "if (First(alt))"
 *		if ( #alts == 1 && 1st element==aLeaf ) use "if (!lex(token))" not Munch
 *	OptBLK:
 *		Always generate "if (First(alt))"
 *		Always gen Munch if 1st element==aLeaf
 *	LoopBLK:
 *		if ( #alts == 1 ) don't generate "if (First(alt))"
 *		Always gen Munch if 1st element==aLeaf
 */
GenIF(atm, f, r, used, m)
Atom *atm;
set *f, *used;
int r,m;	/* m is # of alts in blk */
{
	register Atom **blk = atm->ptr.block;
	int alt, at, start;

	for (alt=1; blk[alt] != NULL; alt++)
	{
		if ( atm->type == aOptBLK || 
			 ((atm->type==aLoopBLK||atm->type==aSubBLK||atm->type==aRule) && m > 1) )
		{
			if ( alt > 1 ) Gen("else if ( ");
			else Gen("if ( ");
			GenIFexpr( f[alt-1], used, r, alt, atm );
			GenNT(" ) {\n");
			tabs++;
		}
		start=1;
		if ( alt==1 && blk[1][1].type == aAction ) start=2;
		for (at=start; blk[alt][at].type != EOL; at++)
		{
			if ( at==start && blk[alt][1].type == aLeaf )
			{
				if ( atm->type == aOptBLK || atm->type == aLoopBLK ||
					 ((atm->type==aRule||atm->type==aSubBLK) && m>1) )
				{
					Gen("Munch;\n");
					continue;
				}
			}
			GenAtom( &(blk[alt][at]), r );
		}
		if ( atm->type == aOptBLK || 
			 ((atm->type==aLoopBLK||atm->type==aSubBLK||atm->type==aRule) && m > 1) )
		{
			--tabs;
			Gen("}\n");
		}
	}
}

GenIFexpr(f, used, r, m, atm)
set f, *used;
Atom *atm;
int r, m;
{
	unsigned *e, *g, firstToken=1, n=0;

	if ( set_deg(f) == 0 )
	{
		if ( m != -1 )
		{
			if ( atm->type == aRule )
			{
				warnFL( eMsg(
					"alt %d rule %s empty first set",
					 m, RuleStr[r]),
					 FileStr[RuleFile[r]], RuleLine[r] );
			}
			else
			{
				errBlk( (*atm), eMsg( " [rule %s] alt %d empty first set",
							 RuleStr[r], m) );
			}
		}
		else
		{
			errBlk( (*atm), eMsg( " [rule %s] optional path has empty first set",
							 RuleStr[r]) );
		}
		return;
	}
	if ( (e=g=set_pdq(f)) == NULL )
	{
		fatal("Cannot allocate IF expr pdq set");
	}
	while ( *e != nil )
	{
		if ( !set_el(*e, *used) )	/* Resolve ambig by using token only 1st time */
		{
			if ( !firstToken ) GenNT(" || ");
			else firstToken = 0;
			GenNT("Token==%s", TokenValue(*e));
			set_orel(*e, used);
			n++;
		}
		e++;
	}
	free( g );
	if ( n == 0 )
	{
		GenNT("0");
		if ( m != -1 )
		{
			if ( atm->type == aRule )
			{
				warnFL( eMsg(
					"warning: alt %d rule %s unreachable",
					 m, RuleStr[r]),
					 FileStr[RuleFile[r]], RuleLine[r] );
			}
			else
			{
				warnBlk( (*atm), eMsg(
					" [rule %s] alt %d unreachable",
					 RuleStr[r], m) );
			}
		}
		else
		{
			warnBlk( (*atm), eMsg(
			 	" [rule %s] optional path disappears",
				 RuleStr[r]) );
		}
	}
}

GenSubBLK(atm, f, r, used)
Atom *atm;
set *f;
int r;
set *used;
{
	register Atom **blk = atm->ptr.block;
	int	m,n;
	
	NumAlts(blk, m);
	MaxDegInFset(f, n);
	/* Don't gen outsidef first set membership code if only one alternative
	 * 'cause no matter what we should enter that single alternative.
	 */
	if ( m <= THRif && n <= THRexpr || m == 1 )	/* Optimize, we are below threshold */
	{
		GenIF(atm, f, r, used, m);
		if ( m > 1 ) Gen("else {%s goto Fail;}\n", StdErrMsg(f, FALSE));
	}
	else
	{
		GenSw(atm, f, r, used);
		GenSwClose( f );
	}
}

GenOptBLK(atm, f, r, used)
Atom *atm;
set *f;
int r;
set *used;
{
	register Atom **blk = atm->ptr.block;
	int	m,n;
	
	NumAlts(blk, m);
	MaxDegInFset(f, n);
	if ( m <= THRif && n <= THRexpr )	/* Optimize, we are below threshold */
	{
		GenIF(atm, f, r, used, m);
		Gen("else if (!( ");
		GenIFexpr( f[m], used, r, -1, atm );
		GenNT(" )) {%s goto Fail;}\n", StdErrMsg(f, FALSE));
	}
	else
	{
		GenSw(atm, f, r, used);
		GenCase( f[m], used, r, -1, atm );
		tabs++;
		Gen("break;\n");
		--tabs;
		GenSwClose( f );
	}
}

GenLoopBLK(atm, f, r, used)
Atom *atm;
set *f;
int r;
set *used;
{
	register Atom **blk = atm->ptr.block;
	int	m,n;
	
	NumAlts(blk, m);
	MaxDegInFset(f, n);
	/* If only one alt and expr is simple enough, use "while (First(alt))" */
	if ( m == 1 && n <= THRexpr )
	{
		Gen("while ( ");
		GenIFexpr( f[0], used, r, 1, atm );
		GenNT(" )\n");
		Gen("{\n");
		tabs++;
		GenIF(atm, f, r, used, m);
		Gen("sREL;\n");
		tabs--;
		Gen("}\n");
		Gen("if (!( ");
		GenIFexpr( f[m], used, r, -1, atm );
		GenNT(" )) {%s goto Fail;}\n", StdErrMsg(f, FALSE));
		return;
	}
	Gen("do {\n");
	tabs++;
	if ( m <= THRif && n <= THRexpr )	/* Optimize, we are below threshold */
	{
		GenIF(atm, f, r, used, m);
		NewLabel;
		Gen("else goto %s;\n", label);
	}
	else
	{
		GenSw(atm, f, r, used);
		GenCase( f[m], used, r, -1, atm );
		NewLabel;
		tabs++;
		Gen("goto %s;\n", label);
		--tabs;
		GenSwClose( f );
	}
	Gen("sREL;\n");
	--tabs;
	Gen("} while (1);\n");
	Gen("%s: ;\n", label);
	if ( m <= THRif && n <= THRexpr )
	{
		Gen("if (!( ");
		GenIFexpr( f[m], used, r, -1, atm );
		GenNT(" )) {%s goto Fail;}\n", StdErrMsg(f, FALSE));
	}
}

GenSw(atm, f, r, used)
Atom *atm;
set *f, *used;
int r;
{
	Atom **blk = atm->ptr.block;
	int alt, at, start;
	
	Gen("switch ( Token )\n");
	Gen("{\n");
	for (alt=1; blk[alt] != NULL; alt++)
	{
		GenCase( f[alt-1], used, r, alt, atm );
		tabs++;
		start=1;
		if ( alt==1 && blk[1][1].type == aAction ) start=2;
		for (at=start; blk[alt][at].type != EOL; at++)
		{
			if ( at==start && blk[alt][1].type == aLeaf )
			{
				Gen("Munch;\n");
				continue;
			}
			GenAtom( &(blk[alt][at]), r );
		}
		Gen("break;\n");
		--tabs;
	}
}

GenSwClose( f )
set *f;
{
	Gen("default : %s goto Fail;\n", StdErrMsg(f, FALSE));
	Gen("}\n");
}

GenAtom(a, r)
Atom *a;
int r;
{
	set *f;

	switch ( a->type )
	{
		case aLeaf :
			if ( RegExprStr[a->token] != NULL )
				if ( RegExprStr[a->token][1] == '@' )
				{
					if ( (a+1)->type != EOL && (a+1)->type != aAction )
					{
						warnFL( eMsg("rule %s elements beyond EOF (\"@\") unreachable",
								RuleStr[r]), a->file, a->line );
					}
				}
			Gen("if ( !lex(%s) ) { %s goto Fail; }\n", TokenValue(a->token),
											StdErrMsg(a->token,TRUE));
			break;
		case aRule :
			/* warnRule(a, r); */
			if ( a->inheritance == NULL )
			{
				if ( ForceInherit )
				{
					Gen("aPush(aArg(0));\n");
					Gen("if (!%s()) goto Fail;\n", a->ptr.rule);
				}
				else
				{
					Gen("Make0; if (!%s()) goto Fail;\n", a->ptr.rule);
				}
			}
			else
			{
				GenBlkPreamble(a);
				Gen("if (!%s()) goto Fail;\n", a->ptr.rule);
				if ( a->inheritance[0] == '=' )
				{
					tabs--;
					Gen("}\n");
				}
			}
			break;
		case aAction :
			dumpAction( a->ptr.action, output, tabs );
			break;
		case aSubBLK :
		case aOptBLK :
		case aLoopBLK :
			if ( a->ptr.block == NULL ) break;
			if ( emptyBlk(a->ptr.block) ) break;
            if ( a->inheritance == NULL )
            {
                if ( ForceInherit )
                {
                    Gen("aPush(aArg(0));\n");
                }
                else Gen("Make0;\n");
            }
            else GenBlkPreamble(a);
			fAtom(a,r,FALSE,&f);
			ambigSub(f, a, r);
			GenBlk(a, f, r);
			if ( a->inheritance != NULL )
				if ( a->inheritance[0] == '=' )
				{
					tabs--;
					Gen("}\n");
				}
			freeFset(f);
			break;
	}
}

GenBlkPreamble(a)
Atom *a;
{
	switch ( a->inheritance[0] )
	{
		case '{' :	Gen("Make0;\n");
					Gen("%s\n", a->inheritance);
					break;
		case '=' :	Gen("{\n");
					tabs++;
					Gen("static Attrib inh%s;\n", a->inheritance);
					Gen("aPush(inh);\n");
					break;
		default  :	Gen("aPush(%s);\n", a->inheritance);
					break;
	}
}

GenCase( f, used, r, m, atm )
set f;
set *used;
int r,m;
Atom *atm;
{
	unsigned *e,*g;
	char *s;
	unsigned n=0;

	if ( set_deg(f) == 0 )
	{
		if ( m != -1 )
		{
			if ( atm->type == aRule )
			{
				warnFL( eMsg(
					"alt %d rule %s empty first set",
					 m, RuleStr[r]),
					 FileStr[RuleFile[r]], RuleLine[r] );
			}
			else
			{
				errBlk( (*atm), eMsg( " [rule %s] alt %d empty first set",
							 RuleStr[r], m) );
			}
		}
		else
		{
			errBlk( (*atm), eMsg( " [rule %s] optional path has empty first set",
							 RuleStr[r]) );
		}
		return;
	}
	if ( (e=g=set_pdq(f)) == NULL )
	{
		fatal("Cannot allocate IF expr pdq set");
	}
	while ( *e != nil )
	{
		if ( !set_el(*e, *used) )
		{
			s = TokenValue(*e);
			if ( *s > '9' || *s < '0' ) Gen("case %s :\n", s);
			else Gen("case %s : /* %s */\n", s, TokenName(*e));
			set_orel(*e, used);
			n++;
		}
		e++;
	}
	free( g );
	if ( n == 0 )
	{
		if ( m != -1 )
		{
			warnBlk( (*atm), eMsg(
			 	"[rule %s] alt %d unreachable",
				 RuleStr[r], m) );
		}
		else
		{
			warnBlk( (*atm), eMsg(
			 	"[rule %s] optional path disappears",
				 RuleStr[r]) );
		}
	}
}

GenErrHdr()
{
	char *p;
	int i;

	fprintf(errtab, "/*\n");
	fprintf(errtab, " * A n t l r  E r r o r  T a b l e  H e a d e r\n");
	fprintf(errtab, " *\n");
	fprintf(errtab, " * Generated from:");
	for (i=0; i<NumFiles; i++) fprintf(errtab, " %s", FileStr[i]);
	fprintf(errtab, "\n");
	fprintf(errtab, " *\n");
	fprintf(errtab, " * (c) 1989, 1990 by Terence Parr, Hank Dietz and Will Cohen\n");
	fprintf(errtab, " * Purdue University Electrical Engineering\n");
	fprintf(errtab, " * ANTLR Version 1.0B\n");
	fprintf(errtab, " */\n\n");

	fprintf(errtab, "#include <stdio.h>\n");
	fprintf(errtab, "#include \"dlgdef.h\"\n");
	fprintf(errtab, "#define nil ((unsigned)-1)\n");
	fprintf(errtab, "#ifdef MPW		/* Macintosh Programmer's Workshop */\n");
	fprintf(errtab, "#define ErrHdr \"File \\\"%%s\\\"; Line %%d #\"\n");
	fprintf(errtab, "#else\n");
	fprintf(errtab, "#define ErrHdr \"\\\"%%s\\\", line %%d:\"\n");
	fprintf(errtab, "#endif\n\n");
	fprintf(errtab, "extern char *tokens[];\n");
	fprintf(errtab, "char *aSourceFile = \"stdin\";\t/* Set to current src filename */\n\n");
	fprintf(errtab, "unsigned *err_decode(p)\n");
	fprintf(errtab, "register unsigned char *p;\n");
	fprintf(errtab, "{\n");
	fprintf(errtab, "\tstatic unsigned bitmask[] = {\n");
	fprintf(errtab, "\t	0x00000001, 0x00000002, 0x00000004, 0x00000008,\n");
	fprintf(errtab, "\t	0x00000010, 0x00000020, 0x00000040, 0x00000080,\n");
	fprintf(errtab, "\t};\n");
	fprintf(errtab, "\textern unsigned *malloc();\n");
	fprintf(errtab, "\tregister unsigned char *endp = &(p[%d]);\n",
					NumWords(MaxToken)*BytesPerWord);
	fprintf(errtab, "\tregister unsigned *q,*r,e= 0;\n\n");
	fprintf(errtab, "\tr = q = (unsigned *) malloc(%d*sizeof(unsigned));\n",
					(NumWords(MaxToken)*WORDSIZE)+1);
	fprintf(errtab, "\tif ( q == 0 ) return( 0 );\n");
	fprintf(errtab, "\tdo {\n");
	fprintf(errtab, "\t	register unsigned t = *p;\n");
	fprintf(errtab, "\t	register unsigned *b = &(bitmask[0]);\n");
	fprintf(errtab, "\t	do {\n");
	fprintf(errtab, "\t		if ( t & *b ) *q++ = e;\n");
	fprintf(errtab, "\t		e++;\n");
	fprintf(errtab, "\t	} while (++b < &(bitmask[%d]));\n", 8);	/* 8 bits/byte */
	fprintf(errtab, "\t} while (++p < endp);\n");
	fprintf(errtab, "\t*q = nil;\n");
	fprintf(errtab, "\treturn( r );\n");
	fprintf(errtab, "}\n\n");

	fprintf(errtab, "err_print(e)\n");
	fprintf(errtab, "unsigned char *e;\n");
	fprintf(errtab, "{\n");
	fprintf(errtab, "	unsigned *p, *q;\n\n");
	fprintf(errtab, "	if ( (q=p=err_decode(e))==NULL ) return;\n");
	fprintf(errtab, "	fprintf(stderr, \"{\");\n");
	fprintf(errtab, "	while ( *p != nil )\n");
	fprintf(errtab, "	{\n");
	fprintf(errtab, "		fprintf(stderr, \" %%s\", tokens[*p++]);\n");
	fprintf(errtab, "	}\n");
	fprintf(errtab, "	fprintf(stderr, \" }\");\n");
	fprintf(errtab, "	free(q);\n");
	fprintf(errtab, "}\n\n");

	fprintf(errtab, "dfltError(e, single)\n");
	fprintf(errtab, "union { unsigned char *eset; unsigned tok; } e;\n");
	fprintf(errtab, "int single;\n");
	fprintf(errtab, "{\n");
	fprintf(errtab, "\tfprintf(stderr, ErrHdr, aSourceFile, lex_line);\n");
	fprintf(errtab, "\tif ( single )\n");
	fprintf(errtab, "\t{\n");
	fprintf(errtab, "\t\tfprintf(stderr, \" missing %%s (Was \\\"%%s\\\"(%%s))\\n\",\n");
	fprintf(errtab, "\t\t\t\t\t\ttokens[(int)e.tok],\n");
	fprintf(errtab, "\t\t\t\t\t\t(tokens[Token][0]=='@')?\"eof\":LexText,\n");
	fprintf(errtab, "\t\t\t\t\t\ttokens[Token]);\n");
	fprintf(errtab, "\t\treturn;\n");
	fprintf(errtab, "\t}\n");
	fprintf(errtab, "\tfprintf(stderr, \" missing \");\n");
	fprintf(errtab, "\terr_print(e.eset);\n");
	fprintf(errtab, "\tfprintf(stderr, \" (Was \\\"%%s\\\"(%%s))\\n\",\n\t\t(tokens[Token][0]=='@')?\"eof\":LexText, tokens[Token]);\n");
	fprintf(errtab, "}\n\n");
	
	fprintf(errtab, "char *tokens[%d]={\n", MaxToken);
	fprintf(errtab, "\t/* 00 */\t\"Invalid\"");
	for (i=TokenOffset; i<=MaxToken; i++)
	{
		if ( i == EpToken ) continue;
		p = TokenName(i);
		if ( *p == '"' )
			fprintf(errtab, ",\n\t/* %02d */\t%s", i, p);
		else
			fprintf(errtab, ",\n\t/* %02d */\t\"%s\"", i, p);
	}
	fprintf(errtab, "\n};\n");
	fprintf(errtab, "unsigned char err[][%d]={", NumWords(MaxToken)*BytesPerWord);
}

GenFileHdr()
{
	Gen("/*\n");
	Gen(" * A n t l r  T r a n s l a t i o n  H e a d e r\n");
	Gen(" *\n");
	Gen(" * This file translated from: %s\n", FileStr[file]);
	Gen(" *\n");
	Gen(" * (c) 1989, 1990 by Terence Parr, Hank Dietz and Will Cohen\n");
	Gen(" * Purdue University Electrical Engineering\n");
	Gen(" * ANTLR Version 1.0B\n");
	Gen(" */\n");
	Gen("#include <stdio.h>\n");
    if ( DfltErr )
        Gen("#define aError(a,b)    dfltError(a,b)\n");
	if ( AttribAction == NULL && file == 0 )
	{
		warn("warning: no attribute type has been defined");
	}
	dumpAction( AttribAction, output, tabs );
	Gen("#include \"dlgdef.h\"\n");
	Gen("#include \"attrib.h\"\n");
	Gen("#include \"%s\"\n", TokFile);
	Gen("extern unsigned char err[][%d];\n", NumWords(MaxToken)*BytesPerWord);
	Gen("extern char *tokens[];\n");
	if ( file == 0 )
	{
		Gen("#ifndef aStackSize\n");
		Gen("#define aStackSize 200\n");
		Gen("#endif\n");
		Gen("Attrib\taStack[aStackSize];\n");
		Gen("int\t\t_asp=aStackSize;\n");
	}
	Gen("\n");
}

char *
StdErrMsg( f, single )
union { set *fset; unsigned token; } f;
int single;
{
	static char buf[100];
	unsigned nextErrSet();
	
	if ( single )
	{
		sprintf(buf, "aError(%s,1);", TokenValue(f.token));
	}
	else
	{
		sprintf(buf, "aError(&(err[%d][0]),0);", nextErrSet(f.fset));
	}
	return( &(buf[0]) );
}

static
unsigned
nextErrSet(f)
set *f;
{
	set a;
	register unsigned *p, *endp;

	a = fCompact(f);
	if ( a.n == 0 )
	{
		if ( numErrSets > 0 ) putc(',', errtab);
		fprintf(errtab, "\n{ 0x%08x }", 0);
		return(numErrSets++);
	}
	p = a.setword;
	endp = &(a.setword[a.n]);
	if ( numErrSets > 0 ) putc(',', errtab);
	fprintf(errtab, "\n{ ");
	pErrSet(a);
	fprintf(errtab, " }");

	set_free(a);
	return( numErrSets++ );
}

pErrSet(a)
set a;
{
	register unsigned char *p,*endp,*begin;
	int e=0;

	begin=p=set_bytes(a);
	endp = &(p[a.n*BytesPerWord]);
	while ( p < endp )
	{
		if ( e > 0 ) fprintf(errtab, ", ");
		fprintf(errtab, "0x%02x", (unsigned)*p++);
		e++;
	}
	free(begin);
}

/*
 * Return array of unsigned char which is 8bit-word bitset representation of
 * or WORDSIZEbit-word bitset repr.  We need to convert to bytes, cause we
 * don't know wordsize of target machine, but generally unsigned char is
 * 8 bits.
 *
 * The array returned has BytesPerWord*a.n elements.
 * The ith byte is masked off within each word in the set.  That isolated
 * byte is shifted down into the first 8 bits for placing it into a char.
 */
unsigned char *
set_bytes(a)
set a;
{
	static unsigned mask[4] = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
	unsigned char *tab, *t;
	register unsigned *p = a.setword;
	register unsigned *endp = &(a.setword[a.n]);
	
	t = tab = (unsigned char *) malloc( a.n*BytesPerWord );
	if ( tab == NULL ) return( NULL );
	do {
		register unsigned *b = &(mask[0]);
		do {
			*t++ = (*p & *b) >> (8*(b-&(mask[0])));
		} while ( ++b < &(mask[BytesPerWord]) );
		p++;
	} while ( p < endp );
	return( tab );
}

dmpActList(actions)
char **actions;
{
	int a;
	
	for (a=1; actions[a] != NULL; a++)
	{
		dumpAction(actions[a], output, 0);
	}
}

static
dumpAction(s, output, tabs)
char *s;
FILE *output;
int tabs;
{
    int inDQuote, inSQuote;
    
    if ( s == NULL ) return;
	Tab;
    PastWhiteSpace( s );
    inDQuote = inSQuote = FALSE;
    while ( *s != '\0' )
    {
        if ( *s == '\\' )
        {
            putc( *s++, output ); /* Avoid '"' Case */
            if ( *s == '\0' ) return;
            if ( *s == '\'' ) putc( *s++, output );
            if ( *s == '\"' ) putc( *s++, output );
        }
        if ( *s == '\'' )
        {
            if ( !inDQuote ) inSQuote = !inSQuote;
        }
        if ( *s == '"' )
        {
            if ( !inSQuote ) inDQuote = !inDQuote;
        }
        if ( *s == '\n' )
        {
            putc('\n', output);
            PastWhiteSpace( s );
            if ( *s == '}' )
            {
                --tabs;
				Tab;
                putc( *s++, output );
                continue;
            }
            if ( *s == '\0' ) return;
			if ( *s != '#' )	/* #define, #endif etc.. start at col 1 */
            {
				Tab;
			}
        }
        if ( *s == '}' && !(inSQuote || inDQuote) )
        {
            --tabs;            /* Indent one fewer */
        }
        if ( *s == '{' && !(inSQuote || inDQuote) )
        {
            tabs++;            /* Indent one more */
        }
        putc( *s, output );
        s++;
    }
    putc('\n', output);
}

/*
 * Return a string corresponding to the output file name associated
 * with the input file name passed in.
 *
 * Observe the following rules:
 *
 *		f.e		--> f".c"
 *		f		--> f".c"
 *		f.		--> f".c"
 *		f.e.g	--> f.e".c"
 *
 * Where f,e,g are arbitrarily long sequences of characters in a file
 * name.
 *
 * In other words, if a ".x" appears on the end of a file name, make it
 * ".c".  If no ".x" appears, append ".c" to the end of the file name.
 */
char *
outname( fs )
char *fs;
{
	static char buf[MaxFileName+1];
	char *p;
	
	p = buf;
	strcpy(buf, fs);
	while ( *p != '\0' )  {p++;}			/* Stop on '\0' */
	while ( *p != '.' && p != buf ) {--p;}	/* Find '.' */
	if ( p != buf ) *p = '\0';				/* Found '.' */
	strcat(buf, ".c");
	return( buf );
}

/* A L X  S t u f f */

InitAlxFile()
{
	if ( LexFile == NULL ) return;
	alx = fopen(LexFile, "w");
	if ( alx == NULL ) fatal( eMsg("Can't open %s\n", LexFile) );
	DmpAlxHdr();
}

CloseAlxFile()
{
	if ( LexFile == NULL ) return;
	fclose( alx );
}

AlxSep()
{
	if ( LexFile == NULL ) return;
	fprintf(alx, "\n%%%%\n\n");
}

DmpAlxAction(a, t)
char *a;
int t;
{
	if ( LexFile == NULL ) return;
	fprintf(alx, "<<\n");
	dumpAction( a, alx, t );
	fprintf(alx, ">>\n");
}

DmpAlxHdr()
{
	fprintf(alx, "<<\n");
	fprintf(alx, "/* %s -- DLG Description of scanner\n", LexFile);
	fprintf(alx, " *\n");
	fprintf(alx, " * Generated from:");
	{int i; for (i=0; i<NumFiles; i++) fprintf(alx, " %s", FileStr[i]);}
	fprintf(alx, "\n");
	fprintf(alx, " *\n");
	fprintf(alx, " * (c) 1989, 1990 by Terence Parr, Hank Dietz and Will Cohen\n");
	fprintf(alx, " * Purdue University Electrical Engineering\n");
	fprintf(alx, " * ANTLR Version 1.0B\n");
	fprintf(alx, " */\n");
	fprintf(alx, "#include <stdio.h>\n");
	fprintf(alx, "#include \"%s\"\n", TokFile);
	fprintf(alx, "int Token;\n");
	dumpAction( AttribAction, alx, 0 );
	fprintf(alx, "#include \"attrib.h\"\n");
	fprintf(alx, "#ifndef LEX_BUF\n");
	fprintf(alx, "#define LEX_BUF 2000\n");
	fprintf(alx, "#endif\n");
	fprintf(alx, "action0()\n");
	fprintf(alx, "{\n");
	fprintf(alx, "\tlex_err(\"%s\");\n", LexErrorString);
	fprintf(alx, "\tadvance();\n");
	fprintf(alx, "\tLexSkip();\n");
	fprintf(alx, "}\n\n");
	fprintf(alx, "lex(t)\n");
	fprintf(alx, "int t;\n");
	fprintf(alx, "{\n\textern char LexText[];\n");
	fprintf(alx, "\tif ( Token == t )\n");
	fprintf(alx, "\t{\n");
	fprintf(alx, "\t\tMakeAttr;\n");
	fprintf(alx, "\t\tif ( Token != Eof ) GetToken();\n");
	fprintf(alx, "\t\treturn( 1 );\n");
	fprintf(alx, "\t}\n");
	fprintf(alx, "\treturn( 0 );\n");
	fprintf(alx, "}\n");
	fprintf(alx, "\>\>\n");
}

DumpTokens( tokens )
char **tokens;
{
	FILE *f;
	int i;

#ifdef OLD
	tokens += TokenOffset;
#endif
	f = fopen(TokFile, "w");
	if ( f == NULL ) fatal("Can't open token file");
	fprintf(f, "/* %s -- List of labelled tokens\n", TokFile);
	fprintf(f, " *\n");
	fprintf(f, " * Generated from:");
	{int i; for (i=0; i<NumFiles; i++) fprintf(f, " %s", FileStr[i]);}
	fprintf(f, "\n");
	fprintf(f, " *\n");
	fprintf(f, " * (c) 1989, 1990 by Terence Parr, Hank Dietz and Will Cohen\n");
	fprintf(f, " * Purdue University Electrical Engineering\n");
	fprintf(f, " * ANTLR Version 1.0B\n");
	fprintf(f, " */\n");
#ifdef OLD
	i = TokenOffset;
	while ( *tokens != NULL )
	{
		if ( **tokens != '"' && i != EpToken )
		{
			fprintf(f, "#define %s %d\n", *tokens, i);
		}
		tokens++;
		i++;
	}
#endif
	for (i=TokenOffset; i<=MaxToken; i++)
	{
		if ( tokens[i] != NULL && i != EpToken )
			fprintf(f, "#define %s %d\n", tokens[i], i);
	}
	fclose( f );
}

DmpAlxRule(rexpr, label, tokenNumber, action)
char *rexpr, *label;
int tokenNumber;
char *action;
{
	if ( LexFile == NULL ) return;
	if ( rexpr == NULL ) fatal("Hmmm...No regular expression to generate");
	if ( *rexpr != '"' ) return;
	fprintf(alx, "%s\n\t<<\n", StripQuotes(rexpr));
	if ( label != NULL )
	{
		fprintf(alx, "\t\tToken = %s;\n", label);
	}
	else
	{
		fprintf(alx, "\t\tToken = %d;\n", tokenNumber);
	}
	if ( action != NULL )
	{
		dumpAction( action, alx, 2 );
	}
	fprintf(alx, "\t>>\n\n");
}

char *
StripQuotes(s)
char *s;
{
	static char buf[MaxTokenSize+1];
	
	if ( strlen(s) >= MaxTokenSize )
	{
		fatal( eMsg("StripQuotes(): Out of buf space (%d char)\n", MaxTokenSize) );
	}
	if ( *s == '"' )
	{
		strcpy(buf, s+1);
		buf[ strlen(buf)-1 ] = '\0';    /* remove last quote */
		return( buf );
	}
	return( s );
}

/*
 * Return the token value of the token sent in
 *
 * If no token label then return number (string)
 * If token name avail then return token name string
 */
char *
TokenValue( t )
int t;
{
	static char numBuf[10];
	
	if ( TokenStr[t] != NULL ) return( TokenStr[t] );
	sprintf(numBuf, "%d", t);
	return( numBuf );
}

char *
TokenName( t )
int t;
{
	if ( TokenStr[t] != NULL ) return( TokenStr[t] );
	if ( RegExprStr[t] != NULL ) return( RegExprStr[t] );
	return("Invalid");
}

ContainsChar(s, c)
register char *s, c;
{
	while ( *s != c && *s != '\0' ) s++;
	if ( *s == c ) return( TRUE );
	return( FALSE );
}
SHAR_EOF
fi # end of overwriting check
if test -f 'lexhelp.c'
then
	echo shar: will not over-write existing file "'lexhelp.c'"
else
cat << \SHAR_EOF > 'lexhelp.c'

#include <ctype.h>

#define OvfChk(s,n)		{if ( ((s)+n) >= &(LexText[LEX_BUF-3]) ) {				\
							fprintf(stderr, "LexText:\n%s", LexText);			\
							fatalFL( eMsg("lexical buffer OVF size %d",LEX_BUF),\
								FileStr[CurFile], lex_line);}}

#define AddChar(s,c)	addc(&(s), (c))
#define AddStr(s,b,n)	adds(&(s), (b), (n))

static
next()
{
	if ( cur_char == '\n' || cur_char == '\r' ) lex_line++;
	nextChar();
}

static
addc(s,c)
char **s;
char c;
{
	OvfChk(*s,1);
	**s = c;
	(*s)++;
}

static
adds(s,b,n)
char **s, *b;
int n;
{
	OvfChk(*s,n);
	strcpy(*s, b);
	(*s) += n;
}

/* Scarf everything in [...] */
static
scarfParm()
{
	char *s;
	int level = 1;
	
	s = LexText;
	while ( cur_char != LEX_EOF )
	{
		if ( cur_char == '"' )	/* scarf "..." ignoring \" */
		{
			AddChar(s,'"');
			next();
			while ( cur_char != '"' )
			{
				if ( cur_char == '\\' )
				{
					AddChar(s,cur_char);
					next();
					if ( cur_char == '\n' ) lex_line++;
				}
				AddChar(s,cur_char);
				next();
			}
			AddChar(s,'"');
			next();
		}
		switch ( cur_char )
		{
			case '$'	:	/* expression can have $var */
				next();
				if ( cur_char == '$' )
				{
					AddStr(s, "aRet", 4);
					next();
					break;
				}
				if ( isalpha(cur_char) )
				{
					while ( isalpha(cur_char) )
					{
						next();
					}
					AddStr(s, "aRet", 4);
					break;
				}
				if ( !isdigit(cur_char) )
				{
					AddChar(s,'$');
					AddChar(s,cur_char);
					next();
					break;
				}
				sprintf(s, "aArg(");
				s += 5;
				while ( isdigit(cur_char) )
				{
					AddChar(s,cur_char);
					next();
				}
				AddChar(s,')');
				break;
			case '['	: 				/* Nest a level of [ */
				AddChar(s,cur_char);
				next();
				level++;
				break;
			case ']'	:
				--level;				/* Back down a level */
				if ( level == 0 )		/* Back to level 0? */
				{
					next();
					*s = '\0';
					return;
				}
				AddChar(s,cur_char);
				next();
				break;
			case '\\'	:
				next();
				switch ( cur_char )
				{
					case '>'    :   AddChar(s,'>'); break;
					case '$'    :   AddChar(s,'$'); break;
					default     :   AddChar(s,'\\'); AddChar(s,cur_char); break;
				}
				next();
				break;
			default		:
				AddChar(s,cur_char);
				next();
		}
	}
	*s = '\0';
}

static
scarfComment()
{
	while ( cur_char != LEX_EOF )
	{
		if ( cur_char == '*' )
		{
			next();
			if ( cur_char == '/' )
			{
				next();
				return;
			}
		}
		next();
	}
}

scarfAction()
{
	char *s;

	s = LexText;
	while ( cur_char != LEX_EOF )
	{
		if ( cur_char == '"' )	/* scarf "..." ignoring \" */
		{
			AddChar(s,'"');
			next();
			while ( cur_char != '"' )
			{
				if ( cur_char == '\\' )
				{
					AddChar(s,cur_char);
					next();
				}
				AddChar(s,cur_char);
				next();
			}
			AddChar(s,'"');
			next();
		}
		if ( cur_char == '$' )
		{
			next();
			if ( cur_char == '$' )
			{
				AddStr(s, "aRet", 4);
				next();
				continue;
			}
			if ( isalpha(cur_char) )
			{
				while ( isalpha(cur_char) )
				{
					next();
				}
				AddStr(s,"aRet",4);
				continue;
			}
			if ( !isdigit(cur_char) )
			{
				AddChar(s,'$');
				AddChar(s,cur_char);
				next();
				continue;
			}
			AddStr(s, "aArg(", 5);
			while ( isdigit(cur_char) )
			{
				AddChar(s,cur_char);
				next();
			}
			AddChar(s,')');
			continue;
		}
		if ( cur_char == '\\' )
		{
			next();
			switch ( cur_char )
			{
				case '>'    :	AddChar(s,cur_char); break;
				case '$'    :	AddChar(s,cur_char); break;
				default     :	AddChar(s,'\\'); AddChar(s,cur_char); break;
			}
			next();
		}
		else
		if ( cur_char == '>' )
		{
			next();
			if ( cur_char == '>' )
			{
				*s = '\0';
				next();
				return;
			}
			AddChar(s,'>');
			AddChar(s,cur_char);
			next();
		}
		else
		{
			AddChar(s,cur_char);
			next();
		}
	}
}

static
scarfQuotedTerm()
{
	char *s;

	s = LexText+2;
	if ( cur_char == '"' && LexText[1] == '\\' )
	{
		LexText[1] = '"';
		next();
	}
	while ( cur_char != LEX_EOF )
	{
		if ( cur_char == '\\' )
		{
			next();
			switch ( cur_char )
			{
				case '"'	:   AddChar(s,cur_char); break;
				default		:   AddChar(s,'\\'); AddChar(s,cur_char); break;
			}
			next();
		}
		else if ( cur_char == '"' )
		{
			next();
			AddChar(s,'"');
			*s = '\0';
			return;
		}
		else
		{
			AddChar(s,cur_char);
			next();
		}
	}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'main.c'
then
	echo shar: will not over-write existing file "'main.c'"
else
cat << \SHAR_EOF > 'main.c'
/*
 * m a i n . c
 *
 * A n t l r  1.0B
 *
 * Terence Parr
 * Purdue University
 * Summer 1989
 *
 * Forced variable names to be unique to 7 char for portability
 * Terence Parr -- March 1990
 */
#include <stdio.h>
#include "set.h"
#include "dlgdef.h"
#include "struct.h"
#include "attrib.h"
#ifdef MEMCHK
#include "trax.h"
#endif

char		**TokenStr = NULL,
			**RegExprStr = NULL,
			**RuleStr = NULL;

set			FiVisit,	/* Track first/follow set visits */
			FoVisit,
			RuleInh,	/* Track whether rule has inherit override */
			*CrossRef;	/* Used to cross ref rules */

int			*RuleFile = NULL;	/* Which file for rule */
int			*RuleLine = NULL;	/* Which line for rule */

char		**ActStr = NULL;	/* Keep all actions before rules */
char		**ActStr2 = NULL;/* Keep all actions after rules */
char		**FailActionStr = NULL;

Rule		Rules;
int			EpToken, EofToken, NumRules=0, NumFiles=0, CurFile=0;
int			MaxToken=0;
int			Save=0;
int			FoSave=0;
int			FoRequest=0;
int			FoCompute=0;
int			FoPartial=0;
int			MaxAlts=15;	/* Updated by grammar to reflect max alts */
int			Terminate=0;

char		*AttribAction=NULL;
char		*FileStr[15] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};

/* Options */
char		*LexFile =	"parser.dlg";
int			ForceInherit = 0;
int			MakeTrax = 0;
int			PrintGrammar = 0;
int			UseCache = 1;
int			NoCode=0;
int			PrFirstSub = 1;
int			PrintFo = 1;
int			PrintFi = 1;
int			CR=0;
int			debug=0;
int			BigErr=0;
int         DfltErr=1;

extern int THRexpr, THRif;

/* O p t i o n   L i s t  S t u f f */
void pDErr()				{ DfltErr = 0; }
void pTrax()				{ MakeTrax = 1; }
void pCache()				{ UseCache = 0; }
void pPrint()				{ PrintGrammar = 1; }
void pNoLex()				{ LexFile = NULL; }
void pLexFile(s,t) char *s,*t;{ LexFile = t; }
void pNoCode()				{ NoCode = 1; pNoLex(); }
void pInherit()				{ ForceInherit = 1; }
void pFile(s) char *s;		{ FileStr[NumFiles++] = s; }
void pPrintSub()			{ PrFirstSub = 0; }
void pPrFi()				{ PrintFi = 0; }
void pPrFo()				{ PrintFo = 0; }
void pCross()				{ CR = 1; }
void pBig()					{ BigErr = 1; }
void pExpr(s,t) char *s,*t;	{ THRexpr = atoi(t); }
void pAlt(s,t) char *s,*t;	{ THRif = atoi(t); }
void pDeb(s,t) char *s,*t;
	{	if ( *t != '.' ) debug |= (1 << (atoi(t)-1));
		else {
			fprintf(stderr, "\t%2s\tPrint follow cache after each follow\n","1");
			fprintf(stderr, "\t%2s\tPrint \"entering function\" kinda stuff\n","2");
			fprintf(stderr, "\t%2s\tPrint guts of follow calculation\n","3");
			fprintf(stderr, "\t%2s\tPrint out cache statistics\n","4");
			fprintf(stderr, "\t%2s\tPrint out memory information at end\n","5");
			exit(0);
		}
	}

typedef struct {
			char *option;
			int  arg;
			void (*process)();
			char *descr;
		} Opt;

Opt options[] = {
	{ "-T", 0, pTrax,	"Place aTrax() call at start of rules" },
	{ "-z", 0, pCache,	"Turn off cache" },
	{ "-p", 0, pPrint,	"Print out the grammar" },
	{ "-n", 0, pNoLex,	"No lexical output (parser.dlg, tokens.h)" },
	{ "-l", 1, pLexFile,"Rename lexical output filename" },
	{ "-c", 0, pNoCode,	"Generate no C code parser" },
	{ "-I", 0, pInherit,"Turn on default inheritance" },
	{ "-s", 0, pPrintSub,"Do not print first sets of subrules" },
	{ "-fi",0, pPrFi,	"Do not print first sets" },
	{ "-fo",0, pPrFo,	"Do not print follow sets" },
	{ "-R", 0, pCross,	"Print rule cross reference" },
	{ "-e", 1, pExpr,	"Set expression threshold (def 3)" },
	{ "-a", 1, pAlt,	"Set alternative threshold (def 3)" },
	{ "-w", 1, pBig,	"Produce better warning messages for subrules" },
	{ "-d", 1, pDeb,	"Turn on debug code (def 0; '.' => list codes)" },
    { "-E", 0, pDErr,   "Turn off \"#define aError(a,b) dfltError(a,b)\"\n" },
	{ "*",  0, pFile, "" },	/* anything else is a file */
	{ NULL, 0, NULL }
};

main(argc, argv)
int argc;
char *argv[];
{
	fprintf(stderr, "Antlr parser generator   Version 1.0B   (c) 1989, 1990\n");
	if ( argc == 1 ) 
	{
		Opt *p = options;
		fprintf(stderr, "antlr [options] f1 f2 ... fn\n");
		while ( *(p->option) != '*' )
		{
			fprintf(stderr, "\t%s %s\t%s\n",
							p->option,
							(p->arg)?"___":"   ",
							p->descr);
			p++;
		}
	}
	ProcessArgs(argc-1, &(argv[1]), options);
	init();
	readDescr();
	if ( Terminate ) { cleanUp(); exit(-1); }
	InitCache(NumRules+1);
	{int new; EpToken = defTname( "[Epsilon]", "e", &new );}
	CrossRef = (set *) calloc(NumRules+1, sizeof(set));
	if ( CrossRef == NULL ) fatal("Cannot allocate cross ref");
	
	/* G e n  O u t p u t */
	if ( LexFile != NULL ) DumpTokens( TokenStr );
	set_size( NumWords(MaxToken) );
	if ( PrintGrammar ) dispRules( Rules, stdout );
	InhChk( Rules );	/* Check inheritance consistency && compute cross ref */
	if ( NoCode ) CheckRules( Rules );
	else GenRules( Rules );
	DEBUG(4) {
		fprintf(stderr, "First cache saved %d Operations\n", Save);
		fprintf(stderr, "There were %d follow set requests\n", FoRequest);
		fprintf(stderr, "%d required no computation\n", FoSave);
		fprintf(stderr, "%d required partial computation\n", FoPartial);
		fprintf(stderr, "%d/%d = %f required complete computation\n",
						FoCompute,FoRequest, ((float)FoCompute)/((float)FoRequest));
		fprintf(stderr, "Computed F(%d rules) = %d complete follows\n", NumRules, FoCompute);
	}

	if ( CR )
	{
		int i;
		
		printf("\nCross Reference:\n\n");
		for (i=1; i<=NumRules; i++)
		{
			printf("Rule %12s referenced by ", RuleStr[i]);
			if ( CrossRef[i].n == 0 ) printf("NO ONE");
			else set_prR(CrossRef[i]);
			putchar('\n');
		}
		printf("\nRules with explicit inheritance: ");
		if ( RuleInh.n == 0 ) printf("NONE");
		else set_prR(RuleInh);
		putchar('\n');
	}

	cleanUp();
	exit(0);
}

static
readDescr()
{
	FILE *f;

	f = NextFile();
	if ( f == NULL )
	{
		warn("\nNo grammar description found (exiting...)");
		cleanUp();
		exit(-1);
	}
	ANTLR(grammar, f);
}

FILE *
NextFile()
{
	FILE *f;

	for (;;)
	{
		if ( CurFile >= NumFiles ) return(NULL);
		f = fopen(FileStr[CurFile], "r");
		if ( f == NULL )
		{
			warn( eMsg("File %s doesn't exist (ignoring...)",
					FileStr[CurFile]) );
			CurFile++;	/* Look for next file */
		}
		else
		{
			aSourceFile = FileStr[CurFile];
			return(f);
		}
	}
}

static
init()
{
	AttribAction = NULL;
	InitStrArray( TokenStr );
	InitStrArray( RegExprStr );
	InitStrArray( RuleStr );
	FiVisit = FoVisit = RuleInh = empty;
}

cleanUp()
{
#ifndef MEMCHK
	if ( AttribAction != NULL ) free( AttribAction );
	set_free( FiVisit );
	set_free( FoVisit );
	set_free( RuleInh );
	if ( RuleFile != NULL ) free( RuleFile );
	if ( RuleLine != NULL ) free( RuleLine );
	if ( Rules != NULL ) freeRules( Rules );
	if ( TokenStr != NULL ) freeStrArray( TokenStr );
	if ( RegExprStr != NULL ) freeStrArray( RegExprStr );
	if ( ActStr != NULL ) freeStrArray( ActStr );
	if ( ActStr2 != NULL ) freeStrArray( ActStr2 );
	if ( FailActionStr != NULL ) freeStrArray( FailActionStr );
	if ( RuleStr != NULL ) freeStrArray( RuleStr );
	if ( CrossRef != NULL )
	{
		int i;
		for (i=1; i<=NumRules; i++)
		{
			set_free( CrossRef[i] );
		}
		free( CrossRef );
	}
	KillCache(NumRules+1);
#else
	mWipe();		/* Free all memory */
	DEBUG(5) {
		mHist(stderr);
		fprintf(stderr, "Max memory allocated at one time, %d\n", mMax);
	}
#endif
}

char *
eMsg(s, a1, a2, a3, a4, a5, a6)
char *s;
long a1,a2,a3,a4,a5,a6;
{
	static char buf[150];
	
	sprintf(buf, s, a1, a2, a3, a4, a5, a6);
	return( buf );
}

/*
 * Add rule 'r' to the RuleStr array if not already there.
 * Return position where 'r' was placed.
 * Return 0 if duplicate.
 */
defRname(r)
char *r;
{
	static int i=0;
	char *p;
	
	if ( strPos(RuleStr, r) != 0 )
	{
		warn( eMsg("Duplicate rule redefinition: %s", r) );
		return(0);
	}
	
	p = (char *) calloc(strlen(r)+1, sizeof(char));
	if ( p == NULL ) fatal("Can't Alloc RuleName");
	strcpy(p, r);
	extStrArray(RuleStr, i);
	RuleStr[i] = p;
	extStrArray(RuleStr, i);
	RuleStr[i] = NULL;
	return( --i );
}

/*
 * Add token 't' to the TokenStr array if not already there and a token name.
 * If reg expr, add to reg expr array
 * Return position where 't' was placed.
 */
defTname(t, e, new)
char *t, *e;
int *new;
{
	int i=0,j=0;
	char *p;
	
/*
	fprintf(stderr, "entering defTname, %s == %s\n",
						(t==NULL)?"NULL":t,
						(e==NULL)?"NULL":e);
	fprintf(stderr, "Tokens\n");
	for (k=1; k<sizeT(TokenStr); k++)
	{
		fprintf(stderr, "[%d] '%s'\n", k, (TokenStr[k]==NULL)?"NULL":TokenStr[k]);
	}
	fprintf(stderr, "\nExprs\n");
	for (k=1; k<sizeT(RegExprStr); k++)
	{
		fprintf(stderr, "[%d] '%s'\n", k, (RegExprStr[k]==NULL)?"NULL":RegExprStr[k]);
	}
*/

	if ( e == NULL && t == NULL ) fatal("defTname: Hmmm... both ptrs are NULL");
	if ( t != NULL ) i=strPos(TokenStr, t);
	if ( e != NULL ) j=strPos(RegExprStr, e);
	if ( i != j && i!=0 && j!=0 )
	{
		warnFL( eMsg("Token name %s and rexpr %s are different tokens; ignored",
						TokenStr[i], RegExprStr[j]),
				aSourceFile,
				lex_line );
	}
	if ( i!=0 || j!=0 ) *new = FALSE;
	else *new = TRUE;
	if ( i==0 && t != NULL )
	{
		p = (char *) calloc(strlen(t)+1, sizeof(char));
		if ( p == NULL ) fatal("Can't Alloc TokenName");
		strcpy(p, t);
		if ( j == 0 )
		{
			/* doesn't exist anywhere, create the token */
			extStrArray(TokenStr, MaxToken); TokenStr[MaxToken--] = p;
			extStrArray(RegExprStr, MaxToken);
			i = MaxToken;
		}
		else
		{
			if ( TokenStr[j] != NULL )
			{
				warnFL( eMsg("Redefinition of token name %s for rexpr %s to %s; ignored",
								TokenStr[j], RegExprStr[j], p),
						aSourceFile,
						lex_line );
				free(p);
			}
			else TokenStr[j] = p;
		}
	}
	if ( j==0 && e != NULL )
	{
		p = (char *) calloc(strlen(e)+1, sizeof(char));
		if ( p == NULL ) fatal("Can't Alloc RegExprStr");
		strcpy(p, e);
		if ( i == 0 )
		{
			/* must create token */
			extStrArray(RegExprStr, MaxToken); RegExprStr[MaxToken--] = p;
			extStrArray(TokenStr, MaxToken);
			j = MaxToken;
		}
		else
		{
			if ( RegExprStr[i] != NULL )
			{
				warnFL( eMsg("Redefinition of rexpr %s for token name %s to %s; ignored",
								RegExprStr[i], TokenStr[i], p),
						aSourceFile,
						lex_line );
				free(p);
			}
			else RegExprStr[i] = p;
		}
	}

	return( (i!=0)?i:j );
}

freeAtom(a)
Atom *a;
{
	if ( a == NULL ) return;
	switch ( a->type )
	{
		case aRule :
			free( a->ptr.rule );
			if ( a->inheritance != NULL ) free( a->inheritance );
			break;
		case aAction :
			free( a->ptr.action );
			break;
		case aSubBLK :
		case aOptBLK :
		case aLoopBLK :
			freeBlk( a->ptr.block );
			if ( a->inheritance != NULL ) free( a->inheritance );
			break;
	}
}

freeAlt(alt)
Atom *alt;
{
	int i;
	
	if ( alt == NULL ) return;
	for (i=1; alt[i].type != EOL; i++) freeAtom( &(alt[i]) );
	free( alt );
}

freeBlk(b)
Atom **b;
{
	int i;
	
	if ( b == NULL ) return;
	for (i=1; b[i] != NULL; i++) freeAlt( b[i] );
	free( b );
}

freeRules(r)
Atom ***r;
{
	int i;
	
	for (i=1; r[i] != NULL; i++) freeBlk( r[i] );
	free( r );
}

strPos(a, s)
char **a, *s;
{
	int i;
	
	for (i=1; i<sizeT(a); i++)
	{
		if ( a[i]==NULL ) continue;
		if ( strcmp(a[i],s) == StrSame ) return( i );
	}
	return( 0 );
}

freeStrArray(a)
char **a;
{
	int i;
	
	for (i=1; i<sizeT(a); i++)
	{
		if ( a[i] != NULL )
			if ( a[i]!=NULL ) free( a[i] );
	}
	free( a );
}

dispAtom(a,f)
Atom a;
FILE *f;
{
	switch ( a.type )
	{
		case aLeaf :	fprintf(f," %s", TokenName(a.token));
						break;
		case aRule :	fprintf(f," %s", a.ptr.rule);
						break;
		case aAction :	/*fprintf(f,"<<...>>");*/
						break;
		case aSubBLK :	fprintf(f," (");
						dispBlk(a.ptr.block,f);
						fprintf(f," )");
						break;
		case aOptBLK :	fprintf(f," {");
						dispBlk(a.ptr.block,f);
						fprintf(f," }");
						break;
		case aLoopBLK :	fprintf(f," (");
						dispBlk(a.ptr.block,f);
						fprintf(f," )*");
						break;
	}
}

dispAlt(alt,f)
Atom *alt;
FILE *f;
{
	int i;
	
	for (i=1; alt[i].type != EOL; i++)
	{
		dispAtom( alt[i], f );
	}
}

dispBlk(b,f)
Atom **b;
FILE *f;
{
	int i;
	
	for (i=1; b[i] != NULL; i++)
	{
		dispAlt( b[i], f);
		if ( b[i+1]!=NULL ) fprintf(f," |");
	}
}

dispRules(r,f)
Atom ***r;
FILE *f;
{
	int i, old;
	
	old = -1;
	for (i=1; r[i] != NULL; i++)
	{
		if ( RuleFile[i] != old )
		{
			old = RuleFile[i];
			fprintf(f,"\n[File %s]\n\n", FileStr[old]);
		}
		fprintf(f,"%s :", RuleStr[i]);
		dispBlk( r[i],f );
		fprintf(f," ;\n\n");
	}
}

ProcessArgs(argc, argv, options)
int argc;
char **argv;
Opt *options;
{
	Opt *p;
	
	while ( argc-- > 0 )
	{
		p = options;
		while ( p->option != NULL )
		{
			if ( strcmp(p->option, "*") == 0 ||
				 strcmp(p->option, *argv) == 0 )
			{
				if ( p->arg )
				{
					(*p->process)( *argv, *(argv+1) );
					argv++;
					argc--;
				}
				else
					(*p->process)( *argv );
				break;
			}
			p++;
		}
		argv++;
	}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'makefile'
then
	echo shar: will not over-write existing file "'makefile'"
else
cat << \SHAR_EOF > 'makefile'
CFLAGS=-I../h -DMEMCHK -g

SRC = fset.c main.c trax.c scan.c antlr.c chk.c gen.c set.c err.c
OBJ = fset.o main.o trax.o scan.o antlr.o chk.o gen.o set.o err.o

antlr1.0B : $(OBJ) $(SRC)
	cc -g -o antlr $(OBJ)

scan.c : parser.dlg
	dlg -C2 parser.dlg scan.c
SHAR_EOF
fi # end of overwriting check
if test -f 'parser.dlg'
then
	echo shar: will not over-write existing file "'parser.dlg'"
else
cat << \SHAR_EOF > 'parser.dlg'
<<
/* parser.dlg -- DLG Description of scanner
 *
 * Generated from: antlr.g
 *
 * (c) 1989, 1990 by Terence Parr, Hank Dietz and Will Cohen
 * Purdue University Electrical Engineering
 * ANTLR Version 1.0B
 */
#include <stdio.h>
#include "tokens.h"
int Token;
#include "set.h"
#include "struct.h"
#ifdef MEMCHK
#include "trax.h"
#endif
#include "attrib.h"
#ifndef LEX_BUF
#define LEX_BUF 2000
#endif
action0()
{
	lex_err("Invalid token");
	advance();
	LexSkip();
}

lex(t)
int t;
{
	extern char LexText[];
	if ( Token == t )
	{
		MakeAttr;
		if ( Token != Eof ) GetToken();
		return( 1 );
	}
	return( 0 );
}
>>

%%

[\t\ ]
	<<
		Token = 1;
		LexSkip(); 
	>>

[\n\r]
	<<
		Token = 2;
		lex_line++; LexSkip(); 
	>>

/\*
	<<
		Token = 3;
		scarfComment(); LexSkip(); 
	>>

\*/
	<<
		Token = 4;
		warn("Missing /* found dangling */"); LexSkip(); 
	>>

\>\>
	<<
		Token = 5;
		warn("Missing << found dangling \>\>"); LexSkip(); 
	>>

\<\<
	<<
		Token = Action;
		scarfAction(); 
	>>

#attrib
	<<
		Token = 7;
	>>

#lex
	<<
		Token = 9;
	>>

action
	<<
		Token = 10;
	>>

:
	<<
		Token = 12;
	>>

;
	<<
		Token = 13;
	>>

#token
	<<
		Token = 14;
	>>

\|
	<<
		Token = 17;
	>>

\(
	<<
		Token = 19;
	>>

\)
	<<
		Token = 20;
	>>

\*
	<<
		Token = 21;
	>>

\{
	<<
		Token = 22;
	>>

\}
	<<
		Token = 23;
	>>

[a-z] [A-Za-z0-9_]*
	<<
		Token = NonTerminal;
	>>

[A-Z] [A-Za-z0-9_]*
	<<
		Token = TokenTerm;
	>>

\[
	<<
		Token = Override;
		scarfParm(); 
	>>

"[\0x20-\0x21\0x23-\0x7e]
	<<
		Token = QuotedTerm;
		scarfQuotedTerm(); 
	>>

@
	<<
		Token = Eof;
		/* L o o k  F o r  A n o t h e r  F i l e */
		{
			FILE *f;
			CloseLexInputStream();
			CurFile++;
			f = NextFile();
			if ( f == NULL )
			{
				Token = Eof;
				return;
			}
			SetLexInputStream( f );
			advance();	/* Get 1st char of this file */
			LexSkip();	/* Skip the Eof (@) char i.e continue */
		}
	>>


%%

<<
#include "lexhelp.c"
>>
SHAR_EOF
fi # end of overwriting check
if test -f 'scan.c'
then
	echo shar: will not over-write existing file "'scan.c'"
else
cat << \SHAR_EOF > 'scan.c'

/* parser.dlg -- DLG Description of scanner
 *
 * Generated from: antlr.g
 *
 * (c) 1989, 1990 by Terence Parr, Hank Dietz and Will Cohen
 * Purdue University Electrical Engineering
 * ANTLR Version 1.0B
 */
#include <stdio.h>
#include "tokens.h"
int Token;
#include "set.h"
#include "struct.h"
#ifdef MEMCHK
#include "trax.h"
#endif
#include "attrib.h"
#ifndef LEX_BUF
#define LEX_BUF 2000
#endif
action0()
{
	lex_err("Invalid token");
	advance();
	LexSkip();
}

lex(t)
int t;
{
	extern char LexText[];
	if ( Token == t )
	{
		MakeAttr;
		if ( Token != Eof ) GetToken();
		return( 1 );
	}
	return( 0 );
}

static FILE *inputStream;
char LexText[LEX_BUF];
static int lex_c = ' ';
static int lex_mode;
int lex_line = 1;


#define LEX_EOF -1
unsigned char shift[];
int (*actions[])();
static
action1()
{ 
		Token = 1;
		LexSkip(); 
	
}

static
action2()
{ 
		Token = 2;
		lex_line++; LexSkip(); 
	
}

static
action3()
{ 
		Token = 3;
		scarfComment(); LexSkip(); 
	
}

static
action4()
{ 
		Token = 4;
		warn("Missing /* found dangling */"); LexSkip(); 
	
}

static
action5()
{ 
		Token = 5;
		warn("Missing << found dangling \>\>"); LexSkip(); 
	
}

static
action6()
{ 
		Token = Action;
		scarfAction(); 
	
}

static
action7()
{ 
		Token = 7;
	
}

static
action8()
{ 
		Token = 9;
	
}

static
action9()
{ 
		Token = 10;
	
}

static
action10()
{ 
		Token = 12;
	
}

static
action11()
{ 
		Token = 13;
	
}

static
action12()
{ 
		Token = 14;
	
}

static
action13()
{ 
		Token = 17;
	
}

static
action14()
{ 
		Token = 19;
	
}

static
action15()
{ 
		Token = 20;
	
}

static
action16()
{ 
		Token = 21;
	
}

static
action17()
{ 
		Token = 22;
	
}

static
action18()
{ 
		Token = 23;
	
}

static
action19()
{ 
		Token = NonTerminal;
	
}

static
action20()
{ 
		Token = TokenTerm;
	
}

static
action21()
{ 
		Token = Override;
		scarfParm(); 
	
}

static
action22()
{ 
		Token = QuotedTerm;
		scarfQuotedTerm(); 
	
}

static
action23()
{ 
		Token = Eof;
		/* L o o k  F o r  A n o t h e r  F i l e */
		{
			FILE *f;
			CloseLexInputStream();
			CurFile++;
			f = NextFile();
			if ( f == NULL )
			{
				Token = Eof;
				return;
			}
			SetLexInputStream( f );
			advance();	/* Get 1st char of this file */
			LexSkip();	/* Skip the Eof (@) char i.e continue */
		}
	
}

#define DfaStates	47
#define NumAtoms	34
typedef unsigned char DfaState;

DfaState accepts[];
DfaState *dfa[];

static DfaState state0[NumAtoms] = {
  1, 2, 3, 2, 47, 4, 5, 6, 7, 8, 9, 47, 
  10, 11, 12, 13, 14, 15, 16, 17, 17, 17, 17, 17, 
  17, 17, 17, 17, 17, 17, 17, 18, 19, 20
};

static DfaState state1[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state2[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state3[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state4[NumAtoms] = {
  47, 47, 47, 21, 21, 47, 21, 21, 21, 21, 21, 21, 
  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 
  21, 21, 21, 21, 21, 21, 21, 21, 21, 21
};

static DfaState state5[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 22, 47, 47, 47, 47, 47, 
  47, 23, 47, 47, 47, 24, 47, 47, 47, 47
};

static DfaState state6[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state7[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state8[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 25, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state9[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 26, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state10[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state11[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state12[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 27, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state13[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 28, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state14[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 29, 
  47, 47, 47, 47, 29, 47, 29, 29, 29, 29, 29, 29, 
  29, 29, 29, 29, 29, 29, 29, 47, 47, 47
};

static DfaState state15[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state16[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 30, 
  47, 47, 47, 47, 30, 47, 30, 30, 31, 30, 30, 30, 
  30, 30, 30, 30, 30, 30, 30, 47, 47, 47
};

static DfaState state17[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 30, 
  47, 47, 47, 47, 30, 47, 30, 30, 30, 30, 30, 30, 
  30, 30, 30, 30, 30, 30, 30, 47, 47, 47
};

static DfaState state18[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state19[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state20[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state21[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state22[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 32, 47, 47, 47, 47
};

static DfaState state23[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 33, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state24[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 34, 47, 47, 47, 47, 47, 47
};

static DfaState state25[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state26[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state27[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state28[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state29[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 29, 
  47, 47, 47, 47, 29, 47, 29, 29, 29, 29, 29, 29, 
  29, 29, 29, 29, 29, 29, 29, 47, 47, 47
};

static DfaState state30[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 30, 
  47, 47, 47, 47, 30, 47, 30, 30, 30, 30, 30, 30, 
  30, 30, 30, 30, 30, 30, 30, 47, 47, 47
};

static DfaState state31[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 30, 
  47, 47, 47, 47, 30, 47, 30, 30, 30, 30, 30, 30, 
  30, 30, 30, 30, 30, 35, 30, 47, 47, 47
};

static DfaState state32[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 36, 47, 47, 47, 47
};

static DfaState state33[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 37, 47, 47, 47
};

static DfaState state34[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  38, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state35[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 30, 
  47, 47, 47, 47, 30, 47, 30, 30, 30, 30, 30, 39, 
  30, 30, 30, 30, 30, 30, 30, 47, 47, 47
};

static DfaState state36[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 40, 47, 47, 47, 47, 47
};

static DfaState state37[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state38[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 41, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state39[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 30, 
  47, 47, 47, 47, 30, 47, 30, 30, 30, 30, 30, 30, 
  30, 30, 30, 42, 30, 30, 30, 47, 47, 47
};

static DfaState state40[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 43, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state41[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 44, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state42[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 30, 
  47, 47, 47, 47, 30, 47, 30, 30, 30, 30, 30, 30, 
  30, 30, 45, 30, 30, 30, 30, 47, 47, 47
};

static DfaState state43[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 46, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state44[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};

static DfaState state45[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 30, 
  47, 47, 47, 47, 30, 47, 30, 30, 30, 30, 30, 30, 
  30, 30, 30, 30, 30, 30, 30, 47, 47, 47
};

static DfaState state46[NumAtoms] = {
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 
  47, 47, 47, 47, 47, 47, 47, 47, 47, 47
};


static DfaState *dfa[47] = {
	state0,
	state1,
	state2,
	state3,
	state4,
	state5,
	state6,
	state7,
	state8,
	state9,
	state10,
	state11,
	state12,
	state13,
	state14,
	state15,
	state16,
	state17,
	state18,
	state19,
	state20,
	state21,
	state22,
	state23,
	state24,
	state25,
	state26,
	state27,
	state28,
	state29,
	state30,
	state31,
	state32,
	state33,
	state34,
	state35,
	state36,
	state37,
	state38,
	state39,
	state40,
	state41,
	state42,
	state43,
	state44,
	state45,
	state46
};


static DfaState accepts[47] = {
0, 23, 1, 2, 0, 0, 14, 15, 16, 0, 10, 11, 
  0, 0, 20, 21, 19, 19, 17, 13, 18, 22, 0, 0, 
  0, 4, 3, 6, 5, 20, 19, 19, 0, 0, 0, 19, 
  0, 8, 0, 19, 0, 0, 19, 0, 12, 9, 7
};

static int (*actions[24])() = {
	action0,
	action1,
	action2,
	action3,
	action4,
	action5,
	action6,
	action7,
	action8,
	action9,
	action10,
	action11,
	action12,
	action13,
	action14,
	action15,
	action16,
	action17,
	action18,
	action19,
	action20,
	action21,
	action22,
	action23
};

static unsigned char shift[129] = {
  0, 34, 34, 34, 34, 34, 34, 34, 34, 34, 1, 2, 
  34, 34, 2, 34, 34, 34, 34, 34, 34, 34, 34, 34, 
  34, 34, 34, 34, 34, 34, 34, 34, 34, 3, 4, 5, 
  6, 4, 4, 4, 4, 7, 8, 9, 4, 4, 4, 4, 
  10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 
  13, 14, 4, 15, 4, 4, 16, 16, 16, 16, 16, 16, 
  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
  16, 16, 16, 16, 16, 16, 16, 16, 17, 4, 4, 4, 
  11, 4, 18, 19, 20, 21, 22, 21, 21, 21, 23, 21, 
  24, 25, 21, 26, 27, 21, 21, 28, 21, 29, 21, 21, 
  21, 30, 21, 21, 31, 32, 33, 4, 34
};



#define _SHIFT(c) ((&shift[1])[c])
#include "dlgauto.h"

#include "lexhelp.c"

SHAR_EOF
fi # end of overwriting check
if test -f 'set.c'
then
	echo shar: will not over-write existing file "'set.c'"
else
cat << \SHAR_EOF > 'set.c'
/*	set.c

	The following is a general-purpose set library originally developed
	by Hank Dietz and enhanced by Terence Parr to allow dynamic sets.
	
	Sets are now structs containing the #words in the set and
	a pointer to the actual set words.
	
	Generally, sets need not be explicitly allocated.  They are
	created/extended/shrunk when appropriate (e.g. in set_of()).
	HOWEVER, sets need to be destroyed (free()ed) when they go out of scope
	or are otherwise no longer needed.  A routine is provided to
	free a set.
	
	Sets can be explicitly created with set_new(s, max_elem).
	
	Sets can be declared to have minimum size to reduce realloc traffic.
	Default minimum size = 1.
	
	Sets can be explicitly initialized to have no elements (set.n == 0)
	by using the 'empty' initializer:
	
	Examples:
		set a = empty;	-- set_deg(a) == 0
		
		return( empty );
	
	Example set creation and destruction:
	
	set
	set_of2(e,g)
	unsigned e,g;
	{
		set a,b,c;
		
		b = set_of(e);		-- Creates space for b and sticks in e
		set_new(c, g);		-- set_new(); set_orel() ==> set_of()
		set_orel(g, &c);
		a = set_or(b, c);
		.
		.
		.
		set_free(b);
		set_free(c);
		return( a );
	}

	(C) 1987 by Hank Dietz
	
	Modified by:
		Terence Parr
		Purdue University
		October 1989
*/

#include <stdio.h>
#include "set.h"
#ifdef MEMCHK
#include "trax.h"
#else
char *malloc(), *realloc();
#endif

/* elems can be a maximum of 32 bits */
static unsigned bitmask[] = {
	0x00000001, 0x00000002, 0x00000004, 0x00000008,
	0x00000010, 0x00000020, 0x00000040, 0x00000080,
	0x00000100, 0x00000200, 0x00000400, 0x00000800,
	0x00001000, 0x00002000, 0x00004000, 0x00008000,
	0x00010000, 0x00020000, 0x00040000, 0x00080000,
	0x00100000, 0x00200000, 0x00400000, 0x00800000,
	0x01000000, 0x02000000, 0x04000000, 0x08000000,
	0x10000000, 0x20000000, 0x40000000, 0x80000000
};

set empty = set_init;
static unsigned min=1;

#define StrSize		200

#ifdef MEMCHK
#define CHK(a)					\
	if ( a.setword != NULL )	\
	  if ( !valid(a.setword) )	\
		{fprintf(stderr, "%s(%d): invalid set\n",__FILE__,__LINE__); exit(-1);}
#else
#define CHK(a)
#endif

/*
 * Set the minimum size (in words) of a set to reduce realloc calls
 */
void
set_size(n)
unsigned n;
{
	min = n;
}

unsigned int
set_deg(a)
set a;
{
	/* Fast compute degree of a set... the number
	   of elements present in the set.  Assumes
	   that all word bits are used in the set
	   and that SETSIZE(a) is a multiple of WORDSIZE.
	*/
	register unsigned *p = &(a.setword[0]);
	register unsigned *endp = &(a.setword[a.n]);
	register unsigned degree = 0;

	CHK(a);
	if ( a.n == 0 ) return(0);
	while ( p < endp )
	{
		register unsigned t = *p;
		register unsigned *b = &(bitmask[0]);
		do {
			if (t & *b) ++degree;
		} while (++b < &(bitmask[WORDSIZE]));
		p++;
	}

	return(degree);
}

set
set_or(b,c)
set b, c;
{
	/* Fast set union operation */
	/* resultant set size is max(b, c); */
	set *big;
	set t;
	unsigned int m,n;
	register unsigned *r, *p, *q, *endp;

	CHK(b); CHK(c);
	t = empty;
	if (b.n > c.n) {big= &b; m=b.n; n=c.n;} else {big= &c; m=c.n; n=b.n;}
	set_ext(&t, m);
	r = t.setword;

	/* Or b,c until max of smaller set */
	q = c.setword;
	p = b.setword;
	endp = &(b.setword[n]);
	while ( p < endp ) *r++ = *p++ | *q++;	

	/* Copy rest of bigger set into result */
	p = &(big->setword[n]);
	endp = &(big->setword[m]);
	while ( p < endp ) *r++ = *p++;

	return(t);
}

set
set_and(b,c)
set b, c;
{
	/* Fast set intersection operation */
	/* resultant set size is min(b, c); */
	set t;
	unsigned int n;
	register unsigned *r, *p, *q, *endp;

	CHK(b); CHK(c);
	t = empty;
	n = (b.n > c.n) ? c.n : b.n;
	set_ext(&t, n);
	r = t.setword;

	/* & b,c until max of smaller set */
	q = c.setword;
	p = b.setword;
	endp = &(b.setword[n]);
	while ( p < endp ) *r++ = *p++ & *q++;	

	return(t);
}

set
set_dif(b,c)
set b, c;
{
	/* Fast set difference operation b - c */
	/* resultant set size is size(b) */
	set t;
	unsigned int n;
	register unsigned *r, *p, *q, *endp;

	CHK(b); CHK(c);
	t = empty;
	n = (b.n <= c.n) ? b.n : c.n ;
	set_ext(&t, b.n);
	r = t.setword;

	/* Dif b,c until smaller set size */
	q = c.setword;
	p = b.setword;
	endp = &(b.setword[n]);
	while ( p < endp ) *r++ = *p++ & (~ *q++);	

	/* Copy rest of b into result if size(b) > c */
	if ( b.n > n )
	{
		p = &(b.setword[n]);
		endp = &(b.setword[b.n]);
		while ( p < endp ) *r++ = *p++;
	}

	return(t);
}

set
set_of(b)
unsigned b;
{
	/* Fast singleton set constructor operation */
	static set a;

	if ( b == nil ) return( empty );
	set_new(a, b);
	a.setword[DIVWORD(b)] = bitmask[MODWORD(b)];

	return(a);
}

/*
 * Extend (or shrink) the set passed in to have n words.
 *
 * if n is smaller than the minimum, boost n to have the minimum.
 * if the new set size is the same as the old one, do nothing.
 */
void
set_ext(a, n)
set *a;
unsigned int n;
{
	register unsigned *p;
	register unsigned *endp;
	unsigned int size;
	
	CHK((*a));
    if ( a->n == 0 )
    {
        a->setword = (unsigned *) calloc(n, BytesPerWord);
        if ( a->setword == NULL )
        {
            fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n);
			*((char *)5) = 1;
            exit(-1);
        }
        a->n = n;
        return;
    }
	if ( n < min ) n = min;
	if ( a->n == n || n == 0 ) return;
	size = a->n;
	a->n = n;
	a->setword = (unsigned *) realloc( a->setword, (n*BytesPerWord) );
	if ( a->setword == NULL )
	{
		fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n);
		exit(-1);
	}

	p    = &(a->setword[size]);		/* clear from old size to new size */
	endp = &(a->setword[a->n]);
	do {
		*p++ = 0;
	} while ( p < endp );
}

set
set_not(a)
set a;
{
	/* Fast not of set a (assumes all bits used) */
	/* size of resultant set is size(a) */
	/* ~empty = empty cause we don't know how bit to make set */
	set t;
	register unsigned *r;
	register unsigned *p = a.setword;
	register unsigned *endp = &(a.setword[a.n]);

	CHK(a);
	t = empty;
	if ( a.n == 0 ) return( empty );
	set_ext(&t, a.n);
	r = t.setword;
	
	do {
		*r++ = (~ *p++);
	} while ( p < endp );

	return(t);
}

int
set_equ(a,b)
set a, b;
{
	/* Fast set equality comparison operation */
	register unsigned *p = a.setword;
	register unsigned *q = b.setword;
	register unsigned *endp = &(a.setword[a.n]);

	CHK(a); CHK(b);
	if ( a.n != b.n ) return(0);
	else if ( a.n==0 ) return(1);	/* empty == empty */
	
	do {
		if (*p != *q) return(0);
		++q;
	} while ( ++p < endp );

	return(1);
}

int
set_sub(a,b)
set a, b;
{
	/* Fast check for a is a proper subset of b (alias a < b) */
	register unsigned *p = a.setword;
	register unsigned *q = b.setword;
	register unsigned *endp = &(a.setword[a.n]);
	register int asubset = 0;

	CHK(a); CHK(b);
	if ( a.n > b.n ) return(0);
	if ( a.n == 0 ) return(1);		/* empty is sub of everything */
	if (a.n==0 && b.n==0) return(1);/* empty prop sub of empty */

	do {
		/* Prune tests based on guess that most set words
		   will match, particularly if a is a subset of b.
		*/
		if (*p != *q) {
			if (*p & ~(*q)) {
				/* Fail -- a contains something b does not */
				return(0);
			}
			/* At least this word was a proper subset, hence
			   even if all other words are equal, a is a
			   proper subset of b.
			*/
			asubset = 1;
		}
		++q;
	} while (++p < endp);

	/* at this point, a,b are equ or a subset */
	if ( asubset || b.n == a.n ) return(asubset);
	
	/* if !asubset, size(b) > size(a), then a=b and must check rest of b */
	p = q;
	endp = &(a.setword[b.n]);
	do
	{
		if ( *p++ ) return(1);
	} while ( p < endp );

	return(0);
}

unsigned
set_int(b)
set b;
{
	/* Fast pick any element of the set b */
	register unsigned *p = b.setword;
	register unsigned *endp = &(b.setword[b.n]);

	CHK(b);
	if ( b.n == 0 ) return( nil );

	do {
		if (*p) {
			/* Found a non-empty word of the set */
			register unsigned i = ((p - b.setword) << LogWordSize);
			register unsigned t = *p;
			p = &(bitmask[0]);
			while (!(*p & t)) {
				++i; ++p;
			}
			return(i);
		}
	} while (++p < endp);

	/* Empty -- only element it contains is nil */
	return(nil);
}

int
set_el(b,a)
unsigned b;
set a;
{
	CHK(a);
	/* nil is an element of every set */
	if (b == nil) return(1);
	if ( a.n == 0 || NumWords(b) > a.n ) return(0);
	
	/* Otherwise, we have to check */
	return( a.setword[DIVWORD(b)] & bitmask[MODWORD(b)] );
}

set_nil(a)
set a;
{
	/* Fast check for nil set */
	register unsigned *p = a.setword;
	register unsigned *endp = &(a.setword[a.n]);

	CHK(a);
	if ( a.n == 0 ) return(1);
	/* The set is not empty if any word used to store
	   the set is non-zero.  This means one must be a
	   bit careful about doing things like negation.
	*/
	do {
		if (*p) return(0);
	} while (++p < endp);
	
	return(1);
}

char *
set_str(a)
set a;
{
	/* Fast convert set a into ASCII char string...
	   assumes that all word bits are used in the set
	   and that SETSIZE is a multiple of WORDSIZE.
	   Trailing 0 bits are removed from the string.
	   if no bits are on or set is empty, "" is returned.
	*/
	register unsigned *p = a.setword;
	register unsigned *endp = &(a.setword[a.n]);
	static char str_tmp[StrSize+1];
	register char *q = &(str_tmp[0]);

	CHK(a);
	if ( a.n==0 ) {*q=0; return( &(str_tmp[0]) );}
	do {
		register unsigned t = *p;
		register unsigned *b = &(bitmask[0]);
		do {
			*(q++) = ((t & *b) ? '1' : '0');
		} while (++b < &(bitmask[WORDSIZE]));
	} while (++p < endp);

	/* Trim trailing 0s & NULL terminate the string */
	while ((q > &(str_tmp[0])) && (*(q-1) != '1')) --q;
	*q = 0;

	return(&(str_tmp[0]));
}

set
set_val(s)
register char *s;
{
	/* Fast convert set ASCII char string into a set.
	   If the string ends early, the remaining set bits
	   are all made zero.
	   The resulting set size is just big enough to hold all elements.
	*/
	static set a;
	register unsigned *p, *endp;

	set_new(a, strlen(s));
	p = a.setword;
	endp = &(a.setword[a.n]);
	do {
		register unsigned *b = &(bitmask[0]);
		/* Start with a word with no bits on */
		*p = 0;
		do {
			if (*s) {
				if (*s == '1') {
					/* Turn-on this bit */
					*p |= *b;
				}
				++s;
			}
		} while (++b < &(bitmask[WORDSIZE]));
	} while (++p < endp);

	return(a);
}

/*
 * Or element e into set a.  a can be empty.
 */
void
set_orel(e, a)
unsigned e;
set *a;
{
	CHK((*a));
	if ( e == nil ) return;
	if ( NumWords(e) > a->n ) set_ext(a, NumWords(e));
	a->setword[DIVWORD(e)] |= bitmask[MODWORD(e)];
}

/*
 * Or set b into set a.  a can be empty. does nothing if b empty.
 */
void
set_orin(a, b)
set *a, b;
{
	/* Fast set union operation */
	/* size(a) is max(a, b); */
	unsigned int m;
	register unsigned *p,
					  *q    = b.setword,
					  *endq = &(b.setword[b.n]);

	CHK((*a)); CHK(b);
	if ( b.n == 0 ) return;
	m = (a->n > b.n) ? a->n : b.n;
	set_ext(a, m);
	p = a->setword;
	do {
		*p++ |= *q++;
	} while ( q < endq );
}

void
set_rm(e,a)		/* removes elem arg1 from set arg2 */
unsigned e;
set a;
{
	/* Does not effect size of set */
	CHK(a);
	if ( (e == nil) || (NumWords(e) > a.n) ) return;
	a.setword[DIVWORD(e)] ^= (a.setword[DIVWORD(e)]&bitmask[MODWORD(e)]);
}

void
set_clr(a)		/* clears all elems of set arg1 */
set a;
{
	/* Does not effect size of set */
	register unsigned *p = a.setword;
	register unsigned *endp = &(a.setword[a.n]);
	
	CHK(a);
	if ( a.n == 0 ) return;
	do {
		*p++ = 0;
	} while ( p < endp );
}

set
set_dup(a)
set a;
{
	set b;
	register unsigned *p,
					  *q    = a.setword,
					  *endq = &(a.setword[a.n]);
	
	CHK(a);
	b = empty;
	if ( a.n == 0 ) return( empty );
	set_ext(&b, a.n);
	p = b.setword;
	do {
		*p++ = *q++;
	} while ( q < endq );
	
	return(b);
}

/*
 * Return a nil terminated list of unsigned ints that represents all
 * "on" bits in the bit set.
 *
 * e.g. {011011} --> {1, 2, 4, 5, nil}
 *
 * set_PDQ and set_pdq are useful when an operation is required on each element
 * of a set.  Normally, the sequence is:
 *
 *		while ( set_deg(a) > 0 ) {
 *			e = set_int(a);
 *			set_rm(e, a);
 *			...process e...
 *		}
 * Now,
 *
 *		t = e = set_pdq(a);
 *		while ( *e != nil ) {
 *			...process *e...
 *			e++;
 *		}
 *		free( t );
 *
 * We have saved many set calls and have not destroyed set a.
 */
set_PDQ(a, q)
set a;
register unsigned *q;
{
	register unsigned *p = a.setword,
					  *endp = &(a.setword[a.n]);
	register unsigned e=0;

	CHK(a);
	if ( set_deg(a) == 0 ) return;
	do {
		register unsigned t = *p;
		register unsigned *b = &(bitmask[0]);
		do {
			if ( t & *b ) *q++ = e;
			e++;
		} while (++b < &(bitmask[WORDSIZE]));
	} while (++p < endp);
	*q = nil;
}

/*
 * Same as set_PDQ except allocate memory.  set_pdq is the natural function
 * to use.
 */
unsigned *
set_pdq(a)
set a;
{
	unsigned *q;
	
	CHK(a);
	if ( set_deg(a) == 0 ) return(NULL);
	q = (unsigned *) malloc((set_deg(a)+1)*BytesPerWord);
	if ( q == NULL ) return( NULL );
	set_PDQ(a, q);
	return( q );
}
SHAR_EOF
fi # end of overwriting check
if test -f 'set.h'
then
	echo shar: will not over-write existing file "'set.h'"
else
cat << \SHAR_EOF > 'set.h'
/*	set.h

	The following is a general-purpose set library originally developed
	by Hank Dietz and enhanced by Terence Parr to allow dynamic sets.
	
	Sets are now structs containing the #words in the set and
	a pointer to the actual set words.

	(C) 1987 by Hank Dietz
	
	Modified by:
		Terence Parr
		Purdue University
		October 1989
*/

/* Define usable bits per unsigned int word */
#ifdef PC
#define WORDSIZE 16
#define LogWordSize	4
#else
#define	WORDSIZE 32
#define LogWordSize 5
#endif
#define BytesPerWord	sizeof(unsigned)

#define	SETSIZE(a) ((a).n<<LogWordSize)		/* Maximum items per set */
#define	MODWORD(x) ((x) & (WORDSIZE-1))		/* x % WORDSIZE */
#define	DIVWORD(x) ((x) >> LogWordSize)		/* x / WORDSIZE */
#define	nil	((unsigned) -1)		/* An impossible set member all bits on (big!) */

typedef struct {
			unsigned int n;		/* Number of words in set */
			unsigned *setword;
		} set;

#define set_init	{0, NULL}

#define	NumBytes(x)		(((x)>>3)+1)				/* Num bytes to hold x */
#define	NumWords(x)		(((x)>>LogWordSize)+1)		/* Num words to hold x */


/* M a c r o s */

/* make arg1 a set big enough to hold max elem # of arg2 */
#define set_new(a,max) \
if (((a).setword=(unsigned *)calloc(NumWords(max),BytesPerWord))==NULL)	\
		fprintf(stderr, "set_new: Cannot allocate set with max of %d\n", max); \
		(a).n = NumWords(max);

#define set_free(a)									\
	if ( (a).setword != NULL ) free((a).setword);	\
	(a) = empty;

set	set_and();		/* returns arg1 intersection arg2 */
unsigned int set_deg();		/* returns degree (element count) of set arg */
set	set_dif();		/* returns set difference, arg1 - arg2 */
int	set_el();		/* returns non-0 if arg1 is an element of arg2 */
int	set_equ();		/* returns non-0 if arg1 equals arg2 */
unsigned set_int();		/* returns an int which is in the set arg */
int	set_nil();		/* returns non-0 if arg1 is nil */
set	set_not();		/* returns not arg (well, sort-of) */
set	set_of();		/* returns singleton set of int arg */
set	set_or();		/* returns arg1 union arg2 */
void set_orin();	/* OR's set arg2 into set arg1 */
char *set_str();	/* formats a string representing set arg */
int	set_sub();		/* returns non-0 if arg1 is a proper subset of arg2 */
set	set_val();		/* converts set_str-format string arg into a set */
void set_ext();		/* resizes arg1 to have arg2 words */
void set_rm();		/* removes elem arg1 from set arg2 */
void set_clr();		/* clears all elems of set arg1 */
set set_dup();		/* return duplicate of set arg1 */
void set_orel();	/* OR elem arg2 into set arg1 */
void set_size();	/* Set minimum set size */
unsigned *set_pdq();

extern set empty;

SHAR_EOF
fi # end of overwriting check
if test -f 'struct.h'
then
	echo shar: will not over-write existing file "'struct.h'"
else
cat << \SHAR_EOF > 'struct.h'
/*
 * s t r u c t . h
 *
 * Define the structure of all antlr 2.0 data structures.
 */

#define StrSame			0
#define FIRST			1		/* Used as cache entry type */
#define FOLLOW			2

/* Only used in previous version of antlr (before 1.0B) */
#define NilStr	((char *) 1)	/* Not end of list, but not action; used in Actions */

#define D_NumAlts		10
#define D_NumAtoms		10
#define D_NumRules		10
#define Chunk			10

#define D_StrArraySize	20		/* Must be bigger than 0 */

/* A t o m  T y p e s */
#define aLeaf		1
#define aRule		2
#define aAction		3
#define aSubBLK		4
#define aOptBLK		5
#define aLoopBLK	6
#define EOL			7		/* End Of List */

#ifndef TRUE
#define TRUE	1
#endif
#ifndef FALSE
#define FALSE	0
#endif

#define MaxTokenSize	100

/* D a t a  S t r u c t u r e s */

struct atm {
	unsigned short type;
	unsigned short token;	/* Term-token or Rule # */
	union {
		char *action;		/* Points to an action */
		struct atm **block;	/* Points to a subblock */
		char *rule;			/* Points to rule name */
	} ptr;
	char *inheritance;		/* Do I inherit anything? (Rule or SubBlock) */
	struct atm *parent;		/* If blk, what blk am I nested in */
	int line;
	char *file;				/* Track for error information (usually for blks) */
};

typedef union {
			struct atm atom;
			struct atm *alt;
			struct atm **blk;
			char *inh;		/* Inheritance override for block or rule */
		} Attrib;

typedef struct atm Atom;
typedef Atom	*Alt;
typedef Alt		*Block;
typedef Block	*Rule;

/* M a c r o s */

#define markFi(r)	set_orel(r, &FiVisit);
#define markFo(r)	set_orel(r, &FoVisit);
#define unMarkFi(r)	set_rm(r, FiVisit);
#define unMarkFo(r)	set_rm(r, FoVisit);

/*
 * DEBUG macro
 * Bits 1..WORDSIZE-1 are set according to what the user
 * wants printed out.
 */
#define DEBUG(n)	if ( debug & (1<<(n-1)) ) 

/* E x p a n d a b l e  L i s t  M a c r o s */
#define sizeT(a)		*((unsigned int *) &((a)[0]))
#define makeBlkAtom(a,t,p,ln)										\
			(a).ptr.block=p; (a).type = t; (a).parent=NULL;			\
			(a).inheritance=NULL; (a).file = FileStr[CurFile];		\
			(a).line = ln;

#define InitStrArray(p)										\
	(p) = (char **) calloc(D_StrArraySize+1,sizeof(char *));\
	if ( (p) == NULL ) fatal("Can't Alloc Str Array");		\
	sizeT(p) = D_StrArraySize+1; p[1] = NULL;

#define InitRules(p)										\
	(p) = (Atom ***) calloc(D_NumRules+1,sizeof(Atom **));	\
	if ( (p) == NULL ) fatal("Can't Alloc Rules");			\
	sizeT(p) = D_NumRules+1;

#define InitRuleLine(p)		InitRuleFile(p)
#define InitRuleFile(p)										\
	(p) = (int *) calloc(D_NumRules+1,sizeof(int));			\
	if ( (p) == NULL ) fatal("Can't Alloc RuleFile");		\
	sizeT(p) = D_NumRules+1;

#define InitBlock(p)										\
	(p) = (Atom **) calloc(D_NumAlts+1, sizeof(Atom *));	\
	if ( (p) == NULL ) fatal("Can't Alloc Block");			\
	sizeT(p) = D_NumAlts+1;

#define InitAlt(p)										\
	(p) = (Atom *) calloc(D_NumAtoms+1, sizeof(Atom));	\
	if ( (p) == NULL ) fatal("Can't Alloc Alt");		\
	sizeT(p) = D_NumAtoms+1;

#define extAlt(a,i)										\
	if ( ++i == sizeT(a) )								\
	{													\
		(a) = (Atom *) realloc(a, (sizeT(a)+Chunk)*sizeof(Atom));	\
		if ( (a) == NULL ) fatal("Can't Extend Alt");	\
		sizeT(a) += Chunk;								\
	}

#define extBlk(a,i)										\
	if ( ++i == sizeT(a) )								\
	{													\
		(a) = (Atom **) realloc(a, (sizeT(a)+Chunk)*sizeof(Alt));	\
		if ( (a) == NULL ) fatal("Can't Extend Block");	\
		sizeT(a) += Chunk;								\
		if ( sizeT(a) > MaxAlts ) MaxAlts = sizeT(a);	\
	}

#define extRule(a,i)									\
	if ( ++i == sizeT(a) )								\
	{													\
		(a) = (Atom ***) realloc(a, (sizeT(a)+Chunk)*sizeof(Block));\
		if ( (a) == NULL ) fatal("Can't Extend Rules");	\
		sizeT(a) += Chunk;								\
	}

#define extRuleLine(a,i)		extRuleFile(a,i)
#define extRuleFile(a,i)								\
	if ( ++i == sizeT(a) )								\
	{													\
		(a) = (int *) realloc(a, (sizeT(a)+Chunk)*sizeof(int));\
		if ( (a) == NULL ) fatal("Can't Extend RuleFile");	\
		sizeT(a) += Chunk;								\
	}

#define extStrArray(a,i)								\
	if ( ++i == sizeT(a) )								\
	{													\
		register char **p;								\
		(a) = (char **) realloc(a, (sizeT(a)+Chunk)*sizeof(char *));\
		if ( (a) == NULL ) fatal("Can't Extend Rules");	\
		p = &(a[sizeT(a)]);								\
		sizeT(a) += Chunk;								\
		{	register int i;								\
			for (i=1; i<=Chunk; i++) *p++ = NULL; }		\
	}

#define defRule(i,r)	extRule(Rules,i); Rules[i] = r;
#define defRuleFile(i,f)	extRuleFile(RuleFile,i); RuleFile[i] = f;
#define defRuleLine(i,l)	extRuleLine(RuleLine,i); RuleLine[i] = l;
#define defBlk(a,i,b)	extBlk(a,i); (a)[i] = b;
#define defAlt(a,i,alt)	extAlt(a,i); (a)[i] = alt;

#define skipActions(p) while ( (*(p)).type == aAction ) {(p)++;}

/* E r r o r  r o u t i n e s */

#ifdef MPW		/* Macintosh Programmer's Workshop */
#define ErrHdr "File \"%s\"; Line %d #"
#else
#define ErrHdr "\"%s\", line %d:"
#endif

#define fatal(err)	fatalFL(err, __FILE__, __LINE__)
#define fatalFL(err, f, l)														\
			{fprintf(stderr, ErrHdr, f, l);										\
			fprintf(stderr, " %s\n", err);										\
			cleanUp();															\
			exit(-1);}
#define warn(err)	fprintf(stderr, "%s\n", err);
#define warnFL(err,f,l)															\
			{fprintf(stderr, ErrHdr, f, l);										\
			fprintf(stderr, " %s\n", err);}
#define warnFLNoCR( err,f,l )													\
			{fprintf(stderr, ErrHdr, f, l);										\
			fprintf(stderr, " warning: %s", err);}

#define warnBlk( a,err )														\
			{fprintf(stderr, ErrHdr, (a).file, (a).line);						\
			fprintf(stderr, " warning:");										\
			if ( BigErr ) dispAtom( (a), stderr );								\
			else fprintf(stderr, " subrule");									\
			fprintf(stderr, "%s\n", err);}
#define warnBlkNoCR( a,err )													\
			{fprintf(stderr, ErrHdr, (a).file, (a).line);						\
			fprintf(stderr, " warning:");										\
			if ( BigErr ) dispAtom( (a), stderr );								\
			else fprintf(stderr, " subrule");									\
			fprintf(stderr, "%s", err);}
#define errBlk( a,err )															\
			{fprintf(stderr, ErrHdr, (a).file, (a).line);						\
			if ( BigErr ) dispAtom( (a), stderr );								\
			else fprintf(stderr, " subrule");									\
			fprintf(stderr, "%s\n", err);}
#define setMsg( err, t )														\
			{fprintf(stderr, err);												\
			set_fpT(stderr, t);												\
			fprintf(stderr, "\n");}


/* E x t e r n s */

extern char		**TokenStr,
				**RegExprStr,
				**RuleStr,
				*FileStr[],
				**ActStr,
				**ActStr2,
				**FailActionStr,
				*eMsg(),
				*AttribAction,
				*LexFile;

extern set		FiVisit,
				FoVisit,
				RuleInh,
				*CrossRef;

extern int		MaxAlts;

extern Rule		Rules;
extern int		EpToken, EofToken, NumRules, NumFiles, CurFile, MaxToken;
extern int		ForceInherit, MakeTrax, Terminate, CR;

set 			*First(),
				Follow(),
				*fBlock(),
				fMidAlt(),
				followAlt(),
				followBlk(),
				fAlt(),
				fAtom(),
				*newFset(),
				*dupFset(),
				fCompact();
void			freeFset();

extern int		debug;
				
extern FILE		*NextFile();
extern int		*RuleFile, *RuleLine;
extern int		Save;
extern int		FoSave;
extern int		FoCompute;
extern int		FoPartial;
extern int		FoRequest;
extern int		UseCache;
extern int		BigErr, DfltErr;
extern int		NoCode,PrFirstSub,PrintFo,PrintFi;
extern set		*Cached();
extern unsigned char *set_bytes();
extern char		*TokenName(), *TokenValue();
extern char		*aSourceFile;

#ifndef MEMCHK
char *malloc(), *calloc(), *realloc();
#endif
SHAR_EOF
fi # end of overwriting check
if test -f 'tokens.h'
then
	echo shar: will not over-write existing file "'tokens.h'"
else
cat << \SHAR_EOF > 'tokens.h'
/* tokens.h -- List of labelled tokens
 *
 * Generated from: antlr.g
 *
 * (c) 1989, 1990 by Terence Parr, Hank Dietz and Will Cohen
 * Purdue University Electrical Engineering
 * ANTLR Version 1.0B
 */
#define Action 6
#define Eof 8
#define NonTerminal 11
#define TokenTerm 15
#define QuotedTerm 16
#define Override 18
SHAR_EOF
fi # end of overwriting check
if test -f 'trax.c'
then
	echo shar: will not over-write existing file "'trax.c'"
else
cat << \SHAR_EOF > 'trax.c'
/*
 * trax.c -- Memory allocation functions
 *
 * This file contains routines to track memory allocation.
 *
 * The user may free all memory allocated so far or until the last marker.
 * Also, the user may specify allocation types and then free them selectively
 * later.
 *
 * Note:
 *		free() is never needed again by the user.  However, it may be used
 *		to minimize the maximum amount of memory used at any one moment.  It
 *		is provided for backward compatibility as well.
 *
 * Example:
 *
 *	#include "trax.h"
 *	...
 *	main()
 *	{
 *		char *p;
 *
 *		p = malloc(23);
 *		malloc(220);
 *		malloc(10);
 *
 *		mWipe();		-- deallocate all memory.
 *	}
 *
 *	Another example:
 *
 *	#define TreeNodes	1
 *	#define	Misc		2
 *
 *	main()
 *	{
 *		mMark(TreeNodes);
 *		malloc(...)
 *		malloc(...)
 *		mMark(Misc);
 *		malloc(...)
 *
 *		mWeed(TreeNodes);	-- deallocate all TreeNodes
 *		mWeed(Misc);		-- deallocate all misc memory
 *	}
 *
 * The following routines are available:
 *
 *		mMalloc()		-- Same as malloc, but track memory
 *		mCalloc()		-- Same as calloc, but track memory
 *		mrealloc()		-- Same as realloc, but track memory
 *		mFree()			-- Free the pointer passed in
 *		mMark()			-- Memory from now on is marked as type 'code'
 *		mWeed()			-- Free all memory blocks with certain type
 *		mWipe()			-- Free all memory
 *		mSetErr()		-- Specify an error reporting function
 *		mLog(f,code)	-- Print a report to stream f
 *		mHist(f)		-- Print a report of all types to stream f
 *		mMax			-- Global unsigned int that reflects max mem allocated
 *		mTotal			-- Global unsigned int that reflects total mem allocated
 *		mCur			-- Global unsigned int reflecting current mem allocated
 *
 * Address Alignment:
 *
 *		All pointers returned by mCalloc, mMalloc are sizeof(Trax)+base;
 *			where base is returned by the malloc().
 *
 * Memory corruption detection:
 *
 *		Memory corruption detection is possible when a buffer is overrun by
 *			1 byte.
 *		Magic words are 2 chars long and are accessed independently to avoid
 *			memory address alignment problems on different machines.
 *
 * Note: group array must be initialized to 0 by compiler
 *
 * The user identifies/marks memory with a code from 0..nCodes-1.  They are
 * indices into a table of pointers to linked lists.  0 is the default memory
 * code.
 *
 * Terence Parr
 * Purdue University Electrical Engineering
 * December 1989
 */

#include <stdio.h>
#include "trax.h"
#undef malloc
#undef free
#undef calloc
#undef realloc

#define bufstart(m)		((char *)(m))+sizeof(Trax)
#define magicwd1(m)		(*(bufstart(m)+m->size))
#define magicwd2(m)		(*(bufstart(m)+m->size+1))
#define badmagic(m)		( magicwd1(m) != MagicWd1 && magicwd2(m) != MagicWd2 )
#define nCodes			20

static Trax *group[nCodes];
static int Code = 0;
unsigned mMax = 0, mTotal = 0;
unsigned mCur = 0;

void defErr();
static void (*mError)() = defErr;

char *
mMalloc(n, code, file, line)
unsigned n, line, code;
char *file;
{
	register Trax *m, *h;

	if ( code >= nCodes )
	{
		(*mError)("malloc: memory code %d out of range 0..%d\n", code, nCodes-1); 
		return( NULL );
	}
	if ( code == 0 ) code = Code;
	h = group[code];
	m = (Trax *) malloc( n+sizeof(Trax)+(2*sizeof(char)) );
	if ( m == NULL )
	{
		(*mError)("malloc: can't allocate %d bytes at %s(%d)\n", n, file?file:"???", line);
		return( NULL );
	}
	m->size = n;
	m->line = line;
	m->file = file;
	m->code = code;
	m->mword = ValidBuf;
	if ( h != NULL ) h->prev = m;
	m->next = h;
	m->prev = NULL;
	group[code] = m;
	magicwd1(m) = MagicWd1;
	magicwd2(m) = MagicWd2;
	mCur += n;
	mTotal += n;
	if ( mCur > mMax ) mMax = mCur;
	return( bufstart(m) );
}

char *
mCalloc(n, s, code, file, line)
unsigned n, s, line, code;
char *file;
{
	register unsigned bytes = n*s;
	register Trax *m, *h;

	if ( code >= nCodes )
	{
		(*mError)("calloc: memory code %d out of range 0..%d\n", code, nCodes-1); 
		return( NULL );
	}
	if ( code == 0 ) code = Code;
	h = group[code];
	m = (Trax *) malloc( bytes+sizeof(Trax)+(2*sizeof(char)) );
	if ( m == NULL )
	{
		(*mError)("calloc: can't allocate %d bytes at %s(%d)\n", n, file?file:"???", line);
		return( NULL );
	}
	m->size = bytes;
	m->line = line;
	m->file = file;
	m->code = code;
	m->mword = ValidBuf;
	{	register char *p, *endp;
	
		p = bufstart(m),
		endp = p+bytes;
		do { *p++ = '\0'; } while ( p < endp );
	}
	if ( h != NULL ) h->prev = m;
	m->next = h;
	m->prev = NULL;
	group[code] = m;
	magicwd1(m) = MagicWd1;
	magicwd2(m) = MagicWd2;
	mCur += bytes;
	mTotal += bytes;
	if ( mCur > mMax ) mMax = mCur;
	return( bufstart(m) );
}

char *
mRealloc(p, n, file, line)
register char *p;
char *file;
unsigned n, line;
{
	register Trax *m;
	
	if ( p == NULL )
	{
		(*mError)("realloc: NULL ptr; attempted at %s(%d)\n", file?file:"???", line);
		return( NULL );
	}
	m = (Trax *) realloc(mInfo(p), n+sizeof(Trax)+(2*sizeof(char)));
	if ( m == NULL )
	{
		(*mError)("realloc: can't reallocate to %d bytes at %s(%d)\n", n, file?file:"???", line);
		return( NULL );
	}
	mCur += (n - m->size);
	if ( n > m->size ) mTotal += (n - m->size);
	if ( mCur > mMax ) mMax = mCur;
	m->size = n;
	magicwd1(m) = MagicWd1;
	magicwd2(m) = MagicWd2;
	if ( mInfo(p) == m ) return( p );
	/*
	 * Buffer has been moved.  Must adjust 'prev' pointer of next buf in list
	 * also, adjust 'next' pointer of prev buf in list
	 */
	if ( m->next != NULL ) (m->next)->prev = m;
	if ( m->prev != NULL ) (m->prev)->next = m;
    else group[m->code] = m;
	return( bufstart(m) );
}

mFree(p, file, line)
char *p;
{
	register Trax *m;
	
	if ( p == NULL )
	{
		(*mError)("free: NULL ptr; attempted at %s(%d)\n", file?file:"???", line);
		return;
	}
	if ( odd(p) )
	{
		(*mError)("free: invalid ptr (odd address); attempted at %s(%d)\n", file?file:"???", line);
		return;
	}
	m = mInfo(p);
	if ( m->mword != ValidBuf )
	{
		(*mError)("free: invalid ptr (unallocated); attempted at %s(%d)\n", file?file:"???", line);
		return;
	}
	if ( badmagic(m) )
	{
		(*mError)("free: memory corruption; code %d attempted at %s(%d) allocated at %s(%d)\n",
					m->code,
					file?file:"???",
					line,
					m->file?m->file:"???",
					m->line);
		return;
	}
	if ( m->prev != NULL ) (m->prev)->next = m->next;
	else group[m->code] = m->next;
	if ( m->next != NULL ) (m->next)->prev = m->prev;
	m->mword = 0;
	mCur -= m->size;
	free(m);
}

mMark(code)
unsigned code;
{
	if ( code >= nCodes )
	{
		(*mError)("mMark: memory code %d out of range 0..%d\n", code, nCodes-1); 
		return;
	}
	Code = code;
}

mWeed(code)
unsigned code;
{
	register Trax *m, *p;
	
	if ( code >= nCodes )
	{
		(*mError)("mWeed: memory code %d out of range 0..%d\n", code, nCodes-1); 
		return;
	}
	if ( code == 0 ) code = Code;
	m = group[code];
	while ( m != NULL )
	{
		p = m->next;
		if ( badmagic(m) )
		{
			(*mError)("mWeed: memory corruption; code %d allocated at %s(%d)\n",
						code,
						m->file?m->file:"???",
						m->line);
		}
		else
		{
			m->mword = 0;
			mCur -= m->size;
			free( m );
		}
		m = p;
	}
	group[code] = NULL;
}

mWipe()
{
	int i;
	for (i=0; i<nCodes; i++) mWeed(i);
}

mHist(f)
FILE *f;
{
	int i;
	for (i=0; i<nCodes; i++)
	{
		if ( group[i] != NULL ) mLog(f, i);
	}
}

mLog(f, code)
FILE *f;
unsigned code;
{
	register Trax *p;
	
	if ( code >= nCodes )
	{
		(*mError)("mWeed: memory code %d out of range 0..%d\n", code, nCodes-1); 
		return;
	}
	p = group[code];
	fprintf(f, "Memory Log of memory code %d:\n\n", code);
	while ( p != NULL )
	{
		fprintf(f, "[%s(%d) size %d]%s\n",
					p->file, p->line, p->size,
					badmagic(p)?" (corrupt)":"");
		p = p->next;
	}
	fprintf(f, "\n");
}

void
defErr(err, a1, a2, a3, a4, a5, a6)
char *err;
long a1, a2, a3, a4, a5, a6;
{
	fprintf(stderr, err, a1, a2, a3, a4, a5, a6);
}
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0
