"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