🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.sources.mac
Article #59

Flex for the Mac (part 3 of 7)

#59
From: macintosh
Date: Thu, 30 Jun 1988 17:00
1503 lines
39248 bytes
[Flex for the Mac - part 3 of 7]

---
#! /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:
#	flex/alloca.a
#	flex/bzero.c
#	flex/ccl.c
#	flex/dfa.c
#	flex/ecs.c
#	flex/main.c
# This archive created: Wed Jun 29 07:03:15 1988
# By:	Roger L. Long (bytebug@dhw68k.cts.com)
export PATH; PATH=/bin:$PATH
echo shar: extracting "'alloca.a'" '(646 characters)'
if test -f 'alloca.a'
then
	echo shar: will not over-write existing file "'alloca.a'"
else
sed 's/^X//' << \SHAR_EOF > 'alloca.a'
X;;
X;; Alloca() for Macintosh Programmer's Workshop C.
X;; alloca(n) allocates n bytes of storage in the stack
X;; frame of the caller.
X;;
X	CASE ON
X	
Xalloca PROC EXPORT
X        move.l  (sp)+,a0        ; pop return address
X        move.l  (sp)+,d0        ; pop parameter = size in bytes
X        add.l   #3,d0       	; round size up to long word
X        and.l   #-4,d0        	; mask out lower two bits of size
X        sub.l   d0,sp           ; allocate by moving stack pointer
X        move.l  sp,d0           ; return pointer
X        add.l   #-4,sp          ; new top of stack
X        jmp     (a0)            ; return to caller
X        ENDP
X		END
X		
SHAR_EOF
if test 646 -ne "`wc -c < 'alloca.a'`"
then
	echo shar: error transmitting "'alloca.a'" '(should have been 646 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bzero.c'" '(84 characters)'
if test -f 'bzero.c'
then
	echo shar: will not over-write existing file "'bzero.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bzero.c'
Xbzero(x,size)
Xchar *x;
Xint size;
X{
X int i;
X for(i=0;i<size;i++){
X  *(x+i) = 0;
X }
X}
SHAR_EOF
if test 84 -ne "`wc -c < 'bzero.c'`"
then
	echo shar: error transmitting "'bzero.c'" '(should have been 84 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ccl.c'" '(2257 characters)'
if test -f 'ccl.c'
then
	echo shar: will not over-write existing file "'ccl.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ccl.c'
X/* ccl - routines for character classes */
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/* ccladd - add a single character to a ccl
X *
X * synopsis
X *    int cclp;
X *    char ch;
X *    ccladd( cclp, ch );
X */
X
Xccladd( cclp, ch )
Xint cclp;
Xchar ch;
X
X    {
X    int ind, len, newpos, i;
X
X    len = ccllen[cclp];
X    ind = cclmap[cclp];
X
X    /* check to see if the character is already in the ccl */
X
X    for ( i = 0; i < len; ++i )
X	if ( ccltbl[ind + i] == ch )
X	    return;
X
X    newpos = ind + len;
X
X    if ( newpos >= current_max_ccl_tbl_size )
X	{
X	current_max_ccl_tbl_size += MAX_CCL_TBL_SIZE_INCREMENT;
X
X	++num_reallocs;
X
X	ccltbl = reallocate_character_array( ccltbl, current_max_ccl_tbl_size );
X	}
X
X    ccllen[cclp] = len + 1;
X    ccltbl[newpos] = ch;
X    }
X
X
X/* cclinit - make an empty ccl
X *
X * synopsis
X *    int cclinit();
X *    new_ccl = cclinit();
X */
X
Xint cclinit()
X
X    {
X    if ( ++lastccl >= current_maxccls )
X	{
X	current_maxccls += MAXCCLS_INCREMENT;
X
X	++num_reallocs;
X
X	cclmap = reallocate_integer_array( cclmap, current_maxccls );
X	ccllen = reallocate_integer_array( ccllen, current_maxccls );
X	cclng = reallocate_integer_array( cclng, current_maxccls );
X	}
X
X    if ( lastccl == 1 )
X	/* we're making the first ccl */
X	cclmap[lastccl] = 0;
X
X    else
X	/* the new pointer is just past the end of the last ccl.  Since
X	 * the cclmap points to the \first/ character of a ccl, adding the
X	 * length of the ccl to the cclmap pointer will produce a cursor
X	 * to the first free space
X	 */
X	cclmap[lastccl] = cclmap[lastccl - 1] + ccllen[lastccl - 1];
X
X    ccllen[lastccl] = 0;
X    cclng[lastccl] = 0;	/* ccl's start out life un-negated */
X
X    return ( lastccl );
X    }
X
X
X/* cclnegate - negate a ccl
X *
X * synopsis
X *    int cclp;
X *    cclnegate( ccl );
X */
X
Xcclnegate( cclp )
Xint cclp;
X
X    {
X    cclng[cclp] = 1;
X    }
SHAR_EOF
if test 2257 -ne "`wc -c < 'ccl.c'`"
then
	echo shar: error transmitting "'ccl.c'" '(should have been 2257 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'dfa.c'" '(10776 characters)'
