summaryrefslogtreecommitdiff
path: root/libfsm/goto.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libfsm/goto.cc')
-rw-r--r--libfsm/goto.cc978
1 files changed, 0 insertions, 978 deletions
diff --git a/libfsm/goto.cc b/libfsm/goto.cc
deleted file mode 100644
index 610f44d1..00000000
--- a/libfsm/goto.cc
+++ /dev/null
@@ -1,978 +0,0 @@
-/*
- * 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 "goto.h"
-#include "redfsm.h"
-#include "bstmap.h"
-#include "gendata.h"
-
-#include <sstream>
-
-using std::ostringstream;
-
-IpLabel *Goto::allocateLabels( IpLabel *labels, IpLabel::Type type, int n )
-{
- if ( labels == 0 ) {
- labels = new IpLabel[n];
- for ( int id = 0; id < n; id++ ) {
- labels[id].type = type;
- labels[id].stid = id;
- }
- }
-
- return labels;
-}
-
-void Goto::setTableState( TableArray::State state )
-{
- for ( ArrayVector::Iter i = arrayVector; i.lte(); i++ ) {
- TableArray *tableArray = *i;
- tableArray->setState( state );
- }
-}
-
-/* Emit the goto to take for a given transition. */
-std::ostream &Goto::COND_GOTO( RedCondPair *cond )
-{
- out << "goto " << ctrLabel[cond->id].reference() << ";";
- return out;
-}
-
-/* Emit the goto to take for a given transition. */
-std::ostream &Goto::TRANS_GOTO( RedTransAp *trans )
-{
- if ( trans->condSpace == 0 || trans->condSpace->condSet.length() == 0 ) {
- /* Existing. */
- assert( trans->numConds() == 1 );
- RedCondPair *cond = trans->outCond( 0 );
-
- /* Go to the transition which will go to the state. */
- out << "goto " << ctrLabel[cond->id].reference() << ";";
- }
- else {
- out << ck << " = 0;\n";
- for ( GenCondSet::Iter csi = trans->condSpace->condSet; csi.lte(); csi++ ) {
- out << "if ( ";
- CONDITION( out, *csi );
- Size condValOffset = (1 << csi.pos());
- out << " )\n" << ck << " += " << condValOffset << ";\n";
- }
- CondKey lower = 0;
- CondKey upper = trans->condFullSize() - 1;
- COND_B_SEARCH( trans, lower, upper, 0, trans->numConds()-1 );
-
- if ( trans->errCond() != 0 ) {
- COND_GOTO( trans->errCond() ) << "\n";
- }
- }
-
- return out;
-}
-
-/* Write out the array of actions. */
-void Goto::taActions()
-{
- actions.start();
-
- 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();
-}
-
-void Goto::GOTO_HEADER( RedStateAp *state )
-{
- /* Label the state. */
- out << "case " << state->id << ":\n";
-}
-
-
-void Goto::SINGLE_SWITCH( RedStateAp *state )
-{
- /* Load up the singles. */
- int numSingles = state->outSingle.length();
- RedTransEl *data = state->outSingle.data;
-
- if ( numSingles == 1 ) {
- /* If there is a single single key then write it out as an if. */
- out << "if ( " << GET_KEY() << " == " <<
- KEY(data[0].lowKey) << " ) {\n";
-
- /* Virtual function for writing the target of the transition. */
- TRANS_GOTO(data[0].value) << "\n";
- out << "}\n";
- }
- else if ( numSingles > 1 ) {
- /* Write out single keys in a switch if there is more than one. */
- out << "switch( " << GET_KEY() << " ) {\n";
-
- /* Write out the single indices. */
- for ( int j = 0; j < numSingles; j++ ) {
- out << "case " << KEY(data[j].lowKey) << ": {\n";
- TRANS_GOTO(data[j].value) << "\n";
- out << "}\n";
- }
-
- /* Close off the transition switch. */
- out << "}\n";
- }
-}
-
-void Goto::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(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(data[mid].value) << "\n";
- out << "}\n";
- }
- else {
- out << "} else if ( " << GET_KEY() << " <= " <<
- KEY(data[mid].highKey) << " ) {\n";
- TRANS_GOTO(data[mid].value) << "\n";
- 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(data[mid].value) << "\n";
- out << "}\n";
- }
- else {
- out << "} else if ( " << GET_KEY() << " >= " <<
- KEY(data[mid].lowKey) << " ) {\n";
- TRANS_GOTO(data[mid].value) << "\n";
- 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(data[mid].value) << "\n";
- out << "}\n";
- }
- else if ( limitLow && !limitHigh ) {
- out << "if ( " << GET_KEY() << " <= " <<
- KEY(data[mid].highKey) << " ) {\n";
- TRANS_GOTO(data[mid].value) << "\n";
- out << "}\n";
- }
- else if ( !limitLow && limitHigh ) {
- out << "if ( " << KEY(data[mid].lowKey) << " <= " <<
- GET_KEY() << " ) {\n";
- TRANS_GOTO(data[mid].value) << "\n";
- out << "}\n";
- }
- else {
- /* Both high and low are at the limit. No tests to do. */
- out << "{\n";
- TRANS_GOTO(data[mid].value) << "\n";
- out << "}\n";
- }
- }
-}
-
-/* Write out a key from the fsm code gen. Depends on wether or not the key is
- * signed. */
-string Goto::CKEY( CondKey key )
-{
- ostringstream ret;
- ret << key.getVal();
- return ret.str();
-}
-
-void Goto::COND_B_SEARCH( RedTransAp *trans, CondKey lower,
- CondKey upper, int low, int high )
-{
- /* Get the mid position, staying on the lower end of the range. */
- int mid = (low + high) >> 1;
-// RedCondEl *data = trans->outCond(0);
-
- /* Determine if we need to look higher or lower. */
- bool anyLower = mid > low;
- bool anyHigher = mid < high;
-
- CondKey midKey = trans->outCondKey( mid );
- RedCondPair *midTrans = trans->outCond( mid );
-
- /* Determine if the keys at mid are the limits of the alphabet. */
- bool limitLow = midKey == lower;
- bool limitHigh = midKey == upper;
-
- if ( anyLower && anyHigher ) {
- /* Can go lower and higher than mid. */
- out << "if ( " << ck << " < " <<
- CKEY(midKey) << " ) {\n";
- COND_B_SEARCH( trans, lower, midKey-1, low, mid-1 );
- out << "} else if ( " << ck << " > " <<
- CKEY(midKey) << " ) {\n";
- COND_B_SEARCH( trans, midKey+1, upper, mid+1, high );
- out << "} else {\n";
- COND_GOTO(midTrans) << "\n";
- out << "}\n";
- }
- else if ( anyLower && !anyHigher ) {
- /* Can go lower than mid but not higher. */
- out << "if ( " << ck << " < " <<
- CKEY(midKey) << " ) {\n";
- COND_B_SEARCH( trans, lower, midKey-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";
- COND_GOTO(midTrans) << "\n";
- out << "}\n";
- }
- else {
- out << "} else if ( " << ck << " <= " <<
- CKEY(midKey) << " ) {\n";
- COND_GOTO(midTrans) << "\n";
- out << "}\n";
- }
- }
- else if ( !anyLower && anyHigher ) {
- /* Can go higher than mid but not lower. */
- out << "if ( " << ck << " > " <<
- CKEY(midKey) << " ) {\n";
- COND_B_SEARCH( trans, midKey+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";
- COND_GOTO(midTrans) << "\n";
- out << "}\n";
- }
- else {
- out << "} else if ( " << ck << " >= " <<
- CKEY(midKey) << " ) {\n";
- COND_GOTO(midTrans) << "\n";
- 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 ( " << ck << " == " <<
- CKEY(midKey) << " ) {\n";
- COND_GOTO(midTrans) << "\n";
- out << "}\n";
- }
- else if ( limitLow && !limitHigh ) {
- out << "if ( " << ck << " <= " <<
- CKEY(midKey) << " ) {\n";
- COND_GOTO(midTrans) << "\n";
- out << "}\n";
- }
- else if ( !limitLow && limitHigh ) {
- out << "if ( " << CKEY(midKey) << " <= " << ck << " )\n {";
- COND_GOTO(midTrans) << "\n";
- out << "}\n";
- }
- else {
- /* Both high and low are at the limit. No tests to do. */
- COND_GOTO(midTrans) << "\n";
- }
- }
-}
-
-void Goto::STATE_GOTO_ERROR()
-{
- /* Bail out immediately. */
- out << " goto " << _again << ";\n";
-}
-
-void Goto::FROM_STATE_ACTION_EMIT( RedStateAp *state )
-{
- if ( state->fromStateAction != 0 ) {
- /* Write every action in the list. */
- for ( GenActionTable::Iter item = state->fromStateAction->key; item.lte(); item++ ) {
- ACTION( out, item->value, IlOpts( state->id, false,
- state->fromStateAction->anyNextStmt() ) );
- out << "\n";
- }
- }
-}
-
-std::ostream &Goto::STATE_CASES()
-{
- bool eof = redFsm->anyEofActivity() || redFsm->anyNfaStates();
-
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
- /* Writing code above state gotos. */
- GOTO_HEADER( st );
-
- FROM_STATE_ACTION_EMIT( st );
-
- if ( !noEnd && eof ) {
- out <<
- "if ( " << P() << " == " << vEOF() << " ) {\n";
-
- if ( st->eofTrans != 0 )
- TRANS_GOTO( st->eofTrans );
-
- out <<
- " goto " << _again << ";\n"
- "}\n"
- "else {\n";
- }
-
- if ( st == redFsm->errState )
- STATE_GOTO_ERROR();
- else {
- /* Try singles. */
- if ( st->outSingle.length() > 0 )
- SINGLE_SWITCH( st );
-
- /* Default case is to binary search for the ranges, if that fails then */
- if ( st->outRange.length() > 0 ) {
- RANGE_B_SEARCH( st, keyOps->minKey, keyOps->maxKey,
- 0, st->outRange.length() - 1 );
- }
-
- /* Write the default transition. */
- TRANS_GOTO( st->defTrans ) << "\n";
- }
-
- if ( !noEnd && eof ) {
- out <<
- "}\n";
- }
- }
- return out;
-}
-
-std::ostream &Goto::TRANSITION( RedCondPair *pair )
-{
- /* Write the label for the transition so it can be jumped to. */
- if ( ctrLabel[pair->id].isReferenced )
- out << "_ctr" << pair->id << ": ";
-
- /* Destination state. */
- if ( pair->action != 0 && pair->action->anyCurStateRef() )
- out << ps << " = " << vCS() << ";";
- out << vCS() << " = " << pair->targ->id << "; ";
-
- if ( pair->action != 0 ) {
- /* Write out the transition func. */
- out << "goto f" << pair->action->actListId << ";\n";
- }
- else {
- /* No code to execute, just loop around. */
- out << "goto " << _again << ";\n";
- }
- return out;
-}
-
-std::ostream &Goto::TRANSITIONS()
-{
- for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) {
- if ( trans->condSpace == 0 )
- TRANSITION( &trans->p );
- }
-
- for ( CondApSet::Iter cond = redFsm->condSet; cond.lte(); cond++ )
- TRANSITION( &cond->p );
-
- return out;
-}
-
-unsigned int Goto::TO_STATE_ACTION( RedStateAp *state )
-{
- int act = 0;
- if ( state->toStateAction != 0 )
- act = state->toStateAction->location+1;
- return act;
-}
-
-unsigned int Goto::FROM_STATE_ACTION( RedStateAp *state )
-{
- int act = 0;
- if ( state->fromStateAction != 0 )
- act = state->fromStateAction->location+1;
- return act;
-}
-
-unsigned int Goto::EOF_ACTION( RedStateAp *state )
-{
- int act = 0;
- if ( state->eofAction != 0 )
- act = state->eofAction->location+1;
- return act;
-}
-
-void Goto::taToStateActions()
-{
- toStateActions.start();
-
- /* Take one off for the psuedo start state. */
- int numStates = redFsm->stateList.length();
- unsigned int *vals = new unsigned int[numStates];
- memset( vals, 0, sizeof(unsigned int)*numStates );
-
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
- vals[st->id] = TO_STATE_ACTION(st);
-
- for ( int st = 0; st < redFsm->nextStateId; st++ ) {
- /* Write any eof action. */
- toStateActions.value( vals[st] );
- }
- delete[] vals;
-
- toStateActions.finish();
-}
-
-void Goto::taFromStateActions()
-{
- fromStateActions.start();
-
- /* Take one off for the psuedo start state. */
- int numStates = redFsm->stateList.length();
- unsigned int *vals = new unsigned int[numStates];
- memset( vals, 0, sizeof(unsigned int)*numStates );
-
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
- vals[st->id] = FROM_STATE_ACTION(st);
-
- for ( int st = 0; st < redFsm->nextStateId; st++ ) {
- /* Write any eof action. */
- fromStateActions.value( vals[st] );
- }
- delete[] vals;
-
- fromStateActions.finish();
-}
-
-void Goto::taEofActions()
-{
- eofActions.start();
-
- /* Take one off for the psuedo start state. */
- int numStates = redFsm->stateList.length();
- unsigned int *vals = new unsigned int[numStates];
- memset( vals, 0, sizeof(unsigned int)*numStates );
-
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ )
- vals[st->id] = EOF_ACTION(st);
-
- for ( int st = 0; st < redFsm->nextStateId; st++ ) {
- /* Write any eof action. */
- eofActions.value( vals[st] );
- }
- delete[] vals;
-
- eofActions.finish();
-}
-
-void Goto::taNfaOffsets()
-{
- nfaOffsets.start();
-
- /* Offset of zero means no NFA targs, real targs start at 1. */
- long offset = 1;
-
- /* Take one off for the psuedo start state. */
- int numStates = redFsm->stateList.length();
- unsigned int *vals = new unsigned int[numStates];
- memset( vals, 0, sizeof(unsigned int)*numStates );
-
- for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
- if ( st->nfaTargs == 0 ) {
- vals[st->id] = 0;
- //nfaOffsets.value( 0 );
- }
- else {
- vals[st->id] = offset;
- //nfaOffsets.value( offset );
- offset += 1 + st->nfaTargs->length();
- }
- }
-
- for ( int st = 0; st < redFsm->nextStateId; st++ )
- nfaOffsets.value( vals[st] );
- delete[] vals;
-
- nfaOffsets.finish();
-}
-
-void Goto::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 Goto::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 Goto::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 Goto::EOF_CHECK( ostream &ret )
-{
- ret <<
- " if ( " << P() << " == " << PE() << " )\n"
- " goto " << _test_eof << ";\n";
-}
-
-void Goto::GOTO( ostream &ret, int gotoDest, bool inFinish )
-{
- ret << OPEN_GEN_BLOCK() << vCS() << " = " << gotoDest << "; ";
-
- if ( inFinish && !noEnd )
- EOF_CHECK( ret );
-
- ret << "goto " << _again << ";";
-
- ret << CLOSE_GEN_BLOCK();
-}
-
-void Goto::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
-{
- ret << OPEN_GEN_BLOCK() << vCS() << " = " << OPEN_HOST_EXPR();
- INLINE_LIST( ret, ilItem->children, 0, inFinish, false );
- ret << CLOSE_HOST_EXPR() << ";";
-
- if ( inFinish && !noEnd )
- EOF_CHECK( ret );
-
- ret << " goto " << _again << ";";
-
- ret << CLOSE_GEN_BLOCK();
-}
-
-void Goto::CURS( ostream &ret, bool inFinish )
-{
- ret << "(" << ps << ")";
-}
-
-void Goto::TARGS( ostream &ret, bool inFinish, int targState )
-{
- ret << "(" << vCS() << ")";
-}
-
-void Goto::NEXT( ostream &ret, int nextDest, bool inFinish )
-{
- ret << vCS() << " = " << nextDest << ";";
-}
-
-void Goto::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
-{
- ret << vCS() << " = (";
- INLINE_LIST( ret, ilItem->children, 0, inFinish, false );
- ret << ");";
-}
-
-void Goto::CALL( ostream &ret, int callDest, int targState, bool inFinish )
-{
- ret << OPEN_GEN_BLOCK();
-
- if ( red->prePushExpr != 0 ) {
- ret << OPEN_HOST_BLOCK( red->prePushExpr );
- INLINE_LIST( ret, red->prePushExpr->inlineList, 0, false, false );
- ret << CLOSE_HOST_BLOCK();
- }
-
- ret << STACK() << "[" << TOP() << "] = " << vCS() << "; " <<
- TOP() << " += 1;" << vCS() << " = " <<
- callDest << ";";
-
- if ( inFinish && !noEnd )
- EOF_CHECK( ret );
-
- ret << " goto " << _again << ";";
-
- ret << CLOSE_GEN_BLOCK();
-}
-
-void Goto::NCALL( ostream &ret, int callDest, int targState, bool inFinish )
-{
- ret << OPEN_GEN_BLOCK();
-
- if ( red->prePushExpr != 0 ) {
- ret << OPEN_HOST_BLOCK( red->prePushExpr );
- INLINE_LIST( ret, red->prePushExpr->inlineList, 0, false, false );
- ret << CLOSE_HOST_BLOCK();
- }
-
- ret << STACK() << "[" << TOP() << "] = " << vCS() << "; " <<
- TOP() << " += 1;" << vCS() << " = " <<
- callDest << "; " << CLOSE_GEN_BLOCK();
-}
-
-void Goto::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
-{
- ret << OPEN_GEN_BLOCK();
-
- if ( red->prePushExpr != 0 ) {
- ret << OPEN_HOST_BLOCK( red->prePushExpr );
- INLINE_LIST( ret, red->prePushExpr->inlineList, 0, false, false );
- ret << CLOSE_HOST_BLOCK();
- }
-
- ret << STACK() << "[" << TOP() << "] = " << vCS() << "; " << TOP() << " += 1;" <<
- vCS() << " = " << OPEN_HOST_EXPR();
- INLINE_LIST( ret, ilItem->children, targState, inFinish, false );
- ret << CLOSE_HOST_EXPR() << ";";
-
- if ( inFinish && !noEnd )
- EOF_CHECK( ret );
-
- ret << " goto " << _again << ";";
-
- ret << CLOSE_GEN_BLOCK();
-}
-
-void Goto::NCALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
-{
- ret << OPEN_GEN_BLOCK();
-
- if ( red->prePushExpr != 0 ) {
- ret << OPEN_HOST_BLOCK( red->prePushExpr );
- INLINE_LIST( ret, red->prePushExpr->inlineList, 0, false, false );
- ret << CLOSE_HOST_BLOCK();
- }
-
- ret << STACK() << "[" << TOP() << "] = " << vCS() << "; " << TOP() << " += 1;" <<
- vCS() << " = " << OPEN_HOST_EXPR();
- INLINE_LIST( ret, ilItem->children, targState, inFinish, false );
- ret << CLOSE_HOST_EXPR() << "; " << CLOSE_GEN_BLOCK();
-}
-
-void Goto::RET( ostream &ret, bool inFinish )
-{
- ret << OPEN_GEN_BLOCK() << TOP() << "-= 1;" << vCS() << " = " << STACK() << "[" << TOP() << "];";
-
- if ( red->postPopExpr != 0 ) {
- ret << OPEN_HOST_BLOCK( red->postPopExpr );
- INLINE_LIST( ret, red->postPopExpr->inlineList, 0, false, false );
- ret << CLOSE_HOST_BLOCK();
- }
-
- if ( inFinish && !noEnd )
- EOF_CHECK( ret );
-
- ret << "goto " << _again << ";" << CLOSE_GEN_BLOCK();
-}
-
-void Goto::NRET( ostream &ret, bool inFinish )
-{
- ret << OPEN_GEN_BLOCK() << TOP() << "-= 1;" << vCS() << " = " << STACK() << "[" << TOP() << "];";
-
- if ( red->postPopExpr != 0 ) {
- ret << OPEN_HOST_BLOCK( red->postPopExpr );
- INLINE_LIST( ret, red->postPopExpr->inlineList, 0, false, false );
- ret << CLOSE_HOST_BLOCK();
- }
-
- ret << CLOSE_GEN_BLOCK();
-}
-
-void Goto::BREAK( ostream &ret, int targState, bool csForced )
-{
- ret << OPEN_GEN_BLOCK() << P() << " += 1; " << "goto " << _out << "; " << CLOSE_GEN_BLOCK();
-}
-
-void Goto::NBREAK( ostream &ret, int targState, bool csForced )
-{
- ret << OPEN_GEN_BLOCK() << P() << " += 1; " << nbreak << " = 1; " << CLOSE_GEN_BLOCK();
-}
-
-void Goto::tableDataPass()
-{
- if ( type == Loop )
- taActions();
-
- taToStateActions();
- taFromStateActions();
- taEofActions();
-
- taNfaTargs();
- taNfaOffsets();
- taNfaPushActions();
- taNfaPopTrans();
-}
-
-void Goto::genAnalysis()
-{
- /* For directly executable machines there is no required state
- * ordering. Choose a depth-first ordering to increase the
- * potential for fall-throughs. */
- redFsm->depthFirstOrdering();
-
- /* Choose default transitions and the single transition. */
- redFsm->chooseDefaultSpan();
-
- /* Choose single. */
- redFsm->moveSelectTransToSingle();
-
- /* 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();
-
- /* 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 Goto::writeData()
-{
- if ( type == Loop ) {
- if ( redFsm->anyActions() )
- taActions();
- }
-
- if ( redFsm->anyToStateActions() )
- taToStateActions();
-
- if ( redFsm->anyFromStateActions() )
- taFromStateActions();
-
- if ( redFsm->anyEofActions() )
- taEofActions();
-
- taNfaTargs();
- taNfaOffsets();
- taNfaPushActions();
- taNfaPopTrans();
-
- STATE_IDS();
-}
-
-void Goto::writeExec()
-{
- int maxCtrId = redFsm->nextCondId > redFsm->nextTransId ? redFsm->nextCondId : redFsm->nextTransId;
- ctrLabel = allocateLabels( ctrLabel, IpLabel::Ctr, maxCtrId );
-
- out << "{\n";
-
- DECLARE( INT(), cpc );
- DECLARE( INT(), ck );
- DECLARE( INT(), pop_test );
- DECLARE( INT(), nbreak );
- DECLARE( INT(), ps, " = 0" );
- DECLARE( INT(), new_recs );
- DECLARE( INT(), alt );
- DECLARE( INDEX( ARR_TYPE( actions ) ), acts );
- DECLARE( UINT(), nacts );
-
- out << "\n";
-
- out << EMIT_LABEL( _resume );
-
- /* Do we break out on no more input. */
- bool eof = redFsm->anyEofActivity() || redFsm->anyNfaStates();
- if ( !noEnd ) {
- if ( eof ) {
- out <<
- " if ( " << P() << " == " << PE() << " && " << P() << " != " << vEOF() << " )\n"
- " goto " << _out << ";\n";
- }
- else {
- out <<
- " if ( " << P() << " == " << PE() << " )\n"
- " goto " << _out << ";\n";
- }
- }
-
- NFA_PUSH( vCS() );
-
- out <<
- " switch ( " << vCS() << " ) {\n";
- STATE_CASES() <<
- " }\n"
- "\n";
- TRANSITIONS() <<
- "\n";
-
- if ( redFsm->anyRegActions() )
- EXEC_FUNCS() << "\n";
-
- out << EMIT_LABEL( _again );
-
- if ( !noEnd && eof ) {
- out <<
- " if ( " << P() << " == " << vEOF() << " ) {\n"
- " if ( " << vCS() << " >= " << FIRST_FINAL_STATE() << " )\n"
- " goto " << _out << ";\n"
- " }\n"
- " else {\n";
- }
-
- TO_STATE_ACTIONS();
-
- if ( redFsm->errState != 0 ) {
- out <<
- " if ( " << vCS() << " != " << redFsm->errState->id << " ) {\n";
- }
-
- out <<
- " " << P() << " += 1;\n"
- " goto " << _resume << ";\n";
-
- if ( redFsm->errState != 0 ) {
- out <<
- " }\n";
- }
-
- if ( !noEnd && eof ) {
- out <<
- " }\n";
- }
-
- if ( redFsm->anyNfaStates() ) {
- out <<
- " if ( nfa_len == 0 )\n"
- " goto " << _out << ";\n"
- "\n"
- " nfa_count += 1;\n"
- " nfa_len -= 1;\n"
- " " << P() << " = nfa_bp[nfa_len].p;\n"
- ;
-
- if ( redFsm->bAnyNfaPops ) {
- NFA_FROM_STATE_ACTION_EXEC();
-
- NFA_POP_TEST_EXEC();
-
- out <<
- " if ( " << pop_test << " )\n"
- " " << vCS() << " = nfa_bp[nfa_len].state;\n"
- " else\n"
- " " << vCS() << " = " << ERROR_STATE() << ";\n";
- }
- else {
- out <<
- " " << vCS() << " = nfa_bp[nfa_len].state;\n";
-
- }
-
- NFA_POST_POP();
-
- out << "goto " << _resume << ";\n";
- }
-
- out << EMIT_LABEL( _out );
-
- out << "}\n";
-}