home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / lex / dfa.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-12  |  27.1 KB  |  1,088 lines

  1. /*-
  2.  * Copyright (c) 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Vern Paxson of Lawrence Berkeley Laboratory.
  7.  * 
  8.  * The United States Government has rights in this work pursuant
  9.  * to contract no. DE-AC03-76SF00098 between the United States
  10.  * Department of Energy and the University of California.
  11.  *
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 1. Redistributions of source code must retain the above copyright
  16.  *    notice, this list of conditions and the following disclaimer.
  17.  * 2. Redistributions in binary form must reproduce the above copyright
  18.  *    notice, this list of conditions and the following disclaimer in the
  19.  *    documentation and/or other materials provided with the distribution.
  20.  * 3. All advertising materials mentioning features or use of this software
  21.  *    must display the following acknowledgement:
  22.  *    This product includes software developed by the University of
  23.  *    California, Berkeley and its contributors.
  24.  * 4. Neither the name of the University nor the names of its contributors
  25.  *    may be used to endorse or promote products derived from this software
  26.  *    without specific prior written permission.
  27.  *
  28.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38.  * SUCH DAMAGE.
  39.  */
  40.  
  41. #ifndef lint
  42. static char sccsid[] = "@(#)dfa.c    5.2 (Berkeley) 6/18/90";
  43. #endif /* not lint */
  44.  
  45. /* dfa - DFA construction routines */
  46.  
  47. #include "flexdef.h"
  48.  
  49. /* declare functions that have forward references */
  50.  
  51. void dump_associated_rules PROTO((FILE*, int));
  52. void dump_transitions PROTO((FILE*, int[]));
  53. void sympartition PROTO((int[], int, int[], int[]));
  54. int symfollowset PROTO((int[], int, int, int[]));
  55.  
  56.  
  57. /* check_for_backtracking - check a DFA state for backtracking
  58.  *
  59.  * synopsis
  60.  *     int ds, state[numecs];
  61.  *     check_for_backtracking( ds, state );
  62.  *
  63.  * ds is the number of the state to check and state[] is its out-transitions,
  64.  * indexed by equivalence class, and state_rules[] is the set of rules
  65.  * associated with this state
  66.  */
  67.  
  68. void check_for_backtracking( ds, state )
  69. int ds;
  70. int state[];
  71.  
  72.     {
  73.     if ( (reject && ! dfaacc[ds].dfaacc_set) || ! dfaacc[ds].dfaacc_state )
  74.     { /* state is non-accepting */
  75.     ++num_backtracking;
  76.  
  77.     if ( backtrack_report )
  78.         {
  79.         fprintf( backtrack_file, "State #%d is non-accepting -\n", ds );
  80.  
  81.         /* identify the state */
  82.         dump_associated_rules( backtrack_file, ds );
  83.  
  84.         /* now identify it further using the out- and jam-transitions */
  85.         dump_transitions( backtrack_file, state );
  86.  
  87.         putc( '\n', backtrack_file );
  88.         }
  89.     }
  90.     }
  91.  
  92.  
  93. /* check_trailing_context - check to see if NFA state set constitutes
  94.  *                          "dangerous" trailing context
  95.  *
  96.  * synopsis
  97.  *    int nfa_states[num_states+1], num_states;
  98.  *    int accset[nacc+1], nacc;
  99.  *    check_trailing_context( nfa_states, num_states, accset, nacc );
  100.  *
  101.  * NOTES
  102.  *    Trailing context is "dangerous" if both the head and the trailing
  103.  *  part are of variable size \and/ there's a DFA state which contains
  104.  *  both an accepting state for the head part of the rule and NFA states
  105.  *  which occur after the beginning of the trailing context.
  106.  *  When such a rule is matched, it's impossible to tell if having been
  107.  *  in the DFA state indicates the beginning of the trailing context
  108.  *  or further-along scanning of the pattern.  In these cases, a warning
  109.  *  message is issued.
  110.  *
  111.  *    nfa_states[1 .. num_states] is the list of NFA states in the DFA.
  112.  *    accset[1 .. nacc] is the list of accepting numbers for the DFA state.
  113.  */
  114.  
  115. void check_trailing_context( nfa_states, num_states, accset, nacc )
  116. int *nfa_states, num_states;
  117. int *accset;
  118. register int nacc;
  119.  
  120.     {
  121.     register int i, j;
  122.  
  123.     for ( i = 1; i <= num_states; ++i )
  124.     {
  125.     int ns = nfa_states[i];
  126.     register int type = state_type[ns];
  127.     register int ar = assoc_rule[ns];
  128.  
  129.     if ( type == STATE_NORMAL || rule_type[ar] != RULE_VARIABLE )
  130.         { /* do nothing */
  131.         }
  132.  
  133.     else if ( type == STATE_TRAILING_CONTEXT )
  134.         {
  135.         /* potential trouble.  Scan set of accepting numbers for
  136.          * the one marking the end of the "head".  We assume that
  137.          * this looping will be fairly cheap since it's rare that
  138.          * an accepting number set is large.
  139.          */
  140.         for ( j = 1; j <= nacc; ++j )
  141.         if ( accset[j] & YY_TRAILING_HEAD_MASK )
  142.             {
  143.             fprintf( stderr,
  144.              "%s: Dangerous trailing context in rule at line %d\n",
  145.                  program_name, rule_linenum[ar] );
  146.             return;
  147.             }
  148.         }
  149.     }
  150.     }
  151.  
  152.  
  153. /* dump_associated_rules - list the rules associated with a DFA state
  154.  *
  155.  * synopisis
  156.  *     int ds;
  157.  *     FILE *file;
  158.  *     dump_associated_rules( file, ds );
  159.  *
  160.  * goes through the set of NFA states associated with the DFA and
  161.  * extracts the first MAX_ASSOC_RULES unique rules, sorts them,
  162.  * and writes a report to the given file
  163.  */
  164.  
  165. void dump_associated_rules( file, ds )
  166. FILE *file;
  167. int ds;
  168.  
  169.     {
  170.     register int i, j;
  171.     register int num_associated_rules = 0;
  172.     int rule_set[MAX_ASSOC_RULES + 1];
  173.     int *dset = dss[ds];
  174.     int size = dfasiz[ds];
  175.     
  176.     for ( i = 1; i <= size; ++i )
  177.     {
  178.     register rule_num = rule_linenum[assoc_rule[dset[i]]];
  179.  
  180.     for ( j = 1; j <= num_associated_rules; ++j )
  181.         if ( rule_num == rule_set[j] )
  182.         break;
  183.  
  184.     if ( j > num_associated_rules )
  185.         { /* new rule */
  186.         if ( num_associated_rules < MAX_ASSOC_RULES )
  187.         rule_set[++num_associated_rules] = rule_num;
  188.         }
  189.     }
  190.  
  191.     bubble( rule_set, num_associated_rules );
  192.  
  193.     fprintf( file, " associated rule line numbers:" );
  194.  
  195.     for ( i = 1; i <= num_associated_rules; ++i )
  196.     {
  197.     if ( i % 8 == 1 )
  198.         putc( '\n', file );
  199.     
  200.     fprintf( file, "\t%d", rule_set[i] );
  201.     }
  202.     
  203.     putc( '\n', file );
  204.     }
  205.  
  206.  
  207. /* dump_transitions - list the transitions associated with a DFA state
  208.  *
  209.  * synopisis
  210.  *     int state[numecs];
  211.  *     FILE *file;
  212.  *     dump_transitions( file, state );
  213.  *
  214.  * goes through the set of out-transitions and lists them in human-readable
  215.  * form (i.e., not as equivalence classes); also lists jam transitions
  216.  * (i.e., all those which are not out-transitions, plus EOF).  The dump
  217.  * is done to the given file.
  218.  */
  219.  
  220. void dump_transitions( file, state )
  221. FILE *file;
  222. int state[];
  223.  
  224.     {
  225.     register int i, ec;
  226.     int out_char_set[CSIZE];
  227.  
  228.     for ( i = 0; i < csize; ++i )
  229.     {
  230.     ec = abs( ecgroup[i] );
  231.     out_char_set[i] = state[ec];
  232.     }
  233.     
  234.     fprintf( file, " out-transitions: " );
  235.  
  236.     list_character_set( file, out_char_set );
  237.  
  238.     /* now invert the members of the set to get the jam transitions */
  239.     for ( i = 0; i < csize; ++i )
  240.     out_char_set[i] = ! out_char_set[i];
  241.  
  242.     fprintf( file, "\n jam-transitions: EOF " );
  243.  
  244.     list_character_set( file, out_char_set );
  245.  
  246.     putc( '\n', file );
  247.     }
  248.  
  249.  
  250. /* epsclosure - construct the epsilon closure of a set of ndfa states
  251.  *
  252.  * synopsis
  253.  *    int t[current_max_dfa_size], numstates, accset[num_rules + 1], nacc;
  254.  *    int hashval;
  255.  *    int *epsclosure();
  256.  *    t = epsclosure( t, &numstates, accset, &nacc, &hashval );
  257.  *
  258.  * NOTES
  259.  *    the epsilon closure is the set of all states reachable by an arbitrary
  260.  *  number of epsilon transitions which themselves do not have epsilon
  261.  *  transitions going out, unioned with the set of states which have non-null
  262.  *  accepting numbers.  t is an array of size numstates of nfa state numbers.
  263.  *  Upon return, t holds the epsilon closure and numstates is updated.  accset
  264.  *  holds a list of the accepting numbers, and the size of accset is given
  265.  *  by nacc.  t may be subjected to reallocation if it is not large enough
  266.  *  to hold the epsilon closure.
  267.  *
  268.  *    hashval is the hash value for the dfa corresponding to the state set
  269.  */
  270.  
  271. int *epsclosure( t, ns_addr, accset, nacc_addr, hv_addr )
  272. int *t, *ns_addr, accset[], *nacc_addr, *hv_addr;
  273.  
  274.     {
  275.     register int stkpos, ns, tsp;
  276.     int numstates = *ns_addr, nacc, hashval, transsym, nfaccnum;
  277.     int stkend, nstate;
  278.     static int did_stk_init = false, *stk; 
  279.  
  280. #define MARK_STATE(state) \
  281.     trans1[state] = trans1[state] - MARKER_DIFFERENCE;
  282.  
  283. #define IS_MARKED(state) (trans1[state] < 0)
  284.  
  285. #define UNMARK_STATE(state) \
  286.     trans1[state] = trans1[state] + MARKER_DIFFERENCE;
  287.  
  288. #define CHECK_ACCEPT(state) \
  289.     { \
  290.     nfaccnum = accptnum[state]; \
  291.     if ( nfaccnum != NIL ) \
  292.         accset[++nacc] = nfaccnum; \
  293.     }
  294.  
  295. #define DO_REALLOCATION \
  296.     { \
  297.     current_max_dfa_size += MAX_DFA_SIZE_INCREMENT; \
  298.     ++num_reallocs; \
  299.     t = reallocate_integer_array( t, current_max_dfa_size ); \
  300.     stk = reallocate_integer_array( stk, current_max_dfa_size ); \
  301.     } \
  302.  
  303. #define PUT_ON_STACK(state) \
  304.     { \
  305.     if ( ++stkend >= current_max_dfa_size ) \
  306.         DO_REALLOCATION \
  307.     stk[stkend] = state; \
  308.     MARK_STATE(state) \
  309.     }
  310.  
  311. #define ADD_STATE(state) \
  312.     { \
  313.     if ( ++numstates >= current_max_dfa_size ) \
  314.         DO_REALLOCATION \
  315.     t[numstates] = state; \
  316.     hashval = hashval + state; \
  317.     }
  318.  
  319. #define STACK_STATE(state) \
  320.     { \
  321.     PUT_ON_STACK(state) \
  322.     CHECK_ACCEPT(state) \
  323.     if ( nfaccnum != NIL || transchar[state] != SYM_EPSILON ) \
  324.         ADD_STATE(state) \
  325.     }
  326.  
  327.     if ( ! did_stk_init )
  328.     {
  329.     stk = allocate_integer_array( current_max_dfa_size );
  330.     did_stk_init = true;
  331.     }
  332.  
  333.     nacc = stkend = hashval = 0;
  334.  
  335.     for ( nstate = 1; nstate <= numstates; ++nstate )
  336.     {
  337.     ns = t[nstate];
  338.  
  339.     /* the state could be marked if we've already pushed it onto
  340.      * the stack
  341.      */
  342.     if ( ! IS_MARKED(ns) )
  343.         PUT_ON_STACK(ns)
  344.  
  345.     CHECK_ACCEPT(ns)
  346.     hashval = hashval + ns;
  347.     }
  348.  
  349.     for ( stkpos = 1; stkpos <= stkend; ++stkpos )
  350.     {
  351.     ns = stk[stkpos];
  352.     transsym = transchar[ns];
  353.  
  354.     if ( transsym == SYM_EPSILON )
  355.         {
  356.         tsp = trans1[ns] + MARKER_DIFFERENCE;
  357.  
  358.         if ( tsp != NO_TRANSITION )
  359.         {
  360.         if ( ! IS_MARKED(tsp) )
  361.             STACK_STATE(tsp)
  362.  
  363.         tsp = trans2[ns];
  364.  
  365.         if ( tsp != NO_TRANSITION )
  366.             if ( ! IS_MARKED(tsp) )
  367.             STACK_STATE(tsp)
  368.         }
  369.         }
  370.     }
  371.  
  372.     /* clear out "visit" markers */
  373.  
  374.     for ( stkpos = 1; stkpos <= stkend; ++stkpos )
  375.     {
  376.     if ( IS_MARKED(stk[stkpos]) )
  377.         {
  378.         UNMARK_STATE(stk[stkpos])
  379.         }
  380.     else
  381.         flexfatal( "consistency check failed in epsclosure()" );
  382.     }
  383.  
  384.     *ns_addr = numstates;
  385.     *hv_addr = hashval;
  386.     *nacc_addr = nacc;
  387.  
  388.     return ( t );
  389.     }
  390.  
  391.  
  392. /* increase_max_dfas - increase the maximum number of DFAs */
  393.  
  394. void increase_max_dfas()
  395.  
  396.     {
  397.     current_max_dfas += MAX_DFAS_INCREMENT;
  398.  
  399.     ++num_reallocs;
  400.  
  401.     base = reallocate_integer_array( base, current_max_dfas );
  402.     def = reallocate_integer_array( def, current_max_dfas );
  403.     dfasiz = reallocate_integer_array( dfasiz, current_max_dfas );
  404.     accsiz = reallocate_integer_array( accsiz, current_max_dfas );
  405.     dhash = reallocate_integer_array( dhash, current_max_dfas );
  406.     dss = reallocate_int_ptr_array( dss, current_max_dfas );
  407.     dfaacc = reallocate_dfaacc_union( dfaacc, current_max_dfas );
  408.  
  409.     if ( nultrans )
  410.     nultrans = reallocate_integer_array( nultrans, current_max_dfas );
  411.     }
  412.  
  413.  
  414. /* ntod - convert an ndfa to a dfa
  415.  *
  416.  * synopsis
  417.  *    ntod();
  418.  *
  419.  *  creates the dfa corresponding to the ndfa we've constructed.  the
  420.  *  dfa starts out in state #1.
  421.  */
  422.  
  423. void ntod()
  424.  
  425.     {
  426.     int *accset, ds, nacc, newds;
  427.     int sym, hashval, numstates, dsize;
  428.     int num_full_table_rows;    /* used only for -f */
  429.     int *nset, *dset;
  430.     int targptr, totaltrans, i, comstate, comfreq, targ;
  431.     int *epsclosure(), snstods(), symlist[CSIZE + 1];
  432.     int num_start_states;
  433.     int todo_head, todo_next;
  434.  
  435.     /* note that the following are indexed by *equivalence classes*
  436.      * and not by characters.  Since equivalence classes are indexed
  437.      * beginning with 1, even if the scanner accepts NUL's, this
  438.      * means that (since every character is potentially in its own
  439.      * equivalence class) these arrays must have room for indices
  440.      * from 1 to CSIZE, so their size must be CSIZE + 1.
  441.      */
  442.     int duplist[CSIZE + 1], state[CSIZE + 1];
  443.     int targfreq[CSIZE + 1], targstate[CSIZE + 1];
  444.  
  445.     /* this is so find_table_space(...) will know where to start looking in
  446.      * chk/nxt for unused records for space to put in the state
  447.      */
  448.     if ( fullspd )
  449.     firstfree = 0;
  450.  
  451.     accset = allocate_integer_array( num_rules + 1 );
  452.     nset = allocate_integer_array( current_max_dfa_size );
  453.  
  454.     /* the "todo" queue is represented by the head, which is the DFA
  455.      * state currently being processed, and the "next", which is the
  456.      * next DFA state number available (not in use).  We depend on the
  457.      * fact that snstods() returns DFA's \in increasing order/, and thus
  458.      * need only know the bounds of the dfas to be processed.
  459.      */
  460.     todo_head = todo_next = 0;
  461.  
  462.     for ( i = 0; i <= csize; ++i )
  463.     {
  464.     duplist[i] = NIL;
  465.     symlist[i] = false;
  466.     }
  467.  
  468.     for ( i = 0; i <= num_rules; ++i )
  469.     accset[i] = NIL;
  470.  
  471.     if ( trace )
  472.     {
  473.     dumpnfa( scset[1] );
  474.     fputs( "\n\nDFA Dump:\n\n", stderr );
  475.     }
  476.  
  477.     inittbl();
  478.  
  479.     /* check to see whether we should build a separate table for transitions
  480.      * on NUL characters.  We don't do this for full-speed (-F) scanners,
  481.      * since for them we don't have a simple state number lying around with
  482.      * which to index the table.  We also don't bother doing it for scanners
  483.      * unless (1) NUL is in its own equivalence class (indicated by a
  484.      * positive value of ecgroup[NUL]), (2) NUL's equilvalence class is
  485.      * the last equivalence class, and (3) the number of equivalence classes
  486.      * is the same as the number of characters.  This latter case comes about
  487.      * when useecs is false or when its true but every character still
  488.      * manages to land in its own class (unlikely, but it's cheap to check
  489.      * for).  If all these things are true then the character code needed
  490.      * to represent NUL's equivalence class for indexing the tables is
  491.      * going to take one more bit than the number of characters, and therefore
  492.      * we won't be assured of being able to fit it into a YY_CHAR variable.
  493.      * This rules out storing the transitions in a compressed table, since
  494.      * the code for interpreting them uses a YY_CHAR variable (perhaps it
  495.      * should just use an integer, though; this is worth pondering ... ###).
  496.      *
  497.      * Finally, for full tables, we want the number of entries in the
  498.      * table to be a power of two so the array references go fast (it
  499.      * will just take a shift to compute the major index).  If encoding
  500.      * NUL's transitions in the table will spoil this, we give it its
  501.      * own table (note that this will be the case if we're not using
  502.      * equivalence classes).
  503.      */
  504.  
  505.     /* note that the test for ecgroup[0] == numecs below accomplishes
  506.      * both (1) and (2) above
  507.      */
  508.     if ( ! fullspd && ecgroup[0] == numecs )
  509.     { /* NUL is alone in its equivalence class, which is the last one */
  510.     int use_NUL_table = (numecs == csize);
  511.  
  512.     if ( fulltbl && ! use_NUL_table )
  513.         { /* we still may want to use the table if numecs is a power of 2 */
  514.         int power_of_two;
  515.  
  516.         for ( power_of_two = 1; power_of_two <= csize; power_of_two *= 2 )
  517.         if ( numecs == power_of_two )
  518.             {
  519.             use_NUL_table = true;
  520.             break;
  521.             }
  522.         }
  523.  
  524.     if ( use_NUL_table )
  525.         nultrans = allocate_integer_array( current_max_dfas );
  526.         /* from now on, nultrans != nil indicates that we're
  527.          * saving null transitions for later, separate encoding
  528.          */
  529.     }
  530.  
  531.  
  532.     if ( fullspd )
  533.     {
  534.     for ( i = 0; i <= numecs; ++i )
  535.         state[i] = 0;
  536.     place_state( state, 0, 0 );
  537.     }
  538.  
  539.     else if ( fulltbl )
  540.     {
  541.     if ( nultrans )
  542.         /* we won't be including NUL's transitions in the table,
  543.          * so build it for entries from 0 .. numecs - 1
  544.          */
  545.         num_full_table_rows = numecs;
  546.  
  547.     else
  548.         /* take into account the fact that we'll be including
  549.          * the NUL entries in the transition table.  Build it
  550.          * from 0 .. numecs.
  551.          */
  552.         num_full_table_rows = numecs + 1;
  553.  
  554.     /* declare it "short" because it's a real long-shot that that
  555.      * won't be large enough.
  556.      */
  557.     printf( "static short int yy_nxt[][%d] =\n    {\n",
  558.         /* '}' so vi doesn't get too confused */
  559.         num_full_table_rows );
  560.  
  561.     /* generate 0 entries for state #0 */
  562.     for ( i = 0; i < num_full_table_rows; ++i )
  563.         mk2data( 0 );
  564.  
  565.     /* force ',' and dataflush() next call to mk2data */
  566.     datapos = NUMDATAITEMS;
  567.  
  568.     /* force extra blank line next dataflush() */
  569.     dataline = NUMDATALINES;
  570.     }
  571.  
  572.     /* create the first states */
  573.  
  574.     num_start_states = lastsc * 2;
  575.  
  576.     for ( i = 1; i <= num_start_states; ++i )
  577.     {
  578.     numstates = 1;
  579.  
  580.     /* for each start condition, make one state for the case when
  581.      * we're at the beginning of the line (the '%' operator) and
  582.      * one for the case when we're not
  583.      */
  584.     if ( i % 2 == 1 )
  585.         nset[numstates] = scset[(i / 2) + 1];
  586.     else
  587.         nset[numstates] = mkbranch( scbol[i / 2], scset[i / 2] );
  588.  
  589.     nset = epsclosure( nset, &numstates, accset, &nacc, &hashval );
  590.  
  591.     if ( snstods( nset, numstates, accset, nacc, hashval, &ds ) )
  592.         {
  593.         numas += nacc;
  594.         totnst += numstates;
  595.         ++todo_next;
  596.  
  597.         if ( variable_trailing_context_rules && nacc > 0 )
  598.         check_trailing_context( nset, numstates, accset, nacc );
  599.         }
  600.     }
  601.  
  602.     if ( ! fullspd )
  603.     {
  604.     if ( ! snstods( nset, 0, accset, 0, 0, &end_of_buffer_state ) )
  605.         flexfatal( "could not create unique end-of-buffer state" );
  606.  
  607.     ++numas;
  608.     ++num_start_states;
  609.     ++todo_next;
  610.     }
  611.  
  612.     while ( todo_head < todo_next )
  613.     {
  614.     targptr = 0;
  615.     totaltrans = 0;
  616.  
  617.     for ( i = 1; i <= numecs; ++i )
  618.         state[i] = 0;
  619.  
  620.     ds = ++todo_head;
  621.  
  622.     dset = dss[ds];
  623.     dsize = dfasiz[ds];
  624.  
  625.     if ( trace )
  626.         fprintf( stderr, "state # %d:\n", ds );
  627.  
  628.     sympartition( dset, dsize, symlist, duplist );
  629.  
  630.     for ( sym = 1; sym <= numecs; ++sym )
  631.         {
  632.         if ( symlist[sym] )
  633.         {
  634.         symlist[sym] = 0;
  635.  
  636.         if ( duplist[sym] == NIL )
  637.             { /* symbol has unique out-transitions */
  638.             numstates = symfollowset( dset, dsize, sym, nset );
  639.             nset = epsclosure( nset, &numstates, accset,
  640.                        &nacc, &hashval );
  641.  
  642.             if ( snstods( nset, numstates, accset,
  643.                   nacc, hashval, &newds ) )
  644.             {
  645.             totnst = totnst + numstates;
  646.             ++todo_next;
  647.             numas += nacc;
  648.  
  649.             if ( variable_trailing_context_rules && nacc > 0 )
  650.                 check_trailing_context( nset, numstates,
  651.                 accset, nacc );
  652.             }
  653.  
  654.             state[sym] = newds;
  655.  
  656.             if ( trace )
  657.             fprintf( stderr, "\t%d\t%d\n", sym, newds );
  658.  
  659.             targfreq[++targptr] = 1;
  660.             targstate[targptr] = newds;
  661.             ++numuniq;
  662.             }
  663.  
  664.         else
  665.             {
  666.             /* sym's equivalence class has the same transitions
  667.              * as duplist(sym)'s equivalence class
  668.              */
  669.             targ = state[duplist[sym]];
  670.             state[sym] = targ;
  671.  
  672.             if ( trace )
  673.             fprintf( stderr, "\t%d\t%d\n", sym, targ );
  674.  
  675.             /* update frequency count for destination state */
  676.  
  677.             i = 0;
  678.             while ( targstate[++i] != targ )
  679.             ;
  680.  
  681.             ++targfreq[i];
  682.             ++numdup;
  683.             }
  684.  
  685.         ++totaltrans;
  686.         duplist[sym] = NIL;
  687.         }
  688.         }
  689.  
  690.     numsnpairs = numsnpairs + totaltrans;
  691.  
  692.     if ( caseins && ! useecs )
  693.         {
  694.         register int j;
  695.  
  696.         for ( i = 'A', j = 'a'; i <= 'Z'; ++i, ++j )
  697.         state[i] = state[j];
  698.         }
  699.  
  700.     if ( ds > num_start_states )
  701.         check_for_backtracking( ds, state );
  702.  
  703.     if ( nultrans )
  704.         {
  705.         nultrans[ds] = state[NUL_ec];
  706.         state[NUL_ec] = 0;    /* remove transition */
  707.         }
  708.  
  709.     if ( fulltbl )
  710.         {
  711.         /* supply array's 0-element */
  712.         if ( ds == end_of_buffer_state )
  713.         mk2data( -end_of_buffer_state );
  714.         else
  715.         mk2data( end_of_buffer_state );
  716.  
  717.         for ( i = 1; i < num_full_table_rows; ++i )
  718.         /* jams are marked by negative of state number */
  719.         mk2data( state[i] ? state[i] : -ds );
  720.  
  721.         /* force ',' and dataflush() next call to mk2data */
  722.         datapos = NUMDATAITEMS;
  723.  
  724.         /* force extra blank line next dataflush() */
  725.         dataline = NUMDATALINES;
  726.         }
  727.  
  728.         else if ( fullspd )
  729.         place_state( state, ds, totaltrans );
  730.  
  731.     else if ( ds == end_of_buffer_state )
  732.         /* special case this state to make sure it does what it's
  733.          * supposed to, i.e., jam on end-of-buffer
  734.          */
  735.         stack1( ds, 0, 0, JAMSTATE );
  736.  
  737.     else /* normal, compressed state */
  738.         {
  739.         /* determine which destination state is the most common, and
  740.          * how many transitions to it there are
  741.          */
  742.  
  743.         comfreq = 0;
  744.         comstate = 0;
  745.  
  746.         for ( i = 1; i <= targptr; ++i )
  747.         if ( targfreq[i] > comfreq )
  748.             {
  749.             comfreq = targfreq[i];
  750.             comstate = targstate[i];
  751.             }
  752.  
  753.         bldtbl( state, ds, totaltrans, comstate, comfreq );
  754.         }
  755.     }
  756.  
  757.     if ( fulltbl )
  758.     dataend();
  759.  
  760.     else if ( ! fullspd )
  761.     {
  762.     cmptmps();  /* create compressed template entries */
  763.  
  764.     /* create tables for all the states with only one out-transition */
  765.     while ( onesp > 0 )
  766.         {
  767.         mk1tbl( onestate[onesp], onesym[onesp], onenext[onesp],
  768.             onedef[onesp] );
  769.         --onesp;
  770.         }
  771.  
  772.     mkdeftbl();
  773.     }
  774.     }
  775.  
  776.  
  777. /* snstods - converts a set of ndfa states into a dfa state
  778.  *
  779.  * synopsis
  780.  *    int sns[numstates], numstates, newds, accset[num_rules + 1], nacc, hashval;
  781.  *    int snstods();
  782.  *    is_new_state = snstods( sns, numstates, accset, nacc, hashval, &newds );
  783.  *
  784.  * on return, the dfa state number is in newds.
  785.  */
  786.  
  787. int snstods( sns, numstates, accset, nacc, hashval, newds_addr )
  788. int sns[], numstates, accset[], nacc, hashval, *newds_addr;
  789.  
  790.     {
  791.     int didsort = 0;
  792.     register int i, j;
  793.     int newds, *oldsns;
  794.  
  795.     for ( i = 1; i <= lastdfa; ++i )
  796.     if ( hashval == dhash[i] )
  797.         {
  798.         if ( numstates == dfasiz[i] )
  799.         {
  800.         oldsns = dss[i];
  801.  
  802.         if ( ! didsort )
  803.             {
  804.             /* we sort the states in sns so we can compare it to
  805.              * oldsns quickly.  we use bubble because there probably
  806.              * aren't very many states
  807.              */
  808.             bubble( sns, numstates );
  809.             didsort = 1;
  810.             }
  811.  
  812.         for ( j = 1; j <= numstates; ++j )
  813.             if ( sns[j] != oldsns[j] )
  814.             break;
  815.  
  816.         if ( j > numstates )
  817.             {
  818.             ++dfaeql;
  819.             *newds_addr = i;
  820.             return ( 0 );
  821.             }
  822.  
  823.         ++hshcol;
  824.         }
  825.  
  826.         else
  827.         ++hshsave;
  828.         }
  829.  
  830.     /* make a new dfa */
  831.  
  832.     if ( ++lastdfa >= current_max_dfas )
  833.     increase_max_dfas();
  834.  
  835.     newds = lastdfa;
  836.  
  837.     dss[newds] = (int *) malloc( (unsigned) ((numstates + 1) * sizeof( int )) );
  838.  
  839.     if ( ! dss[newds] )
  840.     flexfatal( "dynamic memory failure in snstods()" );
  841.  
  842.     /* if we haven't already sorted the states in sns, we do so now, so that
  843.      * future comparisons with it can be made quickly
  844.      */
  845.  
  846.     if ( ! didsort )
  847.     bubble( sns, numstates );
  848.  
  849.     for ( i = 1; i <= numstates; ++i )
  850.     dss[newds][i] = sns[i];
  851.  
  852.     dfasiz[newds] = numstates;
  853.     dhash[newds] = hashval;
  854.  
  855.     if ( nacc == 0 )
  856.     {
  857.     if ( reject )
  858.         dfaacc[newds].dfaacc_set = (int *) 0;
  859.     else
  860.         dfaacc[newds].dfaacc_state = 0;
  861.  
  862.     accsiz[newds] = 0;
  863.     }
  864.  
  865.     else if ( reject )
  866.     {
  867.     /* we sort the accepting set in increasing order so the disambiguating
  868.      * rule that the first rule listed is considered match in the event of
  869.      * ties will work.  We use a bubble sort since the list is probably
  870.      * quite small.
  871.      */
  872.  
  873.     bubble( accset, nacc );
  874.  
  875.     dfaacc[newds].dfaacc_set =
  876.         (int *) malloc( (unsigned) ((nacc + 1) * sizeof( int )) );
  877.  
  878.     if ( ! dfaacc[newds].dfaacc_set )
  879.         flexfatal( "dynamic memory failure in snstods()" );
  880.  
  881.     /* save the accepting set for later */
  882.     for ( i = 1; i <= nacc; ++i )
  883.         dfaacc[newds].dfaacc_set[i] = accset[i];
  884.  
  885.     accsiz[newds] = nacc;
  886.     }
  887.  
  888.     else
  889.     { /* find lowest numbered rule so the disambiguating rule will work */
  890.     j = num_rules + 1;
  891.  
  892.     for ( i = 1; i <= nacc; ++i )
  893.         if ( accset[i] < j )
  894.         j = accset[i];
  895.  
  896.     dfaacc[newds].dfaacc_state = j;
  897.     }
  898.  
  899.     *newds_addr = newds;
  900.  
  901.     return ( 1 );
  902.     }
  903.  
  904.  
  905. /* symfollowset - follow the symbol transitions one step
  906.  *
  907.  * synopsis
  908.  *    int ds[current_max_dfa_size], dsize, transsym;
  909.  *    int nset[current_max_dfa_size], numstates;
  910.  *    numstates = symfollowset( ds, dsize, transsym, nset );
  911.  */
  912.  
  913. int symfollowset( ds, dsize, transsym, nset )
  914. int ds[], dsize, transsym, nset[];
  915.  
  916.     {
  917.     int ns, tsp, sym, i, j, lenccl, ch, numstates;
  918.     int ccllist;
  919.  
  920.     numstates = 0;
  921.  
  922.     for ( i = 1; i <= dsize; ++i )
  923.     { /* for each nfa state ns in the state set of ds */
  924.     ns = ds[i];
  925.     sym = transchar[ns];
  926.     tsp = trans1[ns];
  927.  
  928.     if ( sym < 0 )
  929.         { /* it's a character class */
  930.         sym = -sym;
  931.         ccllist = cclmap[sym];
  932.         lenccl = ccllen[sym];
  933.  
  934.         if ( cclng[sym] )
  935.         {
  936.         for ( j = 0; j < lenccl; ++j )
  937.             { /* loop through negated character class */
  938.             ch = ccltbl[ccllist + j];
  939.  
  940.             if ( ch == 0 )
  941.             ch = NUL_ec;
  942.  
  943.             if ( ch > transsym )
  944.             break;    /* transsym isn't in negated ccl */
  945.  
  946.             else if ( ch == transsym )
  947.             /* next 2 */ goto bottom;
  948.             }
  949.  
  950.         /* didn't find transsym in ccl */
  951.         nset[++numstates] = tsp;
  952.         }
  953.  
  954.         else
  955.         for ( j = 0; j < lenccl; ++j )
  956.             {
  957.             ch = ccltbl[ccllist + j];
  958.  
  959.             if ( ch == 0 )
  960.             ch = NUL_ec;
  961.  
  962.             if ( ch > transsym )
  963.             break;
  964.  
  965.             else if ( ch == transsym )
  966.             {
  967.             nset[++numstates] = tsp;
  968.             break;
  969.             }
  970.             }
  971.         }
  972.  
  973.     else if ( sym >= 'A' && sym <= 'Z' && caseins )
  974.         flexfatal( "consistency check failed in symfollowset" );
  975.  
  976.     else if ( sym == SYM_EPSILON )
  977.         { /* do nothing */
  978.         }
  979.  
  980.     else if ( abs( ecgroup[sym] ) == transsym )
  981.         nset[++numstates] = tsp;
  982.  
  983. bottom:
  984.     ;
  985.     }
  986.  
  987.     return ( numstates );
  988.     }
  989.  
  990.  
  991. /* sympartition - partition characters with same out-transitions
  992.  *
  993.  * synopsis
  994.  *    integer ds[current_max_dfa_size], numstates, duplist[numecs];
  995.  *    symlist[numecs];
  996.  *    sympartition( ds, numstates, symlist, duplist );
  997.  */
  998.  
  999. void sympartition( ds, numstates, symlist, duplist )
  1000. int ds[], numstates, duplist[];
  1001. int symlist[];
  1002.  
  1003.     {
  1004.     int tch, i, j, k, ns, dupfwd[CSIZE + 1], lenccl, cclp, ich;
  1005.  
  1006.     /* partitioning is done by creating equivalence classes for those
  1007.      * characters which have out-transitions from the given state.  Thus
  1008.      * we are really creating equivalence classes of equivalence classes.
  1009.      */
  1010.  
  1011.     for ( i = 1; i <= numecs; ++i )
  1012.     { /* initialize equivalence class list */
  1013.     duplist[i] = i - 1;
  1014.     dupfwd[i] = i + 1;
  1015.     }
  1016.  
  1017.     duplist[1] = NIL;
  1018.     dupfwd[numecs] = NIL;
  1019.  
  1020.     for ( i = 1; i <= numstates; ++i )
  1021.     {
  1022.     ns = ds[i];
  1023.     tch = transchar[ns];
  1024.  
  1025.     if ( tch != SYM_EPSILON )
  1026.         {
  1027.         if ( tch < -lastccl || tch > csize )
  1028.         {
  1029.         if ( tch > csize && tch <= CSIZE )
  1030.             flexerror( "scanner requires -8 flag" );
  1031.  
  1032.         else
  1033.             flexfatal(
  1034.             "bad transition character detected in sympartition()" );
  1035.         }
  1036.  
  1037.         if ( tch >= 0 )
  1038.         { /* character transition */
  1039.         /* abs() needed for fake %t ec's */
  1040.         int ec = abs( ecgroup[tch] );
  1041.  
  1042.         mkechar( ec, dupfwd, duplist );
  1043.         symlist[ec] = 1;
  1044.         }
  1045.  
  1046.         else
  1047.         { /* character class */
  1048.         tch = -tch;
  1049.  
  1050.         lenccl = ccllen[tch];
  1051.         cclp = cclmap[tch];
  1052.         mkeccl( ccltbl + cclp, lenccl, dupfwd, duplist, numecs,
  1053.             NUL_ec );
  1054.  
  1055.         if ( cclng[tch] )
  1056.             {
  1057.             j = 0;
  1058.  
  1059.             for ( k = 0; k < lenccl; ++k )
  1060.             {
  1061.             ich = ccltbl[cclp + k];
  1062.  
  1063.             if ( ich == 0 )
  1064.                 ich = NUL_ec;
  1065.  
  1066.             for ( ++j; j < ich; ++j )
  1067.                 symlist[j] = 1;
  1068.             }
  1069.  
  1070.             for ( ++j; j <= numecs; ++j )
  1071.             symlist[j] = 1;
  1072.             }
  1073.  
  1074.         else
  1075.             for ( k = 0; k < lenccl; ++k )
  1076.             {
  1077.             ich = ccltbl[cclp + k];
  1078.  
  1079.             if ( ich == 0 )
  1080.                 ich = NUL_ec;
  1081.  
  1082.             symlist[ich] = 1;
  1083.             }
  1084.         }
  1085.         }
  1086.     }
  1087.     }
  1088.