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