if test -f 'dfa.c'
then
	echo shar: will not over-write existing file "'dfa.c'"
else
sed 's/^X//' << \SHAR_EOF > 'dfa.c'
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
Xint *epsclosure( t, ns_addr, accset, nacc_addr, hv_addr )
Xint *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
Xincrease_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
Xint snstods( sns, numstates, accset, nacc, hashval, newds_addr )
Xint 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
Xint symfollowset( ds, dsize, transsym, nset )
Xint 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] & BYTEMASK;
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] & BYTEMASK;
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
Xbottom:
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
Xsympartition( ds, numstates, symlist, duplist )
Xint ds[], numstates, duplist[];
Xint 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] & BYTEMASK;
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] & BYTEMASK;
X			symlist[ich] = 1;
X			}
X		}
X	    }
X	}
X    }
SHAR_EOF
if test 10776 -ne "`wc -c < 'dfa.c'`"
then
	echo shar: error transmitting "'dfa.c'" '(should have been 10776 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'ecs.c'" '(5206 characters)'
if test -f 'ecs.c'
then
	echo shar: will not over-write existing file "'ecs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'ecs.c'
X/* ecs - equivalence class 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/* ccl2ecl - convert character classes to set of equivalence classes
X *
X * synopsis
X *    ccl2ecl();
X */
X
Xccl2ecl()
X
X    {
X    int i, ich, newlen, cclp, ccls, cclmec;
X
X    for ( i = 1; i <= lastccl; ++i )
X	{
X	/* we loop through each character class, and for each character
X	 * in the class, add the character's equivalence class to the
X	 * new "character" class we are creating.  Thus when we are all
X	 * done, character classes will really consist of collections
X	 * of equivalence classes
X	 */
X
X	newlen = 0;
X	cclp = cclmap[i];
X
X	for ( ccls = 0; ccls < ccllen[i]; ++ccls )
X	    {
X	    ich = ccltbl[cclp + ccls] & BYTEMASK;
X	    cclmec = ecgroup[ich];
X	    if ( cclmec > 0 )
X		{
X		ccltbl[cclp + newlen] = cclmec;
X		++newlen;
X		}
X	    }
X
X	ccllen[i] = newlen;
X	}
X    }
X
X
X/* cre8ecs - associate equivalence class numbers with class members
X *
X * synopsis
X *    int cre8ecs();
X *    number of classes = cre8ecs( fwd, bck, num );
X *
X *  fwd is the forward linked-list of equivalence class members.  bck
X *  is the backward linked-list, and num is the number of class members.
X *  Returned is the number of classes.
X */
X
Xint cre8ecs( fwd, bck, num )
Xint fwd[], bck[], num;
X
X    {
X    int i, j, numcl;
X
X    numcl = 0;
X
X    /* create equivalence class numbers.  From now on, abs( bck(x) )
X     * is the equivalence class number for object x.  If bck(x)
X     * is positive, then x is the representative of its equivalence
X     * class.
X     */
X
X    for ( i = 1; i <= num; ++i )
X	if ( bck[i] == NIL )
X	    {
X	    bck[i] = ++numcl;
X	    for ( j = fwd[i]; j != NIL; j = fwd[j] )
X		bck[j] = -numcl;
X	    }
X
X    return ( numcl );
X    }
X
X
X/* mkeccl - update equivalence classes based on character class xtions
X *
X * synopsis
X *    char ccls[];
X *    int lenccl, fwd[llsiz], bck[llsiz], llsiz;
X *    mkeccl( ccls, lenccl, fwd, bck, llsiz );
X *
X * where ccls contains the elements of the character class, lenccl is the
X * number of elements in the ccl, fwd is the forward link-list of equivalent
X * characters, bck is the backward link-list, and llsiz size of the link-list
X *
X * Modified by Earle R. Horton, May, 1988 to allow for the possibility that
X * negative characters may be valid in the character set of the compiler.
X */
X
Xmkeccl( ccls, lenccl, fwd, bck, llsiz )
Xchar ccls[];
Xint lenccl, fwd[], bck[], llsiz;
X
X    {
X    int cclp, oldec, newec;
X    int cclm, i, j;
X	short *tmpccl;
X	
X	/* [ERH] Read chars into a short array on the stack. */
X	tmpccl = (short *)alloca(current_max_ccl_tbl_size * sizeof(short));
X	for (i=0; i < current_max_ccl_tbl_size; i++)
X		tmpccl[i] = ccls[i] & BYTEMASK;
X
X    /* note that it doesn't matter whether or not the character class is
X     * negated.  The same results will be obtained in either case.
X     */
X
X    cclp = 0;
X
X    while ( cclp < lenccl )
X	{
X	cclm = tmpccl[cclp];
X	oldec = bck[cclm];
X	newec = cclm;
X
X	j = cclp + 1;
X
X	for ( i = fwd[cclm]; i != NIL && i <= llsiz; i = fwd[i] )
X	    { /* look for the symbol in the character class */
X	    for ( ; j < lenccl && tmpccl[j] <= i; ++j )
X		if ( tmpccl[j] == i )
X		    {
X		    /* we found an old companion of cclm in the ccl.
X		     * link it into the new equivalence class and flag it as
X		     * having been processed
X		     */
X
X		    bck[i] = newec;
X		    fwd[newec] = i;
X		    newec = i;
X		    tmpccl[j] = -i;	/* set flag so we don't reprocess */
X			/*
X			 * [ERH]  This trick will not work if negative characters are
X			 * valid.  E.g. DEC multi-nationals, Macintosh option-characters.
X			 */
X
X		    /* get next equivalence class member */
X		    /* next 2 */ goto next_pt;
X		    }
X
X	    /* symbol isn't in character class.  Put it in the old equivalence
X	     * class
X	     */
X
X	    bck[i] = oldec;
X
X	    if ( oldec != NIL )
X		fwd[oldec] = i;
X
X	    oldec = i;
Xnext_pt:
X	    ;
X	    }
X
X	if ( bck[cclm] != NIL || oldec != bck[cclm] )
X	    {
X	    bck[cclm] = NIL;
X	    fwd[oldec] = NIL;
X	    }
X
X	fwd[newec] = NIL;
X
X	/* find next ccl member to process */
X
X	for ( ++cclp; tmpccl[cclp] < 0 && cclp < lenccl; ++cclp )
X	    {
X	    /* reset "doesn't need processing" flag */
X	    tmpccl[cclp] = -tmpccl[cclp];
X	    }
X	}
X	/* [ERH] Feed shorts back into chars. */
X	for (i=0; i < current_max_ccl_tbl_size; i++)
X		ccls[i] = tmpccl[i];
X    }
X
X
X/* mkechar - create equivalence class for single character
X *
X * synopsis
X *    int tch, fwd[], bck[];
X *    mkechar( tch, fwd, bck );
X */
X
Xmkechar( tch, fwd, bck )
Xint tch, fwd[], bck[];
X
X    {
X    /* if until now the character has been a proper subset of
X     * an equivalence class, break it away to create a new ec
X     */
X
X    if ( fwd[tch] != NIL )
X	bck[fwd[tch]] = bck[tch];
X
X    if ( bck[tch] != NIL )
X	fwd[bck[tch]] = fwd[tch];
X
X    fwd[tch] = NIL;
X    bck[tch] = NIL;
X    }
SHAR_EOF
if test 5206 -ne "`wc -c < 'ecs.c'`"
then
	echo shar: error transmitting "'ecs.c'" '(should have been 5206 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'main.c'" '(14297 characters)'
