#include "ldefs.h"
#include "once.h"

	/* lex [-[drcyvntf]] [file] ... [file] */

main( argc, argv )
int      argc;
char   **argv;
{
	register int i;
	char     Xpushc[TOKENSIZE];
	pushptr = pushc = Xpushc;

#ifdef DEBUG
	signal( 10, buserr  );
	signal( 11, segviol );
#endif DEBUG
	while( argc > 1 && argv[1][0] == '-' ){
		i = 0;
		while( argv[1][++i] ){
			switch( argv[1][i] ){
#ifdef DEBUG
			  case 'd':
					debug++;
					break;
			  case 'y':
					yydebug = TRUE;
					break;
#endif
			  case 'c':
			  case 'C':
					break;
			  case 't':
			  case 'T':
					fout = stdout;
					errorf = stderr;
					break;
			  case 'v':
			  case 'V':
					report = 1;
					break;
			  case 'f':
			  case 'F':
					optim = FALSE;
					break;
			  case 'n':
			  case 'N':
					report = 0;
					break;
			  default:
					warning( "Unknown key %c", "  %c", argv[1][i] );
			}
		}
		argc--;
		argv++;
	}
#ifdef SMALL
	if( fout == NULL )
		setbuf( stdout, NULL );
#endif
	sargc = argc;
	sargv = argv;
	if( argc > 1 ){
#ifdef SMALL
		extern char _sibuf[];

		setbuf( stdin, NULL );
#endif
		fclose( stdin );
		fin = fopen( argv[++fptr], "r" );         /* open argv[1] */
#ifdef SMALL
		setbuf( fin, _sibuf );
#endif
		sargc--;
		sargv++;
	}else
		fin = stdin;
	if( fin == NULL ){
		if( argc > 1 )
			error( "Can't read input file %s", "     %s", argv[1] );
		else
			error( "Can't read stdin", "   . " );
	}
	gch();
		/* may be gotten: def, subs, sname, schar, ccl, dchar */
	get1core();
		/* may be gotten: name, left, right, nullstr, parent */
	scopy( "INITIAL", sp );
	sname[0] = sp;
	sp += slength( "INITIAL" ) + 1;
	sname[1] = 0;
	if( yyparse( 0 ) )
		exit( 1 ); /* error return code */
		/* may be disposed of: def, subs, dchar */
	free1core();
		/* may be gotten: tmpstat, foll, positions, gotof, nexts, nchar, state, atable, sfall, cpackflg */
	get2core();
	ptail();
	mkmatch();
#ifdef DEBUG
	if( debug )
		pccl();
#endif
	sect  = ENDSECTION;
	if( tptr > 0 )
		cfoll( tptr - 1 );
#ifdef DEBUG
	if( debug )
		pfoll();
#endif
	cgoto();
#ifdef DEBUG
	if( debug ){
		printf( ediag( "Print %d states:\n"," %d :\n"), stnum + 1 );
		for( i = 0; i <= stnum; i++ )
			stprt( i );
	}
#endif
		/* may be disposed of: positions, tmpstat, foll, state, name, left, right, parent, ccl, schar, sname */
		/* may be gotten: verify, advance, stoff */
	free2core();
	get3core();
	layout();
		/* may be disposed of: verify, advance, stoff, nexts, nchar,
			gotof, atable, ccpackflg, sfall */
#ifdef DEBUG
	free3core();
#endif
	if( ZCH > NCH )
		cname = "/usr/lib/lex/ebcform";
	drivercopy( cname );
	fclose( fout );
	if(
#ifdef DEBUG
		debug   ||
#endif
			report == 1 )
		statistics();

	fclose( stdout );
	fclose( stderr );
	exit( 0 );        /* success return code */
}

drivercopy(s)
char *s;
{
	register i;
#ifdef SMALL
	char XB[BUFSIZ];
#endif

	fother = fopen( s, "r" );
	if( fother == NULL )
		error( "No lex driver, file %s", "  Lex,  %s", cname );
#ifdef SMALL
	setbuf( fother, XB );
#endif
	while( ( i = getc( fother ) ) != EOF )
		putc( i, fout );

	fclose( fother );
}

get1core()
{
	ccptr =
	ccl   = myalloc( CCLSIZE,   sizeof( *ccl   ) );
	pcptr =
	pchar = myalloc( pchlen,    sizeof( *pchar ) );
	def   = myalloc( DEFSIZE,   sizeof( *def   ) );
	subs  = myalloc( DEFSIZE,   sizeof( *subs  ) );
	dp    =
	dchar = myalloc( DEFCHAR,   sizeof( *dchar ) );
	sname = myalloc( STARTSIZE, sizeof( *sname ) );
	sp    =
	schar = myalloc( STARTCHAR, sizeof( *schar ) );
	if( ccl == 0   || def == 0 || subs == 0 || dchar == 0 ||
	    sname == 0 || schar == 0                            )
		error( "Too small memory to start", "    " );
}

