Initialize Tizen 2.3
[external/ragel.git] / ragel / csflat.cpp
1 /*
2  *  Copyright 2004-2006 Adrian Thurston <thurston@complang.org>
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 "ragel.h"
25 #include "csflat.h"
26 #include "redfsm.h"
27 #include "gendata.h"
28
29 std::ostream &CSharpFlatCodeGen::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 &CSharpFlatCodeGen::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 &CSharpFlatCodeGen::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 &CSharpFlatCodeGen::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 &CSharpFlatCodeGen::TO_STATE_ACTION_SWITCH()
67 {
68         /* Walk the list of functions, printing the cases. */
69         for ( GenActionList::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 &CSharpFlatCodeGen::FROM_STATE_ACTION_SWITCH()
84 {
85         /* Walk the list of functions, printing the cases. */
86         for ( GenActionList::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 &CSharpFlatCodeGen::EOF_ACTION_SWITCH()
101 {
102         /* Walk the list of functions, printing the cases. */
103         for ( GenActionList::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 &CSharpFlatCodeGen::ACTION_SWITCH()
119 {
120         /* Walk the list of functions, printing the cases. */
121         for ( GenActionList::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 &CSharpFlatCodeGen::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 &CSharpFlatCodeGen::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 &CSharpFlatCodeGen::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 &CSharpFlatCodeGen::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 &CSharpFlatCodeGen::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 &CSharpFlatCodeGen::EOF_TRANS()
232 {
233         out << "\t";
234         int totalStateNum = 0;
235         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
236                 /* Write any eof action. */
237
238                 long trans = 0;
239                 if ( st->eofTrans != 0 ) {
240                         assert( st->eofTrans->pos >= 0 );
241                         trans = st->eofTrans->pos+1;
242                 }
243                 out << trans;
244
245                 if ( !st.last() ) {
246                         out << ", ";
247                         if ( ++totalStateNum % IALL == 0 )
248                                 out << "\n\t";
249                 }
250         }
251         out << "\n";
252         return out;
253 }
254
255
256 std::ostream &CSharpFlatCodeGen::COND_KEYS()
257 {
258         out << '\t';
259         int totalTrans = 0;
260         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
261                 /* Emit just cond low key and cond high key. */
262                 out << ALPHA_KEY( st->condLowKey ) << ", ";
263                 out << ALPHA_KEY( st->condHighKey ) << ", ";
264                 if ( ++totalTrans % IALL == 0 )
265                         out << "\n\t";
266         }
267
268         /* Output one last number so we don't have to figure out when the last
269          * entry is and avoid writing a comma. */
270         out << "(char) " << 0 << "\n";
271         return out;
272 }
273
274 std::ostream &CSharpFlatCodeGen::COND_KEY_SPANS()
275 {
276         out << "\t";
277         int totalStateNum = 0;
278         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
279                 /* Write singles length. */
280                 unsigned long long span = 0;
281                 if ( st->condList != 0 )
282                         span = keyOps->span( st->condLowKey, st->condHighKey );
283                 out << span;
284                 if ( !st.last() ) {
285                         out << ", ";
286                         if ( ++totalStateNum % IALL == 0 )
287                                 out << "\n\t";
288                 }
289         }
290         out << "\n";
291         return out;
292 }
293
294 std::ostream &CSharpFlatCodeGen::CONDS()
295 {
296         int totalTrans = 0;
297         out << '\t';
298         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
299                 if ( st->condList != 0 ) {
300                         /* Walk the singles. */
301                         unsigned long long span = keyOps->span( st->condLowKey, st->condHighKey );
302                         for ( unsigned long long pos = 0; pos < span; pos++ ) {
303                                 if ( st->condList[pos] != 0 )
304                                         out << st->condList[pos]->condSpaceId + 1 << ", ";
305                                 else
306                                         out << "0, ";
307                                 if ( ++totalTrans % IALL == 0 )
308                                         out << "\n\t";
309                         }
310                 }
311         }
312
313         /* Output one last number so we don't have to figure out when the last
314          * entry is and avoid writing a comma. */
315         out << 0 << "\n";
316         return out;
317 }
318
319 std::ostream &CSharpFlatCodeGen::COND_INDEX_OFFSET()
320 {
321         out << "\t";
322         int totalStateNum = 0, curIndOffset = 0;
323         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
324                 /* Write the index offset. */
325                 out << curIndOffset;
326                 if ( !st.last() ) {
327                         out << ", ";
328                         if ( ++totalStateNum % IALL == 0 )
329                                 out << "\n\t";
330                 }
331                 
332                 /* Move the index offset ahead. */
333                 if ( st->condList != 0 )
334                         curIndOffset += keyOps->span( st->condLowKey, st->condHighKey );
335         }
336         out << "\n";
337         return out;
338 }
339
340
341 std::ostream &CSharpFlatCodeGen::KEYS()
342 {
343         out << '\t';
344         int totalTrans = 0;
345         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
346                 /* Emit just low key and high key. */
347                 out << ALPHA_KEY( st->lowKey ) << ", ";
348                 out << ALPHA_KEY( st->highKey ) << ", ";
349                 if ( ++totalTrans % IALL == 0 )
350                         out << "\n\t";
351         }
352
353         /* Output one last number so we don't have to figure out when the last
354          * entry is and avoid writing a comma. */
355         out << "(char) " << 0 << "\n";
356         return out;
357 }
358
359 std::ostream &CSharpFlatCodeGen::INDICIES()
360 {
361         int totalTrans = 0;
362         out << '\t';
363         for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
364                 if ( st->transList != 0 ) {
365                         /* Walk the singles. */
366                         unsigned long long span = keyOps->span( st->lowKey, st->highKey );
367                         for ( unsigned long long pos = 0; pos < span; pos++ ) {
368                                 out << st->transList[pos]->id << ", ";
369                                 if ( ++totalTrans % IALL == 0 )
370                                         out << "\n\t";
371                         }
372                 }
373
374                 /* The state's default index goes next. */
375                 if ( st->defTrans != 0 )
376                         out << st->defTrans->id << ", ";
377
378                 if ( ++totalTrans % IALL == 0 )
379                         out << "\n\t";
380         }
381
382         /* Output one last number so we don't have to figure out when the last
383          * entry is and avoid writing a comma. */
384         out << 0 << "\n";
385         return out;
386 }
387
388 std::ostream &CSharpFlatCodeGen::TRANS_TARGS()
389 {
390         /* Transitions must be written ordered by their id. */
391         RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
392         for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
393                 transPtrs[trans->id] = trans;
394
395         /* Keep a count of the num of items in the array written. */
396         out << '\t';
397         int totalStates = 0;
398         for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
399                 /* Record the position, need this for eofTrans. */
400                 RedTransAp *trans = transPtrs[t];
401                 trans->pos = t;
402
403                 /* Write out the target state. */
404                 out << trans->targ->id;
405                 if ( t < redFsm->transSet.length()-1 ) {
406                         out << ", ";
407                         if ( ++totalStates % IALL == 0 )
408                                 out << "\n\t";
409                 }
410         }
411         out << "\n";
412         delete[] transPtrs;
413         return out;
414 }
415
416
417 std::ostream &CSharpFlatCodeGen::TRANS_ACTIONS()
418 {
419         /* Transitions must be written ordered by their id. */
420         RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
421         for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
422                 transPtrs[trans->id] = trans;
423
424         /* Keep a count of the num of items in the array written. */
425         out << '\t';
426         int totalAct = 0;
427         for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
428                 /* Write the function for the transition. */
429                 RedTransAp *trans = transPtrs[t];
430                 TRANS_ACTION( trans );
431                 if ( t < redFsm->transSet.length()-1 ) {
432                         out << ", ";
433                         if ( ++totalAct % IALL == 0 )
434                                 out << "\n\t";
435                 }
436         }
437         out << "\n";
438         delete[] transPtrs;
439         return out;
440 }
441
442 void CSharpFlatCodeGen::LOCATE_TRANS()
443 {
444         out <<
445                 "       _keys = " << vCS() << "<<1;\n"
446                 "       _inds = " << IO() << "[" << vCS() << "];\n"
447                 "\n"
448                 "       _slen = " << SP() << "[" << vCS() << "];\n"
449                 "       _trans = " << I() << "[_inds + (\n"
450                 "               _slen > 0 && " << K() << "[_keys] <=" << GET_WIDE_KEY() << " &&\n"
451                 "               " << GET_WIDE_KEY() << " <= " << K() <<"[_keys+1] ?\n"
452                 "               " << GET_WIDE_KEY() << " - " << K() << "[_keys] : _slen ) ];\n"
453                 "\n";
454 }
455
456 void CSharpFlatCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
457 {
458         ret << "{" << vCS() << " = " << gotoDest << "; " << 
459                         CTRL_FLOW() << "goto _again;}";
460 }
461
462 void CSharpFlatCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
463 {
464         ret << "{" << vCS() << " = (";
465         INLINE_LIST( ret, ilItem->children, 0, inFinish );
466         ret << "); " << CTRL_FLOW() << "goto _again;}";
467 }
468
469 void CSharpFlatCodeGen::CURS( ostream &ret, bool inFinish )
470 {
471         ret << "(_ps)";
472 }
473
474 void CSharpFlatCodeGen::TARGS( ostream &ret, bool inFinish, int targState )
475 {
476         ret << "(" << vCS() << ")";
477 }
478
479 void CSharpFlatCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
480 {
481         ret << vCS() << " = " << nextDest << ";";
482 }
483
484 void CSharpFlatCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
485 {
486         ret << vCS() << " = (";
487         INLINE_LIST( ret, ilItem->children, 0, inFinish );
488         ret << ");";
489 }
490
491 void CSharpFlatCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
492 {
493         if ( prePushExpr != 0 ) {
494                 ret << "{";
495                 INLINE_LIST( ret, prePushExpr, 0, false );
496         }
497
498         ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << 
499                         callDest << "; " << CTRL_FLOW() << "goto _again;}";
500
501         if ( prePushExpr != 0 )
502                 ret << "}";
503 }
504
505
506 void CSharpFlatCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
507 {
508         if ( prePushExpr != 0 ) {
509                 ret << "{";
510                 INLINE_LIST( ret, prePushExpr, 0, false );
511         }
512
513         ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = (";
514         INLINE_LIST( ret, ilItem->children, targState, inFinish );
515         ret << "); " << CTRL_FLOW() << "goto _again;}";
516
517         if ( prePushExpr != 0 )
518                 ret << "}";
519 }
520
521
522 void CSharpFlatCodeGen::RET( ostream &ret, bool inFinish )
523 {
524         ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "];";
525
526         if ( postPopExpr != 0 ) {
527                 ret << "{";
528                 INLINE_LIST( ret, postPopExpr, 0, false );
529                 ret << "}";
530         }
531
532         ret << CTRL_FLOW() << "goto _again;}";
533 }
534
535 void CSharpFlatCodeGen::BREAK( ostream &ret, int targState )
536 {
537         outLabelUsed = true;
538         ret << "{" << P() << "++; " << CTRL_FLOW() << "goto _out; }";
539 }
540
541 void CSharpFlatCodeGen::writeData()
542 {
543         /* If there are any transtion functions then output the array. If there
544          * are none, don't bother emitting an empty array that won't be used. */
545         if ( redFsm->anyActions() ) {
546                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
547                 ACTIONS_ARRAY();
548                 CLOSE_ARRAY() <<
549                 "\n";
550         }
551
552         if ( redFsm->anyConditions() ) {
553                 OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
554                 COND_KEYS();
555                 CLOSE_ARRAY() <<
556                 "\n";
557
558                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpan), CSP() );
559                 COND_KEY_SPANS();
560                 CLOSE_ARRAY() <<
561                 "\n";
562
563                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCond), C() );
564                 CONDS();
565                 CLOSE_ARRAY() <<
566                 "\n";
567
568                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondIndexOffset), CO() );
569                 COND_INDEX_OFFSET();
570                 CLOSE_ARRAY() <<
571                 "\n";
572         }
573
574         OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
575         KEYS();
576         CLOSE_ARRAY() <<
577         "\n";
578
579         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSpan), SP() );
580         KEY_SPANS();
581         CLOSE_ARRAY() <<
582         "\n";
583
584         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxFlatIndexOffset), IO() );
585         FLAT_INDEX_OFFSET();
586         CLOSE_ARRAY() <<
587         "\n";
588
589         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
590         INDICIES();
591         CLOSE_ARRAY() <<
592         "\n";
593
594         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
595         TRANS_TARGS();
596         CLOSE_ARRAY() <<
597         "\n";
598
599         if ( redFsm->anyActions() ) {
600                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
601                 TRANS_ACTIONS();
602                 CLOSE_ARRAY() <<
603                 "\n";
604         }
605
606         if ( redFsm->anyToStateActions() ) {
607                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
608                 TO_STATE_ACTIONS();
609                 CLOSE_ARRAY() <<
610                 "\n";
611         }
612
613         if ( redFsm->anyFromStateActions() ) {
614                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
615                 FROM_STATE_ACTIONS();
616                 CLOSE_ARRAY() <<
617                 "\n";
618         }
619
620         if ( redFsm->anyEofActions() ) {
621                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
622                 EOF_ACTIONS();
623                 CLOSE_ARRAY() <<
624                 "\n";
625         }
626
627         if ( redFsm->anyEofTrans() ) {
628                 OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
629                 EOF_TRANS();
630                 CLOSE_ARRAY() <<
631                 "\n";
632         }
633
634         STATE_IDS();
635 }
636
637 void CSharpFlatCodeGen::COND_TRANSLATE()
638 {
639         out << 
640                 "       _widec = " << GET_KEY() << ";\n";
641
642         out <<
643                 "   _keys = " << vCS() << "<<1;\n"
644                 "   _conds = " << CO() << "[" << vCS() << "];\n"
645 //              "       _keys = " << ARR_OFF( CK(), "(" + vCS() + "<<1)" ) << ";\n"
646 //              "       _conds = " << ARR_OFF( C(), CO() + "[" + vCS() + "]" ) << ";\n"
647                 "\n"
648                 "       _slen = " << CSP() << "[" << vCS() << "];\n"
649                 "       if (_slen > 0 && " << CK() << "[_keys] <=" 
650                         << GET_WIDE_KEY() << " &&\n"
651                 "               " << GET_WIDE_KEY() << " <= " << CK() << "[_keys+1])\n"
652                 "               _cond = " << C() << "[_conds+" << GET_WIDE_KEY() << " - " << 
653                         CK() << "[_keys]];\n"
654                 "       else\n"
655                 "               _cond = 0;"
656                 "\n";
657         /*  XXX This version of the code doesn't work because Mono is weird.  Works
658          *  fine in Microsoft's csc, even though the bug report filed claimed it
659          *  didn't.
660                 "       _slen = " << CSP() << "[" << vCS() << "];\n"
661                 "       _cond = _slen > 0 && " << CK() << "[_keys] <=" 
662                         << GET_WIDE_KEY() << " &&\n"
663                 "               " << GET_WIDE_KEY() << " <= " << CK() << "[_keys+1] ?\n"
664                 "               " << C() << "[_conds+" << GET_WIDE_KEY() << " - " << CK() 
665                         << "[_keys]] : 0;\n"
666                 "\n";
667                 */
668         out <<
669                 "       switch ( _cond ) {\n";
670         for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
671                 GenCondSpace *condSpace = csi;
672                 out << "        case " << condSpace->condSpaceId + 1 << ": {\n";
673                 out << TABS(2) << "_widec = " << CAST(WIDE_ALPH_TYPE()) << "(" <<
674                                 KEY(condSpace->baseKey) << " + (" << GET_KEY() << 
675                                 " - " << KEY(keyOps->minKey) << "));\n";
676
677                 for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
678                         out << TABS(2) << "if ( ";
679                         CONDITION( out, *csi );
680                         Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
681                         out << " ) _widec += " << condValOffset << ";\n";
682                 }
683
684                 out << "                }\n";
685                 out << "                break;\n";
686         }
687
688         SWITCH_DEFAULT();
689
690         out <<
691                 "       }\n";
692 }
693
694 void CSharpFlatCodeGen::writeExec()
695 {
696         testEofUsed = false;
697         outLabelUsed = false;
698         initVarTypes();
699
700         out << 
701                 "       {\n"
702                 "       " << slenType << " _slen";
703
704         if ( redFsm->anyRegCurStateRef() )
705                 out << ", _ps";
706
707         out << 
708                 ";\n"
709                 "       " << transType << " _trans";
710
711         if ( redFsm->anyConditions() )
712                 out << ", _cond";
713         out << ";\n";
714
715         if ( redFsm->anyToStateActions() || 
716                         redFsm->anyRegActions() || redFsm->anyFromStateActions() )
717         {
718                 out << 
719                         "       " << actsType << " _acts;\n"
720                         "       " << nactsType << " _nacts;\n"; 
721         }
722
723         out <<
724                 "       " << "int _keys;\n"
725                 "       " << indsType << " _inds;\n";
726                 /*
727                 "       " << PTR_CONST() << WIDE_ALPH_TYPE() << POINTER() << "_keys;\n"
728                 "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxIndex) << POINTER() << "_inds;\n";*/
729
730         if ( redFsm->anyConditions() ) {
731                 out << 
732                         "       " << condsType << " _conds;\n"
733                         "       " << WIDE_ALPH_TYPE() << " _widec;\n";
734         }
735
736         out << "\n";
737
738         if ( !noEnd ) {
739                 testEofUsed = true;
740                 out << 
741                         "       if ( " << P() << " == " << PE() << " )\n"
742                         "               goto _test_eof;\n";
743         }
744
745         if ( redFsm->errState != 0 ) {
746                 outLabelUsed = true;
747                 out << 
748                         "       if ( " << vCS() << " == " << redFsm->errState->id << " )\n"
749                         "               goto _out;\n";
750         }
751
752         out << "_resume:\n";
753
754         if ( redFsm->anyFromStateActions() ) {
755                 out <<
756                         "       _acts = " << FSA() << "[" << vCS() << "];\n"
757                         "       _nacts = " << A() << "[_acts++];\n"
758                         "       while ( _nacts-- > 0 ) {\n"
759                         "               switch ( " << A() << "[_acts++] ) {\n";
760                         FROM_STATE_ACTION_SWITCH();
761                         SWITCH_DEFAULT() <<
762                         "               }\n"
763                         "       }\n"
764                         "\n";
765         }
766
767         if ( redFsm->anyConditions() )
768                 COND_TRANSLATE();
769
770         LOCATE_TRANS();
771
772         if ( redFsm->anyEofTrans() )
773                 out << "_eof_trans:\n";
774
775         if ( redFsm->anyRegCurStateRef() )
776                 out << "        _ps = " << vCS() << ";\n";
777
778         out <<
779                 "       " << vCS() << " = " << TT() << "[_trans];\n"
780                 "\n";
781
782         if ( redFsm->anyRegActions() ) {
783                 out <<
784                         "       if ( " << TA() << "[_trans] == 0 )\n"
785                         "               goto _again;\n"
786                         "\n"
787                         "       _acts = " << TA() << "[_trans];\n"
788                         "       _nacts = " << A() << "[_acts++];\n"
789                         "       while ( _nacts-- > 0 ) {\n"
790                         "               switch ( " << A() << "[_acts++] )\n             {\n";
791                         ACTION_SWITCH();
792                         SWITCH_DEFAULT() <<
793                         "               }\n"
794                         "       }\n"
795                         "\n";
796         }
797
798         if ( redFsm->anyRegActions() || redFsm->anyActionGotos() || 
799                         redFsm->anyActionCalls() || redFsm->anyActionRets() )
800                 out << "_again:\n";
801
802         if ( redFsm->anyToStateActions() ) {
803                 out <<
804                         "       _acts = " << TSA() << "[" << vCS() << "];\n"
805                         "       _nacts = " << A() << "[_acts++];\n"
806                         "       while ( _nacts-- > 0 ) {\n"
807                         "               switch ( " << A() << "[_acts++] ) {\n";
808                         TO_STATE_ACTION_SWITCH();
809                         SWITCH_DEFAULT() <<
810                         "               }\n"
811                         "       }\n"
812                         "\n";
813         }
814
815         if ( redFsm->errState != 0 ) {
816                 outLabelUsed = true;
817                 out << 
818                         "       if ( " << vCS() << " == " << redFsm->errState->id << " )\n"
819                         "               goto _out;\n";
820         }
821
822         if ( !noEnd ) {
823                 out << 
824                         "       if ( ++" << P() << " != " << PE() << " )\n"
825                         "               goto _resume;\n";
826         }
827         else {
828                 out << 
829                         "       " << P() << " += 1;\n"
830                         "       goto _resume;\n";
831         }
832
833         if ( testEofUsed )
834                 out << "        _test_eof: {}\n";
835
836         if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
837                 out << 
838                         "       if ( " << P() << " == " << vEOF() << " )\n"
839                         "       {\n";
840
841                 if ( redFsm->anyEofTrans() ) {
842                         out <<
843                                 "       if ( " << ET() << "[" << vCS() << "] > 0 ) {\n"
844                                 "               _trans = " << CAST(transType) << " (" << ET() << 
845                                         "[" << vCS() << "] - 1);\n"
846                                 "               goto _eof_trans;\n"
847                                 "       }\n";
848                 }
849
850                 if ( redFsm->anyEofActions() ) {
851                         out <<
852                                 "       " << PTR_CONST() << ARRAY_TYPE(redFsm->maxActArrItem) << 
853                                                 POINTER() << "__acts = " << 
854                                                 EA() << "[" << vCS() << "];\n"
855                                 "       " << UINT() << " __nacts = " << CAST(UINT()) << " " <<
856                                                         A() << "[__acts++];\n"
857                                 "       while ( __nacts-- > 0 ) {\n"
858                                 "               switch ( " << A() << "[__acts++] ) {\n";
859                                 EOF_ACTION_SWITCH();
860                                 SWITCH_DEFAULT() <<
861                                 "               }\n"
862                                 "       }\n";
863                 }
864
865                 out <<
866                         "       }\n"
867                         "\n";
868         }
869
870         if ( outLabelUsed )
871                 out << "        _out: {}\n";
872
873         out << "        }\n";
874 }
875
876 void CSharpFlatCodeGen::initVarTypes()
877 {
878         slenType = ARRAY_TYPE(MAX(redFsm->maxSpan, redFsm->maxCondSpan));
879         transType = ARRAY_TYPE(redFsm->maxIndex+1);
880         actsType = ARRAY_TYPE(redFsm->maxActionLoc);
881         nactsType = ARRAY_TYPE(redFsm->maxActArrItem);
882         indsType = ARRAY_TYPE(redFsm->maxFlatIndexOffset);
883         condsType = ARRAY_TYPE(redFsm->maxCondIndexOffset);
884 }