#! /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:
#	automata.c
#	dlg.g
#	dlg.h
#	dlg_a.c
#	dlg_p.c
#	makefile
#	output.c
#	relabel.c
#	sets.c
#	sets.h
#	support.c
#	tokens.h
# This archive created: Sun Mar 25 13:58:18 1990
# By:	CARP Research Group ()
export PATH; PATH=/bin:$PATH
if test -f 'automata.c'
then
	echo shar: will not over-write existing file "'automata.c'"
else
cat << \SHAR_EOF > 'automata.c'
/* main routine and dfa constructor.
 * ee595e project
 *
 * Will Cohen
 * 10/4/89
 */

#include	<stdio.h>
#include	"dlg.h"
#include	"tokens.h"

set	used_chars;	/* marks characters that are actually used in spec */
set	used_classes;	/* marks characters that are actually used in spec */


path	stack[MAX_STACK];	/* used by parser to build nfa */
int	sp = 0;

int		nfa_pool = 0;	/* last nfa node made */
int		dfa_pool = 0;	/* last dfa node made */
				/* also head of undone queue */
int		last_done = 0;	/* last dfa node examined */

nfa_node	*nfa_array;	/* first nfa node in array */
dfa_node	*dfa_array;	/* first dfa node in array */

nfa_node	clear_nfa_node;	/* prototype of node used for init. */
dfa_node	clear_dfa_node;	/* prototype of node used for init. */

int	nfa_set = 0;	/* used so operation done only once even */
			/* though there might be multiple arc to it */
int	dfa_set = 0;	/* same as nfa_set */

int		nfa_state = 0;	/* used to identify each nfa node */
int		dfa_state = 0;	/* used to identify each dfa node */

int		*dfa_hash_table;

/************ flags and options ***********/
int	compress = FALSE;	/* do character class compression */
int	num_of_nfa = SETSIZE;
int	num_of_dfa = SETSIZE;
int	hash_entries = 2*SETSIZE;

/************ file stuff ******************/
FILE *infile;
FILE *outfile;

char *in_file_name;	/* used to report errors */

main(argc, argv)
int argc;
char **argv;
{
	int c,p;

	init_things();
	/* find out options set */
	options(argc, argv);

	init_arrays();

	/* open input, first thing other after first arg without '-' */
	c = 1; argv++;
	while ((c<argc) && (**argv=='-')){
		c++;
		argv++;
		}
	/* check to make sure valid */
	if ((c>=argc) || (**argv=='-'))
		usage();
	in_file_name = *argv;
	infile = fopen(in_file_name,"r");
	if (!infile)
		printf("dlg: Warning: Can't find file %s.\n",*argv);
	/* open output, second thing other after first arg without '-' */
	c++; argv++;
	while ((c<argc) && (**argv=='-')){
		c++;
		argv++;
		}
	/* if check to make sure valid */
	if ((c>=argc) || (**argv=='-'))
		usage();
	outfile = fopen(*argv,"w");
	if (!outfile)
		printf("dlg: Warning: Can't write to file %s.\n",*argv);
	if ((!infile) || (!outfile))
		exit(2);


	
	/* now time to parse input and build nfa graph */
	advance(); /* prime the input */
	if (grammar())
		warning("Syntax error in input specifications ", line_no);
	/* close any loose ends */
	print_tail();
}

nfa_to_dfa(start)
int start;
{
	set x, t, y, classes;
	unsigned *place;	/* keeps track of where in set */
	int d_state;		/* index to dfa state working on*/
	int trans_d_state;	/* state going to on transistion */
	int a;

	x = closure(set_of(start));
	/* Make x a dfa state */
	d_state = dfastate(x);
	last_done = d_state;
	do {
		/* Mark dfa state x as "done" */
		dfa_array[d_state].done = TRUE;
		last_done ++;	/* move forward in queue */
		/* each "class" actually used in alphabet */
		classes = used_classes;
		place = &(classes.setword[0]);
		set_remove_int(classes,a,place);
		while (a != nil){
			/* Add NFA states reached by a... */
			/* each state in x */
			t = reach(dfa_array[d_state].nfa_states,a);
			/* Were any states found? */
			if (!set_nil(t)) {
				/* Yes, compute closure */
				y = closure(t);
				/* Make DFA state of it ... */
				trans_d_state = dfastate(y);
				/* And make transition x->y, labeled with a */
				dfa_array[d_state].trans[a] =
					(short) trans_d_state;
				}
			set_remove_int(classes,a,place);
			}
		/* now check to see if some dfa nodes still need to be
		   done are in the queue. Repeat until none left */
		d_state = last_done;
		} while (last_done<dfa_pool);
}


dfastate(nfa_states)
set nfa_states;		/* list of nfa states it could be */
{
	register int	n,p;

	/* use hash table to find where dfa state goes quickly */
	p = set_hash(nfa_states,hash_entries);
	while ( dfa_hash_table[p] != NIL_INDEX &&
		!set_equ(dfa_array[dfa_hash_table[p]].nfa_states,nfa_states)){
		if (++p >= hash_entries)
				p = 0;
		}
	if ((n = dfa_hash_table[p]) == NIL_INDEX){
		/* make new entry */
		n = NEW_DFA(nfa_states);
		dfa_hash_table[p] = n;
		}
	return n;
}


/* this reach assumes the closure has been done already on set */
set reach(b,a)
set b;
register int a;
{
	register int node;
	register nfa_node *p;
	register unsigned *start;
	set temp;

	start = &(b.setword[0]);
	temp = set_of(nil);
	set_remove_int(b,node,start);
	while (node != nil){
		p = &nfa(node);
		if (set_el(a,p->label))
			set_or_int(temp, p->trans[0]);
		set_remove_int(b,node,start);
		}
	return temp;
}

