diff options
author | smalov <[email protected]> | 2022-02-10 16:47:36 +0300 |
---|---|---|
committer | Daniil Cherednik <[email protected]> | 2022-02-10 16:47:36 +0300 |
commit | cfadda92ca195da3ad68d721a58872a4f1ced696 (patch) | |
tree | c0748b5dcbade83af788c0abfa89c0383d6b779c /contrib/tools/ragel6/cssplit.cpp | |
parent | f70d9720e13aef3a935e3f405b0eac554529e76e (diff) |
Restoring authorship annotation for <[email protected]>. Commit 2 of 2.
Diffstat (limited to 'contrib/tools/ragel6/cssplit.cpp')
-rw-r--r-- | contrib/tools/ragel6/cssplit.cpp | 1020 |
1 files changed, 510 insertions, 510 deletions
diff --git a/contrib/tools/ragel6/cssplit.cpp b/contrib/tools/ragel6/cssplit.cpp index 877dd21597c..8c7464f09ee 100644 --- a/contrib/tools/ragel6/cssplit.cpp +++ b/contrib/tools/ragel6/cssplit.cpp @@ -1,518 +1,518 @@ -/* - * Copyright 2006 Adrian Thurston <[email protected]> - */ - -/* This file is part of Ragel. +/* + * Copyright 2006 Adrian Thurston <[email protected]> + */ + +/* This file is part of Ragel. + * + * Ragel is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * Ragel is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * Ragel is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Ragel; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "ragel.h" -#include "cssplit.h" -#include "gendata.h" -#include <assert.h> - -using std::ostream; -using std::ios; -using std::endl; - -/* Emit the goto to take for a given transition. */ -std::ostream &CSharpSplitCodeGen::TRANS_GOTO( RedTransAp *trans, int level ) -{ - if ( trans->targ->partition == currentPartition ) { - if ( trans->action != 0 ) { - /* Go to the transition which will go to the state. */ - out << TABS(level) << "goto tr" << trans->id << ";"; - } - else { - /* Go directly to the target state. */ - out << TABS(level) << "goto st" << trans->targ->id << ";"; - } - } - else { - if ( trans->action != 0 ) { - /* Go to the transition which will go to the state. */ - out << TABS(level) << "goto ptr" << trans->id << ";"; - trans->partitionBoundary = true; - } - else { - /* Go directly to the target state. */ - out << TABS(level) << "goto pst" << trans->targ->id << ";"; - trans->targ->partitionBoundary = true; - } - } - return out; -} - -/* Called from before writing the gotos for each state. */ -void CSharpSplitCodeGen::GOTO_HEADER( RedStateAp *state, bool stateInPartition ) -{ - bool anyWritten = IN_TRANS_ACTIONS( state ); - - if ( state->labelNeeded ) - out << "st" << state->id << ":\n"; - - if ( state->toStateAction != 0 ) { - /* Remember that we wrote an action. Write every action in the list. */ - anyWritten = true; - for ( GenActionTable::Iter item = state->toStateAction->key; item.lte(); item++ ) - ACTION( out, item->value, state->id, false ); - } - - /* Advance and test buffer pos. */ - if ( state->labelNeeded ) { - if ( !noEnd ) { + * Ragel is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Ragel; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "ragel.h" +#include "cssplit.h" +#include "gendata.h" +#include <assert.h> + +using std::ostream; +using std::ios; +using std::endl; + +/* Emit the goto to take for a given transition. */ +std::ostream &CSharpSplitCodeGen::TRANS_GOTO( RedTransAp *trans, int level ) +{ + if ( trans->targ->partition == currentPartition ) { + if ( trans->action != 0 ) { + /* Go to the transition which will go to the state. */ + out << TABS(level) << "goto tr" << trans->id << ";"; + } + else { + /* Go directly to the target state. */ + out << TABS(level) << "goto st" << trans->targ->id << ";"; + } + } + else { + if ( trans->action != 0 ) { + /* Go to the transition which will go to the state. */ + out << TABS(level) << "goto ptr" << trans->id << ";"; + trans->partitionBoundary = true; + } + else { + /* Go directly to the target state. */ + out << TABS(level) << "goto pst" << trans->targ->id << ";"; + trans->targ->partitionBoundary = true; + } + } + return out; +} + +/* Called from before writing the gotos for each state. */ +void CSharpSplitCodeGen::GOTO_HEADER( RedStateAp *state, bool stateInPartition ) +{ + bool anyWritten = IN_TRANS_ACTIONS( state ); + + if ( state->labelNeeded ) + out << "st" << state->id << ":\n"; + + if ( state->toStateAction != 0 ) { + /* Remember that we wrote an action. Write every action in the list. */ + anyWritten = true; + for ( GenActionTable::Iter item = state->toStateAction->key; item.lte(); item++ ) + ACTION( out, item->value, state->id, false ); + } + + /* Advance and test buffer pos. */ + if ( state->labelNeeded ) { + if ( !noEnd ) { + out << + " if ( ++" << P() << " == " << PE() << " )\n" + " goto _out" << state->id << ";\n"; + } + else { out << - " if ( ++" << P() << " == " << PE() << " )\n" - " goto _out" << state->id << ";\n"; - } - else { - out << - " " << P() << " += 1;\n"; - } - } - - /* Give the state a switch case. */ - out << "case " << state->id << ":\n"; - - if ( state->fromStateAction != 0 ) { - /* Remember that we wrote an action. Write every action in the list. */ - anyWritten = true; - for ( GenActionTable::Iter item = state->fromStateAction->key; item.lte(); item++ ) - ACTION( out, item->value, state->id, false ); - } - - if ( anyWritten ) - genLineDirective( out ); - - /* Record the prev state if necessary. */ - if ( state->anyRegCurStateRef() ) - out << " _ps = " << state->id << ";\n"; -} - -std::ostream &CSharpSplitCodeGen::STATE_GOTOS( int partition ) -{ - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { - if ( st->partition == partition ) { - if ( st == redFsm->errState ) - STATE_GOTO_ERROR(); - else { - /* We call into the base of the goto which calls back into us - * using virtual functions. Set the current partition rather - * than coding parameter passing throughout. */ - currentPartition = partition; - - /* Writing code above state gotos. */ - GOTO_HEADER( st, st->partition == partition ); - - if ( st->stateCondVect.length() > 0 ) { - out << " _widec = " << GET_KEY() << ";\n"; - emitCondBSearch( st, 1, 0, st->stateCondVect.length() - 1 ); - } - - /* Try singles. */ - if ( st->outSingle.length() > 0 ) - emitSingleSwitch( st ); - - /* Default case is to binary search for the ranges, if that fails then */ - if ( st->outRange.length() > 0 ) - emitRangeBSearch( st, 1, 0, st->outRange.length() - 1 ); - - /* Write the default transition. */ - TRANS_GOTO( st->defTrans, 1 ) << "\n"; - } - } - } - return out; -} - - -std::ostream &CSharpSplitCodeGen::PART_TRANS( int partition ) -{ - for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { - if ( trans->partitionBoundary ) { - out << - "ptr" << trans->id << ":\n"; - - if ( trans->action != 0 ) { - /* If the action contains a next, then we must preload the current - * state since the action may or may not set it. */ - if ( trans->action->anyNextStmt() ) - out << " " << vCS() << " = " << trans->targ->id << ";\n"; - - /* Write each action in the list. */ - for ( GenActionTable::Iter item = trans->action->key; item.lte(); item++ ) - ACTION( out, item->value, trans->targ->id, false ); - } - + " " << P() << " += 1;\n"; + } + } + + /* Give the state a switch case. */ + out << "case " << state->id << ":\n"; + + if ( state->fromStateAction != 0 ) { + /* Remember that we wrote an action. Write every action in the list. */ + anyWritten = true; + for ( GenActionTable::Iter item = state->fromStateAction->key; item.lte(); item++ ) + ACTION( out, item->value, state->id, false ); + } + + if ( anyWritten ) + genLineDirective( out ); + + /* Record the prev state if necessary. */ + if ( state->anyRegCurStateRef() ) + out << " _ps = " << state->id << ";\n"; +} + +std::ostream &CSharpSplitCodeGen::STATE_GOTOS( int partition ) +{ + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { + if ( st->partition == partition ) { + if ( st == redFsm->errState ) + STATE_GOTO_ERROR(); + else { + /* We call into the base of the goto which calls back into us + * using virtual functions. Set the current partition rather + * than coding parameter passing throughout. */ + currentPartition = partition; + + /* Writing code above state gotos. */ + GOTO_HEADER( st, st->partition == partition ); + + if ( st->stateCondVect.length() > 0 ) { + out << " _widec = " << GET_KEY() << ";\n"; + emitCondBSearch( st, 1, 0, st->stateCondVect.length() - 1 ); + } + + /* Try singles. */ + if ( st->outSingle.length() > 0 ) + emitSingleSwitch( st ); + + /* Default case is to binary search for the ranges, if that fails then */ + if ( st->outRange.length() > 0 ) + emitRangeBSearch( st, 1, 0, st->outRange.length() - 1 ); + + /* Write the default transition. */ + TRANS_GOTO( st->defTrans, 1 ) << "\n"; + } + } + } + return out; +} + + +std::ostream &CSharpSplitCodeGen::PART_TRANS( int partition ) +{ + for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { + if ( trans->partitionBoundary ) { out << - " goto pst" << trans->targ->id << ";\n"; - trans->targ->partitionBoundary = true; - } - } - - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { - if ( st->partitionBoundary ) { - out << - " pst" << st->id << ":\n" - " " << vCS() << " = " << st->id << ";\n"; - - if ( st->toStateAction != 0 ) { - /* Remember that we wrote an action. Write every action in the list. */ - for ( GenActionTable::Iter item = st->toStateAction->key; item.lte(); item++ ) - ACTION( out, item->value, st->id, false ); - genLineDirective( out ); - } - - ptOutLabelUsed = true; - out << " goto _pt_out; \n"; - } - } - return out; -} - -std::ostream &CSharpSplitCodeGen::EXIT_STATES( int partition ) -{ - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { - if ( st->partition == partition && st->outNeeded ) { - outLabelUsed = true; - out << " _out" << st->id << ": " << vCS() << " = " << - st->id << "; goto _out; \n"; - } - } - return out; -} - - -std::ostream &CSharpSplitCodeGen::PARTITION( int partition ) -{ - outLabelUsed = false; - ptOutLabelUsed = false; - - /* Initialize the partition boundaries, which get set during the writing - * of states. After the state writing we will */ - for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) - trans->partitionBoundary = false; - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) - st->partitionBoundary = false; - - out << " " << ALPH_TYPE() << " *p = *_pp, *pe = *_ppe;\n"; - - if ( redFsm->anyRegCurStateRef() ) - out << " int _ps = 0;\n"; - - if ( redFsm->anyConditions() ) - out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; - - if ( useAgainLabel() ) { - out << - " goto _resume;\n" - "\n" - "_again:\n" - " switch ( " << vCS() << " ) {\n"; - AGAIN_CASES() << - " default: break;\n" - " }\n" - "\n"; - - - if ( !noEnd ) { - outLabelUsed = true; - out << - " if ( ++" << P() << " == " << PE() << " )\n" - " goto _out;\n"; - - } - else { - out << - " " << P() << " += 1;\n"; - } - - out << - "_resume:\n"; - } - - out << - " switch ( " << vCS() << " )\n {\n"; - STATE_GOTOS( partition ); - SWITCH_DEFAULT() << - " }\n"; - PART_TRANS( partition ); - EXIT_STATES( partition ); - - if ( outLabelUsed ) { - out << - "\n" - " _out:\n" - " *_pp = p;\n" - " *_ppe = pe;\n" - " return 0;\n"; - } - - if ( ptOutLabelUsed ) { + "ptr" << trans->id << ":\n"; + + if ( trans->action != 0 ) { + /* If the action contains a next, then we must preload the current + * state since the action may or may not set it. */ + if ( trans->action->anyNextStmt() ) + out << " " << vCS() << " = " << trans->targ->id << ";\n"; + + /* Write each action in the list. */ + for ( GenActionTable::Iter item = trans->action->key; item.lte(); item++ ) + ACTION( out, item->value, trans->targ->id, false ); + } + + out << + " goto pst" << trans->targ->id << ";\n"; + trans->targ->partitionBoundary = true; + } + } + + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { + if ( st->partitionBoundary ) { + out << + " pst" << st->id << ":\n" + " " << vCS() << " = " << st->id << ";\n"; + + if ( st->toStateAction != 0 ) { + /* Remember that we wrote an action. Write every action in the list. */ + for ( GenActionTable::Iter item = st->toStateAction->key; item.lte(); item++ ) + ACTION( out, item->value, st->id, false ); + genLineDirective( out ); + } + + ptOutLabelUsed = true; + out << " goto _pt_out; \n"; + } + } + return out; +} + +std::ostream &CSharpSplitCodeGen::EXIT_STATES( int partition ) +{ + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { + if ( st->partition == partition && st->outNeeded ) { + outLabelUsed = true; + out << " _out" << st->id << ": " << vCS() << " = " << + st->id << "; goto _out; \n"; + } + } + return out; +} + + +std::ostream &CSharpSplitCodeGen::PARTITION( int partition ) +{ + outLabelUsed = false; + ptOutLabelUsed = false; + + /* Initialize the partition boundaries, which get set during the writing + * of states. After the state writing we will */ + for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) + trans->partitionBoundary = false; + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) + st->partitionBoundary = false; + + out << " " << ALPH_TYPE() << " *p = *_pp, *pe = *_ppe;\n"; + + if ( redFsm->anyRegCurStateRef() ) + out << " int _ps = 0;\n"; + + if ( redFsm->anyConditions() ) + out << " " << WIDE_ALPH_TYPE() << " _widec;\n"; + + if ( useAgainLabel() ) { out << - "\n" - " _pt_out:\n" - " *_pp = p;\n" - " *_ppe = pe;\n" - " return 1;\n"; - } - - return out; -} - -std::ostream &CSharpSplitCodeGen::PART_MAP() -{ - int *partMap = new int[redFsm->stateList.length()]; - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) - partMap[st->id] = st->partition; - - out << "\t"; - int totalItem = 0; - for ( int i = 0; i < redFsm->stateList.length(); i++ ) { - out << partMap[i]; - if ( i != redFsm->stateList.length() - 1 ) { - out << ", "; - if ( ++totalItem % IALL == 0 ) - out << "\n\t"; - } - } - - delete[] partMap; - return out; -} - -void CSharpSplitCodeGen::writeData() -{ + " goto _resume;\n" + "\n" + "_again:\n" + " switch ( " << vCS() << " ) {\n"; + AGAIN_CASES() << + " default: break;\n" + " }\n" + "\n"; + + + if ( !noEnd ) { + outLabelUsed = true; + out << + " if ( ++" << P() << " == " << PE() << " )\n" + " goto _out;\n"; + + } + else { + out << + " " << P() << " += 1;\n"; + } + + out << + "_resume:\n"; + } + out << - "const int " << START() << " = " << START_STATE_ID() << ";\n" - "\n"; - - if ( !noFinal ) { + " switch ( " << vCS() << " )\n {\n"; + STATE_GOTOS( partition ); + SWITCH_DEFAULT() << + " }\n"; + PART_TRANS( partition ); + EXIT_STATES( partition ); + + if ( outLabelUsed ) { + out << + "\n" + " _out:\n" + " *_pp = p;\n" + " *_ppe = pe;\n" + " return 0;\n"; + } + + if ( ptOutLabelUsed ) { + out << + "\n" + " _pt_out:\n" + " *_pp = p;\n" + " *_ppe = pe;\n" + " return 1;\n"; + } + + return out; +} + +std::ostream &CSharpSplitCodeGen::PART_MAP() +{ + int *partMap = new int[redFsm->stateList.length()]; + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) + partMap[st->id] = st->partition; + + out << "\t"; + int totalItem = 0; + for ( int i = 0; i < redFsm->stateList.length(); i++ ) { + out << partMap[i]; + if ( i != redFsm->stateList.length() - 1 ) { + out << ", "; + if ( ++totalItem % IALL == 0 ) + out << "\n\t"; + } + } + + delete[] partMap; + return out; +} + +void CSharpSplitCodeGen::writeData() +{ + out << + "const int " << START() << " = " << START_STATE_ID() << ";\n" + "\n"; + + if ( !noFinal ) { + out << + "const int " << FIRST_FINAL() << " = " << FIRST_FINAL_STATE() << ";\n" + "\n"; + } + + if ( !noError ) { + out << + "const int " << ERROR() << " = " << ERROR_STATE() << ";\n" + "\n"; + } + + + OPEN_ARRAY( ARRAY_TYPE(numSplitPartitions), PM() ); + PART_MAP(); + CLOSE_ARRAY() << + "\n"; + + for ( int p = 0; p < redFsm->nParts; p++ ) { + out << "int partition" << p << "( " << ALPH_TYPE() << " **_pp, " << ALPH_TYPE() << + " **_ppe, struct " << FSM_NAME() << " *fsm );\n"; + } + out << "\n"; +} + +std::ostream &CSharpSplitCodeGen::ALL_PARTITIONS() +{ + /* compute the format string. */ + int width = 0, high = redFsm->nParts - 1; + while ( high > 0 ) { + width++; + high /= 10; + } + assert( width <= 8 ); + char suffFormat[] = "_%6.6d.c"; + suffFormat[2] = suffFormat[4] = ( '0' + width ); + + for ( int p = 0; p < redFsm->nParts; p++ ) { + char suffix[10]; + sprintf( suffix, suffFormat, p ); + const char *fn = fileNameFromStem( sourceFileName, suffix ); + const char *include = fileNameFromStem( sourceFileName, ".h" ); + + /* Create the filter on the output and open it. */ + output_filter *partFilter = new output_filter( fn ); + partFilter->open( fn, ios::out|ios::trunc ); + if ( !partFilter->is_open() ) { + error() << "error opening " << fn << " for writing" << endl; + exit(1); + } + + /* Attach the new file to the output stream. */ + std::streambuf *prev_rdbuf = out.rdbuf( partFilter ); + out << - "const int " << FIRST_FINAL() << " = " << FIRST_FINAL_STATE() << ";\n" - "\n"; - } - - if ( !noError ) { - out << - "const int " << ERROR() << " = " << ERROR_STATE() << ";\n" - "\n"; - } - - - OPEN_ARRAY( ARRAY_TYPE(numSplitPartitions), PM() ); - PART_MAP(); - CLOSE_ARRAY() << - "\n"; - - for ( int p = 0; p < redFsm->nParts; p++ ) { - out << "int partition" << p << "( " << ALPH_TYPE() << " **_pp, " << ALPH_TYPE() << - " **_ppe, struct " << FSM_NAME() << " *fsm );\n"; - } - out << "\n"; -} - -std::ostream &CSharpSplitCodeGen::ALL_PARTITIONS() -{ - /* compute the format string. */ - int width = 0, high = redFsm->nParts - 1; - while ( high > 0 ) { - width++; - high /= 10; - } - assert( width <= 8 ); - char suffFormat[] = "_%6.6d.c"; - suffFormat[2] = suffFormat[4] = ( '0' + width ); - - for ( int p = 0; p < redFsm->nParts; p++ ) { - char suffix[10]; - sprintf( suffix, suffFormat, p ); - const char *fn = fileNameFromStem( sourceFileName, suffix ); - const char *include = fileNameFromStem( sourceFileName, ".h" ); - - /* Create the filter on the output and open it. */ - output_filter *partFilter = new output_filter( fn ); - partFilter->open( fn, ios::out|ios::trunc ); - if ( !partFilter->is_open() ) { - error() << "error opening " << fn << " for writing" << endl; - exit(1); - } - - /* Attach the new file to the output stream. */ - std::streambuf *prev_rdbuf = out.rdbuf( partFilter ); - - out << - "#include \"" << include << "\"\n" - "int partition" << p << "( " << ALPH_TYPE() << " **_pp, " << ALPH_TYPE() << - " **_ppe, struct " << FSM_NAME() << " *fsm )\n" - "{\n"; - PARTITION( p ) << - "}\n\n"; - out.flush(); - - /* Fix the output stream. */ - out.rdbuf( prev_rdbuf ); - } - return out; -} - - -void CSharpSplitCodeGen::writeExec() -{ - /* Must set labels immediately before writing because we may depend on the - * noend write option. */ - setLabelsNeeded(); - out << - " {\n" - " int _stat = 0;\n"; - - if ( !noEnd ) { - out << - " if ( " << P() << " == " << PE() << " )\n" - " goto _out;\n"; - } - - out << " goto _resume;\n"; - - /* In this reentry, to-state actions have already been executed on the - * partition-switch exit from the last partition. */ - out << "_reenter:\n"; - - if ( !noEnd ) { - out << - " if ( ++" << P() << " == " << PE() << " )\n" - " goto _out;\n"; - } - else { - out << - " " << P() << " += 1;\n"; - } - - out << "_resume:\n"; - - out << - " switch ( " << PM() << "[" << vCS() << "] ) {\n"; - for ( int p = 0; p < redFsm->nParts; p++ ) { - out << - " case " << p << ":\n" - " _stat = partition" << p << "( &p, &pe, fsm );\n" - " break;\n"; - } + "#include \"" << include << "\"\n" + "int partition" << p << "( " << ALPH_TYPE() << " **_pp, " << ALPH_TYPE() << + " **_ppe, struct " << FSM_NAME() << " *fsm )\n" + "{\n"; + PARTITION( p ) << + "}\n\n"; + out.flush(); + + /* Fix the output stream. */ + out.rdbuf( prev_rdbuf ); + } + return out; +} + + +void CSharpSplitCodeGen::writeExec() +{ + /* Must set labels immediately before writing because we may depend on the + * noend write option. */ + setLabelsNeeded(); out << - " }\n" - " if ( _stat )\n" - " goto _reenter;\n"; - - if ( !noEnd ) - out << " _out: {}\n"; - + " {\n" + " int _stat = 0;\n"; + + if ( !noEnd ) { + out << + " if ( " << P() << " == " << PE() << " )\n" + " goto _out;\n"; + } + + out << " goto _resume;\n"; + + /* In this reentry, to-state actions have already been executed on the + * partition-switch exit from the last partition. */ + out << "_reenter:\n"; + + if ( !noEnd ) { + out << + " if ( ++" << P() << " == " << PE() << " )\n" + " goto _out;\n"; + } + else { + out << + " " << P() << " += 1;\n"; + } + + out << "_resume:\n"; + out << - " }\n"; - - ALL_PARTITIONS(); -} - -void CSharpSplitCodeGen::setLabelsNeeded( RedStateAp *fromState, GenInlineList *inlineList ) -{ - for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { - switch ( item->type ) { - case GenInlineItem::Goto: case GenInlineItem::Call: { - /* In split code gen we only need labels for transitions across - * partitions. */ - if ( fromState->partition == item->targState->partition ){ - /* Mark the target as needing a label. */ - item->targState->labelNeeded = true; - } - break; - } - default: break; - } - - if ( item->children != 0 ) - setLabelsNeeded( fromState, item->children ); - } -} - -void CSharpSplitCodeGen::setLabelsNeeded( RedStateAp *fromState, RedTransAp *trans ) -{ - /* In the split code gen we don't need labels for transitions across - * partitions. */ - if ( fromState->partition == trans->targ->partition ) { - /* If there is no action with a next statement, then the label will be - * needed. */ - trans->labelNeeded = true; - if ( trans->action == 0 || !trans->action->anyNextStmt() ) - trans->targ->labelNeeded = true; - } - - /* Need labels for states that have goto or calls in action code - * invoked on characters (ie, not from out action code). */ - if ( trans->action != 0 ) { - /* Loop the actions. */ - for ( GenActionTable::Iter act = trans->action->key; act.lte(); act++ ) { - /* Get the action and walk it's tree. */ - setLabelsNeeded( fromState, act->value->inlineList ); - } - } -} - -/* Set up labelNeeded flag for each state. */ -void CSharpSplitCodeGen::setLabelsNeeded() -{ - /* If we use the _again label, then we the _again switch, which uses all - * labels. */ - if ( useAgainLabel() ) { - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) - st->labelNeeded = true; - } - else { - /* Do not use all labels by default, init all labelNeeded vars to false. */ - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) - st->labelNeeded = false; - for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) - trans->labelNeeded = false; - - /* Walk all transitions and set only those that have targs. */ - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { - for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) - setLabelsNeeded( st, tel->value ); - - for ( RedTransList::Iter tel = st->outSingle; tel.lte(); tel++ ) - setLabelsNeeded( st, tel->value ); - - if ( st->defTrans != 0 ) - setLabelsNeeded( st, st->defTrans ); - } - } - - if ( !noEnd ) { - for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) - st->outNeeded = st->labelNeeded; - } - else { - if ( redFsm->errState != 0 ) - redFsm->errState->outNeeded = true; - - for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { - /* Any state with a transition in that has a break will need an - * out label. */ - if ( trans->action != 0 && trans->action->anyBreakStmt() ) - trans->targ->outNeeded = true; - } - } -} - + " switch ( " << PM() << "[" << vCS() << "] ) {\n"; + for ( int p = 0; p < redFsm->nParts; p++ ) { + out << + " case " << p << ":\n" + " _stat = partition" << p << "( &p, &pe, fsm );\n" + " break;\n"; + } + out << + " }\n" + " if ( _stat )\n" + " goto _reenter;\n"; + + if ( !noEnd ) + out << " _out: {}\n"; + + out << + " }\n"; + + ALL_PARTITIONS(); +} + +void CSharpSplitCodeGen::setLabelsNeeded( RedStateAp *fromState, GenInlineList *inlineList ) +{ + for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) { + switch ( item->type ) { + case GenInlineItem::Goto: case GenInlineItem::Call: { + /* In split code gen we only need labels for transitions across + * partitions. */ + if ( fromState->partition == item->targState->partition ){ + /* Mark the target as needing a label. */ + item->targState->labelNeeded = true; + } + break; + } + default: break; + } + + if ( item->children != 0 ) + setLabelsNeeded( fromState, item->children ); + } +} + +void CSharpSplitCodeGen::setLabelsNeeded( RedStateAp *fromState, RedTransAp *trans ) +{ + /* In the split code gen we don't need labels for transitions across + * partitions. */ + if ( fromState->partition == trans->targ->partition ) { + /* If there is no action with a next statement, then the label will be + * needed. */ + trans->labelNeeded = true; + if ( trans->action == 0 || !trans->action->anyNextStmt() ) + trans->targ->labelNeeded = true; + } + + /* Need labels for states that have goto or calls in action code + * invoked on characters (ie, not from out action code). */ + if ( trans->action != 0 ) { + /* Loop the actions. */ + for ( GenActionTable::Iter act = trans->action->key; act.lte(); act++ ) { + /* Get the action and walk it's tree. */ + setLabelsNeeded( fromState, act->value->inlineList ); + } + } +} + +/* Set up labelNeeded flag for each state. */ +void CSharpSplitCodeGen::setLabelsNeeded() +{ + /* If we use the _again label, then we the _again switch, which uses all + * labels. */ + if ( useAgainLabel() ) { + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) + st->labelNeeded = true; + } + else { + /* Do not use all labels by default, init all labelNeeded vars to false. */ + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) + st->labelNeeded = false; + for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) + trans->labelNeeded = false; + + /* Walk all transitions and set only those that have targs. */ + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) { + for ( RedTransList::Iter tel = st->outRange; tel.lte(); tel++ ) + setLabelsNeeded( st, tel->value ); + + for ( RedTransList::Iter tel = st->outSingle; tel.lte(); tel++ ) + setLabelsNeeded( st, tel->value ); + + if ( st->defTrans != 0 ) + setLabelsNeeded( st, st->defTrans ); + } + } + + if ( !noEnd ) { + for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) + st->outNeeded = st->labelNeeded; + } + else { + if ( redFsm->errState != 0 ) + redFsm->errState->outNeeded = true; + + for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ ) { + /* Any state with a transition in that has a break will need an + * out label. */ + if ( trans->action != 0 && trans->action->anyBreakStmt() ) + trans->targ->outNeeded = true; + } + } +} + |