void FsmAp::fillGaps( StateAp *state ) { if ( state->outList.length() == 0 ) { /* Add the range on the lower and upper bound. */ attachNewTrans( state, 0, keyOps->minKey, keyOps->maxKey ); } else { TransList srcList; srcList.transfer( state->outList ); /* Check for a gap at the beginning. */ TransList::Iter trans = srcList, next; if ( keyOps->minKey < trans->lowKey ) { /* Make the high key and append. */ Key highKey = trans->lowKey; highKey.decrement(); attachNewTrans( state, 0, keyOps->minKey, highKey ); } /* Write the transition. */ next = trans.next(); state->outList.append( trans ); /* Keep the last high end. */ Key lastHigh = trans->highKey; /* Loop each source range. */ for ( trans = next; trans.lte(); trans = next ) { /* Make the next key following the last range. */ Key nextKey = lastHigh; nextKey.increment(); /* Check for a gap from last up to here. */ if ( nextKey < trans->lowKey ) { /* Make the high end of the range that fills the gap. */ Key highKey = trans->lowKey; highKey.decrement(); attachNewTrans( state, 0, nextKey, highKey ); } /* Reduce the transition. If it reduced to anything then add it. */ next = trans.next(); state->outList.append( trans ); /* Keep the last high end. */ lastHigh = trans->highKey; } /* Now check for a gap on the end to fill. */ if ( lastHigh < keyOps->maxKey ) { /* Get a copy of the default. */ lastHigh.increment(); attachNewTrans( state, 0, lastHigh, keyOps->maxKey ); } } }
void CodeGenData::newTrans( int snum, int tnum, Key lowKey, Key highKey, long targ, long action ) { /* Get the current state and range. */ RedStateAp *curState = allStates + snum; RedTransList &destRange = curState->outRange; if ( curState == redFsm->errState ) return; /* Make the new transitions. */ RedStateAp *targState = targ >= 0 ? (allStates + targ) : wantComplete ? redFsm->getErrorState() : 0; RedAction *actionTable = action >= 0 ? (allActionTables + action) : 0; RedTransAp *trans = redFsm->allocateTrans( targState, actionTable ); RedTransEl transEl( lowKey, highKey, trans ); if ( wantComplete ) { /* If the machine is to be complete then we need to fill any gaps with * the error transitions. */ if ( destRange.length() == 0 ) { /* Range is currently empty. */ if ( keyOps->minKey < lowKey ) { /* The first range doesn't start at the low end. */ Key fillHighKey = lowKey; fillHighKey.decrement(); /* Create the filler with the state's error transition. */ RedTransEl newTel( keyOps->minKey, fillHighKey, redFsm->getErrorTrans() ); destRange.append( newTel ); } } else { /* The range list is not empty, get the the last range. */ RedTransEl *last = &destRange[destRange.length()-1]; Key nextKey = last->highKey; nextKey.increment(); if ( nextKey < lowKey ) { /* There is a gap to fill. Make the high key. */ Key fillHighKey = lowKey; fillHighKey.decrement(); /* Create the filler with the state's error transtion. */ RedTransEl newTel( nextKey, fillHighKey, redFsm->getErrorTrans() ); destRange.append( newTel ); } } } /* Filler taken care of. Append the range. */ destRange.append( RedTransEl( lowKey, highKey, trans ) ); }
/* Check if we can extend the current range by displacing any ranges * ahead to the singles. */ bool RedFsmAp::canExtend( const RedTransList &list, int pos ) { /* Get the transition that we want to extend. */ RedTransAp *extendTrans = list[pos].value; /* Look ahead in the transition list. */ for ( int next = pos + 1; next < list.length(); pos++, next++ ) { /* If they are not continuous then cannot extend. */ Key nextKey = list[next].lowKey; nextKey.decrement(); if ( list[pos].highKey != nextKey ) break; /* Check for the extenstion property. */ if ( extendTrans == list[next].value ) return true; /* If the span of the next element is more than one, then don't keep * checking, it won't be moved to single. */ unsigned long long nextSpan = keyOps->span( list[next].lowKey, list[next].highKey ); if ( nextSpan > 1 ) break; } return false; }
bool FsmAp::outListCovers( StateAp *state ) { /* Must be at least one range to cover. */ if ( state->outList.length() == 0 ) return false; /* The first must start at the lower bound. */ TransList::Iter trans = state->outList.first(); if ( keyOps->minKey < trans->lowKey ) return false; /* Loop starts at second el. */ trans.increment(); /* Loop checks lower against prev upper. */ for ( ; trans.lte(); trans++ ) { /* Lower end of the trans must be one greater than the * previous' high end. */ Key lowKey = trans->lowKey; lowKey.decrement(); if ( trans->prev->highKey < lowKey ) return false; } /* Require that the last range extends to the upper bound. */ trans = state->outList.last(); if ( trans->highKey < keyOps->maxKey ) return false; return true; }
/* Merge neighboring transitions go to the same state and have the same * transitions data. */ void FsmAp::compressTransitions() { for ( StateList::Iter st = stateList; st.lte(); st++ ) { if ( st->outList.length() > 1 ) { for ( TransList::Iter trans = st->outList, next = trans.next(); next.lte(); ) { Key nextLow = next->lowKey; nextLow.decrement(); if ( trans->highKey == nextLow && trans->toState == next->toState && CmpActionTable::compare( trans->actionTable, next->actionTable ) == 0 ) { trans->highKey = next->highKey; st->outList.detach( next ); detachTrans( next->fromState, next->toState, next ); delete next; next = trans.next(); } else { trans.increment(); next.increment(); } } } } }