set closure(b)
set b;
{
	register int node;
	register unsigned *start;	/* keep track place in set */
	set undone;

	undone = b;
	start = &(undone.setword[0]);
	set_remove_int(undone,node,start);
	while (node != nil){
		/* find those epsilon transitions */
		if (nfa(node).trans[0] != NIL_INDEX &&
		    set_nil(nfa(node).label) &&
		    !set_el(nfa(node).trans[0],b)){
			set_or_int(undone,nfa(node).trans[0]);
			set_or_int(b,nfa(node).trans[0]);
			}
		if (nfa(node).trans[1] != NIL_INDEX &&
		    !set_el(nfa(node).trans[1],b)){
			set_or_int(undone,nfa(node).trans[1]);
			set_or_int(b,(nfa(node).trans[1]));
			}
		/* not sure where new nodes put in, so have to
		   start at beginning of set */
		start = &(undone.setword[0]);
		set_remove_int(undone,node,start);
		}
	return b;
}

int NEW_DFA(nfa_states)
set nfa_states;
{
	dfa_array[dfa_pool] = clear_dfa_node;
	dfa_array[dfa_pool].nfa_states = nfa_states;
	return dfa_pool++;
}

print_hash_table(begin,end)
int begin,end;
{
	register i = 0,t=0;

	for(i= begin; i<end; ++i){
		printf("[%d] = %d\t",i,dfa_hash_table[i]);
		if (++t > 4){
			t = 0;
			printf("\n");
			}
		}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'dlg.g'
then
	echo shar: will not over-write existing file "'dlg.g'"
else
cat << \SHAR_EOF > 'dlg.g'
/* this hasn't actually been put though ANTLR, but just is a reference
 * of the ALX grammar with changes from the original handed out in class
 *
 * Will Cohen
 * 10/11/89
 */

/* the lexical analyser converts the '%%', '|', '[', ']', '(', ')',
 * '{', '}', '+', '*', '-', into tokens which are larger than MAXCHAR.
 * This is done so there is less confusion on what a character is when
 * it is time to build the nfa.
 */

/* more than one action allowed at begin and end since ALX allows it */
grammar		: (action)* '%%' rulelist '%%' (action)*
		;

rule_list	: rule (rule)*
		;

rule		: regexpr action
		;

regexpr	: and_expr ('|' andexpr)*
		;

andexpr	: expr (expr)*
		;

expr		: '[' atomlist ']' {repeatsymbol}
		| '(' regexpr ')' {repeatsymbol}
		| '{' regexpr '}' {repeatsymbol}
		| atom {repeatsymbol}
		;

repeatsymbol	: '*'
		| '+'
		;

/* nearatom takes care of range operator.  The nasty left recursion
 * has also been removed from this rule
 */
atomlist	: nearatom (nearatom)*
		;

nearatom	: anychar {'-' anychar}
		;

atom		: anychar
SHAR_EOF
fi # end of overwriting check
if test -f 'dlg.h'
then
	echo shar: will not over-write existing file "'dlg.h'"
else
cat << \SHAR_EOF > 'dlg.h'
/* Header file for the Lexical Analyser Generator (dlg.c)
 * for ee595e
 *
 * Will Cohen
 * 9/27/89
 */

#include	"sets.h"

#define TRUE	1
#define FALSE	0

#define IN	infile
#define OUT	outfile

/* valid characters (classes) for input */
#define FIRST_CHAR	0
#define LAST_CHAR	127
#define NUM_CLASS	(LAST_CHAR-FIRST_CHAR+1+1) /* 1 for LEX_EOF */

#define MAX_STACK	64	/* depth of stack for building nfa's */

#define nfa_node struct _nfa_node
nfa_node {
	int		nfa_set;
	int		accept;	/* what case to use */
	int		trans[2];
	set		label;	/* one arc always labelled with epsilon */
	};

#define dfa_node struct _dfa_node
dfa_node {
	int		done;
	set		nfa_states;
	int		dfa_set;
	short		trans[NUM_CLASS];
	};

#define path	struct _path
path {
	int	l;
	int	r;
	};

/* stuff to manage nfa and dfa graphs */

extern int	nfa_pool;	/* last nfa node made */
extern int	dfa_pool;	/* last dfa node made */
extern nfa_node	*nfa_array;	/* start of allocated space for nfa */
extern dfa_node	*dfa_array;	/* start of allocated space for dfa */
extern int	*dfa_hash_table;

/* definitions to make access nodes in dfa and nfa transparent to implentation
 * (not fully implemented )
 */
#define NIL_INDEX	-1	/* impossible index for array */

#define PUSH_PATH(x)	(stack[sp++] = (x))
#define POP_PATH()	(stack[--sp])
#define TOS		(stack[sp-1])
#define NOS		(stack[sp-2])

#define nfa(x)		(nfa_array[(x)])

/* this macro was made becase the sequence
	e = set_int(s);
	s = set_dif(s,set_of(e));
  was heavily used in closure() and nfa_to_dfa()
  If e is a element in the set, starts searching for elements in word or
  higher in set to save some time.
*/
#define set_remove_int(b,e,s) {\
	/* Fast pick any element of the set b starting at the word pointed\
	   to by s. s needs to be a real variable for this to work */\
	register unsigned *p;\
	register unsigned *endp = &(b.setword[SETWORDS]);\
	register int i;\
	register int nothing = TRUE;\
\
	do {\
		if (*s) {\
			/* Found a non-empty word of the set */\
			register unsigned t = *s;\
			i = ((s - &(b.setword[0])) * WORDSIZE);\
			p = &(bitmask[0]);\
			while ((nothing = !(*p & t))) {\
				++i; ++p;\
				}\
			}\
		} while (nothing && (++s < endp));\
		if (!nothing){\
		    b.setword[DIVWORD(i)] &= (~bitmask[MODWORD(i)]);\
		    e = i;\
		    }\
		else\
		    e = nil;\
}

/* found that set_or(s,set_or(e)); common (doesn't work for nil)*/
#define set_or_int(s,e) (s.setword[ DIVWORD(e)] |= bitmask[MODWORD(e)])

			
/***************************** data ***********************************/
extern int	token;
extern int	line_no;
extern nfa_node	clear_nfa_node;	/* used to initialize new nfas */
extern dfa_node clear_dfa_node;	/* used to initialize new dfas */
extern path	stack[];	/* pass back node list for building nfa */
extern int	sp;		/* stack pointer for above */
extern set	used_chars;	/* used to label trans. arcs */
extern set	used_classes;	/* classes or chars used to label trans. arcs */
extern set	valid_chars;	/* mask off unused portion of set */
extern int	nfa_set;
extern int	num_of_nfa;
extern int	num_of_dfa;
extern int	hash_entries;	/* number of possible entries in hash table */
extern int	compress;	/* flag for character class compression */
extern int	action_no;	/* number of actions produced */
extern unsigned	bitmask[];	/* array used to speed up set operations */
extern int	class_no;	/* number of classes actually used */
extern set	class[];	/* stores partitions of classes */

