[comp.sources.unix] v14i080: Flex, a lex replacement, Part02/05

rsalz@uunet.uu.net (Rich Salz) (05/04/88)

Submitted-by: Vern Paxson <vern@lbl-csam.arpa>
Posting-number: Volume 14, Issue 80
Archive-name: flex/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 5)."
# Contents:  dfa.c flex.fastskel main.c misc.c scan.l
# Wrapped by rsalz@fig.bbn.com on Tue May  3 17:31:27 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dfa.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dfa.c'\"
else
echo shar: Extracting \"'dfa.c'\" \(10732 characters\)
sed "s/^X//" >'dfa.c' <<'END_OF_FILE'
X/* dfa - DFA construction routines */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include "flexdef.h"
X
X/* epsclosure - construct the epsilon closure of a set of ndfa states
X *
X * synopsis
X *    int t[current_max_dfa_size], numstates, accset[accnum + 1], nacc;
X *    int hashval;
X *    int *epsclosure();
X *    t = epsclosure( t, &numstates, accset, &nacc, &hashval );
X *
X * NOTES
X *    the epsilon closure is the set of all states reachable by an arbitrary
X *  number of epsilon transitions which themselves do not have epsilon
X *  transitions going out, unioned with the set of states which have non-null
X *  accepting numbers.  t is an array of size numstates of nfa state numbers.
X *  Upon return, t holds the epsilon closure and numstates is updated.  accset
X *  holds a list of the accepting numbers, and the size of accset is given
X *  by nacc.  t may be subjected to reallocation if it is not large enough
X *  to hold the epsilon closure.
X *
X *    hashval is the hash value for the dfa corresponding to the state set
X */
X
int *epsclosure( t, ns_addr, accset, nacc_addr, hv_addr )
int *t, *ns_addr, accset[], *nacc_addr, *hv_addr;
X
X    {
X    register int stkpos, ns, tsp;
X    int numstates = *ns_addr, nacc, hashval, transsym, nfaccnum;
X    int stkend, nstate;
X    static int did_stk_init = false, *stk; 
X
X#define MARK_STATE(state) \
X	trans1[state] = trans1[state] - MARKER_DIFFERENCE;
X
X#define IS_MARKED(state) (trans1[state] < 0)
X
X#define UNMARK_STATE(state) \
X	trans1[state] = trans1[state] + MARKER_DIFFERENCE;
X
X#define CHECK_ACCEPT(state) \
X	{ \
X	nfaccnum = accptnum[state]; \
X	if ( nfaccnum != NIL ) \
X	    accset[++nacc] = nfaccnum; \
X	}
X
X#define DO_REALLOCATION \
X	{ \
X	current_max_dfa_size += MAX_DFA_SIZE_INCREMENT; \
X	++num_reallocs; \
X	t = reallocate_integer_array( t, current_max_dfa_size ); \
X	stk = reallocate_integer_array( stk, current_max_dfa_size ); \
X	} \
X
X#define PUT_ON_STACK(state) \
X	{ \
X	if ( ++stkend >= current_max_dfa_size ) \
X	    DO_REALLOCATION \
X	stk[stkend] = state; \
X	MARK_STATE(state) \
X	}
X
X#define ADD_STATE(state) \
X	{ \
X	if ( ++numstates >= current_max_dfa_size ) \
X	    DO_REALLOCATION \
X	t[numstates] = state; \
X	hashval = hashval + state; \
X	}
X
X#define STACK_STATE(state) \
X	{ \
X	PUT_ON_STACK(state) \
X	CHECK_ACCEPT(state) \
X	if ( nfaccnum != NIL || transchar[state] != SYM_EPSILON ) \
X	    ADD_STATE(state) \
X	}
X
X    if ( ! did_stk_init )
X	{
X	stk = allocate_integer_array( current_max_dfa_size );
X	did_stk_init = true;
X	}
X
X    nacc = stkend = hashval = 0;
X
X    for ( nstate = 1; nstate <= numstates; ++nstate )
X	{
X	ns = t[nstate];
X
X	/* the state could be marked if we've already pushed it onto
X	 * the stack
X	 */
X	if ( ! IS_MARKED(ns) )
X	    PUT_ON_STACK(ns)
X
X	CHECK_ACCEPT(ns)
X	hashval = hashval + ns;
X	}
X
X    for ( stkpos = 1; stkpos <= stkend; ++stkpos )
X	{
X	ns = stk[stkpos];
X	transsym = transchar[ns];
X
X	if ( transsym == SYM_EPSILON )
X	    {
X	    tsp = trans1[ns] + MARKER_DIFFERENCE;
X
X	    if ( tsp != NO_TRANSITION )
X		{
X		if ( ! IS_MARKED(tsp) )
X		    STACK_STATE(tsp)
X
X		tsp = trans2[ns];
X
X		if ( tsp != NO_TRANSITION )
X		    if ( ! IS_MARKED(tsp) )
X			STACK_STATE(tsp)
X		}
X	    }
X	}
X
X    /* clear out "visit" markers */
X
X    for ( stkpos = 1; stkpos <= stkend; ++stkpos )
X	{
X	if ( IS_MARKED(stk[stkpos]) )
X	    {
X	    UNMARK_STATE(stk[stkpos])
X	    }
X	else
X	    flexfatal( "consistency check failed in epsclosure()" );
X	}
X
X    *ns_addr = numstates;
X    *hv_addr = hashval;
X    *nacc_addr = nacc;
X
X    return ( t );
X    }
X
X
X
X/* increase_max_dfas - increase the maximum number of DFAs */
X
increase_max_dfas()
X
X    {
X    int old_max = current_max_dfas;
X
X    current_max_dfas += MAX_DFAS_INCREMENT;
X
X    ++num_reallocs;
X
X    base = reallocate_integer_array( base, current_max_dfas );
X    def = reallocate_integer_array( def, current_max_dfas );
X    dfasiz = reallocate_integer_array( dfasiz, current_max_dfas );
X    accsiz = reallocate_integer_array( accsiz, current_max_dfas );
X    dhash = reallocate_integer_array( dhash, current_max_dfas );
X    todo = reallocate_integer_array( todo, current_max_dfas );
X    dss = reallocate_integer_pointer_array( dss, current_max_dfas );
X    dfaacc = reallocate_dfaacc_union( dfaacc, current_max_dfas );
X
X    /* fix up todo queue */
X    if ( todo_next < todo_head )
X	{ /* queue was wrapped around the end */
X	register int i;
X
X	for ( i = 0; i < todo_next; ++i )
X	    todo[old_max + i] = todo[i];
X	
X	todo_next += old_max;
X	}
X    }
X
X
X/* snstods - converts a set of ndfa states into a dfa state
X *
X * synopsis
X *    int sns[numstates], numstates, newds, accset[accnum + 1], nacc, hashval;
X *    int snstods();
X *    is_new_state = snstods( sns, numstates, accset, nacc, hashval, &newds );
X *
X * on return, the dfa state number is in newds.
X */
X
int snstods( sns, numstates, accset, nacc, hashval, newds_addr )
int sns[], numstates, accset[], nacc, hashval, *newds_addr;
X
X    {
X    int didsort = 0;
X    register int i, j;
X    int newds, *oldsns;
X    char *malloc();
X
X    for ( i = 1; i <= lastdfa; ++i )
X	if ( hashval == dhash[i] )
X	    {
X	    if ( numstates == dfasiz[i] )
X		{
X		oldsns = dss[i];
X
X		if ( ! didsort )
X		    {
X		    /* we sort the states in sns so we can compare it to
X		     * oldsns quickly.  we use bubble because there probably
X		     * aren't very many states
X		     */
X		    bubble( sns, numstates );
X		    didsort = 1;
X		    }
X
X		for ( j = 1; j <= numstates; ++j )
X		    if ( sns[j] != oldsns[j] )
X			break;
X
X		if ( j > numstates )
X		    {
X		    ++dfaeql;
X		    *newds_addr = i;
X		    return ( 0 );
X		    }
X
X		++hshcol;
X		}
X
X	    else
X		++hshsave;
X	    }
X
X    /* make a new dfa */
X
X    if ( ++lastdfa >= current_max_dfas )
X	increase_max_dfas();
X
X    newds = lastdfa;
X
X    if ( ! (dss[newds] = (int *) malloc( (unsigned) ((numstates + 1) * sizeof( int )) )) )
X	flexfatal( "dynamic memory failure in snstods()" );
X
X    /* if we haven't already sorted the states in sns, we do so now, so that
X     * future comparisons with it can be made quickly
X     */
X
X    if ( ! didsort )
X	bubble( sns, numstates );
X
X    for ( i = 1; i <= numstates; ++i )
X	dss[newds][i] = sns[i];
X
X    dfasiz[newds] = numstates;
X    dhash[newds] = hashval;
X
X    if ( nacc == 0 )
X	{
X	dfaacc[newds].dfaacc_state = 0;
X	accsiz[newds] = 0;
X	}
X
X    else if ( reject )
X	{
X	/* we sort the accepting set in increasing order so the disambiguating
X	 * rule that the first rule listed is considered match in the event of
X	 * ties will work.  We use a bubble sort since the list is probably
X	 * quite small.
X	 */
X
X	bubble( accset, nacc );
X
X	dfaacc[newds].dfaacc_state =
X	    (int) malloc( (unsigned) ((nacc + 1) * sizeof( int )) );
X
X	if ( ! dfaacc[newds].dfaacc_state )
X	    flexfatal( "dynamic memory failure in snstods()" );
X
X	/* save the accepting set for later */
X	for ( i = 1; i <= nacc; ++i )
X	    dfaacc[newds].dfaacc_set[i] = accset[i];
X
X	accsiz[newds] = nacc;
X	}
X
X    else
X	{ /* find lowest numbered rule so the disambiguating rule will work */
X	j = accnum + 1;
X
X	for ( i = 1; i <= nacc; ++i )
X	    if ( accset[i] < j )
X		j = accset[i];
X
X	dfaacc[newds].dfaacc_state = j;
X	}
X
X    *newds_addr = newds;
X
X    return ( 1 );
X    }
X
X
X/* symfollowset - follow the symbol transitions one step
X *
X * synopsis
X *    int ds[current_max_dfa_size], dsize, transsym;
X *    int nset[current_max_dfa_size], numstates;
X *    numstates = symfollowset( ds, dsize, transsym, nset );
X */
X
int symfollowset( ds, dsize, transsym, nset )
int ds[], dsize, transsym, nset[];
X
X    {
X    int ns, tsp, sym, i, j, lenccl, ch, numstates;
X    int ccllist;
X
X    numstates = 0;
X
X    for ( i = 1; i <= dsize; ++i )
X	{ /* for each nfa state ns in the state set of ds */
X	ns = ds[i];
X	sym = transchar[ns];
X	tsp = trans1[ns];
X
X	if ( sym < 0 )
X	    { /* it's a character class */
X	    sym = -sym;
X	    ccllist = cclmap[sym];
X	    lenccl = ccllen[sym];
X
X	    if ( cclng[sym] )
X		{
X		for ( j = 0; j < lenccl; ++j )
X		    { /* loop through negated character class */
X		    ch = ccltbl[ccllist + j];
X
X		    if ( ch > transsym )
X			break;	/* transsym isn't in negated ccl */
X
X		    else if ( ch == transsym )
X			/* next 2 */ goto bottom;
X		    }
X
X		/* didn't find transsym in ccl */
X		nset[++numstates] = tsp;
X		}
X
X	    else
X		for ( j = 0; j < lenccl; ++j )
X		    {
X		    ch = ccltbl[ccllist + j];
X
X		    if ( ch > transsym )
X			break;
X
X		    else if ( ch == transsym )
X			{
X			nset[++numstates] = tsp;
X			break;
X			}
X		    }
X	    }
X
X	else if ( sym >= 'A' && sym <= 'Z' && caseins )
X	    flexfatal( "consistency check failed in symfollowset" );
X
X	else if ( sym == SYM_EPSILON )
X	    { /* do nothing */
X	    }
X
X	else if ( ecgroup[sym] == transsym )
X	    nset[++numstates] = tsp;
X
bottom:
X	;
X	}
X
X    return ( numstates );
X    }
X
X
X/* sympartition - partition characters with same out-transitions
X *
X * synopsis
X *    integer ds[current_max_dfa_size], numstates, duplist[numecs];
X *    symlist[numecs];
X *    sympartition( ds, numstates, symlist, duplist );
X */
X
sympartition( ds, numstates, symlist, duplist )
int ds[], numstates, duplist[];
int symlist[];
X
X    {
X    int tch, i, j, k, ns, dupfwd[CSIZE + 1], lenccl, cclp, ich;
X
X    /* partitioning is done by creating equivalence classes for those
X     * characters which have out-transitions from the given state.  Thus
X     * we are really creating equivalence classes of equivalence classes.
X     */
X
X    for ( i = 1; i <= numecs; ++i )
X	{ /* initialize equivalence class list */
X	duplist[i] = i - 1;
X	dupfwd[i] = i + 1;
X	}
X
X    duplist[1] = NIL;
X    dupfwd[numecs] = NIL;
X
X    for ( i = 1; i <= numstates; ++i )
X	{
X	ns = ds[i];
X	tch = transchar[ns];
X
X	if ( tch != SYM_EPSILON )
X	    {
X	    if ( tch < -lastccl || tch > CSIZE )
X		flexfatal( "bad transition character detected in sympartition()" );
X
X	    if ( tch > 0 )
X		{ /* character transition */
X		mkechar( ecgroup[tch], dupfwd, duplist );
X		symlist[ecgroup[tch]] = 1;
X		}
X
X	    else
X		{ /* character class */
X		tch = -tch;
X
X		lenccl = ccllen[tch];
X		cclp = cclmap[tch];
X		mkeccl( ccltbl + cclp, lenccl, dupfwd, duplist, numecs );
X
X		if ( cclng[tch] )
X		    {
X		    j = 0;
X
X		    for ( k = 0; k < lenccl; ++k )
X			{
X			ich = ccltbl[cclp + k];
X
X			for ( ++j; j < ich; ++j )
X			    symlist[j] = 1;
X			}
X
X		    for ( ++j; j <= numecs; ++j )
X			symlist[j] = 1;
X		    }
X
X		else
X		    for ( k = 0; k < lenccl; ++k )
X			{
X			ich = ccltbl[cclp + k];
X			symlist[ich] = 1;
X			}
X		}
X	    }
X	}
X    }
END_OF_FILE
if test 10732 -ne `wc -c <'dfa.c'`; then
    echo shar: \"'dfa.c'\" unpacked with wrong size!
