From earleh@eleazar.dartmouth.edu Thu Jun 30 12:00:25 1988 Path: utastro!ut-sally!cs.utexas.edu!tut.cis.ohio-state.edu!mailrus!ames!pasteur!ucbvax!hplabs!felix!dhw68k!macintosh From: earleh@eleazar.dartmouth.edu (Earle R. Horton) 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) [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 '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 ---