if test -f 'main.c'
then
	echo shar: will not over-write existing file "'main.c'"
else
sed 's/^X//' << \SHAR_EOF > 'main.c'
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 */
Xint printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
Xint interactive, caseins, useecs, fulltbl, usemecs, reject;
Xint fullspd, gen_line_dirs;
Xint datapos, dataline, linenum;
XFILE *skelfile = NULL;
Xchar *infilename = NULL;
X#ifdef MALLOC_BUFFERS
Xint *onestate,*onesym,*onenext,*onedef,onesp;
X#else
Xint onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
Xint onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
X#endif
Xint current_mns;
Xint accnum, *firstst, *lastst, *finalst, *transchar;
Xint *trans1, *trans2, *accptnum, lastnfa;
X#ifdef MALLOC_BUFFERS
Xint numtemps, numprots, *protprev, *protnext, *prottbl;
Xint *protcomst, firstprot, lastprot,
X#else
Xint numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
Xint protcomst[MSP], firstprot, lastprot,
X#endif
X#ifdef MALLOC_BUFFERS
X	*protsave;
X#else
X	protsave[PROT_SAVE_SIZE];
X#endif
X#ifdef MALLOC_BUFFERS
Xint numecs, *nextecm, *ecgroup, nummecs;
Xint *tecfwd, *tecbck;
X#else
Xint numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs;
Xint tecfwd[CSIZE + 1], tecbck[CSIZE + 1];
X#endif
Xint lastsc, current_max_scs, *scset, *scbol, *scxclu, *actvsc;
Xint current_max_dfa_size, current_max_xpairs;
Xint current_max_template_xpairs, current_max_dfas;
Xint lastdfa, *nxt, *chk, *tnxt;
Xint *base, *def, tblend, firstfree, numtemps, **dss, *dfasiz;
Xunion dfaacc_union *dfaacc;
Xint *accsiz, *dhash, *todo, todo_head, todo_next, numas;
Xint numsnpairs, jambase, jamstate;
Xint lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse;
Xint current_max_ccl_tbl_size;
Xchar *ccltbl;
Xchar *starttime, *endtime, nmstr[MAXLINE];
Xint sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
Xint tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
XFILE *temp_action_file;
Xint end_of_buffer_state;
Xchar *action_file_name = "/tmp/flexXXXXXX";
X
X
X/* flex - main program
X *
X * synopsis (from the shell)
X *    flex [-v] [file ...]
X */
X
Xmain( argc, argv )
Xint argc;
Xchar **argv;
X
X    {
X#ifdef MALLOC_BUFFERS
X#define GETBUF(a,b) a = (int *)(malloc((b)*sizeof(int)))
X	GETBUF(onestate,ONE_STACK_SIZE);
X	GETBUF(onesym,ONE_STACK_SIZE);
X	GETBUF(onenext,ONE_STACK_SIZE);
X	GETBUF(onedef,ONE_STACK_SIZE);
X	GETBUF(protprev,MSP);
X	GETBUF(protnext,MSP);
X	GETBUF(prottbl,MSP);
X	GETBUF(protcomst,MSP);
X	GETBUF(protsave,PROT_SAVE_SIZE);
X	GETBUF(nextecm,CSIZE + 1);
X	GETBUF(ecgroup,CSIZE + 1);
X	GETBUF(tecfwd,CSIZE + 1);
X	GETBUF(tecbck,CSIZE + 1);
X	if(onestate == NULL || onesym == NULL || onenext == NULL || onedef
X		== NULL || protprev == NULL || protnext  == NULL || prottbl  == NULL || 
X		protcomst == NULL || protsave == NULL || nextecm  == NULL || ecgroup 
X		== NULL || tecfwd == NULL || tecbck == NULL){
X		fprintf(stderr,"%s: Out of memory\n",argv[0]);
X		exit(-1);
X	}
X#endif
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
Xflexend( status )
Xint 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
Xflexinit( argc, argv )
Xint argc;
Xchar **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
Xget_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#ifndef MPW			/* Single-user system. */
X    (void) mktemp( action_file_name );
X#endif
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
Xreadin()
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#ifdef MPW		/* See tool interface guidelines in MPW manual. */
X	{
X		char *panicmsg;
X		char *alloca();
X		panicmsg = alloca(128);
X		sprintf(panicmsg,"File %s ; %%d # Fatal parse error.");
X		lerrif(panicmsg,linenum);
X	}
X#else
X	lerrif( "fatal parse error at line %d", linenum );
X#endif
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
Xset_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    }
SHAR_EOF
if test 14297 -ne "`wc -c < 'main.c'`"
then
	echo shar: error transmitting "'main.c'" '(should have been 14297 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
--- end of part 3 ---
Technical Details
Message-ID: <9382@dhw68k.cts.com>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!water!watmath!clyde!bellcore!faline!thumper!ulysses!andante!mit-eddie!bloom-beacon!think!ames!pasteur!ucbvax!hplabs!felix!dhw68k!macintosh
References: <9364@dhw68k.cts.com> <9368@dhw68k.cts.com>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!water!watmath!clyde!bellcore!faline!thumper!ulysses!andante!mit-eddie!bloom-beacon!think!ames!pasteur!ucbvax!hplabs!felix!dhw68k!macintosh
From: macintosh@dhw68k.UUCP
Newsgroups: comp.sources.mac
Subject: Flex for the Mac (part 3 of 7)
Message-ID: <9382@dhw68k.cts.com>
Date: 30 Jun 88 17:00:25 GMT
References: <9364@dhw68k.cts.com> <9368@dhw68k.cts.com>
Sender: macintosh@dhw68k.cts.com
Organization: Dartmouth College, Hanover, NH
Lines: 1503
Approved: bytebug@dhw68k.cts.com (Roger L. Long)