fi
# end of 'dfa.c'
fi
if test -f 'flex.fastskel' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flex.fastskel'\"
else
echo shar: Extracting \"'flex.fastskel'\" \(9304 characters\)
sed "s/^X//" >'flex.fastskel' <<'END_OF_FILE'
X/* A lexical scanner generated by flex */
X
X#define FLEX_FAST_SKEL
X
X#include "fastskeldef.h"
X
X%% section 1 code and the definition of YY_TRANS_OFFSET_TYPE, if needed, go here
X
X#ifndef FLEX_FULL_TABLE
X    /* struct for yy_transition */
X    struct yy_trans_info
X	{
X	/* v is a verify for a transition. */
X	short v;
X
X	/* In cases where its sister v *is* a "yes, there is a transition",
X         * n is* the offset (in records) to the next state.  In most cases
X         * where there is no transition, the value of n is irrelevant.  If n
X         * is the -1th  record of a state, though, then n is the action
X	 * number for that state
X	 */
X	YY_TRANS_OFFSET_TYPE n;
X	};
X#endif
X
X%% data tables for DFA go here
X
X/* these declarations have to come after the section 1 code or lint gets
X * confused about whether the variables are used
X */
XFILE *yyin = stdin, *yyout = stdout;
X
X/* these variables are all declared out here so that section 3 code can
X * manipulate them
X */
static char *yy_c_buf_p;	/* points to current character in buffer */
static char *yy_b_buf_p;	/* points to start of current scan */
static int yy_init = 1;	/* whether we need to initialize */
static int yy_start;	/* start state number */
X
X/* true when we've seen an EOF for the current input file */
static int yy_eof_has_been_seen;
X
static int yy_n_chars;		/* number of characters read into yy_ch_buf */
X
X/* yy_ch_buf has to be 2 characters longer than YY_BUF_SIZE because we need
X * to put in 2 end-of-buffer characters (this is explained where it is
X * done) at the end of yy_ch_buf
X */
static char yy_ch_buf[YY_BUF_SIZE + 2];
X
X/* yy_hold_char holds the character lost when yytext is formed */
static char yy_hold_char;
char *yytext;
static int yyleng;	/* length of yytext */
X
static YY_CS_TYPE yy_last_accepting_state;
static char *yy_last_accepting_cpos;
X
static YY_CS_TYPE yy_get_previous_state();
static int yy_get_next_buffer();
X
X#define FLEX_USES_BACKTRACKING
X
X#ifdef FLEX_USES_BACKTRACKING
X#    ifdef FLEX_FULL_TABLE
X#	define YY_BACKTRACKING_ACTION \
X		if ( l[yy_current_state] ) \
X			{ \
X			yy_last_accepting_state = yy_current_state; \
X			yy_last_accepting_cpos = yy_c_buf_p; \
X			}
X#    else
X#	define YY_BACKTRACKING_ACTION \
X		if ( yy_current_state[-1].n ) \
X			{ \
X			yy_last_accepting_state = yy_current_state; \
X			yy_last_accepting_cpos = yy_c_buf_p; \
X			}
X#    endif
X#else
X#    define YY_BACKTRACKING_ACTION
X#endif
X
YY_DECL
X    {
X    register YY_CS_TYPE yy_current_state;
X    register int yy_c;
X    register struct yy_trans_info *yy_trans_info;
X    register int yy_act;
X
X%% user's declarations go here
X
X    if ( yy_init )
X	{
X	yy_start = 1;	/* first start state */
X
new_file:
X	/* this is where we enter upon encountering and end-of-file and
X	 * yywrap() indicating that we should continue processing
X	 */
X
X	/* we put in the '\n' and start reading from [1] so that an
X	 * initial match-at-newline will be true.
X	 */
X
X	yy_ch_buf[0] = '\n';
X	yy_n_chars = 1;
X
X	/* we always need two end-of-buffer characters.  The first causes
X	 * a transition to the end-of-buffer state.  The second causes
X	 * a jam in that state.
X	 */
X	yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
X	yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
X
X	yy_eof_has_been_seen = 0;
X
X	YY_FAST_INIT;
X	yy_init = 0;
X	}
X
X    while ( 1 )		/* loops until end-of-file is reached */
X	{
X	/* support of yytext and yyleng */
X	YY_DO_BEFORE_SCAN;
X
X	/* yy_b_buf_p points to the position in yy_ch_buf of the start of the
X	 * current run.
X	 */
X	yy_b_buf_p = yy_c_buf_p;
X
X        YY_FIND_START_STATE( yy_current_state );
X
X        YY_FIND_NEXT_MATCH;
X
X	YY_DO_BEFORE_ACTION;
X
X/* we need this label to process the very last action (right before the end of
X * the file)
X */
do_action:
X	YY_FIND_ACTION( yy_act );
X
X#ifdef FLEX_DEBUG
X	fprintf( stderr, "--accepting rule #%d\n", yy_act );
X#endif
X	switch ( yy_act )
X	    {
X%% actions go here
X
X	    case YY_BACK_TRACK:
X		YY_DO_BEFORE_SCAN; /* undo the effects of YY_DO_BEFORE_ACTION */
X		yy_c_buf_p = yy_last_accepting_cpos + 1;
X		yy_current_state = yy_last_accepting_state;
X		YY_DO_BEFORE_ACTION;
X		goto do_action;
X
X	    case YY_NEW_FILE:
X		break; /* begin reading from new file */
X
X	    case YY_DO_DEFAULT:
X		/* we have to eat up one character and recompute yytext and
X		 * yyleng
X		 */
X		YY_DO_BEFORE_SCAN; /* undo the effects of YY_DO_BEFORE_ACTION */
X		++yy_c_buf_p;
X		YY_DO_BEFORE_ACTION;
X		YY_DEFAULT_ACTION;
X		break;
X
X	    case YY_END_OF_BUFFER:
X		YY_DO_BEFORE_SCAN; /* undo the effects of YY_DO_BEFORE_ACTION */
X
X		switch ( yy_get_next_buffer() )
X		    {
X		    case EOB_ACT_END_OF_FILE:
X			{
X			if ( yywrap() )
X			    {
X			    /* note: because we've taken care in
X			     * yy_get_next_buffer() to have set up yy_b_buf_p,
X			     * we can now set up yy_c_buf_p so that if some
X			     * total hoser (like flex itself) wants
X			     * to call the scanner after we return the
X			     * YY_NULL, it'll still work - another YY_NULL
X 			     * will get returned.
X			     */
X			    yy_c_buf_p = yy_b_buf_p;
X			    return ( YY_NULL );
X			    }
X
X			else
X			    goto new_file;
X			}
X			break;
X
X		    case EOB_ACT_RESTART_SCAN:
X			yy_c_buf_p = yy_b_buf_p;
X
X			YY_DO_BEFORE_RESTART;
X			break;
X
X		    case EOB_ACT_LAST_MATCH:
X			yy_c_buf_p = &yy_ch_buf[yy_n_chars];
X
X			yy_current_state = yy_get_previous_state();
X
X			YY_DO_BEFORE_ACTION;
X
X			goto do_action;
X		    }
X		break;
X
X	    default:
X		printf( "action # %d\n", yy_act );
X		YY_FATAL_ERROR( "fatal flex scanner internal error" );
X	    }
X	}
X    }
X
X
X/* yy_get_next_buffer - try to read in new buffer
X *
X * synopsis
X *     int yy_get_next_buffer();
X *     
X * returns a code representing an action
X *     EOB_ACT_LAST_MATCH - 
X *     EOB_ACT_RESTART_SCAN - restart the scanner
X *     EOB_ACT_END_OF_FILE - end of file
X */
X
static int yy_get_next_buffer()
X
X    {
X    if ( yy_c_buf_p != &yy_ch_buf[yy_n_chars + 1] )
X	{
X	YY_FATAL_ERROR( "NULL in input" );
X	/*NOTREACHED*/
X	}
X
X    else
X	{ /* try to read more data */
X	register char *dest = yy_ch_buf;
X	register char *source = yy_b_buf_p - 1; /* copy prev. char, too */
X	register int number_to_move, i;
X	int ret_val;
X	
X	/* first move last chars to start of buffer */
X	number_to_move = yy_c_buf_p - yy_b_buf_p;
X
X	for ( i = 0; i < number_to_move; ++i )
X	    *(dest++) = *(source++);
X
X	if ( yy_eof_has_been_seen )
X	    /* don't do the read, it's not guaranteed to return an EOF,
X	     * just force an EOF
X	     */
X	    yy_n_chars = 0;
X
X	else
X	    /* read in more data */
X	    YY_INPUT( (&yy_ch_buf[number_to_move]), yy_n_chars,
X		      YY_BUF_SIZE - number_to_move - 1 );
X
X	if ( yy_n_chars == 0 )
X	    {
X	    if ( number_to_move == 1 )
X		ret_val = EOB_ACT_END_OF_FILE;
X	    else
X		ret_val = EOB_ACT_LAST_MATCH;
X
X	    yy_eof_has_been_seen = 1;
X	    }
X
X	else
X	    ret_val = EOB_ACT_RESTART_SCAN;
X
X	yy_n_chars += number_to_move;
X	yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
X	yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
X
X	/* yy_b_buf_p begins at the second character in
X	 * yy_ch_buf; the first character is the one which
X	 * preceded it before reading in the latest buffer;
X	 * it needs to be kept around in case it's a
X	 * newline, so yy_get_previous_state() will have
X	 * with '^' rules active
X	 */
X
X	yy_b_buf_p = &yy_ch_buf[1];
X
X	return ( ret_val );
X	}
X    }
X
X
X/* yy_get_previous_state - get the state just before the eob char was reached
X *
X * synopsis
X *     YY_CS_TYPE yy_get_previous_state();
X */
X
static YY_CS_TYPE yy_get_previous_state()
X
X    {
X    register YY_CS_TYPE yy_cur_state;
X    register char *yy_temp_char_ptr;
X
X    YY_FIND_START_STATE( yy_cur_state );
X
X    for ( yy_temp_char_ptr = yy_b_buf_p; yy_temp_char_ptr < yy_c_buf_p; )
X	YY_GET_NEXT_STATE;
X
X    return ( yy_cur_state );
X    }
X
X
static unput( c )
int c;
X
X    {
X    YY_DO_BEFORE_SCAN; /* undo effects of setting up yytext */
X
X    if ( yy_c_buf_p < yy_ch_buf + 2 )
X	{ /* need to shift things up to make room */
X	register int number_to_move = yy_n_chars + 2; /* +2 for EOB chars */
X	register char *dest = &yy_ch_buf[YY_BUF_SIZE + 2];
X	register char *source = &yy_ch_buf[number_to_move];
X
X	while ( source > yy_ch_buf )
X	    *--dest = *--source;
X
X	yy_c_buf_p += dest - source;
X	yy_b_buf_p += dest - source;
X
X	if ( yy_c_buf_p < yy_ch_buf + 2 )
X	    YY_FATAL_ERROR( "flex scanner push-back overflow" );
X	}
X
X    if ( yy_c_buf_p > yy_b_buf_p && yy_c_buf_p[-1] == '\n' )
X	yy_c_buf_p[-2] = '\n';
X
X    *--yy_c_buf_p = c;
X
X    YY_DO_BEFORE_ACTION; /* set up yytext again */
X    }
X
X
static int input()
X
X    {
X    int c;
X
X    YY_DO_BEFORE_SCAN;
X
X    if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
X	{ /* need more input */
X	yy_b_buf_p = yy_c_buf_p;
X	++yy_c_buf_p;
X
X	switch ( yy_get_next_buffer() )
X	    {
X	    /* this code, unfortunately, is somewhat redundant with
X	     * that above
X	     */
X	    case EOB_ACT_END_OF_FILE:
X		{
X		if ( yywrap() )
X		    {
X		    yy_c_buf_p = yy_b_buf_p;
X		    return ( EOF );
X		    }
X
X		yy_ch_buf[0] = '\n';
X		yy_n_chars = 1;
X		yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
X		yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
X		yy_eof_has_been_seen = 0;
X
X		YY_FAST_INIT;
X
X		return ( input() );
X		}
X		break;
X
X	    case EOB_ACT_RESTART_SCAN:
X		yy_c_buf_p = yy_b_buf_p;
X		break;
X
X	    case EOB_ACT_LAST_MATCH:
X		YY_FATAL_ERROR( "unexpected last match in input()" );
X	    }
X	}
X
X    c = *yy_c_buf_p++;
X
X    YY_DO_BEFORE_RESTART;
X
X    return ( c );
X    }
END_OF_FILE
if test 9304 -ne `wc -c <'flex.fastskel'`; then
    echo shar: \"'flex.fastskel'\" unpacked with wrong size!
