summaryrefslogtreecommitdiff
path: root/ragel/switch.cc
diff options
context:
space:
mode:
authorAdrian Thurston <thurston@colm.net>2019-09-08 21:14:08 -0600
committerAdrian Thurston <thurston@colm.net>2019-09-08 21:14:08 -0600
commit01b426837b1aa72d3535ec0f27b13e43993311bc (patch)
tree2dec36611a823f80ee677bd649b0f04ce5d885ee /ragel/switch.cc
parent1058d1029a9a1dda7d6d4c4e07fc775bb1ae4cd0 (diff)
downloadcolm-01b426837b1aa72d3535ec0f27b13e43993311bc.tar.gz
moved /ragel-repos/src to /ragel
This will be what we build after building colm.
Diffstat (limited to 'ragel/switch.cc')
-rw-r--r--ragel/switch.cc1036
1 files changed, 1036 insertions, 0 deletions
diff --git a/ragel/switch.cc b/ragel/switch.cc
new file mode 100644
index 00000000..8355cdac
--- /dev/null
+++ b/ragel/switch.cc
@@ -0,0 +1,1036 @@
+/*
+ * Copyright 2001-2018 Adrian Thurston <thurston@colm.net>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ragel.h"
+#include "switch.h"
+#include "redfsm.h"
+#include "gendata.h"
+
+#include <assert.h>
+
+std::ostream &Switch::TRANS_GOTO( int off, RedTransAp *trans )
+{
+ out << "_trans = " << off << ";\n";
+ return out;
+}
+
+void Switch::RANGE_B_SEARCH( RedStateAp *state, Key lower, Key upper, int low, int high )
+{
+ /* Get the mid position, staying on the lower end of the range. */
+ int mid = (low + high) >> 1;
+ RedTransEl *data = state->outRange.data;
+
+ /* Determine if we need to look higher or lower. */
+ bool anyLower = mid > low;
+ bool anyHigher = mid < high;
+
+ /* Determine if the keys at mid are the limits of the alphabet. */
+ bool limitLow = keyOps->eq( data[mid].lowKey, lower );
+ bool limitHigh = keyOps->eq( data[mid].highKey, upper );
+
+ if ( anyLower && anyHigher ) {
+ /* Can go lower and higher than mid. */
+ out << "if ( " << GET_KEY() << " < " <<
+ KEY(data[mid].lowKey) << " ) {\n";
+ RANGE_B_SEARCH( state, lower, keyOps->sub( data[mid].lowKey, 1 ), low, mid-1 );
+ out << "} else if ( " << GET_KEY() << " > " <<
+ KEY(data[mid].highKey) << " ) {\n";
+ RANGE_B_SEARCH( state, keyOps->add( data[mid].highKey, 1 ), upper, mid+1, high );
+ out << "} else {\n";
+ TRANS_GOTO(transBase + state->outSingle.length() + (mid), data[mid].value ) << "\n";
+ out << "}\n";
+ }
+ else if ( anyLower && !anyHigher ) {
+ /* Can go lower than mid but not higher. */
+ out << "if ( " << GET_KEY() << " < " <<
+ KEY(data[mid].lowKey) << " ) {\n";
+ RANGE_B_SEARCH( state, lower, keyOps->sub( data[mid].lowKey, 1 ), low, mid-1 );
+
+ /* if the higher is the highest in the alphabet then there is no
+ * sense testing it. */
+ if ( limitHigh ) {
+ out << "} else {\n";
+ TRANS_GOTO(transBase + state->outSingle.length() + (mid), data[mid].value) << "\n";
+ out << "}\n";
+ }
+ else {
+ out << "} else if ( " << GET_KEY() << " <= " <<
+ KEY(data[mid].highKey) << " ) {\n";
+ TRANS_GOTO(transBase + state->outSingle.length() + (mid), data[mid].value) << "\n";
+ out << "}\n";
+
+ out << "else {\n";
+ DEFAULT( state );
+ out << "}\n";
+ }
+ }
+ else if ( !anyLower && anyHigher ) {
+ /* Can go higher than mid but not lower. */
+ out << "if ( " << GET_KEY() << " > " <<
+ KEY(data[mid].highKey) << " ) {\n";
+ RANGE_B_SEARCH( state, keyOps->add( data[mid].highKey, 1 ), upper, mid+1, high );
+
+ /* If the lower end is the lowest in the alphabet then there is no
+ * sense testing it. */
+ if ( limitLow ) {
+ out << "} else {\n";
+ TRANS_GOTO(transBase + state->outSingle.length() + (mid), data[mid].value) << "\n";
+ out << "}\n";
+ }
+ else {
+ out << "} else if ( " << GET_KEY() << " >= " <<
+ KEY(data[mid].lowKey) << " ) {\n";
+ TRANS_GOTO(transBase + state->outSingle.length() + (mid), data[mid].value) << "\n";
+ out << "}\n";
+
+ out << "else {\n";
+ DEFAULT( state );
+ out << "}\n";
+ }
+ }
+ else {
+ /* Cannot go higher or lower than mid. It's mid or bust. What
+ * tests to do depends on limits of alphabet. */
+ if ( !limitLow && !limitHigh ) {
+ out << "if ( " << KEY(data[mid].lowKey) << " <= " <<
+ GET_KEY() << " && " << GET_KEY() << " <= " <<
+ KEY(data[mid].highKey) << " ) {\n";
+ TRANS_GOTO(transBase + state->outSingle.length() + (mid), data[mid].value) << "\n";
+ out << "}\n";
+
+ out << "else {\n";
+ DEFAULT( state );
+ out << "}\n";
+ }
+ else if ( limitLow && !limitHigh ) {
+ out << "if ( " << GET_KEY() << " <= " <<
+ KEY(data[mid].highKey) << " ) {\n";
+ TRANS_GOTO(transBase + state->outSingle.length() + (mid), data[mid].value) << "\n";
+ out << "}\n";
+
+ out << "else {\n";
+ DEFAULT( state );
+ out << "}\n";
+ }
+ else if ( !limitLow && limitHigh ) {
+ out << "if ( " << KEY(data[mid].lowKey) << " <= " <<
+ GET_KEY() << " ) {\n";
+ TRANS_GOTO(transBase + state->outSingle.length() + (mid), data[mid].value) << "\n";
+ out << "}\n";
+
+ out << "else {\n";
+ DEFAULT( state );
+ out << "}\n";
+ }
+ else {
+ /* Both high and low are at the limit. No tests to do. */
+ out << "{\n";
+ TRANS_GOTO(transBase + state->outSingle.length() + (mid), data[mid].value) << "\n";
+ out << "}\n";
+ }
+ }
+}
+
+void Switch::SINGLE_SWITCH( RedStateAp *st )
+{
+ /* Load up the singles. */
+ int numSingles = st->outSingle.length();
+ RedTransEl *data = st->outSingle.data;
+
+ if ( numSingles == 1 ) {
+ /* If there is a single single key then write it out as an if. */
+ out << "\tif ( " << GET_KEY() << " == " <<
+ KEY(data[0].lowKey) << " ) {\n\t\t";
+
+ /* Virtual function for writing the target of the transition. */
+ TRANS_GOTO(transBase, data[0].value) << "\n";
+ out << "\t}\n";
+
+ out << "else {\n";
+ NOT_SINGLE( st );
+ out << "}\n";
+ }
+ else if ( numSingles > 1 ) {
+ /* Write out single keys in a switch if there is more than one. */
+ out << "\tswitch( " << GET_KEY() << " ) {\n";
+
+ /* Write out the single indicies. */
+ for ( int j = 0; j < numSingles; j++ ) {
+ out << CASE( KEY(data[j].lowKey) ) << " {\n";
+ TRANS_GOTO(transBase + j, data[j].value) << "\n";
+ out << CEND() << "\n}\n";
+ }
+
+ out << CodeGen::DEFAULT() << " {\n";
+ NOT_SINGLE( st );
+ out << CEND() << "\n}\n";
+
+ /* Close off the transition switch. */
+ out << "\t}\n";
+ }
+}
+
+void Switch::DEFAULT( RedStateAp *st )
+{
+ if ( st->defTrans != 0 ) {
+ TRANS_GOTO( transBase + st->outSingle.length() + st->outRange.length(), st->defTrans ) << "\n";
+ }
+}
+
+void Switch::NOT_SINGLE( RedStateAp *st )
+{
+ if ( st->outRange.length() > 0 ) {
+ RANGE_B_SEARCH( st, keyOps->minKey, keyOps->maxKey,
+ 0, st->outRange.length() - 1 );
+ }
+ else {
+ DEFAULT( st );
+ }
+}
+
+void Switch::LOCATE_TRANS()
+{
+ transBase = 0;
+
+ out <<
+ " switch ( " << vCS() << " ) {\n";
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st == redFsm->errState ) {
+ out << CASE( STR( st->id ) ) << " {\n";
+ out << CEND() << "\n}\n";
+ }
+ else {
+ /* Label the state. */
+ out << CASE( STR( st->id ) ) << " {\n";
+
+ /* Try singles. */
+ if ( st->outSingle.length() > 0 ) {
+ SINGLE_SWITCH( st );
+ }
+ else {
+ NOT_SINGLE( st );
+ }
+
+ out << CEND() << "\n}\n";
+ }
+
+ transBase += st->outSingle.length() +
+ st->outRange.length() +
+ ( st->defTrans != 0 ? 1 : 0 );
+ }
+
+ out <<
+ " }\n"
+ "\n";
+}
+
+void Switch::genAnalysis()
+{
+ redFsm->sortByStateId();
+
+ /* Choose default transitions and the single transition. */
+ redFsm->chooseDefaultSpan();
+
+ /* Choose the singles. */
+ redFsm->moveSelectTransToSingle();
+
+ if ( redFsm->errState != 0 )
+ redFsm->getErrorCond();
+
+ /* If any errors have occured in the input file then don't write anything. */
+ if ( red->id->errorCount > 0 )
+ return;
+
+ /* Anlayze Machine will find the final action reference counts, among other
+ * things. We will use these in reporting the usage of fsm directives in
+ * action code. */
+ red->analyzeMachine();
+
+ setKeyType();
+
+ /* Run the analysis pass over the table data. */
+ setTableState( TableArray::AnalyzePass );
+ tableDataPass();
+
+ /* Switch the tables over to the code gen mode. */
+ setTableState( TableArray::GeneratePass );
+}
+
+
+void Switch::tableDataPass()
+{
+ if ( type == Loop )
+ taActions();
+
+ taKeyOffsets();
+ taSingleLens();
+ taRangeLens();
+ taIndexOffsets();
+ taIndicies();
+
+ taTransCondSpacesWi();
+ taTransOffsetsWi();
+ taTransLengthsWi();
+
+ taTransCondSpaces();
+ taTransOffsets();
+ taTransLengths();
+
+ taCondTargs();
+ taCondActions();
+
+ taToStateActions();
+ taFromStateActions();
+ taEofActions();
+ taEofConds();
+ taEofTrans();
+
+ taKeys();
+ taCondKeys();
+
+ taNfaTargs();
+ taNfaOffsets();
+ taNfaPushActions();
+ taNfaPopTrans();
+}
+
+void Switch::writeData()
+{
+ if ( type == Loop ) {
+ /* If there are any transtion functions then output the array. If there
+ * are none, don't bother emitting an empty array that won't be used. */
+ if ( redFsm->anyActions() )
+ taActions();
+ }
+
+ taKeyOffsets();
+ taKeys();
+ taSingleLens();
+ taRangeLens();
+ taIndexOffsets();
+
+ taTransCondSpaces();
+ taTransOffsets();
+ taTransLengths();
+
+ taCondKeys();
+ taCondTargs();
+ taCondActions();
+
+ if ( redFsm->anyToStateActions() )
+ taToStateActions();
+
+ if ( redFsm->anyFromStateActions() )
+ taFromStateActions();
+
+ if ( redFsm->anyEofActions() )
+ taEofActions();
+
+ taEofConds();
+
+ if ( redFsm->anyEofTrans() )
+ taEofTrans();
+
+ taNfaTargs();
+ taNfaOffsets();
+ taNfaPushActions();
+ taNfaPopTrans();
+
+ STATE_IDS();
+}
+
+
+void Switch::setKeyType()
+{
+ transKeys.setType( ALPH_TYPE(), alphType->size, alphType->isChar );
+ transKeys.isSigned = keyOps->isSigned;
+}
+
+void Switch::setTableState( TableArray::State state )
+{
+ for ( ArrayVector::Iter i = arrayVector; i.lte(); i++ ) {
+ TableArray *tableArray = *i;
+ tableArray->setState( state );
+ }
+}
+
+void Switch::taKeyOffsets()
+{
+ keyOffsets.start();
+
+ int curKeyOffset = 0;
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ keyOffsets.value( curKeyOffset );
+ curKeyOffset += st->outSingle.length() + st->outRange.length() * 2;
+ }
+
+ keyOffsets.finish();
+}
+
+
+void Switch::taSingleLens()
+{
+ singleLens.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
+ singleLens.value( st->outSingle.length() );
+
+ singleLens.finish();
+}
+
+
+void Switch::taRangeLens()
+{
+ rangeLens.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
+ rangeLens.value( st->outRange.length() );
+
+ rangeLens.finish();
+}
+
+void Switch::taIndexOffsets()
+{
+ indexOffsets.start();
+
+ int curIndOffset = 0;
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ /* Write the index offset. */
+ indexOffsets.value( curIndOffset );
+
+ /* Move the index offset ahead. */
+ curIndOffset += st->outSingle.length() + st->outRange.length();
+ if ( st->defTrans != 0 )
+ curIndOffset += 1;
+ }
+
+ indexOffsets.finish();
+}
+
+void Switch::taToStateActions()
+{
+ toStateActions.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
+ TO_STATE_ACTION(st);
+
+ toStateActions.finish();
+}
+
+void Switch::taFromStateActions()
+{
+ fromStateActions.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
+ FROM_STATE_ACTION(st);
+
+ fromStateActions.finish();
+}
+
+void Switch::taEofActions()
+{
+ eofActions.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
+ EOF_ACTION( st );
+
+ eofActions.finish();
+}
+
+void Switch::taEofConds()
+{
+ /*
+ * EOF Cond Spaces
+ */
+ eofCondSpaces.start();
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->outCondSpace != 0 )
+ eofCondSpaces.value( st->outCondSpace->condSpaceId );
+ else
+ eofCondSpaces.value( -1 );
+ }
+ eofCondSpaces.finish();
+
+ /*
+ * EOF Cond Key Indixes
+ */
+ eofCondKeyOffs.start();
+
+ int curOffset = 0;
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ long off = 0;
+ if ( st->outCondSpace != 0 ) {
+ off = curOffset;
+ curOffset += st->outCondKeys.length();
+ }
+ eofCondKeyOffs.value( off );
+ }
+
+ eofCondKeyOffs.finish();
+
+ /*
+ * EOF Cond Key Lengths.
+ */
+ eofCondKeyLens.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ long len = 0;
+ if ( st->outCondSpace != 0 )
+ len = st->outCondKeys.length();
+ eofCondKeyLens.value( len );
+ }
+
+ eofCondKeyLens.finish();
+
+ /*
+ * EOF Cond Keys
+ */
+ eofCondKeys.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->outCondSpace != 0 ) {
+ for ( int c = 0; c < st->outCondKeys.length(); c++ ) {
+ CondKey key = st->outCondKeys[c];
+ eofCondKeys.value( key.getVal() );
+ }
+ }
+ }
+
+ eofCondKeys.finish();
+}
+
+void Switch::taEofTrans()
+{
+ eofTrans.start();
+
+ /* Need to compute transition positions. */
+ int totalTrans = 0;
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ totalTrans += st->outSingle.length();
+ totalTrans += st->outRange.length();
+ if ( st->defTrans != 0 )
+ totalTrans += 1;
+ }
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ long trans = 0;
+ if ( st->eofTrans != 0 ) {
+ trans = totalTrans + 1;
+ totalTrans += 1;
+ }
+
+ eofTrans.value( trans );
+ }
+
+ eofTrans.finish();
+}
+
+void Switch::taKeys()
+{
+ transKeys.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ /* Loop the singles. */
+ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
+ transKeys.value( stel->lowKey.getVal() );
+ }
+
+ /* Loop the state's transitions. */
+ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
+ /* Lower key. */
+ transKeys.value( rtel->lowKey.getVal() );
+
+ /* Upper key. */
+ transKeys.value( rtel->highKey.getVal() );
+ }
+ }
+
+ transKeys.finish();
+}
+
+void Switch::taIndicies()
+{
+ indicies.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ /* Walk the singles. */
+ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ )
+ indicies.value( stel->value->id );
+
+ /* Walk the ranges. */
+ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ )
+ indicies.value( rtel->value->id );
+
+ /* The state's default index goes next. */
+ if ( st->defTrans != 0 )
+ indicies.value( st->defTrans->id );
+ }
+
+ indicies.finish();
+}
+
+void Switch::taTransCondSpaces()
+{
+ transCondSpaces.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ /* Walk the singles. */
+ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
+ RedTransAp *trans = stel->value;
+ if ( trans->condSpace != 0 )
+ transCondSpaces.value( trans->condSpace->condSpaceId );
+ else
+ transCondSpaces.value( -1 );
+ }
+
+ /* Walk the ranges. */
+ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
+ RedTransAp *trans = rtel->value;
+ if ( trans->condSpace != 0 )
+ transCondSpaces.value( trans->condSpace->condSpaceId );
+ else
+ transCondSpaces.value( -1 );
+ }
+
+ /* The state's default index goes next. */
+ if ( st->defTrans != 0 ) {
+ RedTransAp *trans = st->defTrans;
+ if ( trans->condSpace != 0 )
+ transCondSpaces.value( trans->condSpace->condSpaceId );
+ else
+ transCondSpaces.value( -1 );
+ }
+ }
+
+ /* Add any eof transitions that have not yet been written out above. */
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->eofTrans != 0 ) {
+ RedTransAp *trans = st->eofTrans;
+ if ( trans->condSpace != 0 )
+ transCondSpaces.value( trans->condSpace->condSpaceId );
+ else
+ transCondSpaces.value( -1 );
+ }
+ }
+
+ transCondSpaces.finish();
+}
+
+void Switch::taTransOffsets()
+{
+ transOffsets.start();
+
+ int curOffset = 0;
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ /* Walk the singles. */
+ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
+ RedTransAp *trans = stel->value;
+ transOffsets.value( curOffset );
+ curOffset += trans->numConds();
+ }
+
+ /* Walk the ranges. */
+ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
+ RedTransAp *trans = rtel->value;
+ transOffsets.value( curOffset );
+ curOffset += trans->numConds();
+ }
+
+ /* The state's default index goes next. */
+ if ( st->defTrans != 0 ) {
+ RedTransAp *trans = st->defTrans;
+ transOffsets.value( curOffset );
+ curOffset += trans->numConds();
+ }
+ }
+
+ /* Add any eof transitions that have not yet been written out above. */
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->eofTrans != 0 ) {
+ RedTransAp *trans = st->eofTrans;
+ transOffsets.value( curOffset );
+ curOffset += trans->numConds();
+ }
+ }
+
+ errCondOffset = curOffset;
+
+ transOffsets.finish();
+}
+
+void Switch::taTransLengths()
+{
+ transLengths.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ /* Walk the singles. */
+ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
+ RedTransAp *trans = stel->value;
+ transLengths.value( trans->numConds() );
+ }
+
+ /* Walk the ranges. */
+ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
+ RedTransAp *trans = rtel->value;
+ transLengths.value( trans->numConds() );
+ }
+
+ /* The state's default index goes next. */
+ if ( st->defTrans != 0 ) {
+ RedTransAp *trans = st->defTrans;
+ transLengths.value( trans->numConds() );
+ }
+ }
+
+ /* Add any eof transitions that have not yet been written out above. */
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->eofTrans != 0 ) {
+ RedTransAp *trans = st->eofTrans;
+ transLengths.value( trans->numConds() );
+ }
+ }
+
+ transLengths.finish();
+}
+
+void Switch::taTransCondSpacesWi()
+{
+ transCondSpacesWi.start();
+
+ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) {
+ /* Cond Space id. */
+ if ( trans->condSpace != 0 )
+ transCondSpacesWi.value( trans->condSpace->condSpaceId );
+ else
+ transCondSpacesWi.value( -1 );
+ }
+
+ transCondSpacesWi.finish();
+}
+
+void Switch::taTransOffsetsWi()
+{
+ transOffsetsWi.start();
+
+ int curOffset = 0;
+ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) {
+ transOffsetsWi.value( curOffset );
+
+ TransApSet::Iter next = trans;
+ next.increment();
+
+ curOffset += trans->numConds();
+ }
+
+ transOffsetsWi.finish();
+}
+
+void Switch::taTransLengthsWi()
+{
+ transLengthsWi.start();
+
+ for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) {
+ transLengthsWi.value( trans->numConds() );
+
+ TransApSet::Iter next = trans;
+ next.increment();
+ }
+
+ transLengthsWi.finish();
+}
+
+void Switch::taCondKeys()
+{
+ condKeys.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ /* Walk the singles. */
+ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
+ RedTransAp *trans = stel->value;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ CondKey key = trans->outCondKey( c );
+ condKeys.value( key.getVal() );
+ }
+ }
+
+ /* Walk the ranges. */
+ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
+ RedTransAp *trans = rtel->value;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ CondKey key = trans->outCondKey( c );
+ condKeys.value( key.getVal() );
+ }
+ }
+
+ /* The state's default index goes next. */
+ if ( st->defTrans != 0 ) {
+ RedTransAp *trans = st->defTrans;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ CondKey key = trans->outCondKey( c );
+ condKeys.value( key.getVal() );
+ }
+ }
+ }
+
+ /* Add any eof transitions that have not yet been written out above. */
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->eofTrans != 0 ) {
+ RedTransAp *trans = st->eofTrans;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ CondKey key = trans->outCondKey( c );
+ condKeys.value( key.getVal() );
+ }
+ }
+ }
+
+ condKeys.finish();
+}
+
+void Switch::taCondTargs()
+{
+ condTargs.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ /* Walk the singles. */
+ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
+ RedTransAp *trans = stel->value;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ RedCondPair *cond = trans->outCond( c );
+ condTargs.value( cond->targ->id );
+ }
+ }
+
+ /* Walk the ranges. */
+ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
+ RedTransAp *trans = rtel->value;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ RedCondPair *cond = trans->outCond( c );
+ condTargs.value( cond->targ->id );
+ }
+ }
+
+ /* The state's default index goes next. */
+ if ( st->defTrans != 0 ) {
+ RedTransAp *trans = st->defTrans;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ RedCondPair *cond = trans->outCond( c );
+ condTargs.value( cond->targ->id );
+ }
+ }
+ }
+
+ /* Add any eof transitions that have not yet been written out above. */
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->eofTrans != 0 ) {
+ RedTransAp *trans = st->eofTrans;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ RedCondPair *cond = trans->outCond( c );
+ condTargs.value( cond->targ->id );
+ }
+ }
+ }
+
+ if ( redFsm->errCond != 0 ) {
+ RedCondPair *cond = &redFsm->errCond->p;
+ condTargs.value( cond->targ->id );
+ }
+
+ condTargs.finish();
+}
+
+void Switch::taCondActions()
+{
+ condActions.start();
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ /* Walk the singles. */
+ for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
+ RedTransAp *trans = stel->value;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ RedCondPair *cond = trans->outCond( c );
+ COND_ACTION( cond );
+ }
+ }
+
+ /* Walk the ranges. */
+ for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
+ RedTransAp *trans = rtel->value;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ RedCondPair *cond = trans->outCond( c );
+ COND_ACTION( cond );
+ }
+ }
+
+ /* The state's default index goes next. */
+ if ( st->defTrans != 0 ) {
+ RedTransAp *trans = st->defTrans;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ RedCondPair *cond = trans->outCond(c);
+ COND_ACTION( cond );
+ }
+ }
+ }
+
+ /* Add any eof transitions that have not yet been written out above. */
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->eofTrans != 0 ) {
+ RedTransAp *trans = st->eofTrans;
+ for ( int c = 0; c < trans->numConds(); c++ ) {
+ RedCondPair *cond = trans->outCond(c);
+ COND_ACTION( cond );
+ }
+ }
+ }
+
+ if ( redFsm->errCond != 0 ) {
+ RedCondPair *cond = &redFsm->errCond->p;
+ COND_ACTION( cond );
+ }
+
+ condActions.finish();
+}
+
+void Switch::taNfaTargs()
+{
+ nfaTargs.start();
+
+ /* Offset of zero means no NFA targs, put a filler there. */
+ nfaTargs.value( 0 );
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->nfaTargs != 0 ) {
+ nfaTargs.value( st->nfaTargs->length() );
+ for ( RedNfaTargs::Iter targ = *st->nfaTargs; targ.lte(); targ++ )
+ nfaTargs.value( targ->state->id );
+ }
+ }
+
+ nfaTargs.finish();
+}
+
+/* These need to mirror nfa targs. */
+void Switch::taNfaPushActions()
+{
+ nfaPushActions.start();
+
+ nfaPushActions.value( 0 );
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->nfaTargs != 0 ) {
+ nfaPushActions.value( 0 );
+ for ( RedNfaTargs::Iter targ = *st->nfaTargs; targ.lte(); targ++ )
+ NFA_PUSH_ACTION( targ );
+ }
+ }
+
+ nfaPushActions.finish();
+}
+
+void Switch::taNfaPopTrans()
+{
+ nfaPopTrans.start();
+
+ nfaPopTrans.value( 0 );
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->nfaTargs != 0 ) {
+
+ nfaPopTrans.value( 0 );
+
+ for ( RedNfaTargs::Iter targ = *st->nfaTargs; targ.lte(); targ++ )
+ NFA_POP_TEST( targ );
+ }
+ }
+
+ nfaPopTrans.finish();
+}
+
+void Switch::taNfaOffsets()
+{
+ nfaOffsets.start();
+
+ /* Offset of zero means no NFA targs, real targs start at 1. */
+ long offset = 1;
+
+ for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
+ if ( st->nfaTargs == 0 ) {
+ nfaOffsets.value( 0 );
+ }
+ else {
+ nfaOffsets.value( offset );
+ offset += 1 + st->nfaTargs->length();
+ }
+ }
+
+ nfaOffsets.finish();
+}
+
+
+/* Write out the array of actions. */
+std::ostream &Switch::ACTIONS_ARRAY()
+{
+ out << "\t0, ";
+ int totalActions = 1;
+ for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
+ /* Write out the length, which will never be the last character. */
+ out << act->key.length() << ", ";
+ /* Put in a line break every 8 */
+ if ( totalActions++ % 8 == 7 )
+ out << "\n\t";
+
+ for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) {
+ out << item->value->actionId;
+ if ( ! (act.last() && item.last()) )
+ out << ", ";
+
+ /* Put in a line break every 8 */
+ if ( totalActions++ % 8 == 7 )
+ out << "\n\t";
+ }
+ }
+ out << "\n";
+ return out;
+}
+
+void Switch::taActions()
+{
+ actions.start();
+
+ /* Put "no-action" at the beginning. */
+ actions.value( 0 );
+
+ for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
+ /* Write out the length, which will never be the last character. */
+ actions.value( act->key.length() );
+
+ for ( GenActionTable::Iter item = act->key; item.lte(); item++ )
+ actions.value( item->value->actionId );
+ }
+
+ actions.finish();
+}
+
+
+
+