/*************************** functions ********************************/
extern	void	init_things();
extern	void	error();
extern	void	warning();
extern	void	fatal();
extern	set	reach();
extern	set	closure();

/************************** file stuff *******************************/
extern	FILE	*infile;
extern	FILE	*outfile;
extern	char	*in_file_name;	/* remembers name for error reporting */
SHAR_EOF
fi # end of overwriting check
if test -f 'dlg_a.c'
then
	echo shar: will not over-write existing file "'dlg_a.c'"
else
cat << \SHAR_EOF > 'dlg_a.c'
/* lexical analyzer for dlg for ee595e
 * This lexical analyzer is looking for the tokens from the ALX
 * specifications
 *
 * Will Cohen
 * 10/3/89
 */

#include <stdio.h>
#include "dlg.h"
#include "tokens.h"

#define ishex(c)	(c>='0' && c<='9' || c>='a'&& c<='f' || c>='A' && \
				c<='F')
#define isoct(c)	(c>='0' && c<='7')
#define isdec(c)	(c>='0' && c<='9')

int	line_no = 1;		/* keep track of what line advance is on */
int token;
static int look_ahead = EOF;	/* used for two char tokens */

advance()
{
/* generally gets single characters, but will get tokens too */

ignore:	if (look_ahead != EOF){
		/* make it the current token and see what it is */
		token = look_ahead;
		look_ahead = EOF;
		}
	else
		token = getc(IN);
	/* do special cases and conver things into tokens */
	switch (token){
	case '<':	if ((look_ahead = getc(IN)) == '<'){
				token = LESS_LESS;
				look_ahead = EOF;
				}
			break;
	case '>':	if ((look_ahead = getc(IN)) == '>'){
				token = GREAT_GREAT;
				look_ahead = EOF;
				}
			break;
	case '%':	if ((look_ahead = getc(IN)) == '%'){
				token = PER_PER;
				look_ahead = EOF;
				}
			break;
	case EOF:	token = THE_EOF;
			break;
	case '@':	token = LEX_EOF;
			break;
	case '[':	token = OPEN_BRACK;
			break;
	case ']':	token = CLOSE_BRACK;
			break;
	case '(':	token = OPEN_PAR;
			break;
	case ')':	token = CLOSE_PAR;
			break;
	case '{':	token = OPEN_BRACE;
			break;
	case '}':	token = CLOSE_BRACE;
			break;
	case '*':	token = ZERO_MORE;
			break;
	case '+':	token = ONE_MORE;
			break;
	case '-':	token = RANGE;
			break;
	case '|':	token = OR;
			break;
	case '~':	token = NOT;
			break;
	/* not the best solution but ' ' and tabs are ignored */
	case '\r':
	case '\n':	++line_no;
	case ' ':
	case '\t':	goto ignore;
	case '\\':	look_ahead = getc(IN);
			if (look_ahead == '0'){
				/* could be hex or octal */
				look_ahead = getc(IN);
				if (look_ahead == 'x'){
					look_ahead = getc(IN);
					in_hex();
					}
				else
					in_oct();
				}
			else if(isdec(look_ahead))
					in_dec();
			else{
				switch(look_ahead){
				case 'n':	token = '\n';
						break;
				case 't':	token = '\t';
						break;
				case 'b':	token = '\b';
						break;
				case 'r':	token = '\r';
						break;
				case 'f':	token = '\f';
						break;
				default:
						token = look_ahead;
				}
				look_ahead = EOF;
				}
			break;
	}
}

in_hex()
{	register c = look_ahead;
	int d;

	token = 0;
	while (ishex(look_ahead)){
		if (c>='0' && c<='9')
			d = c - '0';
		else if (c>='a' && c<='f')
			d = c - 'a' + 10;
		else if (c>='A' && c<='F')
			d = c - 'A' + 10;
		token = token*16 + d;
		c = look_ahead = getc(IN);
	}
}

in_oct()
{
	token = 0;
	while (isoct(look_ahead)){
		token = token*8 + (look_ahead - '0');
		look_ahead = getc(IN);
	}
}

in_dec()
{
	token = 0;
	while (isdec(look_ahead)){
		token = token*10 + (look_ahead - '0');
		look_ahead = getc(IN);
	}
}


