Removed the write eof command.
[external/ragel.git] / rlgen-cd / flatcodegen.cpp
1 /*
2  *  Copyright 2004-2006 Adrian Thurston <thurston@cs.queensu.ca>
3  *            2004 Erich Ocean <eric.ocean@ampede.com>
4  *            2005 Alan West <alan@alanz.com>
5  */
6
7 /*  This file is part of Ragel.
8  *
9  *  Ragel is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  * 
14  *  Ragel is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  * 
19  *  You should have received a copy of the GNU General Public License
20  *  along with Ragel; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
22  */
23
24 #include "rlgen-cd.h"
25 #include "flatcodegen.h"
26 #include "redfsm.h"
27 #include "gendata.h"
28
29 std::ostream &FlatCodeGen::TO_STATE_ACTION( RedStateAp *state )
30 {
31         int act = 0;
32         if ( state->toStateAction != 0 )
33                 act = state->toStateAction->location+1;
34         out << act;
35         return out;
36 }
37
38 std::ostream &FlatCodeGen::FROM_STATE_ACTION( RedStateAp *state )
39 {
40         int act = 0;
41         if ( state->fromStateAction != 0 )
42                 act = state->fromStateAction->location+1;
43         out << act;
44         return out;
45 }
46
47 std::ostream &FlatCodeGen::EOF_ACTION( RedStateAp *state )
48 {
49         int act = 0;
50         if ( state->eofAction != 0 )
51                 act = state->eofAction->location+1;
52         out << act;
53         return out;
54 }
55
56 std::ostream &FlatCodeGen::TRANS_ACTION( RedTransAp *trans )
57 {
58         /* If there are actions, emit them. Otherwise emit zero. */
59         int act = 0;
60         if ( trans->action != 0 )
61                 act = trans->action->location+1;
62         out << act;
63         return out;
64 }
65
66 std::ostream &FlatCodeGen::TO_STATE_ACTION_SWITCH()
67 {
68         /* Walk the list of functions, printing the cases. */
69         for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
70                 /* Write out referenced actions. */
71                 if ( act->numToStateRefs > 0 ) {
72                         /* Write the case label, the action and the case break */
73                         out << "\tcase " << act->actionId << ":\n";
74                         ACTION( out, act, 0, false );
75                         out << "\tbreak;\n";
76                 }
77         }
78
79         genLineDirective( out );
80         return out;
81 }
82
83 std::ostream &FlatCodeGen::FROM_STATE_ACTION_SWITCH()
84 {
85         /* Walk the list of functions, printing the cases. */
86         for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
87                 /* Write out referenced actions. */
88                 if ( act->numFromStateRefs > 0 ) {
89                         /* Write the case label, the action and the case break */
90                         out << "\tcase " << act->actionId << ":\n";
91                         ACTION( out, act, 0, false );
92                         out << "\tbreak;\n";
93                 }
94         }
95
96         genLineDirective( out );
97         return out;
98 }
99
100 std::ostream &FlatCodeGen::EOF_ACTION_SWITCH()
101 {
102         /* Walk the list of functions, printing the cases. */
103         for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
104                 /* Write out referenced actions. */
105                 if ( act->numEofRefs > 0 ) {
106                         /* Write the case label, the action and the case break */
107                         out << "\tcase " << act->actionId << ":\n";
108                         ACTION( out, act, 0, true );
109                         out << "\tbreak;\n";
110                 }
111         }
112
113         genLineDirective( out );
114         return out;
115 }
116
117
118 std::ostream &FlatCodeGen::ACTION_SWITCH()
119 {
120         /* Walk the list of functions, printing the cases. */
121         for ( ActionList::Iter act = actionList; act.lte(); act++ ) {
122                 /* Write out referenced actions. */
123                 if ( act->numTransRefs > 0 ) {
124                         /* Write the case label, the action and the case break */
125                         out << "\tcase " << act->actionId << ":\n";
126                         ACTION( out, act, 0, false );
127                         out << "\tbreak;\n";
128                 }
129         }
130
131         genLineDirective( out );
132         return out;
133 }
134
135
136 std::ostream &FlatCodeGen::FLAT_INDEX_OFFSET()
137 {
138         out << "\t";
139         int totalStateNum = 0, curIndOffset = 0;
140         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
141                 /* Write the index offset. */
142                 out << curIndOffset;
143                 if ( !st.last() ) {
144                         out << ", ";
145                         if ( ++totalStateNum % IALL == 0 )
146                                 out << "\n\t";
147                 }
148                 
149                 /* Move the index offset ahead. */
150                 if ( st->transList != 0 )
151                         curIndOffset += keyOps->span( st->lowKey, st->highKey );
152
153                 if ( st->defTrans != 0 )
154                         curIndOffset += 1;
155         }
156         out << "\n";
157         return out;
158 }
159
160 std::ostream &FlatCodeGen::KEY_SPANS()
161 {
162         out << "\t";
163         int totalStateNum = 0;
164         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
165                 /* Write singles length. */
166                 unsigned long long span = 0;
167                 if ( st->transList != 0 )
168                         span = keyOps->span( st->lowKey, st->highKey );
169                 out << span;
170                 if ( !st.last() ) {
171                         out << ", ";
172                         if ( ++totalStateNum % IALL == 0 )
173                                 out << "\n\t";
174                 }
175         }
176         out << "\n";
177         return out;
178 }
179
180 std::ostream &FlatCodeGen::TO_STATE_ACTIONS()
181 {
182         out << "\t";
183         int totalStateNum = 0;
184         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
185                 /* Write any eof action. */
186                 TO_STATE_ACTION(st);
187                 if ( !st.last() ) {
188                         out << ", ";
189                         if ( ++totalStateNum % IALL == 0 )
190                                 out << "\n\t";
191                 }
192         }
193         out << "\n";
194         return out;
195 }
196
197 std::ostream &FlatCodeGen::FROM_STATE_ACTIONS()
198 {
199         out << "\t";
200         int totalStateNum = 0;
201         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
202                 /* Write any eof action. */
203                 FROM_STATE_ACTION(st);
204                 if ( !st.last() ) {
205                         out << ", ";
206                         if ( ++totalStateNum % IALL == 0 )
207                                 out << "\n\t";
208                 }
209         }
210         out << "\n";
211         return out;
212 }
213
214 std::ostream &FlatCodeGen::EOF_ACTIONS()
215 {
216         out << "\t";
217         int totalStateNum = 0;
218         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
219                 /* Write any eof action. */
220                 EOF_ACTION(st);
221                 if ( !st.last() ) {
222                         out << ", ";
223                         if ( ++totalStateNum % IALL == 0 )
224                                 out << "\n\t";
225                 }
226         }
227         out << "\n";
228         return out;
229 }
230
231 std::ostream &FlatCodeGen::COND_KEYS()
232 {
233         out << '\t';
234         int totalTrans = 0;
235         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
236                 /* Emit just cond low key and cond high key. */
237                 out << KEY( st->condLowKey ) << ", ";
238                 out << KEY( st->condHighKey ) << ", ";
239                 if ( ++totalTrans % IALL == 0 )
240                         out << "\n\t";
241         }
242
243         /* Output one last number so we don't have to figure out when the last
244          * entry is and avoid writing a comma. */
245         out << 0 << "\n";
246         return out;
247 }
248
249 std::ostream &FlatCodeGen::COND_KEY_SPANS()
250 {
251         out << "\t";
252         int totalStateNum = 0;
253         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
254                 /* Write singles length. */
255                 unsigned long long span = 0;
256                 if ( st->condList != 0 )
257                         span = keyOps->span( st->condLowKey, st->condHighKey );
258                 out << span;
259                 if ( !st.last() ) {
260                         out << ", ";
261                         if ( ++totalStateNum % IALL == 0 )
262                                 out << "\n\t";
263                 }
264         }
265         out << "\n";
266         return out;
267 }
268
269 std::ostream &FlatCodeGen::CONDS()
270 {
271         int totalTrans = 0;
272         out << '\t';
273         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
274                 if ( st->condList != 0 ) {
275                         /* Walk the singles. */
276                         unsigned long long span = keyOps->span( st->condLowKey, st->condHighKey );
277                         for ( unsigned long long pos = 0; pos < span; pos++ ) {
278                                 if ( st->condList[pos] != 0 )
279                                         out << st->condList[pos]->condSpaceId + 1 << ", ";
280                                 else
281                                         out << "0, ";
282                                 if ( ++totalTrans % IALL == 0 )
283                                         out << "\n\t";
284                         }
285                 }
286         }
287
288         /* Output one last number so we don't have to figure out when the last
289          * entry is and avoid writing a comma. */
290         out << 0 << "\n";
291         return out;
292 }
293
294 std::ostream &FlatCodeGen::COND_INDEX_OFFSET()
295 {
296         out << "\t";
297         int totalStateNum = 0, curIndOffset = 0;
298         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
299                 /* Write the index offset. */
300                 out << curIndOffset;
301                 if ( !st.last() ) {
302                         out << ", ";
303                         if ( ++totalStateNum % IALL == 0 )
304                                 out << "\n\t";
305                 }
306                 
307                 /* Move the index offset ahead. */
308                 if ( st->condList != 0 )
309                         curIndOffset += keyOps->span( st->condLowKey, st->condHighKey );
310         }
311         out << "\n";
312         return out;
313 }
314
315
316 std::ostream &FlatCodeGen::KEYS()
317 {
318         out << '\t';
319         int totalTrans = 0;
320         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
321                 /* Emit just low key and high key. */
322                 out << KEY( st->lowKey ) << ", ";
323                 out << KEY( st->highKey ) << ", ";
324                 if ( ++totalTrans % IALL == 0 )
325                         out << "\n\t";
326         }
327
328         /* Output one last number so we don't have to figure out when the last
329          * entry is and avoid writing a comma. */
330         out << 0 << "\n";
331         return out;
332 }
333
334 std::ostream &FlatCodeGen::INDICIES()
335 {
336         int totalTrans = 0;
337         out << '\t';
338         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
339                 if ( st->transList != 0 ) {
340                         /* Walk the singles. */
341                         unsigned long long span = keyOps->span( st->lowKey, st->highKey );
342                         for ( unsigned long long pos = 0; pos < span; pos++ ) {
343                                 out << st->transList[pos]->id << ", ";
344                                 if ( ++totalTrans % IALL == 0 )
345                                         out << "\n\t";
346                         }
347                 }
348
349                 /* The state's default index goes next. */
350                 if ( st->defTrans != 0 )
351                         out << st->defTrans->id << ", ";
352
353                 if ( ++totalTrans % IALL == 0 )
354                         out << "\n\t";
355         }
356
357         /* Output one last number so we don't have to figure out when the last
358          * entry is and avoid writing a comma. */
359         out << 0 << "\n";
360         return out;
361 }
362
363 std::ostream &FlatCodeGen::TRANS_TARGS()
364 {
365         /* Transitions must be written ordered by their id. */
366         RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
367         for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
368                 transPtrs[trans->id] = trans;
369
370         /* Keep a count of the num of items in the array written. */
371         out << '\t';
372         int totalStates = 0;
373         for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
374                 /* Write out the target state. */
375                 RedTransAp *trans = transPtrs[t];
376                 out << trans->targ->id;
377                 if ( t < redFsm->transSet.length()-1 ) {
378                         out << ", ";
379                         if ( ++totalStates % IALL == 0 )
380                                 out << "\n\t";
381                 }
382         }
383         out << "\n";
384         delete[] transPtrs;
385         return out;
386 }
387
388
389 std::ostream &FlatCodeGen::TRANS_ACTIONS()
390 {
391         /* Transitions must be written ordered by their id. */
392         RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
393         for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
394                 transPtrs[trans->id] = trans;
395
396         /* Keep a count of the num of items in the array written. */
397         out << '\t';
398         int totalAct = 0;
399         for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
400                 /* Write the function for the transition. */
401                 RedTransAp *trans = transPtrs[t];
402                 TRANS_ACTION( trans );
403                 if ( t < redFsm->transSet.length()-1 ) {
404                         out << ", ";
405                         if ( ++totalAct % IALL == 0 )
406                                 out << "\n\t";
407                 }
408         }
409         out << "\n";
410         delete[] transPtrs;
411         return out;
412 }
413
414 void FlatCodeGen::LOCATE_TRANS()
415 {
416         out <<
417                 "       _keys = " << ARR_OFF( K(), "(" + CS() + "<<1)" ) << ";\n"
418                 "       _inds = " << ARR_OFF( I(), IO() + "[" + CS() + "]" ) << ";\n"
419                 "\n"
420                 "       _slen = " << SP() << "[" << CS() << "];\n"
421                 "       _trans = _inds[ _slen > 0 && _keys[0] <=" << GET_WIDE_KEY() << " &&\n"
422                 "               " << GET_WIDE_KEY() << " <= _keys[1] ?\n"
423                 "               " << GET_WIDE_KEY() << " - _keys[0] : _slen ];\n"
424                 "\n";
425 }
426
427 void FlatCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
428 {
429         ret << "{" << CS() << " = " << gotoDest << "; " << 
430                         CTRL_FLOW() << "goto _again;}";
431 }
432
433 void FlatCodeGen::GOTO_EXPR( ostream &ret, InlineItem *ilItem, bool inFinish )
434 {
435         ret << "{" << CS() << " = (";
436         INLINE_LIST( ret, ilItem->children, 0, inFinish );
437         ret << "); " << CTRL_FLOW() << "goto _again;}";
438 }
439
440 void FlatCodeGen::CURS( ostream &ret, bool inFinish )
441 {
442         ret << "(_ps)";
443 }
444
445 void FlatCodeGen::TARGS( ostream &ret, bool inFinish, int targState )
446 {
447         ret << "(" << CS() << ")";
448 }
449
450 void FlatCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
451 {
452         ret << CS() << " = " << nextDest << ";";
453 }
454
455 void FlatCodeGen::NEXT_EXPR( ostream &ret, InlineItem *ilItem, bool inFinish )
456 {
457         ret << CS() << " = (";
458         INLINE_LIST( ret, ilItem->children, 0, inFinish );
459         ret << ");";
460 }
461
462 void FlatCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
463 {
464         if ( prePushExpr != 0 ) {
465                 ret << "{";
466                 INLINE_LIST( ret, prePushExpr, 0, false );
467         }
468
469         ret << "{" << STACK() << "[" << TOP() << "++] = " << CS() << "; " << CS() << " = " << 
470                         callDest << "; " << CTRL_FLOW() << "goto _again;}";
471
472         if ( prePushExpr != 0 )
473                 ret << "}";
474 }
475
476
477 void FlatCodeGen::CALL_EXPR( ostream &ret, InlineItem *ilItem, int targState, bool inFinish )
478 {
479         if ( prePushExpr != 0 ) {
480                 ret << "{";
481                 INLINE_LIST( ret, prePushExpr, 0, false );
482         }
483
484         ret << "{" << STACK() << "[" << TOP() << "++] = " << CS() << "; " << CS() << " = (";
485         INLINE_LIST( ret, ilItem->children, targState, inFinish );
486         ret << "); " << CTRL_FLOW() << "goto _again;}";
487
488         if ( prePushExpr != 0 )
489                 ret << "}";
490 }
491
492
493 void FlatCodeGen::RET( ostream &ret, bool inFinish )
494 {
495         ret << "{" << CS() << " = " << STACK() << "[--" << TOP() << "];";
496
497         if ( postPopExpr != 0 ) {
498                 ret << "{";
499                 INLINE_LIST( ret, postPopExpr, 0, false );
500                 ret << "}";
501         }
502
503         ret << CTRL_FLOW() << "goto _again;}";
504 }
505
506 void FlatCodeGen::BREAK( ostream &ret, int targState )
507 {
508         outLabelUsed = true;
509         ret << CTRL_FLOW() << "goto _out;";
510 }
511
512 void FlatCodeGen::writeData()
513 {
514         /* If there are any transtion functions then output the array. If there
515          * are none, don't bother emitting an empty array that won't be used. */
516         if ( redFsm->anyActions() ) {
517                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
518                 ACTIONS_ARRAY();
519                 CLOSE_ARRAY() <<
520                 "\n";
521         }
522
523         if ( redFsm->anyConditions() ) {
524                 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
525                 COND_KEYS();
526                 CLOSE_ARRAY() <<
527                 "\n";
528
529                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() );
530                 COND_KEY_SPANS();
531                 CLOSE_ARRAY() <<
532                 "\n";
533
534                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() );
535                 CONDS();
536                 CLOSE_ARRAY() <<
537                 "\n";
538
539                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() );
540                 COND_INDEX_OFFSET();
541                 CLOSE_ARRAY() <<
542                 "\n";
543         }
544
545         OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
546         KEYS();
547         CLOSE_ARRAY() <<
548         "\n";
549
550         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() );
551         KEY_SPANS();
552         CLOSE_ARRAY() <<
553         "\n";
554
555         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() );
556         FLAT_INDEX_OFFSET();
557         CLOSE_ARRAY() <<
558         "\n";
559
560         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
561         INDICIES();
562         CLOSE_ARRAY() <<
563         "\n";
564
565         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
566         TRANS_TARGS();
567         CLOSE_ARRAY() <<
568         "\n";
569
570         if ( redFsm->anyActions() ) {
571                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
572                 TRANS_ACTIONS();
573                 CLOSE_ARRAY() <<
574                 "\n";
575         }
576
577         if ( redFsm->anyToStateActions() ) {
578                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
579                 TO_STATE_ACTIONS();
580                 CLOSE_ARRAY() <<
581                 "\n";
582         }
583
584         if ( redFsm->anyFromStateActions() ) {
585                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
586                 FROM_STATE_ACTIONS();
587                 CLOSE_ARRAY() <<
588                 "\n";
589         }
590
591         if ( redFsm->anyEofActions() ) {
592                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
593                 EOF_ACTIONS();
594                 CLOSE_ARRAY() <<
595                 "\n";
596         }
597
598         STATE_IDS();
599 }
600
601 void FlatCodeGen::COND_TRANSLATE()
602 {
603         out << 
604                 "       _widec = " << GET_KEY() << ";\n";
605
606         out <<
607                 "       _keys = " << ARR_OFF( CK(), "(" + CS() + "<<1)" ) << ";\n"
608                 "       _conds = " << ARR_OFF( C(), CO() + "[" + CS() + "]" ) << ";\n"
609                 "\n"
610                 "       _slen = " << CSP() << "[" << CS() << "];\n"
611                 "       _cond = _slen > 0 && _keys[0] <=" << GET_WIDE_KEY() << " &&\n"
612                 "               " << GET_WIDE_KEY() << " <= _keys[1] ?\n"
613                 "               _conds[" << GET_WIDE_KEY() << " - _keys[0]] : 0;\n"
614                 "\n";
615
616         out <<
617                 "       switch ( _cond ) {\n";
618         for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
619                 CondSpace *condSpace = csi;
620                 out << "        case " << condSpace->condSpaceId + 1 << ": {\n";
621                 out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" <<
622                                 KEY(condSpace->baseKey) << " + (" << GET_KEY() << 
623                                 " - " << KEY(keyOps->minKey) << "));\n";
624
625                 for ( CondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
626                         out << TABS(2) << "if ( ";
627                         CONDITION( out, *csi );
628                         Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
629                         out << " ) _widec += " << condValOffset << ";\n";
630                 }
631
632                 out << "                }\n";
633                 out << "                break;\n";
634         }
635
636         SWITCH_DEFAULT();
637
638         out <<
639                 "       }\n";
640 }
641
642 void FlatCodeGen::writeExec()
643 {
644         testEofUsed = false;
645         outLabelUsed = false;
646
647         out << 
648                 "       {\n"
649                 "       int _slen";
650
651         if ( redFsm->anyRegCurStateRef() )
652                 out << ", _ps";
653
654         out << 
655                 ";\n"
656                 "       int _trans";
657
658         if ( redFsm->anyConditions() )
659                 out << ", _cond";
660         out << ";\n";
661
662         if ( redFsm->anyToStateActions() || 
663                         redFsm->anyRegActions() || redFsm->anyFromStateActions() )
664         {
665                 out << 
666                         "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxActArrItem) << POINTER() << "_acts;\n"
667                         "       " << UINT() << " _nacts;\n"; 
668         }
669
670         out <<
671                 "       " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n"
672                 "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxIndex) << POINTER() << "_inds;\n";
673
674         if ( redFsm->anyConditions() ) {
675                 out << 
676                         "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxCond) << POINTER() << "_conds;\n"
677                         "       " << WIDE_ALPH_TYPE() << " _widec;\n";
678         }
679
680         out << "\n";
681
682         if ( hasEnd ) {
683                 testEofUsed = true;
684                 out << 
685                         "       if ( " << P() << " == " << PE() << " )\n"
686                         "               goto _test_eof;\n";
687         }
688
689         if ( redFsm->errState != 0 ) {
690                 outLabelUsed = true;
691                 out << 
692                         "       if ( " << CS() << " == " << redFsm->errState->id << " )\n"
693                         "               goto _out;\n";
694         }
695
696         out << "_resume:\n";
697
698         if ( redFsm->anyFromStateActions() ) {
699                 out <<
700                         "       _acts = " << ARR_OFF( A(), FSA() + "[" + CS() + "]" ) << ";\n"
701                         "       _nacts = " << CAST(UINT()) << " *_acts++;\n"
702                         "       while ( _nacts-- > 0 ) {\n"
703                         "               switch ( *_acts++ ) {\n";
704                         FROM_STATE_ACTION_SWITCH();
705                         SWITCH_DEFAULT() <<
706                         "               }\n"
707                         "       }\n"
708                         "\n";
709         }
710
711         if ( redFsm->anyConditions() )
712                 COND_TRANSLATE();
713
714         LOCATE_TRANS();
715
716         if ( redFsm->anyRegCurStateRef() )
717                 out << "        _ps = " << CS() << ";\n";
718
719         out <<
720                 "       " << CS() << " = " << TT() << "[_trans];\n"
721                 "\n";
722
723         if ( redFsm->anyRegActions() ) {
724                 out <<
725                         "       if ( " << TA() << "[_trans] == 0 )\n"
726                         "               goto _again;\n"
727                         "\n"
728                         "       _acts = " << ARR_OFF( A(), TA() + "[_trans]" ) << ";\n"
729                         "       _nacts = " << CAST(UINT()) << " *_acts++;\n"
730                         "       while ( _nacts-- > 0 ) {\n"
731                         "               switch ( *(_acts++) )\n         {\n";
732                         ACTION_SWITCH();
733                         SWITCH_DEFAULT() <<
734                         "               }\n"
735                         "       }\n"
736                         "\n";
737         }
738
739         if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || 
740                         redFsm->anyActionCalls() || redFsm->anyActionRets() )
741                 out << "_again:\n";
742
743         if ( redFsm->anyToStateActions() ) {
744                 out <<
745                         "       _acts = " << ARR_OFF( A(),  TSA() + "[" + CS() + "]" ) << ";\n"
746                         "       _nacts = " << CAST(UINT()) << " *_acts++;\n"
747                         "       while ( _nacts-- > 0 ) {\n"
748                         "               switch ( *_acts++ ) {\n";
749                         TO_STATE_ACTION_SWITCH();
750                         SWITCH_DEFAULT() <<
751                         "               }\n"
752                         "       }\n"
753                         "\n";
754         }
755
756         if ( redFsm->errState != 0 ) {
757                 outLabelUsed = true;
758                 out << 
759                         "       if ( " << CS() << " == " << redFsm->errState->id << " )\n"
760                         "               goto _out;\n";
761         }
762
763         if ( hasEnd ) {
764                 out << 
765                         "       if ( ++" << P() << " != " << PE() << " )\n"
766                         "               goto _resume;\n";
767         }
768         else {
769                 out << 
770                         "       " << P() << " += 1;\n"
771                         "       goto _resume;\n";
772         }
773
774         if ( testEofUsed )
775                 out << "        _test_eof: {}\n";
776
777         if ( redFsm->anyEofActions() ) {
778                 out << 
779                         "       if ( " << P() << " == " << EOFV() << " )\n"
780                         "       {\n"
781                         "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxActArrItem) << POINTER() << "__acts = " << 
782                                         ARR_OFF( A(), EA() + "[" + CS() + "]" ) << ";\n"
783                         "       " << UINT() << " __nacts = " << CAST(UINT()) << " *__acts++;\n"
784                         "       while ( __nacts-- > 0 ) {\n"
785                         "               switch ( *__acts++ ) {\n";
786                         EOF_ACTION_SWITCH();
787                         SWITCH_DEFAULT() <<
788                         "               }\n"
789                         "       }\n"
790                         "       }\n"
791                         "\n";
792         }
793
794
795         if ( outLabelUsed )
796                 out << "        _out: {}\n";
797
798         out << "        }\n";
799 }