Article View: comp.sources.mac
Article #59Flex for the Mac (part 3 of 7)
From: macintosh
Date: Thu, 30 Jun 1988 17:00
Date: Thu, 30 Jun 1988 17:00
1503 lines
39248 bytes
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!macintoshReferences:
<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)