/* spits out input file until '>>' found */
scarf_action()
{
more:	while ((token = getc(IN))!=EOF && token!='>'){
		if (token == '\n'){
			++line_no;
			}
		putc(token,OUT);
		}
	/* could be EOF or '>' */
	switch (token){
	case EOF:	token = LEX_EOF;
			look_ahead = EOF;
			return;
			break;
	case '>':	if ((look_ahead = getc(IN)) == '>'){
				/* end of action */
				putc('\n',OUT);
				token = GREAT_GREAT;
				look_ahead = EOF;
				return;
				}
			else{
				/* false alarm, just one '>', not '>>' */
				putc(token,OUT);
				putc(look_ahead,OUT);
				}
			goto more;
	}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'dlg_p.c'
then
	echo shar: will not over-write existing file "'dlg_p.c'"
else
cat << \SHAR_EOF > 'dlg_p.c'
/* parser that follows ALX grammar for ee595e
 *
 * Will Cohen
 * 10/3/89
 *
 *
 * the lexical analyser converts the '%%', '|', '[', ']', '(', ')',
 * '{', '}', '+', '*', '-', '!' into tokens which are larger than MAXCHAR.
 * This is done so there is less confusion on what a character is when
 * it is time to build the nfa.
 *

* more than one action allowed at begin and end since ALX allows it *
grammar		: (action)* '%%' rulelist '%%' (action)*
		;

rule_list	: rule (rule)*
		;

rule		: regexpr action
		;

regexpr		: and_expr ('|' andexpr)*
		;

andexpr		: expr (expr)*
		;

expr		: {'~'} '[' atomlist ']' {repeatsymbol}
		| '(' regexpr ')' {repeatsymbol}
		| '{' regexpr '}' {repeatsymbol}
		| atom {repeatsymbol}
		;

repeatsymbol	: '*'
		| '+'
		;

 * nearatom takes care of range operator.  The nasty left recursion
 * has also been removed from this rule
 *
atomlist	: (nearatom)*
		;

nearatom	: anychar {'-' anychar}
		;

atom		: anychar

*/


#include <stdio.h>
#include "dlg.h"
#include "tokens.h"

int	action_no = 0;	/* keep track of actions outputed */
set	temp_label;	/* used to sum up possible labels on arc */
set	valid_chars;	/* mask to get rid elements that aren't used
			   in set */
int	flag_paren = FALSE;
int	flag_brace = FALSE;


grammar()
{
	used_chars = set_of(nil);
	/* optional actions section changed to allow multiple actions */
	while(!action())
		/* empty body */;
	/* THIS really SHOULDN'T be here */
	print_head();
	if (token != PER_PER)
		error("\"\%\%\" missing ",line_no);
	advance();
	if (rulelist())
		return TRUE;
	if (token != PER_PER)
		error("\"\%\%\" missing ",line_no);
	advance();
	/* do class compression here */
	if (compress)
		relabel();
	else{
		used_classes = used_chars;
		class_no = LAST_CHAR+2;
		}
	/* convert nfa to dfa */
	nfa_to_dfa(TOS.l);
	/* print out dfa in correct format */
	print_tables();
	/* optional actions at end changed to allow multiple actions */
	while(!action())
		/* empty body */;
	return FALSE;
}

rulelist()
{
	int	t;

	if (rule())
		return TRUE;
	while (!rule()){
		/* not really paths on stack any more, just index
		   to the regular expressions */
		t = NEW_NFA();
		nfa(t).trans[0] = NOS.l;
		nfa(t).trans[1] = TOS.l;
		NOS.l = t; NOS.r = NIL_INDEX;
		POP_PATH();
		}
	return FALSE;
}

rule()
{
	if (regexpr()){
		path	t;

		if (token == LESS_LESS){
			/* put something on the stack just as a place holder */
			t.l = NULL; t.r = NULL;
			PUSH_PATH(t);
		
			error("no expression for action  ",line_no);
			/* don't return TRUE; */
			}
		else
			return TRUE;
		}
	fprintf(OUT,"static\nact%d()\n{ ",++action_no);
	if (action())
		error("action missing ",line_no);
	fprintf(OUT,"}\n\n");
	/* mark accept state */
	nfa(TOS.r).accept = action_no;
	return FALSE;
}

regexpr(){
	/* check for unmatched } or ) at end of regular expression and
	   possibly more regexpr's */
	int failed;

	flag_paren = FALSE;
	flag_brace = FALSE;
	failed = regexpr1();
	/* time to see if there are surplus ')' or '}' */
	if (failed){
		while ((token == CLOSE_PAR) || (token == CLOSE_BRACE)){
			if ((!flag_paren) && (token == CLOSE_PAR)){
				error("unmatched \")\"  ",line_no);
				flag_paren = TRUE;
				}
			if ((!flag_brace) && (token == CLOSE_BRACE)){
				error("unmatched \"}\"  ",line_no);
				flag_brace = TRUE;
				}
			advance();
			}
	/* clean up other fragments of regular expression by resyncing
		on "<<" then */
		if (flag_paren || flag_brace)
			while(token != LESS_LESS)
				advance();
	}
	return failed;
}

regexpr1()
{
	int	t1,t2;

	if (andexpr())
		return TRUE;
	while (TRUE){
		if ( token != OR)
			break;
		advance();
		if (andexpr())
			return TRUE;
		t1 = NEW_NFA(); t2 = NEW_NFA();
		nfa(t1).trans[0] = NOS.l;
		nfa(NOS.r).trans[1] = t2;
		nfa(t1).trans[1] = TOS.l;
		nfa(TOS.r).trans[1] = t2;
		NOS.l = t1; NOS.r = t2;
		POP_PATH();
		}
	return FALSE;
}

andexpr()
{
	if (expr())
		return TRUE;
	while(!expr()){
		nfa(NOS.r).trans[1] = TOS.l;
		NOS.r = TOS.r;
		POP_PATH();
		}
	return FALSE;
}

expr()
{
	int complement = FALSE;

	switch(token){
	case NOT:	advance();
			complement = TRUE;
			if (token != OPEN_BRACK){
				error("no set to complement  ",line_no);
				/* ignore ~ and just treat as default */
				goto ignore_not;
				}
	case OPEN_BRACK: advance();
			if (atomlist(complement))
				return TRUE;
			if (token != CLOSE_BRACK)
				error("closing bracket assumed  ",line_no);
				/* don't return TRUE; */
			else
				advance();
			repeatsymbol();
			return FALSE;
	case OPEN_PAR:	advance();
			if (regexpr())
				return TRUE;
			if (token != CLOSE_PAR)
				error("closing parenthesis assumed  ",line_no);
				/* don't return TRUE; */
			else
				advance();
			repeatsymbol();
			return FALSE;
	case OPEN_BRACE: advance();
			if (regexpr())
				return TRUE;
			if (token != CLOSE_BRACE)
				error("closing brace assumed  ",line_no);
				/* don't return TRUE; */
			else
				advance();
			{ /* make optional */
				int t1, t2;

				t1 = NEW_NFA(); t2 = NEW_NFA();
				nfa(t1).trans[0] = TOS.l;
				nfa(t1).trans[1] = t2;
				nfa(TOS.r).trans[1] = t2;
				TOS.l = t1; TOS.r = t2;
			}
			repeatsymbol();
			return FALSE;
	ignore_not:
	default:	if (atom())
				return TRUE;
			/* add to used char */
			used_chars = set_or(used_chars,temp_label);
			repeatsymbol();
			return FALSE;
	}
}

repeatsymbol()
{
	int	t1,t2;

	switch(token){
	case ZERO_MORE:	advance();
			/* add epsilon arc to make repeatable */
			nfa(TOS.r).trans[0] = TOS.l;
			t1 = NEW_NFA(); t2 = NEW_NFA();
			nfa(t1).trans[0] = TOS.l;
			nfa(t1).trans[1] = t2;
			nfa(TOS.r).trans[1] = t2;
			TOS.l = t1; TOS.r = t2;
			return FALSE;
	case ONE_MORE:	advance();
			/* add epsilon arc to make repeatable */
			nfa(TOS.r).trans[0] = TOS.l;
			/* label should still be epsilon */
			return FALSE;
	default:	return TRUE;
	}
}

/* much simplified from the original grammar spec */
/* RANGE ('-') operator handled in nearatom */
atomlist(complement)
int complement;
{
	path	t;

	temp_label = set_of(nil);
	t.l = NEW_NFA();
	t.r = NEW_NFA();
	nfa(t.l).trans[0] = t.r;
	PUSH_PATH(t);
	while(!nearatom())
	/* labels accumlated in temp_label by nearatom() */;
	if (complement) 
		/* EOF will not be in the complement */
		temp_label = set_and(set_not(temp_label),
			valid_chars);
	/* add to used char */
	used_chars = set_or(used_chars,temp_label);
	nfa(t.l).label = temp_label;
	return FALSE;
}

action()
{

	if (token != LESS_LESS)
		return TRUE;
	scarf_action();
	if (token != GREAT_GREAT)
		return TRUE;
	advance();
	return FALSE;
}

nearatom()
{
	register int	b,e;

	if (token > MAXCHAR)
		return TRUE;
	/* all characters shift up one to make room for LEX_EOF */
	b = token+1;
	temp_label = set_or(temp_label, set_of(b));
	/* munch the character */
	advance();
	/* takes care of range operator, '-' */
	if (token != RANGE)
		return FALSE;
	advance();
	if (token > MAXCHAR){
		error("missing end of range",line_no);
		return TRUE;
		}
	/* all characters shift up one to make room for LEX_EOF */
	e = token+1;
	/* now fill in space between char b and e */
	while (b<=e)
		temp_label = set_or(temp_label,set_of(b++));
	/* munch the character */
	advance();
	return FALSE;
}

atom()
{
	path	t;

	if (token > MAXCHAR)
		return TRUE;
	/* build section of nfa */
	t.l = NEW_NFA();
	t.r = NEW_NFA();
	nfa(t.l).trans[0] = t.r;
	/* all characters shift up one to make room for LEX_EOF */
	nfa(t.l).label = set_of(token+1);
	PUSH_PATH(t);
	used_chars = set_or(used_chars, nfa(t.l).label);
	/* munch the character */
	advance();
	return FALSE;
}

int NEW_NFA()
{
	nfa_array[nfa_pool] = clear_nfa_node;
	return nfa_pool++;
}
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'
SRC = automata.c relabel.c dlg_p.c dlg_a.c support.c sets.c output.c
OBJ = automata.c relabel.o dlg_p.o dlg_a.o support.o sets.o output.o
OP = -g

dlg : $(OBJ) $(SRC)
	cc $(OP) -o dlg $(OBJ)

dlg_a.o : dlg_a.c tokens.h dlg.h sets.h
	cc $(OP) -c dlg_a.c

dlg_p.o : dlg_p.c tokens.h dlg.h sets.h
	cc $(OP) -c dlg_p.c

relabel.o : relabel.c dlg.h sets.h
	cc $(OP) -c relabel.c

automata.o : automata.c dlg.h sets.h
	cc $(OP) -c automata.c

sets.o : sets.c sets.h
	cc $(OP) -c sets.c

support.o : support.c dlg.h sets.h
	cc $(OP) -c support.c

output.o : output.c dlg.h sets.h
	cc $(OP) -c output.c

SHAR_EOF
fi # end of overwriting check
if test -f 'output.c'
then
	echo shar: will not over-write existing file "'output.c'"
else
cat << \SHAR_EOF > 'output.c'
/* routines that print out stuff
 *
 * Will Cohen
 * 10/26/89
 *
 * for ee595e
 *
 * most of these are pretty simple.
 */

#include <stdio.h>
#include "tokens.h"
#include "dlg.h"

#define MAX_ON_LINE 11

/* This section is MACHINE DEPENDENT */
#define DIF_SIZE
long typesize[DIF_SIZE]  = { 0x7f, 0x7fff, 0x7fffffff, 0x7fffffff };
char t0[] = "unsigned char";
char t1[] = "unsigned short";
char t2[] = "unsigned int";
char t3[] = "unsigned long";
char *typevar[DIF_SIZE] = { t0, t1, t2, t3};


print_head()
{
	fprintf(OUT,"static FILE *inputStream;\n");
	fprintf(OUT,"char LexText[LEX_BUF];\n");
	fprintf(OUT,"static int lex_c = ' ';\n");
	fprintf(OUT,"static int lex_mode;\n");
	fprintf(OUT,"int lex_line = 1;\n");
	fprintf(OUT,"\n");
	/* LEX_EOF is probably not right */
	fprintf(OUT,"\n#define LEX_EOF -1\n");
	if (compress)
		fprintf(OUT,"unsigned char shift[];\n");
	fprintf(OUT,"int (*actions[])();\n");
}

print_tail()
{
}

/* output the table of DFA for general use */
print_tables()
{
	char *minsize();

	fprintf(OUT,"#define DfaStates\t%d\n",dfa_pool);
	fprintf(OUT,"#define NumAtoms\t%d\n", class_no);
	fprintf(OUT,"typedef %s DfaState;\n\n",minsize(dfa_pool));
	fprintf(OUT,"DfaState accepts[];\n");
	fprintf(OUT,"DfaState *dfa[];\n\n");

	print_node_table();
	print_dfa_table();
	print_accept_table();
	print_action_table();
	if (compress)
		print_shift_table();
	fprintf(OUT,"\n");
	fprintf(OUT,"\n");
	if (compress)
		fprintf(OUT,"#define _SHIFT(c) ((&shift[1])[c])\n");
	else
		fprintf(OUT,"#define _SHIFT(c) (1+c)\n");
	fprintf(OUT,"#include \"dlgauto.h\"\n");
}

/* figures out the smallest variable type that will hold the transitions
 */
char *minsize(elements)
int elements;
{
	int i = 0;

	while (elements > typesize[i])
		++i;
	return typevar[i];
		
}

print_node_table()
{
	register int	i, j;
	register int	trans, items_on_line;

	for (i = 0; i<dfa_pool; i++){
		fprintf(OUT,"static DfaState st%d[NumAtoms] = {\n  ",i);
		items_on_line = 0;
		j = 0;
		while(TRUE){
			trans = (int) dfa_array[i].trans[j];
			if (trans == NIL_INDEX)
				trans = dfa_pool;
			fprintf(OUT,"%d", trans);
			if ((++j) >= class_no)
				break;
			fprintf(OUT,", ");
			if ((++items_on_line)>MAX_ON_LINE){
				fprintf(OUT,"\n  ");
				items_on_line = 0;
				}
			}
		fprintf(OUT,"\n};\n\n");
		}
}

print_dfa_table()
{
	register int	i;

	fprintf(OUT,"\nDfaState *dfa[%d] = {\n",dfa_pool);
	for (i = 0; i<(dfa_pool-1); i++){
		fprintf(OUT,"\tst%d,\n",i);
		}
	fprintf(OUT,"\tst%d\n",i);
	fprintf(OUT,"};\n\n");
}

print_accept_table()
{
	register int	i = 0;
	register int	items_on_line = 0;

	fprintf(OUT,"\nDfaState accepts[%d] = {\n",dfa_pool);
	while (TRUE){
		int accept = 0;
		set nfa_states;
		register int nfa_index;
		register unsigned *start = &(nfa_states.setword[0]);

		nfa_states = dfa_array[i].nfa_states;
		set_remove_int(nfa_states,nfa_index,start);
		while(nfa_index != nil){
			accept = nfa(nfa_index).accept;
			if (accept)
				break;
			set_remove_int(nfa_states,nfa_index,start);
			}
		fprintf(OUT,"%d",accept);
		if ((++i)>=dfa_pool)
			break;
		fprintf(OUT,", ");
		if ((++items_on_line)>MAX_ON_LINE){
			fprintf(OUT,"\n  ");
			items_on_line = 0;
			}
		}
	fprintf(OUT,"\n};\n\n");
}

print_action_table()
{
	register int	i;

	fprintf(OUT,"int (*actions[%d])() = {\n",action_no+1);
	fprintf(OUT,"\taction0,\n");
	for (i = 1; i<action_no; i++){
		fprintf(OUT,"\tact%d,\n",i);
		}
	fprintf(OUT,"\tact%d\n",i);
	fprintf(OUT,"};\n\n");
}

print_shift_table()
{
	register int	i = 0, j;
	register int	items_on_line = 0;

	fprintf(OUT,"unsigned char shift[%d] = {\n  ",LAST_CHAR+2);
	while (TRUE){
		/* find which partition character i is in */
		for (j = 0; j<class_no; j++){
			if (set_el(i,class[j]))
				break;
			}
		fprintf(OUT,"%d",j);
		if ((++i)>(LAST_CHAR+1))
			break;
		fprintf(OUT,", ");
		if ((++items_on_line)>MAX_ON_LINE){
			fprintf(OUT,"\n  ");
			items_on_line = 0;
			}
		}
	fprintf(OUT,"\n};\n\n");
}

print_nfa_node(p)
int p;	/* state number also index into array */
{
	 register nfa_node *t;

	if (p != NIL_INDEX){
		t = &(nfa_array[p]);
		printf("NFA state : %d\naccept state : %d\n",
			p,t->accept);
		if (t->trans[0] != NIL_INDEX){
			printf("trans[0] => %d on ", t->trans[0]);
			print_set(t->label);
			printf("\n");
			}
		else
			printf("trans[0] => nil\n");
		if (t->trans[1] != NIL_INDEX)
			printf("trans[1] => %d on epsilon\n", t->trans[1]);
		else
			printf("trans[1] => nil\n");
		printf("\n");
		}
}

print_set(label)
set label;
{
	register int c;
	register unsigned *start = &(label.setword[0]);

	if (set_nil(label))
		printf("epsilon ");
	else{
		c = nil;
		set_remove_int(label,c,start);
		while (c != nil){
			printf("%d ",c);
			set_remove_int(label,c,start);
			}
		}
}

print_nfa(p)
int p;	/* state number also index into array */
{
/* each node has a marker on it so it only gets printed once */

	++nfa_set; /* get new number */

	s_print_nfa(p);
}

s_print_nfa(p)
int p;	/* state number also index into array */
{
	if ((p != NIL_INDEX) && nfa_array[p].nfa_set != nfa_set){
		nfa_array[p].nfa_set = nfa_set; /* so it is only printed once */
		print_nfa_node(p);
		s_print_nfa(nfa_array[p].trans[0]);
		s_print_nfa(nfa_array[p].trans[1]);
		}
}

print_dfa_node(p)
int p;
{
	int i;

	if (p != NIL_INDEX){
		printf("DFA state :%d\n",p);
		if (dfa_array[p].done)
			printf("done\n");
		else
			printf("undone\n");
		printf("from nfa states : ");
		print_set(dfa_array[p].nfa_states);
		printf("\n");
		for (i=0; i<NUM_CLASS; i++){
			printf("%d ",dfa_array[p].trans[i]);
			}
		printf("\n\n");
		}
}

print_dfa()
{
/* prints out all the dfa nodes actually allocated */

	int i;

	for (i = 0; i<dfa_pool;i++)
		print_dfa_node(i);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'relabel.c'
then
	echo shar: will not over-write existing file "'relabel.c'"
else
cat << \SHAR_EOF > 'relabel.c'
/* This group of functions does the character class compression.
   It goes over the dfa and relabels the arcs with the partitions
   of characters in the NFA.  The partitions are stored in the
   array class.

	Will Cohen
	10/25/89

*/

#include <stdio.h>
#include "dlg.h"

int	class_no;		/* number classes actually used */
int	first_el[NUM_CLASS];	/* first element in each class partition */
set	class[NUM_CLASS];	/* holds partitions from class compression */

/* relabel builds partitions from the the labels on the transistion
   arcs in the NFA.  It then goes through and relabels the arcs with
   the partitions, character classes
*/

relabel()
{
	partition();
	class_label();
}

/* makes character class sets for new labels */
partition()
{
	set current_class;
	set unpart_chars;
	register int label1;
	unsigned *start1;
	register int i;

	unpart_chars = used_chars;
	/* EOF (-1+1) alway in class 0 */
	class[0] = set_of(0);
	first_el[0] = 0;
	used_classes = set_of(0);
	unpart_chars = set_dif(unpart_chars, class[0]);
	class_no = 1;
	start1 = &(unpart_chars.setword[0]);
	set_remove_int(unpart_chars, label1, start1);
	while (label1 != nil){
		current_class = set_of(label1);
		/* don't look for equivalent labels if c <= 1 */
		if (compress > 1){
			current_class = unpart_chars;
			set_or_int(current_class, label1);
			for(i=0; i<nfa_pool; i++){
				if (set_el(label1,nfa(i).label))
					current_class = 
					  set_and(current_class,nfa(i).label);
				else
					current_class = 
					  set_and(current_class,
					  set_not(nfa(i).label));
				}
			unpart_chars = set_dif(unpart_chars,current_class);
			}
		set_or_int(used_classes, class_no);
		first_el[class_no] = label1;
		class[class_no++] = current_class;
		set_remove_int(unpart_chars,label1,start1);
		}
}

/* puts class labels in place of old character labels */
class_label()
{
	set old_label;
	set new_label;
	register int i,j;
	
	for (i = 0; i<nfa_pool; i++){
		new_label = set_of(nil);
		old_label = nfa(i).label;
		for (j = 0; j<class_no; j++){
				/* if one element of class in old_label,
				   all elements are. */
				if (set_el(first_el[j],old_label))
					set_or_int(new_label,j);
			}
		nfa(i).label = new_label;
		}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sets.c'
then
	echo shar: will not over-write existing file "'sets.c'"
else
cat << \SHAR_EOF > 'sets.c'
/*	set_lib.c

	The following is a general-purpose set library which
	allows C programs to be written nearly as though the
	set data-type existed... sets are structs which can
	be freely copied by assignment statements, passed by
	value to functions, returned by value from functions,
	and allocated by ordinary declarations.

	Inconveniences:
	1. Sets are of fixed size because C cannot track a
	   runtime-sized array (no paramtypes yet).
	2. Sets cannot be compared without a function call.
	3. Some strangeness happens if only a portion of a
	   set is used or if there are bits in a word which
	   are ignored in the set representation; e.g., the
	   set_not routine may not function correctly.

	(C) 1987 by Hank Dietz
*/

#include "sets.h"

unsigned bitmask[32] = {
	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
};

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 is a multiple of WORDSIZE.
	*/
	register unsigned *p = &(a.setword[0]);
	register unsigned *endp = &(a.setword[SETWORDS]);
	register degree = 0;

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

	return(degree);
}

set
set_or(b,c)
set b, c;
{
	/* Fast set union operation */
	register unsigned *p = &(b.setword[0]);
	register unsigned *q = &(c.setword[0]);
	register unsigned *endp = &(b.setword[SETWORDS]);

	do {
		*p |= *(q++);
	} while (++p < endp);
	return(b);
}

set
set_and(b,c)
set b, c;
{
	/* Fast set intersection operation */
	register unsigned *p = &(b.setword[0]);
	register unsigned *q = &(c.setword[0]);
	register unsigned *endp = &(b.setword[SETWORDS]);

	do {
		*p &= *(q++);
	} while (++p < endp);
	return(b);
}

set
set_dif(b,c)
set b, c;
{
	/* Fast set difference operation */
	register unsigned *p = &(b.setword[0]);
	register unsigned *q = &(c.setword[0]);
	register unsigned *endp = &(b.setword[SETWORDS]);

	do {
		*p &= (~ *(q++));
	} while (++p < endp);
	return(b);
}

set
set_of(b)
int b;
{
	/* Fast singleton set constructor operation */
	static set a;
	register unsigned *p = &(a.setword[0]);
	register unsigned *endp = &(a.setword[SETWORDS]);

	do {
		*p = 0;
	} while (++p < endp);
	if (b != nil) {
		a.setword[DIVWORD(b)] = bitmask[MODWORD(b)];
	}
	return(a);
}

set
set_not(a)
set a;
{
	/* Fast not of set a (assumes all bits used) */
	register unsigned *p = &(a.setword[0]);
	register unsigned *endp = &(a.setword[SETWORDS]);

	do {
		*p = (~ *p);
	} while (++p < endp);
	return(a);
}

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

	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[0]);
	register unsigned *q = &(b.setword[0]);
	register unsigned *endp = &(a.setword[SETWORDS]);
	register int asubset = 0;

	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);

	return(asubset);
}

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

	do {
		if (*p) {
			/* Found a non-empty word of the set */
			register int i = ((p - &(b.setword[0])) * WORDSIZE);
			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);
}

