fsmap.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. /*
  2. * Copyright 2002-2004 Adrian Thurston <thurston@complang.org>
  3. */
  4. /* This file is part of Ragel.
  5. *
  6. * Ragel is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Ragel is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Ragel; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #include "fsmgraph.h"
  21. #include <iostream>
  22. using std::cerr;
  23. using std::endl;
  24. CondData *condData = 0;
  25. KeyOps *keyOps = 0;
  26. /* Insert an action into an action table. */
  27. void ActionTable::setAction( int ordering, Action *action )
  28. {
  29. /* Multi-insert in case specific instances of an action appear in a
  30. * transition more than once. */
  31. insertMulti( ordering, action );
  32. }
  33. /* Set all the action from another action table in this table. */
  34. void ActionTable::setActions( const ActionTable &other )
  35. {
  36. for ( ActionTable::Iter action = other; action.lte(); action++ )
  37. insertMulti( action->key, action->value );
  38. }
  39. void ActionTable::setActions( int *orderings, Action **actions, int nActs )
  40. {
  41. for ( int a = 0; a < nActs; a++ )
  42. insertMulti( orderings[a], actions[a] );
  43. }
  44. bool ActionTable::hasAction( Action *action )
  45. {
  46. for ( int a = 0; a < length(); a++ ) {
  47. if ( data[a].value == action )
  48. return true;
  49. }
  50. return false;
  51. }
  52. /* Insert an action into an action table. */
  53. void LmActionTable::setAction( int ordering, LongestMatchPart *action )
  54. {
  55. /* Multi-insert in case specific instances of an action appear in a
  56. * transition more than once. */
  57. insertMulti( ordering, action );
  58. }
  59. /* Set all the action from another action table in this table. */
  60. void LmActionTable::setActions( const LmActionTable &other )
  61. {
  62. for ( LmActionTable::Iter action = other; action.lte(); action++ )
  63. insertMulti( action->key, action->value );
  64. }
  65. void ErrActionTable::setAction( int ordering, Action *action, int transferPoint )
  66. {
  67. insertMulti( ErrActionTableEl( action, ordering, transferPoint ) );
  68. }
  69. void ErrActionTable::setActions( const ErrActionTable &other )
  70. {
  71. for ( ErrActionTable::Iter act = other; act.lte(); act++ )
  72. insertMulti( ErrActionTableEl( act->action, act->ordering, act->transferPoint ) );
  73. }
  74. /* Insert a priority into this priority table. Looks out for priorities on
  75. * duplicate keys. */
  76. void PriorTable::setPrior( int ordering, PriorDesc *desc )
  77. {
  78. PriorEl *lastHit = 0;
  79. PriorEl *insed = insert( PriorEl(ordering, desc), &lastHit );
  80. if ( insed == 0 ) {
  81. /* This already has a priority on the same key as desc. Overwrite the
  82. * priority if the ordering is larger (later in time). */
  83. if ( ordering >= lastHit->ordering )
  84. *lastHit = PriorEl( ordering, desc );
  85. }
  86. }
  87. /* Set all the priorities from a priorTable in this table. */
  88. void PriorTable::setPriors( const PriorTable &other )
  89. {
  90. /* Loop src priorities once to overwrite duplicates. */
  91. PriorTable::Iter priorIt = other;
  92. for ( ; priorIt.lte(); priorIt++ )
  93. setPrior( priorIt->ordering, priorIt->desc );
  94. }
  95. /* Set the priority of starting transitions. Isolates the start state so it has
  96. * no other entry points, then sets the priorities of all the transitions out
  97. * of the start state. If the start state is final, then the outPrior of the
  98. * start state is also set. The idea is that a machine that accepts the null
  99. * string can still specify the starting trans prior for when it accepts the
  100. * null word. */
  101. void FsmAp::startFsmPrior( int ordering, PriorDesc *prior )
  102. {
  103. /* Make sure the start state has no other entry points. */
  104. isolateStartState();
  105. /* Walk all transitions out of the start state. */
  106. for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) {
  107. if ( trans->toState != 0 )
  108. trans->priorTable.setPrior( ordering, prior );
  109. }
  110. /* If the new start state is final then set the out priority. This follows
  111. * the same convention as setting start action in the out action table of
  112. * a final start state. */
  113. if ( startState->stateBits & STB_ISFINAL )
  114. startState->outPriorTable.setPrior( ordering, prior );
  115. }
  116. /* Set the priority of all transitions in a graph. Walks all transition lists
  117. * and all def transitions. */
  118. void FsmAp::allTransPrior( int ordering, PriorDesc *prior )
  119. {
  120. /* Walk the list of all states. */
  121. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  122. /* Walk the out list of the state. */
  123. for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
  124. if ( trans->toState != 0 )
  125. trans->priorTable.setPrior( ordering, prior );
  126. }
  127. }
  128. }
  129. /* Set the priority of all transitions that go into a final state. Note that if
  130. * any entry states are final, we will not be setting the priority of any
  131. * transitions that may go into those states in the future. The graph does not
  132. * support pending in transitions in the same way pending out transitions are
  133. * supported. */
  134. void FsmAp::finishFsmPrior( int ordering, PriorDesc *prior )
  135. {
  136. /* Walk all final states. */
  137. for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) {
  138. /* Walk all in transitions of the final state. */
  139. for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ )
  140. trans->priorTable.setPrior( ordering, prior );
  141. }
  142. }
  143. /* Set the priority of any future out transitions that may be made going out of
  144. * this state machine. */
  145. void FsmAp::leaveFsmPrior( int ordering, PriorDesc *prior )
  146. {
  147. /* Set priority in all final states. */
  148. for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
  149. (*state)->outPriorTable.setPrior( ordering, prior );
  150. }
  151. /* Set actions to execute on starting transitions. Isolates the start state
  152. * so it has no other entry points, then adds to the transition functions
  153. * of all the transitions out of the start state. If the start state is final,
  154. * then the func is also added to the start state's out func list. The idea is
  155. * that a machine that accepts the null string can execute a start func when it
  156. * matches the null word, which can only be done when leaving the start/final
  157. * state. */
  158. void FsmAp::startFsmAction( int ordering, Action *action )
  159. {
  160. /* Make sure the start state has no other entry points. */
  161. isolateStartState();
  162. /* Walk the start state's transitions, setting functions. */
  163. for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) {
  164. if ( trans->toState != 0 )
  165. trans->actionTable.setAction( ordering, action );
  166. }
  167. /* If start state is final then add the action to the out action table.
  168. * This means that when the null string is accepted the start action will
  169. * not be bypassed. */
  170. if ( startState->stateBits & STB_ISFINAL )
  171. startState->outActionTable.setAction( ordering, action );
  172. }
  173. /* Set functions to execute on all transitions. Walks the out lists of all
  174. * states. */
  175. void FsmAp::allTransAction( int ordering, Action *action )
  176. {
  177. /* Walk all states. */
  178. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  179. /* Walk the out list of the state. */
  180. for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
  181. if ( trans->toState != 0 )
  182. trans->actionTable.setAction( ordering, action );
  183. }
  184. }
  185. }
  186. /* Specify functions to execute upon entering final states. If the start state
  187. * is final we can't really specify a function to execute upon entering that
  188. * final state the first time. So function really means whenever entering a
  189. * final state from within the same fsm. */
  190. void FsmAp::finishFsmAction( int ordering, Action *action )
  191. {
  192. /* Walk all final states. */
  193. for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) {
  194. /* Walk the final state's in list. */
  195. for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ )
  196. trans->actionTable.setAction( ordering, action );
  197. }
  198. }
  199. /* Add functions to any future out transitions that may be made going out of
  200. * this state machine. */
  201. void FsmAp::leaveFsmAction( int ordering, Action *action )
  202. {
  203. /* Insert the action in the outActionTable of all final states. */
  204. for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
  205. (*state)->outActionTable.setAction( ordering, action );
  206. }
  207. /* Add functions to the longest match action table for constructing scanners. */
  208. void FsmAp::longMatchAction( int ordering, LongestMatchPart *lmPart )
  209. {
  210. /* Walk all final states. */
  211. for ( StateSet::Iter state = finStateSet; state.lte(); state++ ) {
  212. /* Walk the final state's in list. */
  213. for ( TransInList::Iter trans = (*state)->inList; trans.lte(); trans++ )
  214. trans->lmActionTable.setAction( ordering, lmPart );
  215. }
  216. }
  217. void FsmAp::fillGaps( StateAp *state )
  218. {
  219. if ( state->outList.length() == 0 ) {
  220. /* Add the range on the lower and upper bound. */
  221. attachNewTrans( state, 0, keyOps->minKey, keyOps->maxKey );
  222. }
  223. else {
  224. TransList srcList;
  225. srcList.transfer( state->outList );
  226. /* Check for a gap at the beginning. */
  227. TransList::Iter trans = srcList, next;
  228. if ( keyOps->minKey < trans->lowKey ) {
  229. /* Make the high key and append. */
  230. Key highKey = trans->lowKey;
  231. highKey.decrement();
  232. attachNewTrans( state, 0, keyOps->minKey, highKey );
  233. }
  234. /* Write the transition. */
  235. next = trans.next();
  236. state->outList.append( trans );
  237. /* Keep the last high end. */
  238. Key lastHigh = trans->highKey;
  239. /* Loop each source range. */
  240. for ( trans = next; trans.lte(); trans = next ) {
  241. /* Make the next key following the last range. */
  242. Key nextKey = lastHigh;
  243. nextKey.increment();
  244. /* Check for a gap from last up to here. */
  245. if ( nextKey < trans->lowKey ) {
  246. /* Make the high end of the range that fills the gap. */
  247. Key highKey = trans->lowKey;
  248. highKey.decrement();
  249. attachNewTrans( state, 0, nextKey, highKey );
  250. }
  251. /* Reduce the transition. If it reduced to anything then add it. */
  252. next = trans.next();
  253. state->outList.append( trans );
  254. /* Keep the last high end. */
  255. lastHigh = trans->highKey;
  256. }
  257. /* Now check for a gap on the end to fill. */
  258. if ( lastHigh < keyOps->maxKey ) {
  259. /* Get a copy of the default. */
  260. lastHigh.increment();
  261. attachNewTrans( state, 0, lastHigh, keyOps->maxKey );
  262. }
  263. }
  264. }
  265. void FsmAp::setErrorActions( StateAp *state, const ActionTable &other )
  266. {
  267. /* Fill any gaps in the out list with an error transition. */
  268. fillGaps( state );
  269. /* Set error transitions in the transitions that go to error. */
  270. for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
  271. if ( trans->toState == 0 )
  272. trans->actionTable.setActions( other );
  273. }
  274. }
  275. void FsmAp::setErrorAction( StateAp *state, int ordering, Action *action )
  276. {
  277. /* Fill any gaps in the out list with an error transition. */
  278. fillGaps( state );
  279. /* Set error transitions in the transitions that go to error. */
  280. for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
  281. if ( trans->toState == 0 )
  282. trans->actionTable.setAction( ordering, action );
  283. }
  284. }
  285. /* Give a target state for error transitions. */
  286. void FsmAp::setErrorTarget( StateAp *state, StateAp *target, int *orderings,
  287. Action **actions, int nActs )
  288. {
  289. /* Fill any gaps in the out list with an error transition. */
  290. fillGaps( state );
  291. /* Set error target in the transitions that go to error. */
  292. for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
  293. if ( trans->toState == 0 ) {
  294. /* The trans goes to error, redirect it. */
  295. redirectErrorTrans( trans->fromState, target, trans );
  296. trans->actionTable.setActions( orderings, actions, nActs );
  297. }
  298. }
  299. }
  300. void FsmAp::transferOutActions( StateAp *state )
  301. {
  302. for ( ActionTable::Iter act = state->outActionTable; act.lte(); act++ )
  303. state->eofActionTable.setAction( act->key, act->value );
  304. state->outActionTable.empty();
  305. }
  306. void FsmAp::transferErrorActions( StateAp *state, int transferPoint )
  307. {
  308. for ( int i = 0; i < state->errActionTable.length(); ) {
  309. ErrActionTableEl *act = state->errActionTable.data + i;
  310. if ( act->transferPoint == transferPoint ) {
  311. /* Transfer the error action and remove it. */
  312. setErrorAction( state, act->ordering, act->action );
  313. if ( ! state->isFinState() )
  314. state->eofActionTable.setAction( act->ordering, act->action );
  315. state->errActionTable.vremove( i );
  316. }
  317. else {
  318. /* Not transfering and deleting, skip over the item. */
  319. i += 1;
  320. }
  321. }
  322. }
  323. /* Set error actions in the start state. */
  324. void FsmAp::startErrorAction( int ordering, Action *action, int transferPoint )
  325. {
  326. /* Make sure the start state has no other entry points. */
  327. isolateStartState();
  328. /* Add the actions. */
  329. startState->errActionTable.setAction( ordering, action, transferPoint );
  330. }
  331. /* Set error actions in all states where there is a transition out. */
  332. void FsmAp::allErrorAction( int ordering, Action *action, int transferPoint )
  333. {
  334. /* Insert actions in the error action table of all states. */
  335. for ( StateList::Iter state = stateList; state.lte(); state++ )
  336. state->errActionTable.setAction( ordering, action, transferPoint );
  337. }
  338. /* Set error actions in final states. */
  339. void FsmAp::finalErrorAction( int ordering, Action *action, int transferPoint )
  340. {
  341. /* Add the action to the error table of final states. */
  342. for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
  343. (*state)->errActionTable.setAction( ordering, action, transferPoint );
  344. }
  345. void FsmAp::notStartErrorAction( int ordering, Action *action, int transferPoint )
  346. {
  347. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  348. if ( state != startState )
  349. state->errActionTable.setAction( ordering, action, transferPoint );
  350. }
  351. }
  352. void FsmAp::notFinalErrorAction( int ordering, Action *action, int transferPoint )
  353. {
  354. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  355. if ( ! state->isFinState() )
  356. state->errActionTable.setAction( ordering, action, transferPoint );
  357. }
  358. }
  359. /* Set error actions in the states that have transitions into a final state. */
  360. void FsmAp::middleErrorAction( int ordering, Action *action, int transferPoint )
  361. {
  362. /* Isolate the start state in case it is reachable from in inside the
  363. * machine, in which case we don't want it set. */
  364. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  365. if ( state != startState && ! state->isFinState() )
  366. state->errActionTable.setAction( ordering, action, transferPoint );
  367. }
  368. }
  369. /* Set EOF actions in the start state. */
  370. void FsmAp::startEOFAction( int ordering, Action *action )
  371. {
  372. /* Make sure the start state has no other entry points. */
  373. isolateStartState();
  374. /* Add the actions. */
  375. startState->eofActionTable.setAction( ordering, action );
  376. }
  377. /* Set EOF actions in all states where there is a transition out. */
  378. void FsmAp::allEOFAction( int ordering, Action *action )
  379. {
  380. /* Insert actions in the EOF action table of all states. */
  381. for ( StateList::Iter state = stateList; state.lte(); state++ )
  382. state->eofActionTable.setAction( ordering, action );
  383. }
  384. /* Set EOF actions in final states. */
  385. void FsmAp::finalEOFAction( int ordering, Action *action )
  386. {
  387. /* Add the action to the error table of final states. */
  388. for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
  389. (*state)->eofActionTable.setAction( ordering, action );
  390. }
  391. void FsmAp::notStartEOFAction( int ordering, Action *action )
  392. {
  393. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  394. if ( state != startState )
  395. state->eofActionTable.setAction( ordering, action );
  396. }
  397. }
  398. void FsmAp::notFinalEOFAction( int ordering, Action *action )
  399. {
  400. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  401. if ( ! state->isFinState() )
  402. state->eofActionTable.setAction( ordering, action );
  403. }
  404. }
  405. /* Set EOF actions in the states that have transitions into a final state. */
  406. void FsmAp::middleEOFAction( int ordering, Action *action )
  407. {
  408. /* Set the actions in all states that are not the start state and not final. */
  409. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  410. if ( state != startState && ! state->isFinState() )
  411. state->eofActionTable.setAction( ordering, action );
  412. }
  413. }
  414. /*
  415. * Set To State Actions.
  416. */
  417. /* Set to state actions in the start state. */
  418. void FsmAp::startToStateAction( int ordering, Action *action )
  419. {
  420. /* Make sure the start state has no other entry points. */
  421. isolateStartState();
  422. startState->toStateActionTable.setAction( ordering, action );
  423. }
  424. /* Set to state actions in all states. */
  425. void FsmAp::allToStateAction( int ordering, Action *action )
  426. {
  427. /* Insert the action on all states. */
  428. for ( StateList::Iter state = stateList; state.lte(); state++ )
  429. state->toStateActionTable.setAction( ordering, action );
  430. }
  431. /* Set to state actions in final states. */
  432. void FsmAp::finalToStateAction( int ordering, Action *action )
  433. {
  434. /* Add the action to the error table of final states. */
  435. for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
  436. (*state)->toStateActionTable.setAction( ordering, action );
  437. }
  438. void FsmAp::notStartToStateAction( int ordering, Action *action )
  439. {
  440. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  441. if ( state != startState )
  442. state->toStateActionTable.setAction( ordering, action );
  443. }
  444. }
  445. void FsmAp::notFinalToStateAction( int ordering, Action *action )
  446. {
  447. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  448. if ( ! state->isFinState() )
  449. state->toStateActionTable.setAction( ordering, action );
  450. }
  451. }
  452. /* Set to state actions in states that are not final and not the start state. */
  453. void FsmAp::middleToStateAction( int ordering, Action *action )
  454. {
  455. /* Set the action in all states that are not the start state and not final. */
  456. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  457. if ( state != startState && ! state->isFinState() )
  458. state->toStateActionTable.setAction( ordering, action );
  459. }
  460. }
  461. /*
  462. * Set From State Actions.
  463. */
  464. void FsmAp::startFromStateAction( int ordering, Action *action )
  465. {
  466. /* Make sure the start state has no other entry points. */
  467. isolateStartState();
  468. startState->fromStateActionTable.setAction( ordering, action );
  469. }
  470. void FsmAp::allFromStateAction( int ordering, Action *action )
  471. {
  472. /* Insert the action on all states. */
  473. for ( StateList::Iter state = stateList; state.lte(); state++ )
  474. state->fromStateActionTable.setAction( ordering, action );
  475. }
  476. void FsmAp::finalFromStateAction( int ordering, Action *action )
  477. {
  478. /* Add the action to the error table of final states. */
  479. for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
  480. (*state)->fromStateActionTable.setAction( ordering, action );
  481. }
  482. void FsmAp::notStartFromStateAction( int ordering, Action *action )
  483. {
  484. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  485. if ( state != startState )
  486. state->fromStateActionTable.setAction( ordering, action );
  487. }
  488. }
  489. void FsmAp::notFinalFromStateAction( int ordering, Action *action )
  490. {
  491. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  492. if ( ! state->isFinState() )
  493. state->fromStateActionTable.setAction( ordering, action );
  494. }
  495. }
  496. void FsmAp::middleFromStateAction( int ordering, Action *action )
  497. {
  498. /* Set the action in all states that are not the start state and not final. */
  499. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  500. if ( state != startState && ! state->isFinState() )
  501. state->fromStateActionTable.setAction( ordering, action );
  502. }
  503. }
  504. /* Shift the function ordering of the start transitions to start
  505. * at fromOrder and increase in units of 1. Useful before staring.
  506. * Returns the maximum number of order numbers used. */
  507. int FsmAp::shiftStartActionOrder( int fromOrder )
  508. {
  509. int maxUsed = 0;
  510. /* Walk the start state's transitions, shifting function ordering. */
  511. for ( TransList::Iter trans = startState->outList; trans.lte(); trans++ ) {
  512. /* Walk the function data for the transition and set the keys to
  513. * increasing values starting at fromOrder. */
  514. int curFromOrder = fromOrder;
  515. ActionTable::Iter action = trans->actionTable;
  516. for ( ; action.lte(); action++ )
  517. action->key = curFromOrder++;
  518. /* Keep track of the max number of orders used. */
  519. if ( curFromOrder - fromOrder > maxUsed )
  520. maxUsed = curFromOrder - fromOrder;
  521. }
  522. return maxUsed;
  523. }
  524. /* Remove all priorities. */
  525. void FsmAp::clearAllPriorities()
  526. {
  527. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  528. /* Clear out priority data. */
  529. state->outPriorTable.empty();
  530. /* Clear transition data from the out transitions. */
  531. for ( TransList::Iter trans = state->outList; trans.lte(); trans++ )
  532. trans->priorTable.empty();
  533. }
  534. }
  535. /* Zeros out the function ordering keys. This may be called before minimization
  536. * when it is known that no more fsm operations are going to be done. This
  537. * will achieve greater reduction as states will not be separated on the basis
  538. * of function ordering. */
  539. void FsmAp::nullActionKeys( )
  540. {
  541. /* For each state... */
  542. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  543. /* Walk the transitions for the state. */
  544. for ( TransList::Iter trans = state->outList; trans.lte(); trans++ ) {
  545. /* Walk the action table for the transition. */
  546. for ( ActionTable::Iter action = trans->actionTable;
  547. action.lte(); action++ )
  548. action->key = 0;
  549. /* Walk the action table for the transition. */
  550. for ( LmActionTable::Iter action = trans->lmActionTable;
  551. action.lte(); action++ )
  552. action->key = 0;
  553. }
  554. /* Null the action keys of the to state action table. */
  555. for ( ActionTable::Iter action = state->toStateActionTable;
  556. action.lte(); action++ )
  557. action->key = 0;
  558. /* Null the action keys of the from state action table. */
  559. for ( ActionTable::Iter action = state->fromStateActionTable;
  560. action.lte(); action++ )
  561. action->key = 0;
  562. /* Null the action keys of the out transtions. */
  563. for ( ActionTable::Iter action = state->outActionTable;
  564. action.lte(); action++ )
  565. action->key = 0;
  566. /* Null the action keys of the error action table. */
  567. for ( ErrActionTable::Iter action = state->errActionTable;
  568. action.lte(); action++ )
  569. action->ordering = 0;
  570. /* Null the action keys eof action table. */
  571. for ( ActionTable::Iter action = state->eofActionTable;
  572. action.lte(); action++ )
  573. action->key = 0;
  574. }
  575. }
  576. /* Walk the list of states and verify that non final states do not have out
  577. * data, that all stateBits are cleared, and that there are no states with
  578. * zero foreign in transitions. */
  579. void FsmAp::verifyStates()
  580. {
  581. for ( StateList::Iter state = stateList; state.lte(); state++ ) {
  582. /* Non final states should not have leaving data. */
  583. if ( ! (state->stateBits & STB_ISFINAL) ) {
  584. assert( state->outActionTable.length() == 0 );
  585. assert( state->outCondSet.length() == 0 );
  586. assert( state->outPriorTable.length() == 0 );
  587. }
  588. /* Data used in algorithms should be cleared. */
  589. assert( (state->stateBits & STB_BOTH) == 0 );
  590. assert( state->foreignInTrans > 0 );
  591. }
  592. }
  593. /* Compare two transitions according to their relative priority. Since the
  594. * base transition has no priority associated with it, the default is to
  595. * return equal. */
  596. int FsmAp::comparePrior( const PriorTable &priorTable1, const PriorTable &priorTable2 )
  597. {
  598. /* Looking for differing priorities on same keys. Need to concurrently
  599. * scan the priority lists. */
  600. PriorTable::Iter pd1 = priorTable1;
  601. PriorTable::Iter pd2 = priorTable2;
  602. while ( pd1.lte() && pd2.lte() ) {
  603. /* Check keys. */
  604. if ( pd1->desc->key < pd2->desc->key )
  605. pd1.increment();
  606. else if ( pd1->desc->key > pd2->desc->key )
  607. pd2.increment();
  608. /* Keys are the same, check priorities. */
  609. else if ( pd1->desc->priority < pd2->desc->priority )
  610. return -1;
  611. else if ( pd1->desc->priority > pd2->desc->priority )
  612. return 1;
  613. else {
  614. /* Keys and priorities are equal, advance both. */
  615. pd1.increment();
  616. pd2.increment();
  617. }
  618. }
  619. /* No differing priorities on the same key. */
  620. return 0;
  621. }
  622. /* Compares two transitions according to priority and functions. Pointers
  623. * should not be null. Does not consider to state or from state. Compare two
  624. * transitions according to the data contained in the transitions. Data means
  625. * any properties added to user transitions that may differentiate them. Since
  626. * the base transition has no data, the default is to return equal. */
  627. int FsmAp::compareTransData( TransAp *trans1, TransAp *trans2 )
  628. {
  629. /* Compare the prior table. */
  630. int cmpRes = CmpPriorTable::compare( trans1->priorTable,
  631. trans2->priorTable );
  632. if ( cmpRes != 0 )
  633. return cmpRes;
  634. /* Compare longest match action tables. */
  635. cmpRes = CmpLmActionTable::compare(trans1->lmActionTable,
  636. trans2->lmActionTable);
  637. if ( cmpRes != 0 )
  638. return cmpRes;
  639. /* Compare action tables. */
  640. return CmpActionTable::compare(trans1->actionTable,
  641. trans2->actionTable);
  642. }
  643. /* Callback invoked when another trans (or possibly this) is added into this
  644. * transition during the merging process. Draw in any properties of srcTrans
  645. * into this transition. AddInTrans is called when a new transitions is made
  646. * that will be a duplicate of another transition or a combination of several
  647. * other transitions. AddInTrans will be called for each transition that the
  648. * new transition is to represent. */
  649. void FsmAp::addInTrans( TransAp *destTrans, TransAp *srcTrans )
  650. {
  651. /* Protect against adding in from ourselves. */
  652. if ( srcTrans == destTrans ) {
  653. /* Adding in ourselves, need to make a copy of the source transitions.
  654. * The priorities are not copied in as that would have no effect. */
  655. destTrans->lmActionTable.setActions( LmActionTable(srcTrans->lmActionTable) );
  656. destTrans->actionTable.setActions( ActionTable(srcTrans->actionTable) );
  657. }
  658. else {
  659. /* Not a copy of ourself, get the functions and priorities. */
  660. destTrans->lmActionTable.setActions( srcTrans->lmActionTable );
  661. destTrans->actionTable.setActions( srcTrans->actionTable );
  662. destTrans->priorTable.setPriors( srcTrans->priorTable );
  663. }
  664. }
  665. /* Compare the properties of states that are embedded by users. Compares out
  666. * priorities, out transitions, to, from, out, error and eof action tables. */
  667. int FsmAp::compareStateData( const StateAp *state1, const StateAp *state2 )
  668. {
  669. /* Compare the out priority table. */
  670. int cmpRes = CmpPriorTable::
  671. compare( state1->outPriorTable, state2->outPriorTable );
  672. if ( cmpRes != 0 )
  673. return cmpRes;
  674. /* Test to state action tables. */
  675. cmpRes = CmpActionTable::compare( state1->toStateActionTable,
  676. state2->toStateActionTable );
  677. if ( cmpRes != 0 )
  678. return cmpRes;
  679. /* Test from state action tables. */
  680. cmpRes = CmpActionTable::compare( state1->fromStateActionTable,
  681. state2->fromStateActionTable );
  682. if ( cmpRes != 0 )
  683. return cmpRes;
  684. /* Test out action tables. */
  685. cmpRes = CmpActionTable::compare( state1->outActionTable,
  686. state2->outActionTable );
  687. if ( cmpRes != 0 )
  688. return cmpRes;
  689. /* Test out condition sets. */
  690. cmpRes = CmpOutCondSet::compare( state1->outCondSet,
  691. state2->outCondSet );
  692. if ( cmpRes != 0 )
  693. return cmpRes;
  694. /* Test out error action tables. */
  695. cmpRes = CmpErrActionTable::compare( state1->errActionTable,
  696. state2->errActionTable );
  697. if ( cmpRes != 0 )
  698. return cmpRes;
  699. /* Test eof action tables. */
  700. return CmpActionTable::compare( state1->eofActionTable,
  701. state2->eofActionTable );
  702. }
  703. /* Invoked when a state looses its final state status and the leaving
  704. * transition embedding data should be deleted. */
  705. void FsmAp::clearOutData( StateAp *state )
  706. {
  707. /* Kill the out actions and priorities. */
  708. state->outActionTable.empty();
  709. state->outCondSet.empty();
  710. state->outPriorTable.empty();
  711. }
  712. bool FsmAp::hasOutData( StateAp *state )
  713. {
  714. return ( state->outActionTable.length() > 0 ||
  715. state->outCondSet.length() > 0 ||
  716. state->outPriorTable.length() > 0 );
  717. }
  718. /*
  719. * Setting Conditions.
  720. */
  721. void logNewExpansion( Expansion *exp );
  722. void logCondSpace( CondSpace *condSpace );
  723. CondSpace *FsmAp::addCondSpace( const CondSet &condSet )
  724. {
  725. CondSpace *condSpace = condData->condSpaceMap.find( condSet );
  726. if ( condSpace == 0 ) {
  727. /* Do we have enough keyspace left? */
  728. Size availableSpace = condData->lastCondKey.availableSpace();
  729. Size neededSpace = (1 << condSet.length() ) * keyOps->alphSize();
  730. if ( neededSpace > availableSpace )
  731. throw FsmConstructFail( FsmConstructFail::CondNoKeySpace );
  732. Key baseKey = condData->lastCondKey;
  733. baseKey.increment();
  734. condData->lastCondKey += (1 << condSet.length() ) * keyOps->alphSize();
  735. condSpace = new CondSpace( condSet );
  736. condSpace->baseKey = baseKey;
  737. condData->condSpaceMap.insert( condSpace );
  738. #ifdef LOG_CONDS
  739. cerr << "adding new condition space" << endl;
  740. cerr << " condition set: ";
  741. logCondSpace( condSpace );
  742. cerr << endl;
  743. cerr << " baseKey: " << baseKey.getVal() << endl;
  744. #endif
  745. }
  746. return condSpace;
  747. }
  748. void FsmAp::startFsmCondition( Action *condAction, bool sense )
  749. {
  750. /* Make sure the start state has no other entry points. */
  751. isolateStartState();
  752. embedCondition( startState, condAction, sense );
  753. }
  754. void FsmAp::allTransCondition( Action *condAction, bool sense )
  755. {
  756. for ( StateList::Iter state = stateList; state.lte(); state++ )
  757. embedCondition( state, condAction, sense );
  758. }
  759. void FsmAp::leaveFsmCondition( Action *condAction, bool sense )
  760. {
  761. for ( StateSet::Iter state = finStateSet; state.lte(); state++ )
  762. (*state)->outCondSet.insert( OutCond( condAction, sense ) );
  763. }