"Fossies" - the Fresh Open Source Software Archive

Member "ragel-6.10/ragel/mlcodegen.cpp" (24 Mar 2017, 17597 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 "mlcodegen.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 "ragel.h"
   25 #include "mlcodegen.h"
   26 #include "redfsm.h"
   27 #include "gendata.h"
   28 #include <sstream>
   29 #include <iomanip>
   30 #include <string>
   31 #include <assert.h>
   32 
   33 using std::ostream;
   34 using std::ostringstream;
   35 using std::string;
   36 using std::cerr;
   37 using std::endl;
   38 
   39 using std::istream;
   40 using std::ifstream;
   41 using std::ostream;
   42 using std::ios;
   43 using std::cin;
   44 using std::cout;
   45 using std::cerr;
   46 using std::endl;
   47 
   48 void ocamlLineDirective( ostream &out, const char *fileName, int line )
   49 {
   50     if ( noLineDirectives )
   51         return;
   52 
   53     /* Write the line info for to the input file. */
   54     out << "# " << line << " \"";
   55     for ( const char *pc = fileName; *pc != 0; pc++ ) {
   56         if ( *pc == '\\' || *pc == '"' )
   57             out << "\\";
   58     out << *pc;
   59     }
   60     out << "\"\n";
   61 }
   62 
   63 void OCamlCodeGen::genLineDirective( ostream &out )
   64 {
   65     std::streambuf *sbuf = out.rdbuf();
   66     output_filter *filter = static_cast<output_filter*>(sbuf);
   67     ocamlLineDirective( out, filter->fileName, filter->line + 1 );
   68 }
   69 
   70 
   71 /* Init code gen with in parameters. */
   72 OCamlCodeGen::OCamlCodeGen( ostream &out )
   73 :
   74     CodeGenData(out)
   75 {
   76 }
   77 
   78 unsigned int OCamlCodeGen::arrayTypeSize( unsigned long maxVal )
   79 {
   80     long long maxValLL = (long long) maxVal;
   81     HostType *arrayType = keyOps->typeSubsumes( maxValLL );
   82     assert( arrayType != 0 );
   83     return arrayType->size;
   84 }
   85 
   86 string OCamlCodeGen::ARRAY_TYPE( unsigned long maxVal )
   87 {
   88     return ARRAY_TYPE( maxVal, false );
   89 }
   90 
   91 string OCamlCodeGen::ARRAY_TYPE( unsigned long maxVal, bool forceSigned )
   92 {
   93     long long maxValLL = (long long) maxVal;
   94     HostType *arrayType;
   95     if (forceSigned)
   96         arrayType = keyOps->typeSubsumes(true, maxValLL);
   97     else
   98         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 /* Write out the fsm name. */
  110 string OCamlCodeGen::FSM_NAME()
  111 {
  112     return fsmName;
  113 }
  114 
  115 /* Emit the offset of the start state as a decimal integer. */
  116 string OCamlCodeGen::START_STATE_ID()
  117 {
  118     ostringstream ret;
  119     ret << redFsm->startState->id;
  120     return ret.str();
  121 };
  122 
  123 /* Write out the array of actions. */
  124 std::ostream &OCamlCodeGen::ACTIONS_ARRAY()
  125 {
  126     out << "\t0; ";
  127     int totalActions = 1;
  128     for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
  129         /* Write out the length, which will never be the last character. */
  130         out << act->key.length() << ARR_SEP();
  131         /* Put in a line break every 8 */
  132         if ( totalActions++ % 8 == 7 )
  133             out << "\n\t";
  134 
  135         for ( GenActionTable::Iter item = act->key; item.lte(); item++ ) {
  136             out << item->value->actionId;
  137             if ( ! (act.last() && item.last()) )
  138                 out << ARR_SEP();
  139 
  140             /* Put in a line break every 8 */
  141             if ( totalActions++ % 8 == 7 )
  142                 out << "\n\t";
  143         }
  144     }
  145     out << "\n";
  146     return out;
  147 }
  148 
  149 
  150 /*
  151 string OCamlCodeGen::ACCESS()
  152 {
  153     ostringstream ret;
  154     if ( accessExpr != 0 )
  155         INLINE_LIST( ret, accessExpr, 0, false );
  156     return ret.str();
  157 }
  158 */
  159 
  160 string OCamlCodeGen::make_access(char const* name, GenInlineList* x, bool prefix = true)
  161 { 
  162     ostringstream ret;
  163     if ( x == 0 )
  164   {
  165     if (prefix && accessExpr != 0)
  166     {
  167       INLINE_LIST( ret, accessExpr, 0, false);
  168       ret << name;
  169     }
  170     else
  171       ret << name << ".contents"; // ref cell
  172   }
  173     else {
  174         ret << "(";
  175         INLINE_LIST( ret, x, 0, false );
  176         ret << ")";
  177     }
  178     return ret.str();
  179 }
  180 
  181 string OCamlCodeGen::P() { return make_access("p", pExpr, false); }
  182 string OCamlCodeGen::PE() { return make_access("pe", peExpr, false); }
  183 string OCamlCodeGen::vEOF() { return make_access("eof", eofExpr, false); }
  184 string OCamlCodeGen::vCS() { return make_access("cs", csExpr); }
  185 string OCamlCodeGen::TOP() { return make_access("top", topExpr); }
  186 string OCamlCodeGen::STACK() { return make_access("stack", stackExpr); }
  187 string OCamlCodeGen::ACT() { return make_access("act", actExpr); }
  188 string OCamlCodeGen::TOKSTART() { return make_access("ts", tokstartExpr); }
  189 string OCamlCodeGen::TOKEND() { return make_access("te", tokendExpr); }
  190 
  191 string OCamlCodeGen::GET_WIDE_KEY()
  192 {
  193     if ( redFsm->anyConditions() ) 
  194         return "_widec";
  195     else
  196     { ostringstream ret; ret << "Char.code " << GET_KEY(); return ret.str(); }
  197 }
  198 
  199 string OCamlCodeGen::GET_WIDE_KEY( RedStateAp *state )
  200 {
  201     if ( state->stateCondList.length() > 0 )
  202         return "_widec";
  203     else
  204     { ostringstream ret; ret << "Char.code " << GET_KEY(); return ret.str(); }
  205 }
  206 
  207 /* Write out level number of tabs. Makes the nested binary search nice
  208  * looking. */
  209 string OCamlCodeGen::TABS( int level )
  210 {
  211     string result;
  212     while ( level-- > 0 )
  213         result += "\t";
  214     return result;
  215 }
  216 
  217 /* Write out a key from the fsm code gen. Depends on wether or not the key is
  218  * signed. */
  219 string OCamlCodeGen::KEY( Key key )
  220 {
  221     ostringstream ret;
  222     if ( keyOps->isSigned || !hostLang->explicitUnsigned )
  223         ret << key.getVal();
  224     else
  225         ret << (unsigned long) key.getVal() << 'u';
  226     return ret.str();
  227 }
  228 
  229 string OCamlCodeGen::ALPHA_KEY( Key key )
  230 {
  231     ostringstream ret;
  232   ret << key.getVal();
  233   /*
  234     if (key.getVal() > 0xFFFF) {
  235         ret << key.getVal();
  236     } else {
  237         ret << "'\\u" << std::hex << std::setw(4) << std::setfill('0') << 
  238             key.getVal() << "'";
  239     }
  240   */
  241     //ret << "(char) " << key.getVal();
  242     return ret.str();
  243 }
  244 
  245 void OCamlCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish )
  246 {
  247 // The parser gives fexec two children.
  248     ret << "begin " << P() << " <- ";
  249     INLINE_LIST( ret, item->children, targState, inFinish );
  250     ret << " - 1 end; ";
  251 }
  252 
  253 void OCamlCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item, 
  254         int targState, int inFinish )
  255 {
  256     bool catch_all = false;
  257     ret << 
  258         "   begin match " << ACT() << " with\n";
  259 
  260     for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
  261         /* Write the case label, the action and the case break. */
  262         if ( lma->lmId < 0 )
  263         {
  264             catch_all = true;
  265             ret << "    | _ ->\n";
  266         }
  267         else
  268             ret << "    | " << lma->lmId << " ->\n";
  269 
  270         /* Write the block and close it off. */
  271         ret << "    begin ";
  272         INLINE_LIST( ret, lma->children, targState, inFinish );
  273         ret << " end\n";
  274     }
  275 
  276     if (!catch_all)
  277         ret << "  | _ -> assert false\n";
  278 
  279     ret << 
  280         "   end;\n"
  281         "\t";
  282 }
  283 
  284 void OCamlCodeGen::SET_ACT( ostream &ret, GenInlineItem *item )
  285 {
  286     ret << ACT() << " <- " << item->lmId << "; ";
  287 }
  288 
  289 void OCamlCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item )
  290 {
  291     /* The tokend action sets tokend. */
  292     ret << TOKEND() << " <- " << P();
  293     if ( item->offset != 0 ) 
  294         out << "+" << item->offset;
  295     out << "; ";
  296 }
  297 
  298 void OCamlCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item )
  299 {
  300     ret << TOKEND();
  301 }
  302 
  303 void OCamlCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item )
  304 {
  305     ret << TOKSTART() << " <- " << NULL_ITEM() << "; ";
  306 }
  307 
  308 void OCamlCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item )
  309 {
  310     ret << ACT() << " <- 0;";
  311 }
  312 
  313 void OCamlCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item )
  314 {
  315     ret << TOKSTART() << " <- " << P() << "; ";
  316 }
  317 
  318 void OCamlCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item, 
  319         int targState, bool inFinish )
  320 {
  321     if ( item->children->length() > 0 ) {
  322         /* Write the block and close it off. */
  323         ret << "begin ";
  324         INLINE_LIST( ret, item->children, targState, inFinish );
  325         ret << " end";
  326     }
  327 }
  328 
  329 
  330 /* Write out an inline tree structure. Walks the list and possibly calls out
  331  * to virtual functions than handle language specific items in the tree. */
  332 void OCamlCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList, 
  333         int targState, bool inFinish )
  334 {
  335     for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
  336         switch ( item->type ) {
  337         case GenInlineItem::Text:
  338             ret << item->data;
  339             break;
  340         case GenInlineItem::Goto:
  341             GOTO( ret, item->targState->id, inFinish );
  342             break;
  343         case GenInlineItem::Call:
  344             CALL( ret, item->targState->id, targState, inFinish );
  345             break;
  346         case GenInlineItem::Next:
  347             NEXT( ret, item->targState->id, inFinish );
  348             break;
  349         case GenInlineItem::Ret:
  350             RET( ret, inFinish );
  351             break;
  352         case GenInlineItem::PChar:
  353             ret << P();
  354             break;
  355         case GenInlineItem::Char:
  356             ret << GET_KEY();
  357             break;
  358         case GenInlineItem::Hold:
  359             ret << P() << " <- " << P() << " - 1; ";
  360             break;
  361         case GenInlineItem::Exec:
  362             EXEC( ret, item, targState, inFinish );
  363             break;
  364         case GenInlineItem::Curs:
  365             CURS( ret, inFinish );
  366             break;
  367         case GenInlineItem::Targs:
  368             TARGS( ret, inFinish, targState );
  369             break;
  370         case GenInlineItem::Entry:
  371             ret << item->targState->id;
  372             break;
  373         case GenInlineItem::GotoExpr:
  374             GOTO_EXPR( ret, item, inFinish );
  375             break;
  376         case GenInlineItem::CallExpr:
  377             CALL_EXPR( ret, item, targState, inFinish );
  378             break;
  379         case GenInlineItem::NextExpr:
  380             NEXT_EXPR( ret, item, inFinish );
  381             break;
  382         case GenInlineItem::LmSwitch:
  383             LM_SWITCH( ret, item, targState, inFinish );
  384             break;
  385         case GenInlineItem::LmSetActId:
  386             SET_ACT( ret, item );
  387             break;
  388         case GenInlineItem::LmSetTokEnd:
  389             SET_TOKEND( ret, item );
  390             break;
  391         case GenInlineItem::LmGetTokEnd:
  392             GET_TOKEND( ret, item );
  393             break;
  394         case GenInlineItem::LmInitTokStart:
  395             INIT_TOKSTART( ret, item );
  396             break;
  397         case GenInlineItem::LmInitAct:
  398             INIT_ACT( ret, item );
  399             break;
  400         case GenInlineItem::LmSetTokStart:
  401             SET_TOKSTART( ret, item );
  402             break;
  403         case GenInlineItem::SubAction:
  404             SUB_ACTION( ret, item, targState, inFinish );
  405             break;
  406         case GenInlineItem::Break:
  407             BREAK( ret, targState );
  408             break;
  409         }
  410     }
  411 }
  412 /* Write out paths in line directives. Escapes any special characters. */
  413 string OCamlCodeGen::LDIR_PATH( char *path )
  414 {
  415     ostringstream ret;
  416     for ( char *pc = path; *pc != 0; pc++ ) {
  417         if ( *pc == '\\' )
  418             ret << "\\\\";
  419         else
  420             ret << *pc;
  421     }
  422     return ret.str();
  423 }
  424 
  425 void OCamlCodeGen::ACTION( ostream &ret, GenAction *action, int targState, bool inFinish )
  426 {
  427     /* Write the preprocessor line info for going into the source file. */
  428     ocamlLineDirective( ret, action->loc.fileName, action->loc.line );
  429 
  430     /* Write the block and close it off. */
  431     ret << "\t\tbegin ";
  432     INLINE_LIST( ret, action->inlineList, targState, inFinish );
  433     ret << " end;\n";
  434 }
  435 
  436 void OCamlCodeGen::CONDITION( ostream &ret, GenAction *condition )
  437 {
  438     ret << "\n";
  439     ocamlLineDirective( ret, condition->loc.fileName, condition->loc.line );
  440     INLINE_LIST( ret, condition->inlineList, 0, false );
  441 }
  442 
  443 string OCamlCodeGen::ERROR_STATE()
  444 {
  445     ostringstream ret;
  446     if ( redFsm->errState != 0 )
  447         ret << redFsm->errState->id;
  448     else
  449         ret << "-1";
  450     return ret.str();
  451 }
  452 
  453 string OCamlCodeGen::FIRST_FINAL_STATE()
  454 {
  455     ostringstream ret;
  456     if ( redFsm->firstFinState != 0 )
  457         ret << redFsm->firstFinState->id;
  458     else
  459         ret << redFsm->nextStateId;
  460     return ret.str();
  461 }
  462 
  463 void OCamlCodeGen::writeInit()
  464 {
  465     out << "    begin\n";
  466 
  467     if ( !noCS )
  468         out << "\t" << vCS() << " <- " << START() << ";\n";
  469     
  470     /* If there are any calls, then the stack top needs initialization. */
  471     if ( redFsm->anyActionCalls() || redFsm->anyActionRets() )
  472         out << "\t" << TOP() << " <- 0;\n";
  473 
  474     if ( hasLongestMatch ) {
  475         out << 
  476             "   " << TOKSTART() << " <- " << NULL_ITEM() << ";\n"
  477             "   " << TOKEND() << " <- " << NULL_ITEM() << ";\n"
  478             "   " << ACT() << " <- 0;\n";
  479     }
  480     out << "    end;\n";
  481 }
  482 
  483 string OCamlCodeGen::PRE_INCR(string val)
  484 {
  485   ostringstream ret;
  486   ret << "(" << val << " <- " << val << " + 1; " << val << ")";
  487   return ret.str();
  488 }
  489 
  490 string OCamlCodeGen::POST_INCR(string val)
  491 {
  492   ostringstream ret;
  493   ret << "(let temp = " << val << " in " << val << " <- " << val << " + 1; temp)";
  494   return ret.str();
  495 }
  496 
  497 string OCamlCodeGen::PRE_DECR(string val)
  498 {
  499   ostringstream ret;
  500   ret << "(" << val << " <- " << val << " - 1; " << val << ")";
  501   return ret.str();
  502 }
  503 
  504 string OCamlCodeGen::POST_DECR(string val)
  505 {
  506   ostringstream ret;
  507   ret << "(let temp = " << val << " in " << val << " <- " << val << " - 1; temp)";
  508   return ret.str();
  509 }
  510 
  511 string OCamlCodeGen::DATA_PREFIX()
  512 {
  513   if ( data_prefix.empty() ) // init
  514   {
  515     data_prefix = string(fsmName) + "_";
  516     if (data_prefix.size() > 0)
  517       data_prefix[0] = ::tolower(data_prefix[0]); // uncapitalize
  518   }
  519     if ( !noPrefix )
  520         return data_prefix;
  521     return "";
  522 }
  523 
  524 /* Emit the alphabet data type. */
  525 string OCamlCodeGen::ALPH_TYPE()
  526 {
  527     string ret = keyOps->alphType->data1;
  528     if ( keyOps->alphType->data2 != 0 ) {
  529         ret += " ";
  530         ret += + keyOps->alphType->data2;
  531     }
  532     return ret;
  533 }
  534 
  535 /* Emit the alphabet data type. */
  536 string OCamlCodeGen::WIDE_ALPH_TYPE()
  537 {
  538     string ret;
  539     if ( redFsm->maxKey <= keyOps->maxKey )
  540         ret = ALPH_TYPE();
  541     else {
  542         long long maxKeyVal = redFsm->maxKey.getLongLong();
  543         HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
  544         assert( wideType != 0 );
  545 
  546         ret = wideType->data1;
  547         if ( wideType->data2 != 0 ) {
  548             ret += " ";
  549             ret += wideType->data2;
  550         }
  551     }
  552     return ret;
  553 }
  554 
  555 void OCamlCodeGen::STATE_IDS()
  556 {
  557     if ( redFsm->startState != 0 )
  558         STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << TOP_SEP ();
  559 
  560     if ( !noFinal )
  561         STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << TOP_SEP();
  562 
  563     if ( !noError )
  564         STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << TOP_SEP();
  565 
  566     out << "\n";
  567 
  568     if ( !noEntry && entryPointNames.length() > 0 ) {
  569         for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) {
  570             STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en ) << 
  571                     " = " << entryPointIds[en.pos()] << TOP_SEP();
  572         }
  573         out << "\n";
  574     }
  575 }
  576 
  577 
  578 void OCamlCodeGen::writeStart()
  579 {
  580     out << START_STATE_ID();
  581 }
  582 
  583 void OCamlCodeGen::writeFirstFinal()
  584 {
  585     out << FIRST_FINAL_STATE();
  586 }
  587 
  588 void OCamlCodeGen::writeError()
  589 {
  590     out << ERROR_STATE();
  591 }
  592 
  593 string OCamlCodeGen::GET_KEY()
  594 {
  595     ostringstream ret;
  596     if ( getKeyExpr != 0 ) { 
  597         /* Emit the user supplied method of retrieving the key. */
  598         ret << "(";
  599         INLINE_LIST( ret, getKeyExpr, 0, false );
  600         ret << ")";
  601     }
  602     else {
  603         /* Expression for retrieving the key, use simple dereference. */
  604         ret << "data.[" << P() << "]";
  605     }
  606     return ret.str();
  607 }
  608 string OCamlCodeGen::NULL_ITEM()
  609 {
  610     return "-1";
  611 }
  612 
  613 string OCamlCodeGen::POINTER()
  614 {
  615     // XXX C# has no pointers
  616     // multiple items seperated by commas can also be pointer types.
  617     return " ";
  618 }
  619 
  620 string OCamlCodeGen::PTR_CONST()
  621 {
  622     return "";
  623 }
  624 
  625 std::ostream &OCamlCodeGen::OPEN_ARRAY( string type, string name )
  626 {
  627     out << "let " << name << " : " << type << " array = [|" << endl;
  628     return out;
  629 }
  630 
  631 std::ostream &OCamlCodeGen::CLOSE_ARRAY()
  632 {
  633     return out << "|]" << TOP_SEP();
  634 }
  635 
  636 string OCamlCodeGen::TOP_SEP()
  637 {
  638   return "\n"; // original syntax
  639 }
  640 
  641 string OCamlCodeGen::ARR_SEP()
  642 {
  643   return "; ";
  644 }
  645 
  646 string OCamlCodeGen::AT(const string& array, const string& index)
  647 {
  648   ostringstream ret;
  649   ret << array << ".(" << index << ")";
  650   return ret.str();
  651 }
  652 
  653 std::ostream &OCamlCodeGen::STATIC_VAR( string type, string name )
  654 {
  655     out << "let " << name << " : " << type;
  656     return out;
  657 }
  658 
  659 string OCamlCodeGen::ARR_OFF( string ptr, string offset )
  660 {
  661     // XXX C# can't do pointer arithmetic
  662     return "&" + ptr + "[" + offset + "]";
  663 }
  664 
  665 string OCamlCodeGen::CAST( string type )
  666 {
  667   return "";
  668 //  return "(" + type + ")";
  669 }
  670 
  671 string OCamlCodeGen::UINT( )
  672 {
  673     return "uint";
  674 }
  675 
  676 std::ostream &OCamlCodeGen::SWITCH_DEFAULT()
  677 {
  678     out << "        | _ -> ()\n";
  679     return out;
  680 }
  681 
  682 string OCamlCodeGen::CTRL_FLOW()
  683 {
  684     return "if true then ";
  685 }
  686 
  687 void OCamlCodeGen::finishRagelDef()
  688 {
  689     if ( codeStyle == GenGoto || codeStyle == GenFGoto || 
  690             codeStyle == GenIpGoto || codeStyle == GenSplit )
  691     {
  692         /* For directly executable machines there is no required state
  693          * ordering. Choose a depth-first ordering to increase the
  694          * potential for fall-throughs. */
  695         redFsm->depthFirstOrdering();
  696     }
  697     else {
  698         /* The frontend will do this for us, but it may be a good idea to
  699          * force it if the intermediate file is edited. */
  700         redFsm->sortByStateId();
  701     }
  702 
  703     /* Choose default transitions and the single transition. */
  704     redFsm->chooseDefaultSpan();
  705         
  706     /* Maybe do flat expand, otherwise choose single. */
  707     if ( codeStyle == GenFlat || codeStyle == GenFFlat )
  708         redFsm->makeFlat();
  709     else
  710         redFsm->chooseSingle();
  711 
  712     /* If any errors have occured in the input file then don't write anything. */
  713     if ( gblErrorCount > 0 )
  714         return;
  715     
  716     if ( codeStyle == GenSplit )
  717         redFsm->partitionFsm( numSplitPartitions );
  718 
  719     if ( codeStyle == GenIpGoto || codeStyle == GenSplit )
  720         redFsm->setInTrans();
  721 
  722     /* Anlayze Machine will find the final action reference counts, among
  723      * other things. We will use these in reporting the usage
  724      * of fsm directives in action code. */
  725     analyzeMachine();
  726 
  727     /* Determine if we should use indicies. */
  728     calcIndexSize();
  729 }
  730 
  731 ostream &OCamlCodeGen::source_warning( const InputLoc &loc )
  732 {
  733     cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
  734     return cerr;
  735 }
  736 
  737 ostream &OCamlCodeGen::source_error( const InputLoc &loc )
  738 {
  739     gblErrorCount += 1;
  740     assert( sourceFileName != 0 );
  741     cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
  742     return cerr;
  743 }
  744