set_el(b,a)
int b;
set a;
{
	/* nil is an element of every set */
	if (b == nil) return(1);

	/* 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[0]);
	register unsigned *endp = &(a.setword[SETWORDS]);

	/* 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.
	*/
	register unsigned *p = &(a.setword[0]);
	register unsigned *endp = &(a.setword[SETWORDS]);
	static char str_tmp[SETSIZE+1];
	register char *q = &(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[1])) && (*(q-1) != '0')) --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.
	*/
	static set a;
	register unsigned *p = &(a.setword[0]);
	register unsigned *endp = &(a.setword[SETWORDS]);

	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);
}

int
set_hash(a, mod)
set a;
register int mod;
{
	/* Fast hash of set a (assumes all bits used) */
	register unsigned *p = &(a.setword[0]);
	register unsigned *endp = &(a.setword[SETWORDS]);
	register int i = 0;

	do {
		i = ((i + i + (i<0)) ^ (~ *p));
	} while (++p < endp);

	return(((i< 0) ? -i : i) % mod);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'sets.h'
then
	echo shar: will not over-write existing file "'sets.h'"
else
cat << \SHAR_EOF > 'sets.h'
#define	SETSIZE	600			/* maximum items per set */
#define	WORDSIZE 32			/* usable bits per word */
#define	SETWORDS ((SETSIZE+(WORDSIZE-1))/WORDSIZE)
#define MODWORD(x) ((x) & (WORDSIZE-1)) /* x % WORDSIZE */
#define DIVWORD(x) ((x) >> 5)		/* x / WORDSIZE */

#define	nil	SETSIZE			/* an impossible set member */
#define	set	struct _set
set {
	unsigned setword[SETWORDS];	/* Array of words to hold bits */
};

set	set_and();	/* returns arg1 intersection arg2 */
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 */
int	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 */
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 */




SHAR_EOF
fi # end of overwriting check
if test -f 'support.c'
then
	echo shar: will not over-write existing file "'support.c'"
else
cat << \SHAR_EOF > 'support.c'
/* support routines for stringc
 * for ee595e reused for dlg
 *
 * Will Cohen
 * 9/17/89
 */

#include <stdio.h>
#include "dlg.h"

/* sets options from the command line */
options(argc, argv)
int argc;
char **argv;
{
	int errflg = FALSE;

	/* skip over command */
	++argv; -- argc;

	while (( argc ) && ( **argv == '-' )){
		switch ( (*argv)[1] ){
			case 'C': sscanf(&((*argv)[2]),"%d",&compress);
				  break;
			case 'D': sscanf(&((*argv)[2]),"%d",&num_of_dfa);
				  break;
			case 'N': sscanf(&((*argv)[2]),"%d",&num_of_nfa);
				  break;
			case '\0':
				  /* skip it, it could be stdin/stdout */
				  break;
			default:  errflg = TRUE;
				  break;
			}
		++ argv ; -- argc;
		}
	if (errflg)
		usage();
}

void fatal(message,line_no)
char *message;
int line_no;
{
	fprintf(stderr,"Fatal : %s, line : %d\n",message,line_no);
	exit(2);
}

void error(message,line_no)
char *message;
int line_no;
{
	fprintf(stderr,"\"%s\", line %d: %s\n",in_file_name,line_no,message);
}

void warning(message,line_no)
char *message;
int line_no;
{
	fprintf(stderr,"Warning : %s, line : %d\n",message,line_no);
}

void init_things()
{
	register int i;

	/* make one initalized nfa node */
	clear_nfa_node.accept = 0;
	clear_nfa_node.nfa_set = 0;
	clear_nfa_node.trans[0] = NIL_INDEX;
	clear_nfa_node.trans[1] = NIL_INDEX;
	clear_nfa_node.label = set_of(nil);
	

	/* make one initalized dfa node */
	clear_dfa_node.done = FALSE;
	clear_dfa_node.dfa_set = 0;
	for (i=0; i<=NUM_CLASS; ++i)
		clear_dfa_node.trans[i] = NIL_INDEX;

	/* make a set with the valid characters in it.
	   Used to mask off unused elements in set.
	   EOF is not included in this set since it is special.
	   All character shifted by one, so EOF can be element
	   zero in set. */
	{
		register	int i,
				first_el = FIRST_CHAR+1,
				last_el = LAST_CHAR+1;

		valid_chars = set_of(first_el);
		for (i=first_el; i<=last_el; ++i)
			valid_chars = set_or(valid_chars,set_of(i));
	}
}

usage()
{
	fprintf(stderr,"Usage: dlg [-cD#F#] infile outfile");
	fprintf(stderr,"\nDefault Meaning of option\n");
	fprintf(stderr,"C0\tno character class compression\n");
	fprintf(stderr,"C1\tonly compress out unused characters\n");
	fprintf(stderr,"C2\tdo character class compression\n");
	fprintf(stderr,"Dn\tn is maximum number of DFA nodes\n");
	fprintf(stderr,"Nn\tn is maximum number of NFA nodes\n");
	exit(1);
}

/* gets space for arrays and clears out symbol table entries */
init_arrays()
{
	register int	*p,*t;
	char *malloc();

	/* get arrays set up for dfa and nfa's */
	nfa_array = (nfa_node*) malloc(num_of_nfa * sizeof(nfa_node));
	if (!nfa_array)
		error("Unable to allocate space for nfa table.\n",0);
	dfa_array = (dfa_node*) malloc(num_of_dfa * sizeof(dfa_node));
	if (!dfa_array)
		error("Unable to allocate space for dfa table.\n",0);
	dfa_hash_table = (int*) malloc(hash_entries * sizeof(int));
	if (!dfa_hash_table)
		error("Unable to allocate space for dfa hash table.\n",0);
	t = &dfa_hash_table[hash_entries];
	for(p = dfa_hash_table; p < t; p++)
		*p = NIL_INDEX;
}
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 for dlg
 *
 * Will Cohen
 * 10/3/89
 */

#define LEX_EOF		-1		/* this is okay, since array shifted */
#define MAXCHAR 127
#define THE_EOF		MAXCHAR+1	/* different from LEX_EOF, internal use*/
#define EPSILON		MAXCHAR+2	/* just for nfa graphs */
#define PER_PER		MAXCHAR+3
#define LESS_LESS	MAXCHAR+4
#define GREAT_GREAT	MAXCHAR+5
#define OPEN_BRACE	MAXCHAR+6
#define CLOSE_BRACE	MAXCHAR+7
#define OPEN_PAR	MAXCHAR+8
#define CLOSE_PAR	MAXCHAR+9
#define OPEN_BRACK	MAXCHAR+10
#define CLOSE_BRACK	MAXCHAR+11
#define ZERO_MORE	MAXCHAR+12
#define ONE_MORE	MAXCHAR+13
#define OR		MAXCHAR+14
#define RANGE		MAXCHAR+15
#define NOT		MAXCHAR+16
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0
