"Fossies" - the Fresh Open Source Software Archive 
Member "ragel-6.10/ragel/cdcodegen.cpp" (24 Mar 2017, 21233 Bytes) of package /linux/misc/ragel-6.10.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "cdcodegen.cpp" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
6.9_vs_6.10.
1 /*
2 * Copyright 2001-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 "cdcodegen.h"
25 #include "ragel.h"
26 #include "redfsm.h"
27 #include "gendata.h"
28 #include <sstream>
29 #include <string>
30 #include <assert.h>
31
32
33 using std::ostream;
34 using std::ostringstream;
35 using std::string;
36 using std::cerr;
37 using std::endl;
38 using std::istream;
39 using std::ifstream;
40 using std::ostream;
41 using std::ios;
42 using std::cin;
43 using std::cout;
44 using std::cerr;
45 using std::endl;
46
47
48 extern int numSplitPartitions;
49 extern bool noLineDirectives;
50
51 void cdLineDirective( ostream &out, const char *fileName, int line )
52 {
53 if ( noLineDirectives )
54 out << "/* ";
55
56 /* Write the preprocessor line info for to the input file. */
57 out << "#line " << line << " \"";
58 for ( const char *pc = fileName; *pc != 0; pc++ ) {
59 if ( *pc == '\\' )
60 out << "\\\\";
61 else
62 out << *pc;
63 }
64 out << '"';
65
66 if ( noLineDirectives )
67 out << " */";
68
69 out << '\n';
70 }
71
72 void FsmCodeGen::genLineDirective( ostream &out )
73 {
74 std::streambuf *sbuf = out.rdbuf();
75 output_filter *filter = static_cast<output_filter*>(sbuf);
76 cdLineDirective( out, filter->fileName, filter->line + 1 );
77 }
78
79
80 /* Init code gen with in parameters. */
81 FsmCodeGen::FsmCodeGen( ostream &out )
82 :
83 CodeGenData(out)
84 {
85 }
86
87 unsigned int FsmCodeGen::arrayTypeSize( unsigned long maxVal )
88 {
89 long long maxValLL = (long long) maxVal;
90 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
91 assert( arrayType != 0 );
92 return arrayType->size;
93 }
94
95 string FsmCodeGen::ARRAY_TYPE( unsigned long maxVal )
96 {
97 long long maxValLL = (long long) maxVal;
98 HostType *arrayType = keyOps->typeSubsumes( maxValLL );
99 assert( arrayType != 0 );
100
101 string ret = arrayType->data1;
102 if ( arrayType->data2 != 0 ) {
103 ret += " ";
104 ret += arrayType->data2;
105 }
106 return ret;
107 }
108
109
110 /* Write out the fsm name. */
111 string FsmCodeGen::FSM_NAME()
112 {
113 return fsmName;
114 }
115
116 /* Emit the offset of the start state as a decimal integer. */
117 string FsmCodeGen::START_STATE_ID()
118 {
119 ostringstream ret;
120 ret << redFsm->startState->id;
121 return ret.str();
122 };
123
124 /* Write out the array of actions. */
125 std::ostream &FsmCodeGen::ACTIONS_ARRAY()
126 {
127 out << "\t0, ";
128 int totalActions = 1;
129 for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
130 /* Write out the length, which will never be the last character. */
131 out << act->key.length() << ", ";
132 /* Put in a line break every 8 */
133 if ( totalActions++ % 8 == 7 )
134 out << "\n\t";
135
136 for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) {
137 out << item->value->actionId;
138 if ( ! (act.last() && item.last()) )
139 out << ", ";
140
141 /* Put in a line break every 8 */
142 if ( totalActions++ % 8 == 7 )
143 out << "\n\t";
144 }
145 }
146 out << "\n";
147 return out;
148 }
149
150
151 string FsmCodeGen::ACCESS()
152 {
153 ostringstream ret;
154 if ( accessExpr != 0 )
155 INLINE_LIST( ret, accessExpr, 0, false, false );
156 return ret.str();
157 }
158
159
160 string FsmCodeGen::P()
161 {
162 ostringstream ret;
163 if ( pExpr == 0 )
164 ret << "p";
165 else {
166 ret << "(";
167 INLINE_LIST( ret, pExpr, 0, false, false );
168 ret << ")";
169 }
170 return ret.str();
171 }
172
173 string FsmCodeGen::PE()
174 {
175 ostringstream ret;
176 if ( peExpr == 0 )
177 ret << "pe";
178 else {
179 ret << "(";
180 INLINE_LIST( ret, peExpr, 0, false, false );
181 ret << ")";
182 }
183 return ret.str();
184 }
185
186 string FsmCodeGen::vEOF()
187 {
188 ostringstream ret;
189 if ( eofExpr == 0 )
190 ret << "eof";
191 else {
192 ret << "(";
193 INLINE_LIST( ret, eofExpr, 0, false, false );
194 ret << ")";
195 }
196 return ret.str();
197 }
198
199 string FsmCodeGen::vCS()
200 {
201 ostringstream ret;
202 if ( csExpr == 0 )
203 ret << ACCESS() << "cs";
204 else {
205 /* Emit the user supplied method of retrieving the key. */
206 ret << "(";
207 INLINE_LIST( ret, csExpr, 0, false, false );
208 ret << ")";
209 }
210 return ret.str();
211 }
212
213 string FsmCodeGen::TOP()
214 {
215 ostringstream ret;
216 if ( topExpr == 0 )
217 ret << ACCESS() + "top";
218 else {
219 ret << "(";
220 INLINE_LIST( ret, topExpr, 0, false, false );
221 ret << ")";
222 }
223 return ret.str();
224 }
225
226 string FsmCodeGen::STACK()
227 {
228 ostringstream ret;
229 if ( stackExpr == 0 )
230 ret << ACCESS() + "stack";
231 else {
232 ret << "(";
233 INLINE_LIST( ret, stackExpr, 0, false, false );
234 ret << ")";
235 }
236 return ret.str();
237 }
238
239 string FsmCodeGen::ACT()
240 {
241 ostringstream ret;
242 if ( actExpr == 0 )
243 ret << ACCESS() + "act";
244 else {
245 ret << "(";
246 INLINE_LIST( ret, actExpr, 0, false, false );
247 ret << ")";
248 }
249 return ret.str();
250 }
251
252 string FsmCodeGen::TOKSTART()
253 {
254 ostringstream ret;
255 if ( tokstartExpr == 0 )
256 ret << ACCESS() + "ts";
257 else {
258 ret << "(";
259 INLINE_LIST( ret, tokstartExpr, 0, false, false );
260 ret << ")";
261 }
262 return ret.str();
263 }
264
265 string FsmCodeGen::TOKEND()
266 {
267 ostringstream ret;
268 if ( tokendExpr == 0 )
269 ret << ACCESS() + "te";
270 else {
271 ret << "(";
272 INLINE_LIST( ret, tokendExpr, 0, false, false );
273 ret << ")";
274 }
275 return ret.str();
276 }
277
278 string FsmCodeGen::GET_WIDE_KEY()
279 {
280 if ( redFsm->anyConditions() )
281 return "_widec";
282 else
283 return GET_KEY();
284 }
285
286 string FsmCodeGen::GET_WIDE_KEY( RedStateAp *state )
287 {
288 if ( state->stateCondList.length() > 0 )
289 return "_widec";
290 else
291 return GET_KEY();
292 }
293
294 string FsmCodeGen::GET_KEY()
295 {
296 ostringstream ret;
297 if ( getKeyExpr != 0 ) {
298 /* Emit the user supplied method of retrieving the key. */
299 ret << "(";
300 INLINE_LIST( ret, getKeyExpr, 0, false, false );
301 ret << ")";
302 }
303 else {
304 /* Expression for retrieving the key, use simple dereference. */
305 ret << "(*" << P() << ")";
306 }
307 return ret.str();
308 }
309
310 /* Write out level number of tabs. Makes the nested binary search nice
311 * looking. */
312 string FsmCodeGen::TABS( int level )
313 {
314 string result;
315 while ( level-- > 0 )
316 result += "\t";
317 return result;
318 }
319
320 /* Write out a key from the fsm code gen. Depends on wether or not the key is
321 * signed. */
322 string FsmCodeGen::KEY( Key key )
323 {
324 ostringstream ret;
325 if ( keyOps->isSigned || !hostLang->explicitUnsigned )
326 ret << key.getVal();
327 else
328 ret << (unsigned long) key.getVal() << 'u';
329 return ret.str();
330 }
331
332 bool FsmCodeGen::isAlphTypeSigned()
333 {
334 return keyOps->isSigned;
335 }
336
337 bool FsmCodeGen::isWideAlphTypeSigned()
338 {
339 string ret;
340 if ( redFsm->maxKey <= keyOps->maxKey )
341 return isAlphTypeSigned();
342 else {
343 long long maxKeyVal = redFsm->maxKey.getLongLong();
344 HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
345 return wideType->isSigned;
346 }
347 }
348
349 string FsmCodeGen::WIDE_KEY( RedStateAp *state, Key key )
350 {
351 if ( state->stateCondList.length() > 0 ) {
352 ostringstream ret;
353 if ( isWideAlphTypeSigned() )
354 ret << key.getVal();
355 else
356 ret << (unsigned long) key.getVal() << 'u';
357 return ret.str();
358 }
359 else {
360 return KEY( key );
361 }
362 }
363
364 void FsmCodeGen::EOF_CHECK( ostream &ret )
365 {
366 ret <<
367 " if ( " << P() << " == " << PE() << " )\n"
368 " goto _test_eof;\n";
369
370 testEofUsed = true;
371 }
372
373
374 void FsmCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish )
375 {
376 /* The parser gives fexec two children. The double brackets are for D
377 * code. If the inline list is a single word it will get interpreted as a
378 * C-style cast by the D compiler. */
379 ret << "{" << P() << " = ((";
380 INLINE_LIST( ret, item->children, targState, inFinish, false );
381 ret << "))-1;}";
382 }
383
384 void FsmCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item,
385 int targState, int inFinish, bool csForced )
386 {
387 ret <<
388 " switch( " << ACT() << " ) {\n";
389
390 bool haveDefault = false;
391 for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
392 /* Write the case label, the action and the case break. */
393 if ( lma->lmId < 0 ) {
394 ret << " default:\n";
395 haveDefault = true;
396 }
397 else
398 ret << " case " << lma->lmId << ":\n";
399
400 /* Write the block and close it off. */
401 ret << " {";
402 INLINE_LIST( ret, lma->children, targState, inFinish, csForced );
403 ret << "}\n";
404
405 ret << " break;\n";
406 }
407
408 if ( (hostLang->lang == HostLang::D || hostLang->lang == HostLang::D2) && !haveDefault )
409 ret << " default: break;";
410
411 ret <<
412 " }\n"
413 "\t";
414 }
415
416 void FsmCodeGen::SET_ACT( ostream &ret, GenInlineItem *item )
417 {
418 ret << ACT() << " = " << item->lmId << ";";
419 }
420
421 void FsmCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item )
422 {
423 /* The tokend action sets tokend. */
424 ret << TOKEND() << " = " << P();
425 if ( item->offset != 0 )
426 out << "+" << item->offset;
427 out << ";";
428 }
429
430 void FsmCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item )
431 {
432 ret << TOKEND();
433 }
434
435 void FsmCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item )
436 {
437 ret << TOKSTART() << " = " << NULL_ITEM() << ";";
438 }
439
440 void FsmCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item )
441 {
442 ret << ACT() << " = 0;";
443 }
444
445 void FsmCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item )
446 {
447 ret << TOKSTART() << " = " << P() << ";";
448 }
449
450 void FsmCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item,
451 int targState, bool inFinish, bool csForced )
452 {
453 if ( item->children->length() > 0 ) {
454 /* Write the block and close it off. */
455 ret << "{";
456 INLINE_LIST( ret, item->children, targState, inFinish, csForced );
457 ret << "}";
458 }
459 }
460
461
462 /* Write out an inline tree structure. Walks the list and possibly calls out
463 * to virtual functions than handle language specific items in the tree. */
464 void FsmCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList,
465 int targState, bool inFinish, bool csForced )
466 {
467 for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
468 switch ( item->type ) {
469 case GenInlineItem::Text:
470 ret << item->data;
471 break;
472 case GenInlineItem::Goto:
473 GOTO( ret, item->targState->id, inFinish );
474 break;
475 case GenInlineItem::Call:
476 CALL( ret, item->targState->id, targState, inFinish );
477 break;
478 case GenInlineItem::Next:
479 NEXT( ret, item->targState->id, inFinish );
480 break;
481 case GenInlineItem::Ret:
482 RET( ret, inFinish );
483 break;
484 case GenInlineItem::PChar:
485 ret << P();
486 break;
487 case GenInlineItem::Char:
488 ret << GET_KEY();
489 break;
490 case GenInlineItem::Hold:
491 ret << P() << "--;";
492 break;
493 case GenInlineItem::Exec:
494 EXEC( ret, item, targState, inFinish );
495 break;
496 case GenInlineItem::Curs:
497 CURS( ret, inFinish );
498 break;
499 case GenInlineItem::Targs:
500 TARGS( ret, inFinish, targState );
501 break;
502 case GenInlineItem::Entry:
503 ret << item->targState->id;
504 break;
505 case GenInlineItem::GotoExpr:
506 GOTO_EXPR( ret, item, inFinish );
507 break;
508 case GenInlineItem::CallExpr:
509 CALL_EXPR( ret, item, targState, inFinish );
510 break;
511 case GenInlineItem::NextExpr:
512 NEXT_EXPR( ret, item, inFinish );
513 break;
514 case GenInlineItem::LmSwitch:
515 LM_SWITCH( ret, item, targState, inFinish, csForced );
516 break;
517 case GenInlineItem::LmSetActId:
518 SET_ACT( ret, item );
519 break;
520 case GenInlineItem::LmSetTokEnd:
521 SET_TOKEND( ret, item );
522 break;
523 case GenInlineItem::LmGetTokEnd:
524 GET_TOKEND( ret, item );
525 break;
526 case GenInlineItem::LmInitTokStart:
527 INIT_TOKSTART( ret, item );
528 break;
529 case GenInlineItem::LmInitAct:
530 INIT_ACT( ret, item );
531 break;
532 case GenInlineItem::LmSetTokStart:
533 SET_TOKSTART( ret, item );
534 break;
535 case GenInlineItem::SubAction:
536 SUB_ACTION( ret, item, targState, inFinish, csForced );
537 break;
538 case GenInlineItem::Break:
539 BREAK( ret, targState, csForced );
540 break;
541 }
542 }
543 }
544 /* Write out paths in line directives. Escapes any special characters. */
545 string FsmCodeGen::LDIR_PATH( char *path )
546 {
547 ostringstream ret;
548 for ( char *pc = path; *pc != 0; pc++ ) {
549 if ( *pc == '\\' )
550 ret << "\\\\";
551 else
552 ret << *pc;
553 }
554 return ret.str();
555 }
556
557 void FsmCodeGen::ACTION( ostream &ret, GenAction *action, int targState,
558 bool inFinish, bool csForced )
559 {
560 /* Write the preprocessor line info for going into the source file. */
561 cdLineDirective( ret, action->loc.fileName, action->loc.line );
562
563 /* Write the block and close it off. */
564 ret << "\t{";
565 INLINE_LIST( ret, action->inlineList, targState, inFinish, csForced );
566 ret << "}\n";
567 }
568
569 void FsmCodeGen::CONDITION( ostream &ret, GenAction *condition )
570 {
571 ret << "\n";
572 cdLineDirective( ret, condition->loc.fileName, condition->loc.line );
573 INLINE_LIST( ret, condition->inlineList, 0, false, false );
574 }
575
576 string FsmCodeGen::ERROR_STATE()
577 {
578 ostringstream ret;
579 if ( redFsm->errState != 0 )
580 ret << redFsm->errState->id;
581 else
582 ret << "-1";
583 return ret.str();
584 }
585
586 string FsmCodeGen::FIRST_FINAL_STATE()
587 {
588 ostringstream ret;
589 if ( redFsm->firstFinState != 0 )
590 ret << redFsm->firstFinState->id;
591 else
592 ret << redFsm->nextStateId;
593 return ret.str();
594 }
595
596 void FsmCodeGen::writeInit()
597 {
598 out << " {\n";
599
600 if ( !noCS )
601 out << "\t" << vCS() << " = " << START() << ";\n";
602
603 /* If there are any calls, then the stack top needs initialization. */
604 if ( redFsm->anyActionCalls() || redFsm->anyActionRets() )
605 out << "\t" << TOP() << " = 0;\n";
606
607 if ( hasLongestMatch ) {
608 out <<
609 " " << TOKSTART() << " = " << NULL_ITEM() << ";\n"
610 " " << TOKEND() << " = " << NULL_ITEM() << ";\n"
611 " " << ACT() << " = 0;\n";
612 }
613 out << " }\n";
614 }
615
616 string FsmCodeGen::DATA_PREFIX()
617 {
618 if ( !noPrefix )
619 return FSM_NAME() + "_";
620 return "";
621 }
622
623 /* Emit the alphabet data type. */
624 string FsmCodeGen::ALPH_TYPE()
625 {
626 string ret = keyOps->alphType->data1;
627 if ( keyOps->alphType->data2 != 0 ) {
628 ret += " ";
629 ret += + keyOps->alphType->data2;
630 }
631 return ret;
632 }
633
634 /* Emit the alphabet data type. */
635 string FsmCodeGen::WIDE_ALPH_TYPE()
636 {
637 string ret;
638 if ( redFsm->maxKey <= keyOps->maxKey )
639 ret = ALPH_TYPE();
640 else {
641 long long maxKeyVal = redFsm->maxKey.getLongLong();
642 HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
643 assert( wideType != 0 );
644
645 ret = wideType->data1;
646 if ( wideType->data2 != 0 ) {
647 ret += " ";
648 ret += wideType->data2;
649 }
650 }
651 return ret;
652 }
653
654 void FsmCodeGen::STATE_IDS()
655 {
656 if ( redFsm->startState != 0 )
657 STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << ";\n";
658
659 if ( !noFinal )
660 STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << ";\n";
661
662 if ( !noError )
663 STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << ";\n";
664
665 out << "\n";
666
667 if ( !noEntry && entryPointNames.length() > 0 ) {
668 for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) {
669 STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en ) <<
670 " = " << entryPointIds[en.pos()] << ";\n";
671 }
672 out << "\n";
673 }
674 }
675
676 void FsmCodeGen::writeStart()
677 {
678 out << START_STATE_ID();
679 }
680
681 void FsmCodeGen::writeFirstFinal()
682 {
683 out << FIRST_FINAL_STATE();
684 }
685
686 void FsmCodeGen::writeError()
687 {
688 out << ERROR_STATE();
689 }
690
691 /*
692 * Language specific, but style independent code generators functions.
693 */
694
695 string CCodeGen::PTR_CONST()
696 {
697 return "const ";
698 }
699
700 string CCodeGen::PTR_CONST_END()
701 {
702 return "";
703 }
704
705 std::ostream &CCodeGen::OPEN_ARRAY( string type, string name )
706 {
707 out << "static const " << type << " " << name << "[] = {\n";
708 return out;
709 }
710
711 std::ostream &CCodeGen::CLOSE_ARRAY()
712 {
713 return out << "};\n";
714 }
715
716 std::ostream &CCodeGen::STATIC_VAR( string type, string name )
717 {
718 out << "static const " << type << " " << name;
719 return out;
720 }
721
722 string CCodeGen::UINT( )
723 {
724 return "unsigned int";
725 }
726
727 string CCodeGen::ARR_OFF( string ptr, string offset )
728 {
729 return ptr + " + " + offset;
730 }
731
732 string CCodeGen::CAST( string type )
733 {
734 return "(" + type + ")";
735 }
736
737 string CCodeGen::NULL_ITEM()
738 {
739 return "0";
740 }
741
742 string CCodeGen::POINTER()
743 {
744 return " *";
745 }
746
747 std::ostream &CCodeGen::SWITCH_DEFAULT()
748 {
749 return out;
750 }
751
752 string CCodeGen::CTRL_FLOW()
753 {
754 return "";
755 }
756
757 void CCodeGen::writeExports()
758 {
759 if ( exportList.length() > 0 ) {
760 for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) {
761 out << "#define " << DATA_PREFIX() << "ex_" << ex->name << " " <<
762 KEY(ex->key) << "\n";
763 }
764 out << "\n";
765 }
766 }
767
768 /*
769 * D Specific
770 */
771
772 string DCodeGen::NULL_ITEM()
773 {
774 return "null";
775 }
776
777 string DCodeGen::POINTER()
778 {
779 // multiple items seperated by commas can also be pointer types.
780 return "* ";
781 }
782
783 string DCodeGen::PTR_CONST()
784 {
785 return "";
786 }
787
788 string DCodeGen::PTR_CONST_END()
789 {
790 return "";
791 }
792
793 std::ostream &DCodeGen::OPEN_ARRAY( string type, string name )
794 {
795 out << "static const " << type << "[] " << name << " = [\n";
796 return out;
797 }
798
799 std::ostream &DCodeGen::CLOSE_ARRAY()
800 {
801 return out << "];\n";
802 }
803
804 std::ostream &DCodeGen::STATIC_VAR( string type, string name )
805 {
806 out << "static const " << type << " " << name;
807 return out;
808 }
809
810 string DCodeGen::ARR_OFF( string ptr, string offset )
811 {
812 return "&" + ptr + "[" + offset + "]";
813 }
814
815 string DCodeGen::CAST( string type )
816 {
817 return "cast(" + type + ")";
818 }
819
820 string DCodeGen::UINT( )
821 {
822 return "uint";
823 }
824
825 std::ostream &DCodeGen::SWITCH_DEFAULT()
826 {
827 out << " default: break;\n";
828 return out;
829 }
830
831 string DCodeGen::CTRL_FLOW()
832 {
833 return "if (true) ";
834 }
835
836 void DCodeGen::writeExports()
837 {
838 if ( exportList.length() > 0 ) {
839 for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) {
840 out << "static const " << ALPH_TYPE() << " " << DATA_PREFIX() <<
841 "ex_" << ex->name << " = " << KEY(ex->key) << ";\n";
842 }
843 out << "\n";
844 }
845 }
846
847 /*
848 * End D-specific code.
849 */
850
851 /*
852 * D2 Specific
853 */
854
855 string D2CodeGen::NULL_ITEM()
856 {
857 return "null";
858 }
859
860 string D2CodeGen::POINTER()
861 {
862 // multiple items seperated by commas can also be pointer types.
863 return "* ";
864 }
865
866 string D2CodeGen::PTR_CONST()
867 {
868 return "const(";
869 }
870
871 string D2CodeGen::PTR_CONST_END()
872 {
873 return ")";
874 }
875
876 std::ostream &D2CodeGen::OPEN_ARRAY( string type, string name )
877 {
878 out << "enum " << type << "[] " << name << " = [\n";
879 return out;
880 }
881
882 std::ostream &D2CodeGen::CLOSE_ARRAY()
883 {
884 return out << "];\n";
885 }
886
887 std::ostream &D2CodeGen::STATIC_VAR( string type, string name )
888 {
889 out << "enum " << type << " " << name;
890 return out;
891 }
892
893 string D2CodeGen::ARR_OFF( string ptr, string offset )
894 {
895 return "&" + ptr + "[" + offset + "]";
896 }
897
898 string D2CodeGen::CAST( string type )
899 {
900 return "cast(" + type + ")";
901 }
902
903 string D2CodeGen::UINT( )
904 {
905 return "uint";
906 }
907
908 std::ostream &D2CodeGen::SWITCH_DEFAULT()
909 {
910 out << " default: break;\n";
911 return out;
912 }
913
914 string D2CodeGen::CTRL_FLOW()
915 {
916 return "if (true) ";
917 }
918
919 void D2CodeGen::writeExports()
920 {
921 if ( exportList.length() > 0 ) {
922 for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) {
923 out << "enum " << ALPH_TYPE() << " " << DATA_PREFIX() <<
924 "ex_" << ex->name << " = " << KEY(ex->key) << ";\n";
925 }
926 out << "\n";
927 }
928 }
929
930 void D2CodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item,
931 int targState, bool inFinish, bool csForced )
932 {
933 if ( item->children->length() > 0 ) {
934 /* Write the block and close it off. */
935 ret << "{{";
936 INLINE_LIST( ret, item->children, targState, inFinish, csForced );
937 ret << "}}";
938 }
939 }
940
941 void D2CodeGen::ACTION( ostream &ret, GenAction *action, int targState,
942 bool inFinish, bool csForced )
943 {
944 /* Write the preprocessor line info for going into the source file. */
945 cdLineDirective( ret, action->loc.fileName, action->loc.line );
946
947 /* Write the block and close it off. */
948 ret << "\t{{";
949 INLINE_LIST( ret, action->inlineList, targState, inFinish, csForced );
950 ret << "}}\n";
951 }
952
953 /*
954 * End D2-specific code.
955 */
956
957 void FsmCodeGen::finishRagelDef()
958 {
959 if ( codeStyle == GenGoto || codeStyle == GenFGoto ||
960 codeStyle == GenIpGoto || codeStyle == GenSplit )
961 {
962 /* For directly executable machines there is no required state
963 * ordering. Choose a depth-first ordering to increase the
964 * potential for fall-throughs. */
965 redFsm->depthFirstOrdering();
966 }
967 else {
968 /* The frontend will do this for us, but it may be a good idea to
969 * force it if the intermediate file is edited. */
970 redFsm->sortByStateId();
971 }
972
973 /* Choose default transitions and the single transition. */
974 redFsm->chooseDefaultSpan();
975
976 /* Maybe do flat expand, otherwise choose single. */
977 if ( codeStyle == GenFlat || codeStyle == GenFFlat )
978 redFsm->makeFlat();
979 else
980 redFsm->chooseSingle();
981
982 /* If any errors have occured in the input file then don't write anything. */
983 if ( gblErrorCount > 0 )
984 return;
985
986 if ( codeStyle == GenSplit )
987 redFsm->partitionFsm( numSplitPartitions );
988
989 if ( codeStyle == GenIpGoto || codeStyle == GenSplit )
990 redFsm->setInTrans();
991
992 /* Anlayze Machine will find the final action reference counts, among
993 * other things. We will use these in reporting the usage
994 * of fsm directives in action code. */
995 analyzeMachine();
996
997 /* Determine if we should use indicies. */
998 calcIndexSize();
999 }
1000
1001 ostream &FsmCodeGen::source_warning( const InputLoc &loc )
1002 {
1003 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
1004 return cerr;
1005 }
1006
1007 ostream &FsmCodeGen::source_error( const InputLoc &loc )
1008 {
1009 gblErrorCount += 1;
1010 assert( sourceFileName != 0 );
1011 cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
1012 return cerr;
1013 }
1014