fi
# end of 'flex.fastskel'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(12885 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/* flex - tool to generate fast lexical analyzers
X *
X *
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X *
X *
X * ver   date  who    remarks
X * ---   ----  ------ -------------------------------------------------------
X * 04b 30sep87 kg, vp .implemented (part of) Van Jacobson's fast scanner design
X * 04a 27jun86 vp     .translated from Ratfor into C
X * 01a 22aug83 vp     .written.  Original version by Jef Poskanzer.
X */
X
X#include "flexdef.h"
X
X
X/* these globals are all defined and commented in flexdef.h */
int printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
int interactive, caseins, useecs, fulltbl, usemecs, reject;
int fullspd, gen_line_dirs;
int datapos, dataline, linenum;
XFILE *skelfile = NULL;
char *infilename = NULL;
int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
int current_mns;
int accnum, *firstst, *lastst, *finalst, *transchar;
int *trans1, *trans2, *accptnum, lastnfa;
int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
int protcomst[MSP], firstprot, lastprot, protsave[PROT_SAVE_SIZE];
int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs, tecfwd[CSIZE + 1];
int tecbck[CSIZE + 1];
int lastsc, current_max_scs, *scset, *scbol, *scxclu, *actvsc;
int current_max_dfa_size, current_max_xpairs;
int current_max_template_xpairs, current_max_dfas;
int lastdfa, *nxt, *chk, *tnxt;
int *base, *def, tblend, firstfree, numtemps, **dss, *dfasiz;
union dfaacc_union *dfaacc;
int *accsiz, *dhash, *todo, todo_head, todo_next, numas;
int numsnpairs, jambase, jamstate;
int lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse;
int current_max_ccl_tbl_size;
char *ccltbl;
char *starttime, *endtime, nmstr[MAXLINE];
int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
XFILE *temp_action_file;
int end_of_buffer_state;
char *action_file_name = "/tmp/flexXXXXXX";
X
X
X/* flex - main program
X *
X * synopsis (from the shell)
X *    flex [-v] [file ...]
X */
X
main( argc, argv )
int argc;
char **argv;
X
X    {
X    flexinit( argc, argv );
X
X    readin();
X
X    if ( ! syntaxerror )
X	{
X	/* convert the ndfa to a dfa */
X	ntod();
X
X	/* generate the C state transition tables from the DFA */
X	make_tables();
X	}
X
X    /* note, flexend does not return.  It exits with its argument as status. */
X
X    flexend( 0 );
X    }
X
X
X/* flexend - terminate flex
X *
X * synopsis
X *    int status;
X *    flexend( status );
X *
X *    status is exit status.
X *
X * note
X *    This routine does not return.
X */
X
flexend( status )
int status;
X
X    {
X    int tblsiz;
X    char *gettime();
X
X    if ( skelfile != NULL )
X	(void) fclose( skelfile );
X
X    if ( temp_action_file )
X	{
X	(void) fclose( temp_action_file );
X	(void) unlink( action_file_name );
X	}
X
X    if ( printstats )
X	{
X	endtime = gettime();
X
X	fprintf( stderr, "flex usage statistics:\n" );
X	fprintf( stderr, "  started at %s, finished at %s\n",
X		 starttime, endtime );
X
X	fprintf( stderr, "  %d/%d NFA states\n", lastnfa, current_mns );
X	fprintf( stderr, "  %d/%d DFA states (%d words)\n", lastdfa,
X			 current_max_dfas, totnst );
X	fprintf( stderr, "  %d rules\n", accnum );
X	fprintf( stderr, "  %d/%d start conditions\n", lastsc,
X			 current_max_scs );
X	fprintf( stderr, "  %d epsilon states, %d double epsilon states\n",
X		 numeps, eps2 );
X
X	if ( lastccl == 0 )
X	    fprintf( stderr, "  no character classes\n" );
X	else
X	    fprintf( stderr,
X	"  %d/%d character classes needed %d/%d words of storage, %d reused\n",
X		     lastccl, current_maxccls,
X		     cclmap[lastccl] + ccllen[lastccl] - 1,
X		     current_max_ccl_tbl_size, cclreuse );
X
X	fprintf( stderr, "  %d state/nextstate pairs created\n", numsnpairs );
X	fprintf( stderr, "  %d/%d unique/duplicate transitions\n",
X		 numuniq, numdup );
X
X	if ( fulltbl )
X	    {
X	    tblsiz = lastdfa * numecs;
X	    fprintf( stderr, "  %d table entries\n", tblsiz );
X	    }
X
X	else
X	    {
X	    tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
X
X	    fprintf( stderr, "  %d/%d base/def entries created\n",
X		     lastdfa + numtemps, current_max_dfas );
X	    fprintf( stderr, "  %d/%d (peak %d) nxt/chk entries created\n",
X		     tblend, current_max_xpairs, peakpairs );
X	    fprintf( stderr,
X		     "  %d/%d (peak %d) template nxt/chk entries created\n",
X		     numtemps * nummecs, current_max_template_xpairs,
X		     numtemps * numecs );
X	    fprintf( stderr, "  %d empty table entries\n", nummt );
X	    fprintf( stderr, "  %d protos created\n", numprots );
X	    fprintf( stderr, "  %d templates created, %d uses\n",
X		     numtemps, tmpuses );
X	    }
X
X	if ( useecs )
X	    {
X	    tblsiz = tblsiz + CSIZE;
X	    fprintf( stderr, "  %d/%d equivalence classes created\n",
X		     numecs, CSIZE );
X	    }
X
X	if ( usemecs )
X	    {
X	    tblsiz = tblsiz + numecs;
X	    fprintf( stderr, "  %d/%d meta-equivalence classes created\n",
X		     nummecs, CSIZE );
X	    }
X
X	fprintf( stderr, "  %d (%d saved) hash collisions, %d DFAs equal\n",
X		 hshcol, hshsave, dfaeql );
X	fprintf( stderr, "  %d sets of reallocations needed\n", num_reallocs );
X	fprintf( stderr, "  %d total table entries needed\n", tblsiz );
X	}
X
X    exit( status );
X    }
X
X
X/* flexinit - initialize flex
X *
X * synopsis
X *    int argc;
X *    char **argv;
X *    flexinit( argc, argv );
X */
X
flexinit( argc, argv )
int argc;
char **argv;
X
X    {
X    int i, sawcmpflag, use_stdout;
X    char *arg, *skelname = NULL, *gettime(), clower(), *mktemp();
X
X    printstats = syntaxerror = trace = spprdflt = interactive = caseins = false;
X    ddebug = fulltbl = reject = fullspd = false;
X    gen_line_dirs = usemecs = useecs = true;
X
X    sawcmpflag = false;
X    use_stdout = false;
X
X    /* read flags */
X    for ( --argc, ++argv; argc ; --argc, ++argv )
X	{
X	if ( argv[0][0] != '-' || argv[0][1] == '\0' )
X	    break;
X
X	arg = argv[0];
X
X	for ( i = 1; arg[i] != '\0'; ++i )
X	    switch ( arg[i] )
X		{
X		case 'c':
X		    if ( i != 1 )
X			flexerror( "-c flag must be given separately" );
X
X		    if ( ! sawcmpflag )
X			{
X			useecs = false;
X			usemecs = false;
X			fulltbl = false;
X			sawcmpflag = true;
X			}
X
X		    for ( ++i; arg[i] != '\0'; ++i )
X			switch ( clower( arg[i] ) )
X			    {
X			    case 'e':
X				useecs = true;
X				break;
X
X			    case 'F':
X				fullspd = true;
X				break;
X
X			    case 'f':
X				fulltbl = true;
X				break;
X
X			    case 'm':
X				usemecs = true;
X				break;
X
X			    default:
X				lerrif( "unknown -c option %c",
X					(int) arg[i] );
X				break;
X			    }
X		    
X		    goto get_next_arg;
X
X		case 'd':
X		    ddebug = true;
X		    break;
X
X		case 'f':
X		    useecs = usemecs = false;
X		    fulltbl = true;
X		    break;
X
X		case 'I':
X		    interactive = true;
X		    break;
X
X		case 'i':
X		    caseins = true;
X		    break;
X
X		case 'L':
X		    gen_line_dirs = false;
X		    break;
X
X		case 'r':
X		    reject = true;
X		    break;
X
X		case 'F':
X		    useecs = usemecs = false;
X		    fullspd = true;
X		    break;
X
X		case 'S':
X		    if ( i != 1 )
X			flexerror( "-S flag must be given separately" );
X
X		    skelname = arg + i + 1;
X		    goto get_next_arg;
X
X		case 's':
X		    spprdflt = true;
X		    break;
X
X		case 't':
X		    use_stdout = true;
X		    break;
X
X		case 'T':
X		    trace = true;
X		    break;
X
X		case 'v':
X		    printstats = true;
X		    break;
X
X		default:
X		    lerrif( "unknown flag %c", (int) arg[i] );
X		    break;
X		}
X
get_next_arg: /* used by -c and -S flags in lieu of a "continue 2" control */
X	;
X	}
X
X    if ( (fulltbl || fullspd) && usemecs )
X	flexerror( "full table and -cm don't make sense together" );
X
X    if ( (fulltbl || fullspd) && interactive )
X	flexerror( "full table and -I are (currently) incompatible" );
X
X    if ( (fulltbl || fullspd) && reject )
X	flexerror( "reject (-r) cannot be used with -f or -F" );
X
X    if ( fulltbl && fullspd )
X	flexerror( "full table and -F are mutually exclusive" );
X
X    if ( ! skelname )
X	{
X	static char skeleton_name_storage[400];
X
X	skelname = skeleton_name_storage;
X
X	if ( fullspd || fulltbl )
X	    (void) strcpy( skelname, FAST_SKELETON_FILE );
X	else
X	    (void) strcpy( skelname, DEFAULT_SKELETON_FILE );
X	}
X
X    if ( ! use_stdout )
X	{
X	FILE *prev_stdout = freopen( "lex.yy.c", "w", stdout );
X
X	if ( prev_stdout == NULL )
X	    flexerror( "could not create lex.yy.c" );
X	}
X
X    if ( argc )
X	{
X	if ( argc > 1 )
X	    flexerror( "extraneous argument(s) given" );
X
X	yyin = fopen( infilename = argv[0], "r" );
X
X	if ( yyin == NULL )
X	    lerrsf( "can't open %s", argv[0] );
X	}
X
X    else
X	yyin = stdin;
X
X    lastccl = 0;
X    lastsc = 0;
X
X    /* initialize the statistics */
X    starttime = gettime();
X
X    if ( (skelfile = fopen( skelname, "r" )) == NULL )
X	lerrsf( "can't open skeleton file %s", skelname );
X
X    (void) mktemp( action_file_name );
X
X    if ( (temp_action_file = fopen( action_file_name, "w" )) == NULL )
X	lerrsf( "can't open temporary action file %s", action_file_name );
X
X    lastdfa = lastnfa = accnum = numas = numsnpairs = tmpuses = 0;
X    numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
X    numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
X    onesp = numprots = 0;
X
X    linenum = sectnum = 1;
X    firstprot = NIL;
X
X    /* used in mkprot() so that the first proto goes in slot 1
X     * of the proto queue
X     */
X    lastprot = 1;
X
X    if ( useecs )
X	{
X	/* set up doubly-linked equivalence classes */
X	ecgroup[1] = NIL;
X
X	for ( i = 2; i <= CSIZE; ++i )
X	    {
X	    ecgroup[i] = i - 1;
X	    nextecm[i - 1] = i;
X	    }
X
X	nextecm[CSIZE] = NIL;
X	}
X
X    else
X	{ /* put everything in its own equivalence class */
X	for ( i = 1; i <= CSIZE; ++i )
X	    {
X	    ecgroup[i] = i;
X	    nextecm[i] = BAD_SUBSCRIPT;	/* to catch errors */
X	    }
X	}
X
X    set_up_initial_allocations();
X    }
X
X
X/* readin - read in the rules section of the input file(s)
X *
X * synopsis
X *    readin();
X */
X
readin()
X
X    {
X    fputs( "#define YY_DEFAULT_ACTION ", stdout );
X
X    if ( spprdflt )
X	fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )", stdout );
X    else
X	fputs( "ECHO", stdout );
X
X    fputs( ";\n", stdout );
X
X    if ( ddebug )
X	puts( "#define FLEX_DEBUG" );
X    if ( useecs )
X	puts( "#define FLEX_USE_ECS" );
X    if ( usemecs )
X	puts( "#define FLEX_USE_MECS" );
X    if ( interactive )
X	puts( "#define FLEX_INTERACTIVE_SCANNER" );
X    if ( reject )
X	puts( "#define FLEX_REJECT_ENABLED" );
X    if ( fulltbl )
X	puts( "#define FLEX_FULL_TABLE" );
X
X    skelout();
X
X    line_directive_out( stdout );
X
X    if ( yyparse() )
X	lerrif( "fatal parse error at line %d", linenum );
X
X    if ( useecs )
X	{
X	numecs = cre8ecs( nextecm, ecgroup, CSIZE );
X	ccl2ecl();
X	}
X
X    else
X	numecs = CSIZE;
X
X    }
X
X
X
X/* set_up_initial_allocations - allocate memory for internal tables */
X
set_up_initial_allocations()
X
X    {
X    current_mns = INITIAL_MNS;
X    firstst = allocate_integer_array( current_mns );
X    lastst = allocate_integer_array( current_mns );
X    finalst = allocate_integer_array( current_mns );
X    transchar = allocate_integer_array( current_mns );
X    trans1 = allocate_integer_array( current_mns );
X    trans2 = allocate_integer_array( current_mns );
X    accptnum = allocate_integer_array( current_mns );
X
X    current_max_scs = INITIAL_MAX_SCS;
X    scset = allocate_integer_array( current_max_scs );
X    scbol = allocate_integer_array( current_max_scs );
X    scxclu = allocate_integer_array( current_max_scs );
X    actvsc = allocate_integer_array( current_max_scs );
X
X    current_maxccls = INITIAL_MAXCCLS;
X    cclmap = allocate_integer_array( current_maxccls );
X    ccllen = allocate_integer_array( current_maxccls );
X    cclng = allocate_integer_array( current_maxccls );
X
X    current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
X    ccltbl = allocate_character_array( current_max_ccl_tbl_size );
X
X    current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
X
X    current_max_xpairs = INITIAL_MAX_XPAIRS;
X    nxt = allocate_integer_array( current_max_xpairs );
X    chk = allocate_integer_array( current_max_xpairs );
X
X    current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
X    tnxt = allocate_integer_array( current_max_template_xpairs );
X
X    current_max_dfas = INITIAL_MAX_DFAS;
X    base = allocate_integer_array( current_max_dfas );
X    def = allocate_integer_array( current_max_dfas );
X    dfasiz = allocate_integer_array( current_max_dfas );
X    accsiz = allocate_integer_array( current_max_dfas );
X    dhash = allocate_integer_array( current_max_dfas );
X    todo = allocate_integer_array( current_max_dfas );
X    dss = allocate_integer_pointer_array( current_max_dfas );
X    dfaacc = allocate_dfaacc_union( current_max_dfas );
X    }
END_OF_FILE
if test 12885 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'misc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'misc.c'\"
else
echo shar: Extracting \"'misc.c'\" \(9991 characters\)
sed "s/^X//" >'misc.c' <<'END_OF_FILE'
X/* misc - miscellaneous flex routines */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X#include <ctype.h>
X#include "flexdef.h"
X
char *malloc(), *realloc();
X
X
X/* action_out - write the actions from the temporary file to lex.yy.c
X *
X * synopsis
X *     action_out();
X *
X *     Copies the action file up to %% (or end-of-file) to lex.yy.c
X */
X
action_out()
X
X    {
X    char buf[MAXLINE];
X
X    while ( fgets( buf, MAXLINE, temp_action_file ) != NULL )
X	if ( buf[0] == '%' && buf[1] == '%' )
X	    break;
X	else
X	    fputs( buf, stdout );
X    }
X
X
X/* allocate_array - allocate memory for an integer array of the given size */
X
char *allocate_array( size, element_size )
int size, element_size;
X
X    {
X    register char *mem = malloc( (unsigned) (element_size * size) );
X
X    if ( mem == NULL )
X	flexfatal( "memory allocation failed in allocate_array()" );
X
X    return ( mem );
X    }
X
X
X/* bubble - bubble sort an integer array in increasing order
X *
X * synopsis
X *   int v[n], n;
X *   bubble( v, n );
X *
X * description
X *   sorts the first n elements of array v and replaces them in
X *   increasing order.
X *
X * passed
X *   v - the array to be sorted
X *   n - the number of elements of 'v' to be sorted */
X
bubble( v, n )
int v[], n;
X
X    {
X    register int i, j, k;
X
X    for ( i = n; i > 1; --i )
X	for ( j = 1; j < i; ++j )
X	    if ( v[j] > v[j + 1] )	/* compare */
X		{
X		k = v[j];	/* exchange */
X		v[j] = v[j + 1];
X		v[j + 1] = k;
X		}
X    }
X
X
X/* clower - replace upper-case letter to lower-case
X *
X * synopsis:
X *    char clower(), c;
X *    c = clower( c );
X */
X
char clower( c )
register char c;
X
X    {
X    return ( isupper(c) ? tolower(c) : c );
X    }
X
X
X/* copy_string - returns a dynamically allocated copy of a string
X *
X * synopsis
X *    char *str, *copy, *copy_string();
X *    copy = copy_string( str );
X */
X
char *copy_string( str )
register char *str;
X
X    {
X    register char *c;
X    char *copy;
X
X    /* find length */
X    for ( c = str; *c; ++c )
X	;
X
X    copy = malloc( (unsigned) ((c - str + 1) * sizeof( char )) );
X
X    if ( copy == NULL )
X	flexfatal( "dynamic memory failure in copy_string()" );
X
X    for ( c = copy; (*c++ = *str++); )
X	;
X    
X    return ( copy );
X    }
X
X
X/* cshell - shell sort a character array in increasing order
X *
X * synopsis
X *
X *   char v[n];
X *   int n;
X *   cshell( v, n );
X *
X * description
X *   does a shell sort of the first n elements of array v.
X *
X * passed
X *   v - array to be sorted
X *   n - number of elements of v to be sorted
X */
cshell( v, n )
char v[];
int n;
X
X    {
X    int gap, i, j, jg;
X    char k;
X
X    for ( gap = n / 2; gap > 0; gap = gap / 2 )
X	for ( i = gap; i < n; ++i )
X	    for ( j = i - gap; j >= 0; j = j - gap )
X		{
X		jg = j + gap;
X
X		if ( v[j] <= v[jg] )
X		    break;
X
X		k = v[j];
X		v[j] = v[jg];
X		v[jg] = k;
X		}
X    }
X
X
X/* dataend - finish up a block of data declarations
X *
X * synopsis
X *    dataend();
X */
dataend()
X
X    {
X    if ( datapos > 0 )
X	dataflush();
X
X    /* add terminator for initialization */
X    puts( "    } ;\n" );
X
X    dataline = 0;
X    }
X
X
X
X/* dataflush - flush generated data statements
X *
X * synopsis
X *    dataflush();
X */
dataflush()
X
X    {
X    putchar( '\n' );
X
X    if ( ++dataline >= NUMDATALINES )
X	{
X	/* put out a blank line so that the table is grouped into
X	 * large blocks that enable the user to find elements easily
X	 */
X	putchar( '\n' );
X	dataline = 0;
X	}
X
X    /* reset the number of characters written on the current line */
X    datapos = 0;
X    }
X
X/* gettime - return current time
X *
X * synopsis
X *    char *gettime(), *time_str;
X *    time_str = gettime();
X */
X
X/* include sys/types.h to use time_t and make lint happy */
X
X#include <sys/types.h>
X
char *gettime()
X
X    {
X    time_t t, time();
X    char *result, *ctime(), *copy_string();
X
X    t = time( (long *) 0 );
X
X    result = copy_string( ctime( &t ) );
X
X    /* get rid of trailing newline */
X    result[24] = '\0';
X
X    return ( result );
X    }
X
X
X/* lerrif - report an error message formatted with one integer argument
X *
X * synopsis
X *    char msg[];
X *    int arg;
X *    lerrif( msg, arg );
X */
X
lerrif( msg, arg )
char msg[];
int arg;
X
X    {
X    char errmsg[MAXLINE];
X    (void) sprintf( errmsg, msg, arg );
X    flexerror( errmsg );
X    }
X
X
X/* lerrsf - report an error message formatted with one string argument
X *
X * synopsis
X *    char msg[], arg[];
X *    lerrsf( msg, arg );
X */
X
lerrsf( msg, arg )
char msg[], arg[];
X
X    {
X    char errmsg[MAXLINE];
X
X    (void) sprintf( errmsg, msg, arg );
X    flexerror( errmsg );
X    }
X
X
X/* flexerror - report an error message and terminate
X *
X * synopsis
X *    char msg[];
X *    flexerror( msg );
X */
X
flexerror( msg )
char msg[];
X
X    {
X    fprintf( stderr, "flex: %s\n", msg );
X    flexend( 1 );
X    }
X
X
X/* flexfatal - report a fatal error message and terminate
X *
X * synopsis
X *    char msg[];
X *    flexfatal( msg );
X */
X
flexfatal( msg )
char msg[];
X
X    {
X    fprintf( stderr, "flex: fatal internal error %s\n", msg );
X    flexend( 1 );
X    }
X
X
X/* line_directive_out - spit out a "# line" statement */
X
line_directive_out( output_file_name )
XFILE *output_file_name;
X
X    {
X    if ( infilename && gen_line_dirs ) 
X        fprintf( output_file_name, "# line %d \"%s\"\n", linenum, infilename );
X    }
X
X
X/* mk2data - generate a data statement for a two-dimensional array
X *
X * synopsis
X *    int value;
X *    mk2data( value );
X *
X *  generates a data statement initializing the current 2-D array to "value"
X */
mk2data( value )
int value;
X
X    {
X    if ( datapos >= NUMDATAITEMS )
X	{
X	putchar( ',' );
X	dataflush();
X	}
X
X    if ( datapos == 0 )
X	/* indent */
X	fputs( "    ", stdout );
X
X    else
X	putchar( ',' );
X
X    ++datapos;
X
X    printf( "%5d", value );
X    }
X
X
X/* mkdata - generate a data statement
X *
X * synopsis
X *    int value;
X *    mkdata( value );
X *
X *  generates a data statement initializing the current array element to
X *  "value"
X */
mkdata( value )
int value;
X
X    {
X    if ( datapos >= NUMDATAITEMS )
X	{
X	putchar( ',' );
X	dataflush();
X	}
X
X    if ( datapos == 0 )
X	/* indent */
X	fputs( "    ", stdout );
X
X    else
X	putchar( ',' );
X
X    ++datapos;
X
X    printf( "%5d", value );
X    }
X
X
X/* myctoi - return the integer represented by a string of digits
X *
X * synopsis
X *    char array[];
X *    int val, myctoi();
X *    val = myctoi( array );
X *
X */
X
int myctoi( array )
char array[];
X
X    {
X    int val = 0;
X
X    (void) sscanf( array, "%d", &val );
X
X    return ( val );
X    }
X
X
X/* myesc - return character corresponding to escape sequence
X *
X * synopsis
X *    char array[], c, myesc();
X *    c = myesc( array );
X *
X */
X
char myesc( array )
char array[];
X
X    {
X    switch ( array[1] )
X	{
X	case 'n': return ( '\n' );
X	case 't': return ( '\t' );
X	case 'f': return ( '\f' );
X	case 'r': return ( '\r' );
X	case 'b': return ( '\b' );
X
X	case '0':
X	    if ( isdigit(array[2]) )
X		{ /* \0<octal> */
X		char c, esc_char;
X		register int sptr = 2;
X
X		while ( isdigit(array[sptr]) )
X		    /* don't increment inside loop control because the
X		     * macro will expand it to two increments!  (Not a
X		     * problem with the C version of the macro)
X		     */
X		    ++sptr;
X
X		c = array[sptr];
X		array[sptr] = '\0';
X
X		esc_char = otoi( array + 2 );
X		array[sptr] = c;
X
X		if ( esc_char == '\0' )
X		    {
X		    synerr( "escape sequence for null not allowed" );
X		    return ( 1 );
X		    }
X
X		return ( esc_char );
X		}
X
X	    else
X		{
X		synerr( "escape sequence for null not allowed" );
X		return ( 1 );
X		}
X
X#ifdef NOTDEF
X	case '^':
X	    {
X	    register char next_char = array[2];
X
X	    if ( next_char == '?' )
X		return ( 0x7f );
X	    
X	    else if ( next_char >= 'A' && next_char <= 'Z' )
X		return ( next_char - 'A' + 1 );
X    
X	    else if ( next_char >= 'a' && next_char <= 'z' )
X		return ( next_char - 'z' + 1 );
X    
X	    synerr( "illegal \\^ escape sequence" );
X
X	    return ( 1 );
X	    }
X#endif
X	}
X    
X    return ( array[1] );
X    }
X
X
X/* otoi - convert an octal digit string to an integer value
X *
X * synopsis:
X *    int val, otoi();
X *    char str[];
X *    val = otoi( str );
X */
X
int otoi( str )
char str[];
X
X    {
X#ifdef FTLSOURCE
X    fortran int gctoi()
X    int dummy = 1;
X
X    return ( gctoi( str, dummy, 8 ) );
X#else
X    int result;
X
X    (void) sscanf( str, "%o", &result );
X
X    return ( result );
X#endif
X    }
X
X
X
X
X/* reallocate_array - increase the size of a dynamic array */
X
char *reallocate_array( array, size, element_size )
char *array;
int size, element_size;
X
X    {
X    register char *new_array = realloc( array,
X					(unsigned) (size * element_size ));
X
X    if ( new_array == NULL )
X	flexfatal( "attempt to increase array size failed" );
X    
X    return ( new_array );
X    }
X
X
X/* skelout - write out one section of the skeleton file
X *
X * synopsis
X *    skelout();
X *
X * DESCRIPTION
X *    Copies from skelfile to stdout until a line beginning with "%%" or
X *    EOF is found.
X */
skelout()
X
X    {
X    char buf[MAXLINE];
X
X    while ( fgets( buf, MAXLINE, skelfile ) != NULL )
X	if ( buf[0] == '%' && buf[1] == '%' )
X	    break;
X	else
X	    fputs( buf, stdout );
X    }
X
X
X/* transition_struct_out - output a yy_trans_info structure
X *
X * synopsis
X *     int element_v, element_n;
X *     transition_struct_out( element_v, element_n );
X *
X * outputs the yy_trans_info structure with the two elements, element_v and
X * element_n.  Formats the output with spaces and carriage returns.
X */
X
transition_struct_out( element_v, element_n )
int element_v, element_n;
X
X    {
X    printf( "%7d, %5d,", element_v, element_n );
X
X    datapos += TRANS_STRUCT_PRINT_LENGTH;
X
X    if ( datapos >= 75 )
X	{
X	printf( "\n" );
X
X	if ( ++dataline % 10 == 0 )
X	    printf( "\n" );
X
X	datapos = 0;
X	}
X    }
END_OF_FILE
if test 9991 -ne `wc -c <'misc.c'`; then
    echo shar: \"'misc.c'\" unpacked with wrong size!