free1core()
{
	cfree( def,   DEFSIZE, sizeof( *def   ) );
	cfree( subs,  DEFSIZE, sizeof( *subs  ) );
	cfree( dchar, DEFCHAR, sizeof( *dchar ) );
}

get2core()
{
	register int     i;

	gotof     = myalloc( nstates,  sizeof( *gotof     ));
	nexts     = myalloc( ntrans,   sizeof( *nexts     ));
	nchar     = myalloc( ntrans,   sizeof( *nchar     ));
	state     = myalloc( nstates,  sizeof( *state     ));
	atable    = myalloc( nstates,  sizeof( *atable    ));
	sfall     = myalloc( nstates,  sizeof( *sfall     ));
	cpackflg  = myalloc( nstates,  sizeof( *cpackflg  ));
	tmpstat   = myalloc( tptr + 1, sizeof( *tmpstat   ));
	foll      = myalloc( tptr + 1, sizeof( *foll      ));
	nxtpos    =
	positions = myalloc( maxpos,   sizeof( *positions ));
	if( tmpstat == 0 || foll   == 0 || positions == 0 ||
	    gotof   == 0 || nexts  == 0 || nchar     == 0 ||
	    state   == 0 || atable == 0 || sfall     == 0 ||
	    cpackflg == 0                                    )
		error( "Not enough memory for states generation", "     " );
	for( i = 0; i <= tptr; i++ )
		foll[i] = 0;
}

free2core()
{
	cfree( positions, maxpos,    sizeof( *positions ) );
	cfree( tmpstat,   tptr + 1,  sizeof( *tmpstat   ) );
	cfree( foll,      tptr + 1,  sizeof( *foll      ) );
	cfree( name,      treesize,  sizeof( *name      ) );
	cfree( left,      treesize,  sizeof( *left      ) );
	cfree( right,     treesize,  sizeof( *right     ) );
	cfree( parent,    treesize,  sizeof( *parent    ) );
	cfree( nullstr,   treesize,  sizeof( *nullstr   ) );
	cfree( state,     nstates,   sizeof( *state     ) );
	cfree( sname,     STARTSIZE, sizeof( *sname     ) );
	cfree( schar,     STARTCHAR, sizeof( *schar     ) );
	cfree( ccl,       CCLSIZE,   sizeof( *ccl       ) );
}

get3core()
{
	verify  = myalloc( outsize,   sizeof( *verify  ) );
	advance = myalloc( outsize,   sizeof( *advance ) );
	stoff   = myalloc( stnum + 2, sizeof( *stoff   ) );
	if( verify == 0 || advance == 0 || stoff == 0 )
		error( "Not enough memory for final packing", "    " );
}

#ifdef DEBUG
free3core()
{
	cfree( advance,  outsize, sizeof( *advance  ) );
	cfree( verify,   outsize, sizeof( *verify   ) );
	cfree( stoff,    stnum+1, sizeof( *stoff    ) );
	cfree( gotof,    nstates, sizeof( *gotof    ) );
	cfree( nexts,    ntrans,  sizeof( *nexts    ) );
	cfree( nchar,    ntrans,  sizeof( *nchar    ) );
	cfree( atable,   nstates, sizeof( *atable   ) );
	cfree( sfall,    nstates, sizeof( *sfall    ) );
	cfree( cpackflg, nstates, sizeof( *cpackflg ) );
}
#endif

char *myalloc( a, b )
int      a;
int      b;
{
	register int     i;

	i = calloc( a, b );
	if( i == 0 )
		warning( "calloc returns 0", "calloc  0" );
	else if( i == -1 ){
#ifdef DEBUG
		warning("calloc returns -1", "calloc  -1");
#endif
		return( 0 );
	}
	return( i );
}

#ifdef DEBUG
buserr()
{
	fflush( errorf );
	fflush( fout );
	fflush( stdout );
	fprintf( errorf, ediag("Bus error\n", " \n") );
	if( report == 1 )
		statistics();
	fflush( errorf );
}

segviol()
{
	fflush( errorf );
	fflush( fout );
	fflush( stdout );
	fprintf( errorf, ediag( "Segmentation violation\n", " \n") );
	if( report == 1 )
		statistics();
	fflush( errorf );
}
#endif

yyerror( s )
char *s;
{
	fprintf( stderr, "%s\n", s );
}