fi
# end of 'misc.c'
fi
if test -f 'scan.l' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'scan.l'\"
else
echo shar: Extracting \"'scan.l'\" \(9189 characters\)
sed "s/^X//" >'scan.l' <<'END_OF_FILE'
X/* scan.l - scanner for flex input */
X
X/*
X * Copyright (c) 1987, the University of California
X * 
X * The United States Government has rights in this work pursuant to
X * contract no. DE-AC03-76SF00098 between the United States Department of
X * Energy and the University of California.
X * 
X * This program may be redistributed.  Enhancements and derivative works
X * may be created provided the new works, if made available to the general
X * public, are made available for use by anyone.
X */
X
X%{
X#include "flexdef.h"
X#include "parse.h"
X
X#define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
X#define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
X
X#undef YY_DECL
X#define YY_DECL \
X	int flexscan()
X
X#define RETURNCHAR \
X	yylval = yytext[0]; \
X	return ( CHAR );
X
X#define RETURNNAME \
X	(void) strcpy( nmstr, yytext ); \
X	return ( NAME );
X
X#define PUT_BACK_STRING(str, start) \
X	for ( i = strlen( str ) - 1; i >= start; --i ) \
X	    unput(str[i])
X%}
X
X%x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE
X%x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT C_COMMENT_2 ACTION_COMMENT
X%x ACTION_STRING PERCENT_BRACE_ACTION
X
WS		[ \t]+
X
OPTWS		[ \t]*
X
NAME		[a-z_][a-z_0-9]*
X
SCNAME		{NAME}
X
ESCSEQ		\\([^^\n]|"^".|0[0-9]{1,3})
X
X%%
X    static int bracelevel, didadef;
X    int i, cclval;
X    char nmdef[MAXLINE], myesc();
X
X^{WS}.*\n		++linenum; ECHO; /* indented code */
X^#.*\n			++linenum; ECHO; /* treat as a comment */
X^"/*"			ECHO; BEGIN(C_COMMENT);
X^"%s"(tart)?		return ( SCDECL );
X^"%x"			return ( XSCDECL );
X^"%{".*\n		++linenum; line_directive_out( stdout ); BEGIN(CODEBLOCK);
X{WS}			return ( WHITESPACE );
X
X^"%%".*			{
X			sectnum = 2;
X			line_directive_out( stdout );
X			BEGIN(SECT2PROLOG);
X			return ( SECTEND );
X			}
X
X^"%"[^sx{%].*\n		{
X			fprintf( stderr,
X			     "old-style lex command at line %d ignored:\n\t%s",
X				 linenum, yytext );
X			++linenum;
X			}
X
X^{NAME}			{
X			(void) strcpy( nmstr, yytext );
X			didadef = false;
X			BEGIN(PICKUPDEF);
X			}
X
X{SCNAME}		RETURNNAME;
X^{OPTWS}\n		++linenum; /* allows blank lines in section 1 */
X\n			++linenum; return ( '\n' );
X.			synerr( "illegal character" ); BEGIN(RECOVER);
X
X
X<C_COMMENT>"*/"		ECHO; BEGIN(0);
X<C_COMMENT>"*/".*\n	++linenum; ECHO; BEGIN(0);
X<C_COMMENT>[^*\n]+	ECHO;
X<C_COMMENT>"*"		ECHO;
X<C_COMMENT>\n		++linenum; ECHO;
X
X<CODEBLOCK>^"%}".*\n	++linenum; BEGIN(0);
X<CODEBLOCK>.*\n		++linenum; ECHO;
X
X<PICKUPDEF>{WS}		/* separates name and definition */
X
X<PICKUPDEF>[^ \t\n].*	{
X			(void) strcpy( nmdef, yytext );
X
X			for ( i = strlen( nmdef ) - 1;
X			      i >= 0 &&
X			      nmdef[i] == ' ' || nmdef[i] == '\t';
X			      --i )
X			    ;
X
X			nmdef[i + 1] = '\0';
X
X                        ndinstal( nmstr, nmdef );
X			didadef = true;
X			}
X
X<PICKUPDEF>\n		{
X			if ( ! didadef )
X			    synerr( "incomplete name definition" );
X			BEGIN(0);
X			++linenum;
X			}
X
X<RECOVER>.*\n		++linenum; BEGIN(0); RETURNNAME;
X
X
X<SECT2PROLOG>.*\n/[^ \t\n]	{
X			++linenum;
X			ACTION_ECHO;
X			MARK_END_OF_PROLOG;
X			BEGIN(SECT2);
X			}
X
X<SECT2PROLOG>.*\n	++linenum; ACTION_ECHO;
X
X<SECT2>^{OPTWS}\n	++linenum; /* allow blank lines in section 2 */
X
X	/* this horrible mess of a rule matches indented lines which
X	 * do not contain "/*".  We need to make the distinction because
X	 * otherwise this rule will be taken instead of the rule which
X	 * matches the beginning of comments like this one
X	 */
X<SECT2>^{WS}([^/\n]|"/"[^*\n])*("/"?)\n	{
X			synerr( "indented code found outside of action" );
X			++linenum;
X			}
X
X<SECT2>"<"		BEGIN(SC); return ( '<' );
X<SECT2>^"^"		return ( '^' );
X<SECT2>\"		BEGIN(QUOTE); return ( '"' );
X<SECT2>"{"/[0-9]		BEGIN(NUM); return ( '{' );
X<SECT2>"{"[^0-9\n][^}\n]*	BEGIN(BRACEERROR);
X<SECT2>"$"/[ \t\n]	return ( '$' );
X
X<SECT2>{WS}"%{"		{
X			bracelevel = 1;
X			BEGIN(PERCENT_BRACE_ACTION);
X			return ( '\n' );
X			}
X<SECT2>{WS}"|".*\n	++linenum; return ( '\n' );
X
X<SECT2>^{OPTWS}"/*"	ACTION_ECHO; BEGIN(C_COMMENT_2);
X
X<SECT2>{WS}		{ /* needs to be separate from following rule due to
X			   * bug with trailing context
X			   */
X			bracelevel = 0;
X			BEGIN(ACTION);
X			return ( '\n' );
X			}
X
X<SECT2>{OPTWS}/\n	{
X			bracelevel = 0;
X			BEGIN(ACTION);
X			return ( '\n' );
X			}
X
X<SECT2>^{OPTWS}\n	++linenum; return ( '\n' );
X
X<SECT2>^"%%".*		{
X			/* guarantee that the SECT3 rule will have something
X			 * to match
X			 */
X			yyless(1);
X			sectnum = 3;
X			BEGIN(SECT3);
X			return ( EOF ); /* to stop the parser */
X			}
X
X<SECT2>"["([^\\\]\n]|{ESCSEQ})+"]"	{
X			(void) strcpy( nmstr, yytext );
X
X			/* check to see if we've already encountered this ccl */
X			if ( (cclval = ccllookup( nmstr )) )
X			    {
X			    yylval = cclval;
X			    ++cclreuse;
X			    return ( PREVCCL );
X			    }
X			else
X			    {
X			    /* we fudge a bit.  We know that this ccl will
X			     * soon be numbered as lastccl + 1 by cclinit
X			     */
X			    cclinstal( nmstr, lastccl + 1 );
X
X			    /* push back everything but the leading bracket
X			     * so the ccl can be rescanned
X			     */
X			    PUT_BACK_STRING(nmstr, 1);
X
X			    BEGIN(FIRSTCCL);
X			    return ( '[' );
X			    }
X			}
X
X<SECT2>"{"{NAME}"}"	{
X			register char *nmdefptr;
X			char *ndlookup();
X
X			(void) strcpy( nmstr, yytext );
X			nmstr[yyleng - 1] = '\0';  /* chop trailing brace */
X
X			/* lookup from "nmstr + 1" to chop leading brace */
X			if ( ! (nmdefptr = ndlookup( nmstr + 1 )) )
X			    synerr( "undefined {name}" );
X
X			else
X			    { /* push back name surrounded by ()'s */
X			    unput(')');
X			    PUT_BACK_STRING(nmdefptr, 0);
X			    unput('(');
X			    }
X			}
X
X<SECT2>[/|*+?.()]	return ( yytext[0] );
X<SECT2>.		RETURNCHAR;
X<SECT2>\n		++linenum; return ( '\n' );
X
X
X<SC>","			return ( ',' );
X<SC>">"			BEGIN(SECT2); return ( '>' );
X<SC>">"/"^"		BEGIN(CARETISBOL); return ( '>' );
X<SC>{SCNAME}		RETURNNAME;
X<SC>.			synerr( "bad start condition name" );
X
X<CARETISBOL>"^"		BEGIN(SECT2); return ( '^' );
X
X
X<QUOTE>[^"\n]		RETURNCHAR;
X<QUOTE>\"		BEGIN(SECT2); return ( '"' );
X
X<QUOTE>\n		{
X			synerr( "missing quote" );
X			BEGIN(SECT2);
X			++linenum;
X			return ( '"' );
X			}
X
X
X<FIRSTCCL>"^"/[^-\n]	BEGIN(CCL); return ( '^' );
X<FIRSTCCL>"^"/-		return ( '^' );
X<FIRSTCCL>-		BEGIN(CCL); yylval = '-'; return ( CHAR );
X<FIRSTCCL>.		BEGIN(CCL); RETURNCHAR;
X
X<CCL>-/[^\]\n]		return ( '-' );
X<CCL>[^\]\n]		RETURNCHAR;
X<CCL>"]"			BEGIN(SECT2); return ( ']' );
X
X
X<NUM>[0-9]+		{
X			yylval = myctoi( yytext );
X			return ( NUMBER );
X			}
X
X<NUM>","			return ( ',' );
X<NUM>"}"			BEGIN(SECT2); return ( '}' );
X
X<NUM>.			{
X			synerr( "bad character inside {}'s" );
X			BEGIN(SECT2);
X			return ( '}' );
X			}
X
X<NUM>\n			{
X			synerr( "missing }" );
X			BEGIN(SECT2);
X			++linenum;
X			return ( '}' );
X			}
X
X
X<BRACEERROR>"}"		synerr( "bad name in {}'s" ); BEGIN(SECT2);
X<BRACEERROR>\n		synerr( "missing }" ); ++linenum; BEGIN(SECT2);
X
X
X<PERCENT_BRACE_ACTION>{OPTWS}"%}".*	bracelevel = 0;
X<PERCENT_BRACE_ACTION>.*		ACTION_ECHO;
X<PERCENT_BRACE_ACTION>\n		{
X			++linenum;
X			ACTION_ECHO;
X			if ( bracelevel == 0 )
X			    {
X			    fputs( "\tYY_BREAK\n", temp_action_file );
X			    BEGIN(SECT2);
X			    }
X			}
X
X<ACTION>"{"		ACTION_ECHO; ++bracelevel;
X<ACTION>"}"		ACTION_ECHO; --bracelevel;
X<ACTION>[^{}"'/\n]+	ACTION_ECHO;
X<ACTION>"/*"		ACTION_ECHO; BEGIN(ACTION_COMMENT);
X<ACTION>"'"([^'\\\n]|\\.)*"'"	ACTION_ECHO; /* character constant */
X<ACTION>\"		ACTION_ECHO; BEGIN(ACTION_STRING);
X<ACTION>\n		{
X			++linenum;
X			ACTION_ECHO;
X			if ( bracelevel == 0 )
X			    {
X			    fputs( "\tYY_BREAK\n", temp_action_file );
X			    BEGIN(SECT2);
X			    }
X			}
X<ACTION>.		ACTION_ECHO;
X
X<ACTION_COMMENT>"*/"	ACTION_ECHO; BEGIN(ACTION);
X<ACTION_COMMENT>[^*\n]+	ACTION_ECHO;
X<ACTION_COMMENT>"*"	ACTION_ECHO;
X<ACTION_COMMENT>\n	++linenum; ACTION_ECHO;
X<ACTION_COMMENT>.	ACTION_ECHO;
X
X<C_COMMENT_2>"*/"	ACTION_ECHO; BEGIN(SECT2);
X<C_COMMENT_2>"*/".*\n	++linenum; ACTION_ECHO; BEGIN(SECT2);
X<C_COMMENT_2>[^*\n]+	ACTION_ECHO;
X<C_COMMENT_2>"*"	ACTION_ECHO;
X<C_COMMENT_2>\n		++linenum; ACTION_ECHO;
X
X<ACTION_STRING>[^"\\\n]+	ACTION_ECHO;
X<ACTION_STRING>\\.	ACTION_ECHO;
X<ACTION_STRING>\n	++linenum; ACTION_ECHO;
X<ACTION_STRING>\"	ACTION_ECHO; BEGIN(ACTION);
X<ACTION_STRING>.	ACTION_ECHO;
X
X
X<SECT2,QUOTE,CCL>{ESCSEQ}	{
X			yylval = myesc( yytext );
X			return ( CHAR );
X			}
X
X<FIRSTCCL>{ESCSEQ}	{
X			yylval = myesc( yytext );
X			BEGIN(CCL);
X			return ( CHAR );
X			}
X
X
X<SECT3>.|\n		{
X			register int numchars;
X
X			/* black magic - we know the names of a flex scanner's
X			 * internal variables.  We cap the input buffer with
X			 * an end-of-string and dump it to the output.
X			 */
X			YY_DO_BEFORE_SCAN; /* recover from setting up yytext */
X
X#ifdef FLEX_FAST_SKEL
X			fputs( yy_c_buf_p + 1, stdout );
X#else
X			yy_ch_buf[yy_e_buf_p + 1] = '\0';
X
X			/* ignore the first character; it's the second '%'
X			 * put back by the yyless(1) above
X			 */
X			fputs( yy_ch_buf + yy_c_buf_p + 1, stdout );
X#endif
X
X			/* if we don't do this, the data written by write()
X			 * can get overwritten when stdout is finally flushed
X			 */
X			(void) fflush( stdout );
X
X			while ( (numchars = read( fileno(yyin), yy_ch_buf,
X						  YY_BUF_MAX )) > 0 )
X			    (void) write( fileno(stdout), yy_ch_buf, numchars );
X	
X			if ( numchars < 0 )
X			    flexerror( "fatal read error in section 3" );
X
X			return ( EOF );
X			}
X%%
END_OF_FILE
if test 9189 -ne `wc -c <'scan.l'`; then
    echo shar: \"'scan.l'\" unpacked with wrong size!
fi
# end of 'scan.l'
fi
echo shar: End of archive 2 \(of 5\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.