"Fossies" - the Fresh Open Source Software Archive

Member "ragel-6.10/ragel/javacodegen.cpp" (24 Mar 2017, 40555 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 "javacodegen.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 2006-2007 Adrian Thurston <thurston@complang.org>
    3  *            2007 Colin Fleming <colin.fleming@caverock.com>
    4  */
    5 
    6 /*  This file is part of Ragel.
    7  *
    8  *  Ragel is free software; you can redistribute it and/or modify
    9  *  it under the terms of the GNU General Public License as published by
   10  *  the Free Software Foundation; either version 2 of the License, or
   11  *  (at your option) any later version.
   12  * 
   13  *  Ragel is distributed in the hope that it will be useful,
   14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16  *  GNU General Public License for more details.
   17  * 
   18  *  You should have received a copy of the GNU General Public License
   19  *  along with Ragel; if not, write to the Free Software
   20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
   21  */
   22 
   23 #include "ragel.h"
   24 #include "javacodegen.h"
   25 #include "redfsm.h"
   26 #include "gendata.h"
   27 #include <iomanip>
   28 #include <sstream>
   29 
   30 /* Integer array line length. */
   31 #define IALL 12
   32 
   33 /* Static array initialization item count 
   34  * (should be multiple of IALL). */
   35 #define SAIIC 8184
   36 
   37 #define _resume    1
   38 #define _again     2
   39 #define _eof_trans 3
   40 #define _test_eof  4
   41 #define _out       5
   42 
   43 using std::setw;
   44 using std::ios;
   45 using std::ostringstream;
   46 using std::string;
   47 using std::cerr;
   48 
   49 using std::istream;
   50 using std::ifstream;
   51 using std::ostream;
   52 using std::ios;
   53 using std::cin;
   54 using std::cout;
   55 using std::cerr;
   56 using std::endl;
   57 using std::setiosflags;
   58 
   59 void javaLineDirective( ostream &out, const char *fileName, int line )
   60 {
   61     /* Write the preprocessor line info for to the input file. */
   62     out << "// line " << line  << " \"";
   63     for ( const char *pc = fileName; *pc != 0; pc++ ) {
   64         if ( *pc == '\\' )
   65             out << "\\\\";
   66         else
   67             out << *pc;
   68     }
   69     out << "\"\n";
   70 }
   71 
   72 void JavaTabCodeGen::genLineDirective( ostream &out )
   73 {
   74     std::streambuf *sbuf = out.rdbuf();
   75     output_filter *filter = static_cast<output_filter*>(sbuf);
   76     javaLineDirective( out, filter->fileName, filter->line + 1 );
   77 }
   78 
   79 void JavaTabCodeGen::GOTO( ostream &ret, int gotoDest, bool inFinish )
   80 {
   81     ret << "{" << vCS() << " = " << gotoDest << "; _goto_targ = " << _again << "; " << 
   82             CTRL_FLOW() << "continue _goto;}";
   83 }
   84 
   85 void JavaTabCodeGen::GOTO_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
   86 {
   87     ret << "{" << vCS() << " = (";
   88     INLINE_LIST( ret, ilItem->children, 0, inFinish );
   89     ret << "); _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
   90 }
   91 
   92 void JavaTabCodeGen::CALL( ostream &ret, int callDest, int targState, bool inFinish )
   93 {
   94     if ( prePushExpr != 0 ) {
   95         ret << "{";
   96         INLINE_LIST( ret, prePushExpr, 0, false );
   97     }
   98 
   99     ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = " << 
  100             callDest << "; _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
  101 
  102     if ( prePushExpr != 0 )
  103         ret << "}";
  104 }
  105 
  106 void JavaTabCodeGen::CALL_EXPR( ostream &ret, GenInlineItem *ilItem, int targState, bool inFinish )
  107 {
  108     if ( prePushExpr != 0 ) {
  109         ret << "{";
  110         INLINE_LIST( ret, prePushExpr, 0, false );
  111     }
  112 
  113     ret << "{" << STACK() << "[" << TOP() << "++] = " << vCS() << "; " << vCS() << " = (";
  114     INLINE_LIST( ret, ilItem->children, targState, inFinish );
  115     ret << "); _goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
  116 
  117     if ( prePushExpr != 0 )
  118         ret << "}";
  119 }
  120 
  121 void JavaTabCodeGen::RET( ostream &ret, bool inFinish )
  122 {
  123     ret << "{" << vCS() << " = " << STACK() << "[--" << TOP() << "];";
  124 
  125     if ( postPopExpr != 0 ) {
  126         ret << "{";
  127         INLINE_LIST( ret, postPopExpr, 0, false );
  128         ret << "}";
  129     }
  130 
  131     ret << "_goto_targ = " << _again << "; " << CTRL_FLOW() << "continue _goto;}";
  132 }
  133 
  134 void JavaTabCodeGen::BREAK( ostream &ret, int targState )
  135 {
  136     ret << "{ " << P() << " += 1; _goto_targ = " << _out << "; " << 
  137             CTRL_FLOW() << " continue _goto;}";
  138 }
  139 
  140 void JavaTabCodeGen::NEXT( ostream &ret, int nextDest, bool inFinish )
  141 {
  142     ret << vCS() << " = " << nextDest << ";";
  143 }
  144 
  145 void JavaTabCodeGen::NEXT_EXPR( ostream &ret, GenInlineItem *ilItem, bool inFinish )
  146 {
  147     ret << vCS() << " = (";
  148     INLINE_LIST( ret, ilItem->children, 0, inFinish );
  149     ret << ");";
  150 }
  151 
  152 void JavaTabCodeGen::EXEC( ostream &ret, GenInlineItem *item, int targState, int inFinish )
  153 {
  154     /* The parser gives fexec two children. The double brackets are for D
  155      * code. If the inline list is a single word it will get interpreted as a
  156      * C-style cast by the D compiler. */
  157     ret << "{" << P() << " = ((";
  158     INLINE_LIST( ret, item->children, targState, inFinish );
  159     ret << "))-1;}";
  160 }
  161 
  162 /* Write out an inline tree structure. Walks the list and possibly calls out
  163  * to virtual functions than handle language specific items in the tree. */
  164 void JavaTabCodeGen::INLINE_LIST( ostream &ret, GenInlineList *inlineList, 
  165         int targState, bool inFinish )
  166 {
  167     for ( GenInlineList::Iter item = *inlineList; item.lte(); item++ ) {
  168         switch ( item->type ) {
  169         case GenInlineItem::Text:
  170             ret << item->data;
  171             break;
  172         case GenInlineItem::Goto:
  173             GOTO( ret, item->targState->id, inFinish );
  174             break;
  175         case GenInlineItem::Call:
  176             CALL( ret, item->targState->id, targState, inFinish );
  177             break;
  178         case GenInlineItem::Next:
  179             NEXT( ret, item->targState->id, inFinish );
  180             break;
  181         case GenInlineItem::Ret:
  182             RET( ret, inFinish );
  183             break;
  184         case GenInlineItem::PChar:
  185             ret << P();
  186             break;
  187         case GenInlineItem::Char:
  188             ret << GET_KEY();
  189             break;
  190         case GenInlineItem::Hold:
  191             ret << P() << "--;";
  192             break;
  193         case GenInlineItem::Exec:
  194             EXEC( ret, item, targState, inFinish );
  195             break;
  196         case GenInlineItem::Curs:
  197             ret << "(_ps)";
  198             break;
  199         case GenInlineItem::Targs:
  200             ret << "(" << vCS() << ")";
  201             break;
  202         case GenInlineItem::Entry:
  203             ret << item->targState->id;
  204             break;
  205         case GenInlineItem::GotoExpr:
  206             GOTO_EXPR( ret, item, inFinish );
  207             break;
  208         case GenInlineItem::CallExpr:
  209             CALL_EXPR( ret, item, targState, inFinish );
  210             break;
  211         case GenInlineItem::NextExpr:
  212             NEXT_EXPR( ret, item, inFinish );
  213             break;
  214         case GenInlineItem::LmSwitch:
  215             LM_SWITCH( ret, item, targState, inFinish );
  216             break;
  217         case GenInlineItem::LmSetActId:
  218             SET_ACT( ret, item );
  219             break;
  220         case GenInlineItem::LmSetTokEnd:
  221             SET_TOKEND( ret, item );
  222             break;
  223         case GenInlineItem::LmGetTokEnd:
  224             GET_TOKEND( ret, item );
  225             break;
  226         case GenInlineItem::LmInitTokStart:
  227             INIT_TOKSTART( ret, item );
  228             break;
  229         case GenInlineItem::LmInitAct:
  230             INIT_ACT( ret, item );
  231             break;
  232         case GenInlineItem::LmSetTokStart:
  233             SET_TOKSTART( ret, item );
  234             break;
  235         case GenInlineItem::SubAction:
  236             SUB_ACTION( ret, item, targState, inFinish );
  237             break;
  238         case GenInlineItem::Break:
  239             BREAK( ret, targState );
  240             break;
  241         }
  242     }
  243 }
  244 
  245 string JavaTabCodeGen::DATA_PREFIX()
  246 {
  247     if ( !noPrefix )
  248         return FSM_NAME() + "_";
  249     return "";
  250 }
  251 
  252 /* Emit the alphabet data type. */
  253 string JavaTabCodeGen::ALPH_TYPE()
  254 {
  255     string ret = keyOps->alphType->data1;
  256     if ( keyOps->alphType->data2 != 0 ) {
  257         ret += " ";
  258         ret += + keyOps->alphType->data2;
  259     }
  260     return ret;
  261 }
  262 
  263 /* Emit the alphabet data type. */
  264 string JavaTabCodeGen::WIDE_ALPH_TYPE()
  265 {
  266     string ret;
  267     if ( redFsm->maxKey <= keyOps->maxKey )
  268         ret = ALPH_TYPE();
  269     else {
  270         long long maxKeyVal = redFsm->maxKey.getLongLong();
  271         HostType *wideType = keyOps->typeSubsumes( keyOps->isSigned, maxKeyVal );
  272         assert( wideType != 0 );
  273 
  274         ret = wideType->data1;
  275         if ( wideType->data2 != 0 ) {
  276             ret += " ";
  277             ret += wideType->data2;
  278         }
  279     }
  280     return ret;
  281 }
  282 
  283 
  284 
  285 void JavaTabCodeGen::COND_TRANSLATE()
  286 {
  287     out << 
  288         "   _widec = " << GET_KEY() << ";\n"
  289         "   _keys = " << CO() << "[" << vCS() << "]*2\n;"
  290         "   _klen = " << CL() << "[" << vCS() << "];\n"
  291         "   if ( _klen > 0 ) {\n"
  292         "       int _lower = _keys\n;"
  293         "       int _mid;\n"
  294         "       int _upper = _keys + (_klen<<1) - 2;\n"
  295         "       while (true) {\n"
  296         "           if ( _upper < _lower )\n"
  297         "               break;\n"
  298         "\n"
  299         "           _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
  300         "           if ( " << GET_WIDE_KEY() << " < " << CK() << "[_mid] )\n"
  301         "               _upper = _mid - 2;\n"
  302         "           else if ( " << GET_WIDE_KEY() << " > " << CK() << "[_mid+1] )\n"
  303         "               _lower = _mid + 2;\n"
  304         "           else {\n"
  305         "               switch ( " << C() << "[" << CO() << "[" << vCS() << "]"
  306                             " + ((_mid - _keys)>>1)] ) {\n"
  307         ;
  308 
  309     for ( CondSpaceList::Iter csi = condSpaceList; csi.lte(); csi++ ) {
  310         GenCondSpace *condSpace = csi;
  311         out << "    case " << condSpace->condSpaceId << ": {\n";
  312         out << TABS(2) << "_widec = " << KEY(condSpace->baseKey) << 
  313                 " + (" << GET_KEY() << " - " << KEY(keyOps->minKey) << ");\n";
  314 
  315         for ( GenCondSet::Iter csi = condSpace->condSet; csi.lte(); csi++ ) {
  316             out << TABS(2) << "if ( ";
  317             CONDITION( out, *csi );
  318             Size condValOffset = ((1 << csi.pos()) * keyOps->alphSize());
  319             out << " ) _widec += " << condValOffset << ";\n";
  320         }
  321 
  322         out << 
  323             "       break;\n"
  324             "   }\n";
  325     }
  326 
  327     out << 
  328         "               }\n"
  329         "               break;\n"
  330         "           }\n"
  331         "       }\n"
  332         "   }\n"
  333         "\n";
  334 }
  335 
  336 
  337 void JavaTabCodeGen::LOCATE_TRANS()
  338 {
  339     out <<
  340         "   _match: do {\n"
  341         "   _keys = " << KO() << "[" << vCS() << "]" << ";\n"
  342         "   _trans = " << IO() << "[" << vCS() << "];\n"
  343         "   _klen = " << SL() << "[" << vCS() << "];\n"
  344         "   if ( _klen > 0 ) {\n"
  345         "       int _lower = _keys;\n"
  346         "       int _mid;\n"
  347         "       int _upper = _keys + _klen - 1;\n"
  348         "       while (true) {\n"
  349         "           if ( _upper < _lower )\n"
  350         "               break;\n"
  351         "\n"
  352         "           _mid = _lower + ((_upper-_lower) >> 1);\n"
  353         "           if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
  354         "               _upper = _mid - 1;\n"
  355         "           else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid] )\n"
  356         "               _lower = _mid + 1;\n"
  357         "           else {\n"
  358         "               _trans += (_mid - _keys);\n"
  359         "               break _match;\n"
  360         "           }\n"
  361         "       }\n"
  362         "       _keys += _klen;\n"
  363         "       _trans += _klen;\n"
  364         "   }\n"
  365         "\n"
  366         "   _klen = " << RL() << "[" << vCS() << "];\n"
  367         "   if ( _klen > 0 ) {\n"
  368         "       int _lower = _keys;\n"
  369         "       int _mid;\n"
  370         "       int _upper = _keys + (_klen<<1) - 2;\n"
  371         "       while (true) {\n"
  372         "           if ( _upper < _lower )\n"
  373         "               break;\n"
  374         "\n"
  375         "           _mid = _lower + (((_upper-_lower) >> 1) & ~1);\n"
  376         "           if ( " << GET_WIDE_KEY() << " < " << K() << "[_mid] )\n"
  377         "               _upper = _mid - 2;\n"
  378         "           else if ( " << GET_WIDE_KEY() << " > " << K() << "[_mid+1] )\n"
  379         "               _lower = _mid + 2;\n"
  380         "           else {\n"
  381         "               _trans += ((_mid - _keys)>>1);\n"
  382         "               break _match;\n"
  383         "           }\n"
  384         "       }\n"
  385         "       _trans += _klen;\n"
  386         "   }\n"
  387         "   } while (false);\n"
  388         "\n";
  389 }
  390 
  391 /* Determine if we should use indicies or not. */
  392 void JavaTabCodeGen::calcIndexSize()
  393 {
  394     int sizeWithInds = 0, sizeWithoutInds = 0;
  395 
  396     /* Calculate cost of using with indicies. */
  397     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  398         int totalIndex = st->outSingle.length() + st->outRange.length() + 
  399                 (st->defTrans == 0 ? 0 : 1);
  400         sizeWithInds += arrayTypeSize(redFsm->maxIndex) * totalIndex;
  401     }
  402     sizeWithInds += arrayTypeSize(redFsm->maxState) * redFsm->transSet.length();
  403     if ( redFsm->anyActions() )
  404         sizeWithInds += arrayTypeSize(redFsm->maxActionLoc) * redFsm->transSet.length();
  405 
  406     /* Calculate the cost of not using indicies. */
  407     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  408         int totalIndex = st->outSingle.length() + st->outRange.length() + 
  409                 (st->defTrans == 0 ? 0 : 1);
  410         sizeWithoutInds += arrayTypeSize(redFsm->maxState) * totalIndex;
  411         if ( redFsm->anyActions() )
  412             sizeWithoutInds += arrayTypeSize(redFsm->maxActionLoc) * totalIndex;
  413     }
  414 
  415     /* If using indicies reduces the size, use them. */
  416     useIndicies = sizeWithInds < sizeWithoutInds;
  417 }
  418 
  419 int JavaTabCodeGen::TO_STATE_ACTION( RedStateAp *state )
  420 {
  421     int act = 0;
  422     if ( state->toStateAction != 0 )
  423         act = state->toStateAction->location+1;
  424     return act;
  425 }
  426 
  427 int JavaTabCodeGen::FROM_STATE_ACTION( RedStateAp *state )
  428 {
  429     int act = 0;
  430     if ( state->fromStateAction != 0 )
  431         act = state->fromStateAction->location+1;
  432     return act;
  433 }
  434 
  435 int JavaTabCodeGen::EOF_ACTION( RedStateAp *state )
  436 {
  437     int act = 0;
  438     if ( state->eofAction != 0 )
  439         act = state->eofAction->location+1;
  440     return act;
  441 }
  442 
  443 
  444 int JavaTabCodeGen::TRANS_ACTION( RedTransAp *trans )
  445 {
  446     /* If there are actions, emit them. Otherwise emit zero. */
  447     int act = 0;
  448     if ( trans->action != 0 )
  449         act = trans->action->location+1;
  450     return act;
  451 }
  452 
  453 std::ostream &JavaTabCodeGen::TO_STATE_ACTION_SWITCH()
  454 {
  455     /* Walk the list of functions, printing the cases. */
  456     for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  457         /* Write out referenced actions. */
  458         if ( act->numToStateRefs > 0 ) {
  459             /* Write the case label, the action and the case break. */
  460             out << "\tcase " << act->actionId << ":\n";
  461             ACTION( out, act, 0, false );
  462             out << "\tbreak;\n";
  463         }
  464     }
  465 
  466     genLineDirective( out );
  467     return out;
  468 }
  469 
  470 std::ostream &JavaTabCodeGen::FROM_STATE_ACTION_SWITCH()
  471 {
  472     /* Walk the list of functions, printing the cases. */
  473     for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  474         /* Write out referenced actions. */
  475         if ( act->numFromStateRefs > 0 ) {
  476             /* Write the case label, the action and the case break. */
  477             out << "\tcase " << act->actionId << ":\n";
  478             ACTION( out, act, 0, false );
  479             out << "\tbreak;\n";
  480         }
  481     }
  482 
  483     genLineDirective( out );
  484     return out;
  485 }
  486 
  487 std::ostream &JavaTabCodeGen::EOF_ACTION_SWITCH()
  488 {
  489     /* Walk the list of functions, printing the cases. */
  490     for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  491         /* Write out referenced actions. */
  492         if ( act->numEofRefs > 0 ) {
  493             /* Write the case label, the action and the case break. */
  494             out << "\tcase " << act->actionId << ":\n";
  495             ACTION( out, act, 0, true );
  496             out << "\tbreak;\n";
  497         }
  498     }
  499 
  500     genLineDirective( out );
  501     return out;
  502 }
  503 
  504 
  505 std::ostream &JavaTabCodeGen::ACTION_SWITCH()
  506 {
  507     /* Walk the list of functions, printing the cases. */
  508     for ( GenActionList::Iter act = actionList; act.lte(); act++ ) {
  509         /* Write out referenced actions. */
  510         if ( act->numTransRefs > 0 ) {
  511             /* Write the case label, the action and the case break. */
  512             out << "\tcase " << act->actionId << ":\n";
  513             ACTION( out, act, 0, false );
  514             out << "\tbreak;\n";
  515         }
  516     }
  517 
  518     genLineDirective( out );
  519     return out;
  520 }
  521 
  522 std::ostream &JavaTabCodeGen::COND_OFFSETS()
  523 {
  524     int curKeyOffset = 0;
  525     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  526         /* Write the key offset. */
  527         ARRAY_ITEM( INT(curKeyOffset), st.last() );
  528 
  529         /* Move the key offset ahead. */
  530         curKeyOffset += st->stateCondList.length();
  531     }
  532     return out;
  533 }
  534 
  535 std::ostream &JavaTabCodeGen::KEY_OFFSETS()
  536 {
  537     int curKeyOffset = 0;
  538     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  539         /* Write the key offset. */
  540         ARRAY_ITEM( INT(curKeyOffset), st.last() );
  541 
  542         /* Move the key offset ahead. */
  543         curKeyOffset += st->outSingle.length() + st->outRange.length()*2;
  544     }
  545     return out;
  546 }
  547 
  548 
  549 std::ostream &JavaTabCodeGen::INDEX_OFFSETS()
  550 {
  551     int curIndOffset = 0;
  552     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  553         /* Write the index offset. */
  554         ARRAY_ITEM( INT(curIndOffset), st.last() );
  555 
  556         /* Move the index offset ahead. */
  557         curIndOffset += st->outSingle.length() + st->outRange.length();
  558         if ( st->defTrans != 0 )
  559             curIndOffset += 1;
  560     }
  561     return out;
  562 }
  563 
  564 std::ostream &JavaTabCodeGen::COND_LENS()
  565 {
  566     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  567         /* Write singles length. */
  568         ARRAY_ITEM( INT(st->stateCondList.length()), st.last() );
  569     }
  570     return out;
  571 }
  572 
  573 
  574 std::ostream &JavaTabCodeGen::SINGLE_LENS()
  575 {
  576     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  577         /* Write singles length. */
  578         ARRAY_ITEM( INT(st->outSingle.length()), st.last() );
  579     }
  580     return out;
  581 }
  582 
  583 std::ostream &JavaTabCodeGen::RANGE_LENS()
  584 {
  585     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  586         /* Emit length of range index. */
  587         ARRAY_ITEM( INT(st->outRange.length()), st.last() );
  588     }
  589     return out;
  590 }
  591 
  592 std::ostream &JavaTabCodeGen::TO_STATE_ACTIONS()
  593 {
  594     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  595         /* Write any eof action. */
  596         ARRAY_ITEM( INT(TO_STATE_ACTION(st)), st.last() );
  597     }
  598     return out;
  599 }
  600 
  601 std::ostream &JavaTabCodeGen::FROM_STATE_ACTIONS()
  602 {
  603     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  604         /* Write any eof action. */
  605         ARRAY_ITEM( INT(FROM_STATE_ACTION(st)), st.last() );
  606     }
  607     return out;
  608 }
  609 
  610 std::ostream &JavaTabCodeGen::EOF_ACTIONS()
  611 {
  612     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  613         /* Write any eof action. */
  614         ARRAY_ITEM( INT(EOF_ACTION(st)), st.last() );
  615     }
  616     return out;
  617 }
  618 
  619 std::ostream &JavaTabCodeGen::EOF_TRANS()
  620 {
  621     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  622         /* Write any eof action. */
  623         long trans = 0;
  624         if ( st->eofTrans != 0 ) {
  625             assert( st->eofTrans->pos >= 0 );
  626             trans = st->eofTrans->pos+1;
  627         }
  628 
  629         /* Write any eof action. */
  630         ARRAY_ITEM( INT(trans), st.last() );
  631     }
  632     return out;
  633 }
  634 
  635 
  636 std::ostream &JavaTabCodeGen::COND_KEYS()
  637 {
  638     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  639         /* Loop the state's transitions. */
  640         for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
  641             /* Lower key. */
  642             ARRAY_ITEM( KEY( sc->lowKey ), false );
  643             ARRAY_ITEM( KEY( sc->highKey ), false );
  644         }
  645     }
  646 
  647     /* Output one last number so we don't have to figure out when the last
  648      * entry is and avoid writing a comma. */
  649     ARRAY_ITEM( INT(0), true );
  650     return out;
  651 }
  652 
  653 std::ostream &JavaTabCodeGen::COND_SPACES()
  654 {
  655     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  656         /* Loop the state's transitions. */
  657         for ( GenStateCondList::Iter sc = st->stateCondList; sc.lte(); sc++ ) {
  658             /* Cond Space id. */
  659             ARRAY_ITEM( KEY( sc->condSpace->condSpaceId ), false );
  660         }
  661     }
  662 
  663     /* Output one last number so we don't have to figure out when the last
  664      * entry is and avoid writing a comma. */
  665     ARRAY_ITEM( INT(0), true );
  666     return out;
  667 }
  668 
  669 std::ostream &JavaTabCodeGen::KEYS()
  670 {
  671     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  672         /* Loop the singles. */
  673         for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  674             ARRAY_ITEM( KEY( stel->lowKey ), false );
  675         }
  676 
  677         /* Loop the state's transitions. */
  678         for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  679             /* Lower key. */
  680             ARRAY_ITEM( KEY( rtel->lowKey ), false );
  681 
  682             /* Upper key. */
  683             ARRAY_ITEM( KEY( rtel->highKey ), false );
  684         }
  685     }
  686 
  687     /* Output one last number so we don't have to figure out when the last
  688      * entry is and avoid writing a comma. */
  689     ARRAY_ITEM( INT(0), true );
  690     return out;
  691 }
  692 
  693 std::ostream &JavaTabCodeGen::INDICIES()
  694 {
  695     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  696         /* Walk the singles. */
  697         for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  698             ARRAY_ITEM( KEY( stel->value->id ), false );
  699         }
  700 
  701         /* Walk the ranges. */
  702         for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  703             ARRAY_ITEM( KEY( rtel->value->id ), false );
  704         }
  705 
  706         /* The state's default index goes next. */
  707         if ( st->defTrans != 0 ) {
  708             ARRAY_ITEM( KEY( st->defTrans->id ), false );
  709         }
  710     }
  711 
  712     /* Output one last number so we don't have to figure out when the last
  713      * entry is and avoid writing a comma. */
  714     ARRAY_ITEM( INT(0), true );
  715     return out;
  716 }
  717 
  718 std::ostream &JavaTabCodeGen::TRANS_TARGS()
  719 {
  720     int totalTrans = 0;
  721     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  722         /* Walk the singles. */
  723         for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  724             RedTransAp *trans = stel->value;
  725             ARRAY_ITEM( KEY( trans->targ->id ), false );
  726             totalTrans++;
  727         }
  728 
  729         /* Walk the ranges. */
  730         for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  731             RedTransAp *trans = rtel->value;
  732             ARRAY_ITEM( KEY( trans->targ->id ), false );
  733             totalTrans++;
  734         }
  735 
  736         /* The state's default target state. */
  737         if ( st->defTrans != 0 ) {
  738             RedTransAp *trans = st->defTrans;
  739             ARRAY_ITEM( KEY( trans->targ->id ), false );
  740             totalTrans++;
  741         }
  742     }
  743 
  744     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  745         if ( st->eofTrans != 0 ) {
  746             RedTransAp *trans = st->eofTrans;
  747             trans->pos = totalTrans++;
  748             ARRAY_ITEM( KEY( trans->targ->id ), false );
  749         }
  750     }
  751 
  752     /* Output one last number so we don't have to figure out when the last
  753      * entry is and avoid writing a comma. */
  754     ARRAY_ITEM( INT(0), true );
  755     return out;
  756 }
  757 
  758 
  759 std::ostream &JavaTabCodeGen::TRANS_ACTIONS()
  760 {
  761     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  762         /* Walk the singles. */
  763         for ( RedTransList::Iter stel = st->outSingle; stel.lte(); stel++ ) {
  764             RedTransAp *trans = stel->value;
  765             ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
  766         }
  767 
  768         /* Walk the ranges. */
  769         for ( RedTransList::Iter rtel = st->outRange; rtel.lte(); rtel++ ) {
  770             RedTransAp *trans = rtel->value;
  771             ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
  772         }
  773 
  774         /* The state's default index goes next. */
  775         if ( st->defTrans != 0 ) {
  776             RedTransAp *trans = st->defTrans;
  777             ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
  778         }
  779     }
  780 
  781     for ( RedStateList::Iter st = redFsm->stateList; st.lte(); st++ ) {
  782         if ( st->eofTrans != 0 ) {
  783             RedTransAp *trans = st->eofTrans;
  784             ARRAY_ITEM( INT(TRANS_ACTION( trans )), false );
  785         }
  786     }
  787 
  788     /* Output one last number so we don't have to figure out when the last
  789      * entry is and avoid writing a comma. */
  790     ARRAY_ITEM( INT(0), true );
  791     return out;
  792 }
  793 
  794 std::ostream &JavaTabCodeGen::TRANS_TARGS_WI()
  795 {
  796     /* Transitions must be written ordered by their id. */
  797     RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
  798     for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
  799         transPtrs[trans->id] = trans;
  800 
  801     /* Keep a count of the num of items in the array written. */
  802     for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
  803         /* Save the position. Needed for eofTargs. */
  804         RedTransAp *trans = transPtrs[t];
  805         trans->pos = t;
  806 
  807         /* Write out the target state. */
  808         ARRAY_ITEM( INT(trans->targ->id), ( t >= redFsm->transSet.length()-1 ) );
  809     }
  810     delete[] transPtrs;
  811     return out;
  812 }
  813 
  814 
  815 std::ostream &JavaTabCodeGen::TRANS_ACTIONS_WI()
  816 {
  817     /* Transitions must be written ordered by their id. */
  818     RedTransAp **transPtrs = new RedTransAp*[redFsm->transSet.length()];
  819     for ( TransApSet::Iter trans = redFsm->transSet; trans.lte(); trans++ )
  820         transPtrs[trans->id] = trans;
  821 
  822     /* Keep a count of the num of items in the array written. */
  823     for ( int t = 0; t < redFsm->transSet.length(); t++ ) {
  824         /* Write the function for the transition. */
  825         RedTransAp *trans = transPtrs[t];
  826         ARRAY_ITEM( INT(TRANS_ACTION( trans )), ( t >= redFsm->transSet.length()-1 ) );
  827     }
  828     delete[] transPtrs;
  829     return out;
  830 }
  831 
  832 void JavaTabCodeGen::writeExports()
  833 {
  834     if ( exportList.length() > 0 ) {
  835         for ( ExportList::Iter ex = exportList; ex.lte(); ex++ ) {
  836             STATIC_VAR( ALPH_TYPE(), DATA_PREFIX() + "ex_" + ex->name ) 
  837                     << " = " << KEY(ex->key) << ";\n";
  838         }
  839         out << "\n";
  840     }
  841 }
  842 
  843 void JavaTabCodeGen::writeStart()
  844 {
  845     out << START_STATE_ID();
  846 }
  847 
  848 void JavaTabCodeGen::writeFirstFinal()
  849 {
  850     out << FIRST_FINAL_STATE();
  851 }
  852 
  853 void JavaTabCodeGen::writeError()
  854 {
  855     out << ERROR_STATE();
  856 }
  857 
  858 void JavaTabCodeGen::writeData()
  859 {
  860     /* If there are any transtion functions then output the array. If there
  861      * are none, don't bother emitting an empty array that won't be used. */
  862     if ( redFsm->anyActions() ) {
  863         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActArrItem), A() );
  864         ACTIONS_ARRAY();
  865         CLOSE_ARRAY() <<
  866         "\n";
  867     }
  868 
  869     if ( redFsm->anyConditions() ) {
  870         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondOffset), CO() );
  871         COND_OFFSETS();
  872         CLOSE_ARRAY() <<
  873         "\n";
  874 
  875         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondLen), CL() );
  876         COND_LENS();
  877         CLOSE_ARRAY() <<
  878         "\n";
  879 
  880         OPEN_ARRAY( WIDE_ALPH_TYPE(), CK() );
  881         COND_KEYS();
  882         CLOSE_ARRAY() <<
  883         "\n";
  884 
  885         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxCondSpaceId), C() );
  886         COND_SPACES();
  887         CLOSE_ARRAY() <<
  888         "\n";
  889     }
  890 
  891     OPEN_ARRAY( ARRAY_TYPE(redFsm->maxKeyOffset), KO() );
  892     KEY_OFFSETS();
  893     CLOSE_ARRAY() <<
  894     "\n";
  895 
  896     OPEN_ARRAY( WIDE_ALPH_TYPE(), K() );
  897     KEYS();
  898     CLOSE_ARRAY() <<
  899     "\n";
  900 
  901     OPEN_ARRAY( ARRAY_TYPE(redFsm->maxSingleLen), SL() );
  902     SINGLE_LENS();
  903     CLOSE_ARRAY() <<
  904     "\n";
  905 
  906     OPEN_ARRAY( ARRAY_TYPE(redFsm->maxRangeLen), RL() );
  907     RANGE_LENS();
  908     CLOSE_ARRAY() <<
  909     "\n";
  910 
  911     OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset), IO() );
  912     INDEX_OFFSETS();
  913     CLOSE_ARRAY() <<
  914     "\n";
  915 
  916     if ( useIndicies ) {
  917         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndex), I() );
  918         INDICIES();
  919         CLOSE_ARRAY() <<
  920         "\n";
  921 
  922         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
  923         TRANS_TARGS_WI();
  924         CLOSE_ARRAY() <<
  925         "\n";
  926 
  927         if ( redFsm->anyActions() ) {
  928             OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
  929             TRANS_ACTIONS_WI();
  930             CLOSE_ARRAY() <<
  931             "\n";
  932         }
  933     }
  934     else {
  935         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxState), TT() );
  936         TRANS_TARGS();
  937         CLOSE_ARRAY() <<
  938         "\n";
  939 
  940         if ( redFsm->anyActions() ) {
  941             OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TA() );
  942             TRANS_ACTIONS();
  943             CLOSE_ARRAY() <<
  944             "\n";
  945         }
  946     }
  947 
  948     if ( redFsm->anyToStateActions() ) {
  949         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), TSA() );
  950         TO_STATE_ACTIONS();
  951         CLOSE_ARRAY() <<
  952         "\n";
  953     }
  954 
  955     if ( redFsm->anyFromStateActions() ) {
  956         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), FSA() );
  957         FROM_STATE_ACTIONS();
  958         CLOSE_ARRAY() <<
  959         "\n";
  960     }
  961 
  962     if ( redFsm->anyEofActions() ) {
  963         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxActionLoc), EA() );
  964         EOF_ACTIONS();
  965         CLOSE_ARRAY() <<
  966         "\n";
  967     }
  968 
  969     if ( redFsm->anyEofTrans() ) {
  970         OPEN_ARRAY( ARRAY_TYPE(redFsm->maxIndexOffset+1), ET() );
  971         EOF_TRANS();
  972         CLOSE_ARRAY() <<
  973         "\n";
  974     }
  975 
  976     if ( redFsm->startState != 0 )
  977         STATIC_VAR( "int", START() ) << " = " << START_STATE_ID() << ";\n";
  978 
  979     if ( !noFinal )
  980         STATIC_VAR( "int" , FIRST_FINAL() ) << " = " << FIRST_FINAL_STATE() << ";\n";
  981 
  982     if ( !noError )
  983         STATIC_VAR( "int", ERROR() ) << " = " << ERROR_STATE() << ";\n";
  984     
  985     out << "\n";
  986 
  987     if ( !noEntry && entryPointNames.length() > 0 ) {
  988         for ( EntryNameVect::Iter en = entryPointNames; en.lte(); en++ ) {
  989             STATIC_VAR( "int", DATA_PREFIX() + "en_" + *en ) << 
  990                     " = " << entryPointIds[en.pos()] << ";\n";
  991         }
  992         out << "\n";
  993     }
  994 }
  995 
  996 void JavaTabCodeGen::writeExec()
  997 {
  998     out <<
  999         "   {\n"
 1000         "   int _klen";
 1001 
 1002     if ( redFsm->anyRegCurStateRef() )
 1003         out << ", _ps";
 1004 
 1005     out << 
 1006         ";\n"
 1007         "   int _trans = 0;\n";
 1008 
 1009     if ( redFsm->anyConditions() )
 1010         out << "    int _widec;\n";
 1011 
 1012     if ( redFsm->anyToStateActions() || redFsm->anyRegActions() || 
 1013             redFsm->anyFromStateActions() )
 1014     {
 1015         out << 
 1016             "   int _acts;\n"
 1017             "   int _nacts;\n";
 1018     }
 1019 
 1020     out <<
 1021         "   int _keys;\n"
 1022         "   int _goto_targ = 0;\n"
 1023         "\n";
 1024     
 1025     out <<
 1026         "   _goto: while (true) {\n"
 1027         "   switch ( _goto_targ ) {\n"
 1028         "   case 0:\n";
 1029 
 1030     if ( !noEnd ) {
 1031         out << 
 1032             "   if ( " << P() << " == " << PE() << " ) {\n"
 1033             "       _goto_targ = " << _test_eof << ";\n"
 1034             "       continue _goto;\n"
 1035             "   }\n";
 1036     }
 1037 
 1038     if ( redFsm->errState != 0 ) {
 1039         out << 
 1040             "   if ( " << vCS() << " == " << redFsm->errState->id << " ) {\n"
 1041             "       _goto_targ = " << _out << ";\n"
 1042             "       continue _goto;\n"
 1043             "   }\n";
 1044     }
 1045 
 1046     out << "case " << _resume << ":\n"; 
 1047 
 1048     if ( redFsm->anyFromStateActions() ) {
 1049         out <<
 1050             "   _acts = " << FSA() << "[" << vCS() << "]" << ";\n"
 1051             "   _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
 1052             "   while ( _nacts-- > 0 ) {\n"
 1053             "       switch ( " << A() << "[_acts++] ) {\n";
 1054             FROM_STATE_ACTION_SWITCH() <<
 1055             "       }\n"
 1056             "   }\n"
 1057             "\n";
 1058     }
 1059 
 1060     if ( redFsm->anyConditions() )
 1061         COND_TRANSLATE();
 1062 
 1063     LOCATE_TRANS();
 1064 
 1065     if ( useIndicies )
 1066         out << "    _trans = " << I() << "[_trans];\n";
 1067     
 1068     if ( redFsm->anyEofTrans() )
 1069         out << "case " << _eof_trans << ":\n";
 1070 
 1071     if ( redFsm->anyRegCurStateRef() )
 1072         out << "    _ps = " << vCS() << ";\n";
 1073 
 1074     out <<
 1075         "   " << vCS() << " = " << TT() << "[_trans];\n"
 1076         "\n";
 1077 
 1078     if ( redFsm->anyRegActions() ) {
 1079         out <<
 1080             "   if ( " << TA() << "[_trans] != 0 ) {\n"
 1081             "       _acts = " <<  TA() << "[_trans]" << ";\n"
 1082             "       _nacts = " << CAST("int") << " " <<  A() << "[_acts++];\n"
 1083             "       while ( _nacts-- > 0 )\n    {\n"
 1084             "           switch ( " << A() << "[_acts++] )\n"
 1085             "           {\n";
 1086             ACTION_SWITCH() <<
 1087             "           }\n"
 1088             "       }\n"
 1089             "   }\n"
 1090             "\n";
 1091     }
 1092 
 1093     out << "case " << _again << ":\n";
 1094 
 1095     if ( redFsm->anyToStateActions() ) {
 1096         out <<
 1097             "   _acts = " << TSA() << "[" << vCS() << "]" << ";\n"
 1098             "   _nacts = " << CAST("int") << " " << A() << "[_acts++];\n"
 1099             "   while ( _nacts-- > 0 ) {\n"
 1100             "       switch ( " << A() << "[_acts++] ) {\n";
 1101             TO_STATE_ACTION_SWITCH() <<
 1102             "       }\n"
 1103             "   }\n"
 1104             "\n";
 1105     }
 1106 
 1107     if ( redFsm->errState != 0 ) {
 1108         out << 
 1109             "   if ( " << vCS() << " == " << redFsm->errState->id << " ) {\n"
 1110             "       _goto_targ = " << _out << ";\n"
 1111             "       continue _goto;\n"
 1112             "   }\n";
 1113     }
 1114 
 1115     if ( !noEnd ) {
 1116         out << 
 1117             "   if ( ++" << P() << " != " << PE() << " ) {\n"
 1118             "       _goto_targ = " << _resume << ";\n"
 1119             "       continue _goto;\n"
 1120             "   }\n";
 1121     }
 1122     else {
 1123         out << 
 1124             "   " << P() << " += 1;\n"
 1125             "   _goto_targ = " << _resume << ";\n"
 1126             "   continue _goto;\n";
 1127     }
 1128 
 1129     out << "case " << _test_eof << ":\n"; 
 1130 
 1131     if ( redFsm->anyEofTrans() || redFsm->anyEofActions() ) {
 1132         out <<
 1133             "   if ( " << P() << " == " << vEOF() << " )\n"
 1134             "   {\n";
 1135 
 1136         if ( redFsm->anyEofTrans() ) {
 1137             out <<
 1138                 "   if ( " << ET() << "[" << vCS() << "] > 0 ) {\n"
 1139                 "       _trans = " << ET() << "[" << vCS() << "] - 1;\n"
 1140                 "       _goto_targ = " << _eof_trans << ";\n"
 1141                 "       continue _goto;\n"
 1142                 "   }\n";
 1143         }
 1144 
 1145         if ( redFsm->anyEofActions() ) {
 1146             out <<
 1147                 "   int __acts = " << EA() << "[" << vCS() << "]" << ";\n"
 1148                 "   int __nacts = " << CAST("int") << " " << A() << "[__acts++];\n"
 1149                 "   while ( __nacts-- > 0 ) {\n"
 1150                 "       switch ( " << A() << "[__acts++] ) {\n";
 1151                 EOF_ACTION_SWITCH() <<
 1152                 "       }\n"
 1153                 "   }\n";
 1154         }
 1155 
 1156         out <<
 1157             "   }\n"
 1158             "\n";
 1159     }
 1160 
 1161     out << "case " << _out << ":\n"; 
 1162 
 1163     /* The switch and goto loop. */
 1164     out << "    }\n";
 1165     out << "    break; }\n";
 1166 
 1167     /* The execute block. */
 1168     out << "    }\n";
 1169 }
 1170 
 1171 std::ostream &JavaTabCodeGen::OPEN_ARRAY( string type, string name )
 1172 {
 1173     array_type = type;
 1174     array_name = name;
 1175     item_count = 0;
 1176     div_count = 1;
 1177 
 1178     out <<  "private static " << type << "[] init_" << name << "_0()\n"
 1179         "{\n\t"
 1180         "return new " << type << " [] {\n\t";
 1181     return out;
 1182 }
 1183 
 1184 std::ostream &JavaTabCodeGen::ARRAY_ITEM( string item, bool last )
 1185 {
 1186     item_count++;
 1187 
 1188     out << setw(5) << setiosflags(ios::right) << item;
 1189     
 1190     if ( !last ) {
 1191         if ( item_count % SAIIC == 0 ) {
 1192             out << "\n\t};\n};\n"
 1193                 "private static "<< array_type << "[] init_" << 
 1194                 array_name << "_" << div_count << "()\n"
 1195                 "{\n\t"
 1196                 "return new " << array_type << " [] {\n\t";
 1197             div_count++;
 1198         } else if (item_count % IALL == 0) { 
 1199             out << ",\n\t";
 1200         } else {
 1201             out << ",";
 1202         }
 1203     }
 1204     return out;
 1205 }
 1206 
 1207 std::ostream &JavaTabCodeGen::CLOSE_ARRAY()
 1208 {
 1209     out << "\n\t};\n}\n\n";
 1210 
 1211     if (item_count < SAIIC) {
 1212         out << "private static final " << array_type << " " << array_name << 
 1213             "[] = init_" << array_name << "_0();\n\n";
 1214     } else {
 1215         out << "private static final " << array_type << " [] combine_" << array_name
 1216             << "() {\n\t"
 1217             << array_type << " [] combined = new " << array_type << 
 1218             " [ " << item_count << " ];\n\t";
 1219         int block = 0;
 1220         int full_blocks = item_count / SAIIC;
 1221         for (;block < full_blocks; ++block) {
 1222             out << "System.arraycopy ( init_" << array_name << "_" << block << 
 1223                 "(), 0, combined, " << SAIIC * block << ", " << SAIIC << " );\n\t";
 1224         }
 1225         if ( (item_count % SAIIC) > 0 ) {
 1226             out << "System.arraycopy ( init_" << array_name << "_" << block << 
 1227                 "(), 0, combined, " << SAIIC * block << ", " << 
 1228                 (item_count % SAIIC) << " );\n\t";
 1229         }
 1230         out << "return combined;\n}\n";
 1231         out << "private static final " << array_type << " [] " << array_name << 
 1232             " = combine_" << array_name << "();";
 1233     }
 1234     return out;
 1235 }
 1236 
 1237 
 1238 std::ostream &JavaTabCodeGen::STATIC_VAR( string type, string name )
 1239 {
 1240     out << "static final " << type << " " << name;
 1241     return out;
 1242 }
 1243 
 1244 string JavaTabCodeGen::ARR_OFF( string ptr, string offset )
 1245 {
 1246     return ptr + " + " + offset;
 1247 }
 1248 
 1249 string JavaTabCodeGen::CAST( string type )
 1250 {
 1251     return "(" + type + ")";
 1252 }
 1253 
 1254 string JavaTabCodeGen::NULL_ITEM()
 1255 {
 1256     /* In java we use integers instead of pointers. */
 1257     return "-1";
 1258 }
 1259 
 1260 string JavaTabCodeGen::GET_KEY()
 1261 {
 1262     ostringstream ret;
 1263     if ( getKeyExpr != 0 ) { 
 1264         /* Emit the user supplied method of retrieving the key. */
 1265         ret << "(";
 1266         INLINE_LIST( ret, getKeyExpr, 0, false );
 1267         ret << ")";
 1268     }
 1269     else {
 1270         /* Expression for retrieving the key, use simple dereference. */
 1271         ret << DATA() << "[" << P() << "]";
 1272     }
 1273     return ret.str();
 1274 }
 1275 
 1276 string JavaTabCodeGen::CTRL_FLOW()
 1277 {
 1278     return "if (true) ";
 1279 }
 1280 
 1281 unsigned int JavaTabCodeGen::arrayTypeSize( unsigned long maxVal )
 1282 {
 1283     long long maxValLL = (long long) maxVal;
 1284     HostType *arrayType = keyOps->typeSubsumes( maxValLL );
 1285     assert( arrayType != 0 );
 1286     return arrayType->size;
 1287 }
 1288 
 1289 string JavaTabCodeGen::ARRAY_TYPE( unsigned long maxVal )
 1290 {
 1291     long long maxValLL = (long long) maxVal;
 1292     HostType *arrayType = keyOps->typeSubsumes( maxValLL );
 1293     assert( arrayType != 0 );
 1294 
 1295     string ret = arrayType->data1;
 1296     if ( arrayType->data2 != 0 ) {
 1297         ret += " ";
 1298         ret += arrayType->data2;
 1299     }
 1300     return ret;
 1301 }
 1302 
 1303 
 1304 /* Write out the fsm name. */
 1305 string JavaTabCodeGen::FSM_NAME()
 1306 {
 1307     return fsmName;
 1308 }
 1309 
 1310 /* Emit the offset of the start state as a decimal integer. */
 1311 string JavaTabCodeGen::START_STATE_ID()
 1312 {
 1313     ostringstream ret;
 1314     ret << redFsm->startState->id;
 1315     return ret.str();
 1316 };
 1317 
 1318 /* Write out the array of actions. */
 1319 std::ostream &JavaTabCodeGen::ACTIONS_ARRAY()
 1320 {
 1321     ARRAY_ITEM( INT(0), false );
 1322     for ( GenActionTableMap::Iter act = redFsm->actionMap; act.lte(); act++ ) {
 1323         /* Write out the length, which will never be the last character. */
 1324         ARRAY_ITEM( INT(act->key.length()), false );
 1325 
 1326         for ( GenActionTable::Iter item = act->key; item.lte(); item++ )
 1327             ARRAY_ITEM( INT(item->value->actionId), (act.last() && item.last()) );
 1328     }
 1329     return out;
 1330 }
 1331 
 1332 
 1333 string JavaTabCodeGen::ACCESS()
 1334 {
 1335     ostringstream ret;
 1336     if ( accessExpr != 0 )
 1337         INLINE_LIST( ret, accessExpr, 0, false );
 1338     return ret.str();
 1339 }
 1340 
 1341 string JavaTabCodeGen::P()
 1342 { 
 1343     ostringstream ret;
 1344     if ( pExpr == 0 )
 1345         ret << "p";
 1346     else {
 1347         ret << "(";
 1348         INLINE_LIST( ret, pExpr, 0, false );
 1349         ret << ")";
 1350     }
 1351     return ret.str();
 1352 }
 1353 
 1354 string JavaTabCodeGen::PE()
 1355 {
 1356     ostringstream ret;
 1357     if ( peExpr == 0 )
 1358         ret << "pe";
 1359     else {
 1360         ret << "(";
 1361         INLINE_LIST( ret, peExpr, 0, false );
 1362         ret << ")";
 1363     }
 1364     return ret.str();
 1365 }
 1366 
 1367 string JavaTabCodeGen::vEOF()
 1368 {
 1369     ostringstream ret;
 1370     if ( eofExpr == 0 )
 1371         ret << "eof";
 1372     else {
 1373         ret << "(";
 1374         INLINE_LIST( ret, eofExpr, 0, false );
 1375         ret << ")";
 1376     }
 1377     return ret.str();
 1378 }
 1379 
 1380 string JavaTabCodeGen::vCS()
 1381 {
 1382     ostringstream ret;
 1383     if ( csExpr == 0 )
 1384         ret << ACCESS() << "cs";
 1385     else {
 1386         /* Emit the user supplied method of retrieving the key. */
 1387         ret << "(";
 1388         INLINE_LIST( ret, csExpr, 0, false );
 1389         ret << ")";
 1390     }
 1391     return ret.str();
 1392 }
 1393 
 1394 string JavaTabCodeGen::TOP()
 1395 {
 1396     ostringstream ret;
 1397     if ( topExpr == 0 )
 1398         ret << ACCESS() + "top";
 1399     else {
 1400         ret << "(";
 1401         INLINE_LIST( ret, topExpr, 0, false );
 1402         ret << ")";
 1403     }
 1404     return ret.str();
 1405 }
 1406 
 1407 string JavaTabCodeGen::STACK()
 1408 {
 1409     ostringstream ret;
 1410     if ( stackExpr == 0 )
 1411         ret << ACCESS() + "stack";
 1412     else {
 1413         ret << "(";
 1414         INLINE_LIST( ret, stackExpr, 0, false );
 1415         ret << ")";
 1416     }
 1417     return ret.str();
 1418 }
 1419 
 1420 string JavaTabCodeGen::ACT()
 1421 {
 1422     ostringstream ret;
 1423     if ( actExpr == 0 )
 1424         ret << ACCESS() + "act";
 1425     else {
 1426         ret << "(";
 1427         INLINE_LIST( ret, actExpr, 0, false );
 1428         ret << ")";
 1429     }
 1430     return ret.str();
 1431 }
 1432 
 1433 string JavaTabCodeGen::TOKSTART()
 1434 {
 1435     ostringstream ret;
 1436     if ( tokstartExpr == 0 )
 1437         ret << ACCESS() + "ts";
 1438     else {
 1439         ret << "(";
 1440         INLINE_LIST( ret, tokstartExpr, 0, false );
 1441         ret << ")";
 1442     }
 1443     return ret.str();
 1444 }
 1445 
 1446 string JavaTabCodeGen::TOKEND()
 1447 {
 1448     ostringstream ret;
 1449     if ( tokendExpr == 0 )
 1450         ret << ACCESS() + "te";
 1451     else {
 1452         ret << "(";
 1453         INLINE_LIST( ret, tokendExpr, 0, false );
 1454         ret << ")";
 1455     }
 1456     return ret.str();
 1457 }
 1458 
 1459 string JavaTabCodeGen::DATA()
 1460 {
 1461     ostringstream ret;
 1462     if ( dataExpr == 0 )
 1463         ret << ACCESS() + "data";
 1464     else {
 1465         ret << "(";
 1466         INLINE_LIST( ret, dataExpr, 0, false );
 1467         ret << ")";
 1468     }
 1469     return ret.str();
 1470 }
 1471 
 1472 
 1473 string JavaTabCodeGen::GET_WIDE_KEY()
 1474 {
 1475     if ( redFsm->anyConditions() ) 
 1476         return "_widec";
 1477     else
 1478         return GET_KEY();
 1479 }
 1480 
 1481 string JavaTabCodeGen::GET_WIDE_KEY( RedStateAp *state )
 1482 {
 1483     if ( state->stateCondList.length() > 0 )
 1484         return "_widec";
 1485     else
 1486         return GET_KEY();
 1487 }
 1488 
 1489 /* Write out level number of tabs. Makes the nested binary search nice
 1490  * looking. */
 1491 string JavaTabCodeGen::TABS( int level )
 1492 {
 1493     string result;
 1494     while ( level-- > 0 )
 1495         result += "\t";
 1496     return result;
 1497 }
 1498 
 1499 string JavaTabCodeGen::KEY( Key key )
 1500 {
 1501     ostringstream ret;
 1502     if ( keyOps->isSigned || !hostLang->explicitUnsigned )
 1503         ret << key.getVal();
 1504     else
 1505         ret << (unsigned long) key.getVal();
 1506     return ret.str();
 1507 }
 1508 
 1509 string JavaTabCodeGen::INT( int i )
 1510 {
 1511     ostringstream ret;
 1512     ret << i;
 1513     return ret.str();
 1514 }
 1515 
 1516 void JavaTabCodeGen::LM_SWITCH( ostream &ret, GenInlineItem *item, 
 1517         int targState, int inFinish )
 1518 {
 1519     ret << 
 1520         "   switch( " << ACT() << " ) {\n";
 1521 
 1522     for ( GenInlineList::Iter lma = *item->children; lma.lte(); lma++ ) {
 1523         /* Write the case label, the action and the case break. */
 1524         if ( lma->lmId < 0 )
 1525             ret << "    default:\n";
 1526         else
 1527             ret << "    case " << lma->lmId << ":\n";
 1528 
 1529         /* Write the block and close it off. */
 1530         ret << "    {";
 1531         INLINE_LIST( ret, lma->children, targState, inFinish );
 1532         ret << "}\n";
 1533 
 1534         ret << "    break;\n";
 1535     }
 1536 
 1537     ret << 
 1538         "   }\n"
 1539         "\t";
 1540 }
 1541 
 1542 void JavaTabCodeGen::SET_ACT( ostream &ret, GenInlineItem *item )
 1543 {
 1544     ret << ACT() << " = " << item->lmId << ";";
 1545 }
 1546 
 1547 void JavaTabCodeGen::SET_TOKEND( ostream &ret, GenInlineItem *item )
 1548 {
 1549     /* The tokend action sets tokend. */
 1550     ret << TOKEND() << " = " << P();
 1551     if ( item->offset != 0 ) 
 1552         out << "+" << item->offset;
 1553     out << ";";
 1554 }
 1555 
 1556 void JavaTabCodeGen::GET_TOKEND( ostream &ret, GenInlineItem *item )
 1557 {
 1558     ret << TOKEND();
 1559 }
 1560 
 1561 void JavaTabCodeGen::INIT_TOKSTART( ostream &ret, GenInlineItem *item )
 1562 {
 1563     ret << TOKSTART() << " = " << NULL_ITEM() << ";";
 1564 }
 1565 
 1566 void JavaTabCodeGen::INIT_ACT( ostream &ret, GenInlineItem *item )
 1567 {
 1568     ret << ACT() << " = 0;";
 1569 }
 1570 
 1571 void JavaTabCodeGen::SET_TOKSTART( ostream &ret, GenInlineItem *item )
 1572 {
 1573     ret << TOKSTART() << " = " << P() << ";";
 1574 }
 1575 
 1576 void JavaTabCodeGen::SUB_ACTION( ostream &ret, GenInlineItem *item, 
 1577         int targState, bool inFinish )
 1578 {
 1579     if ( item->children->length() > 0 ) {
 1580         /* Write the block and close it off. */
 1581         ret << "{";
 1582         INLINE_LIST( ret, item->children, targState, inFinish );
 1583         ret << "}";
 1584     }
 1585 }
 1586 
 1587 void JavaTabCodeGen::ACTION( ostream &ret, GenAction *action, int targState, bool inFinish )
 1588 {
 1589     /* Write the preprocessor line info for going into the source file. */
 1590     javaLineDirective( ret, action->loc.fileName, action->loc.line );
 1591 
 1592     /* Write the block and close it off. */
 1593     ret << "\t{";
 1594     INLINE_LIST( ret, action->inlineList, targState, inFinish );
 1595     ret << "}\n";
 1596 }
 1597 
 1598 void JavaTabCodeGen::CONDITION( ostream &ret, GenAction *condition )
 1599 {
 1600     ret << "\n";
 1601     javaLineDirective( ret, condition->loc.fileName, condition->loc.line );
 1602     INLINE_LIST( ret, condition->inlineList, 0, false );
 1603 }
 1604 
 1605 string JavaTabCodeGen::ERROR_STATE()
 1606 {
 1607     ostringstream ret;
 1608     if ( redFsm->errState != 0 )
 1609         ret << redFsm->errState->id;
 1610     else
 1611         ret << "-1";
 1612     return ret.str();
 1613 }
 1614 
 1615 string JavaTabCodeGen::FIRST_FINAL_STATE()
 1616 {
 1617     ostringstream ret;
 1618     if ( redFsm->firstFinState != 0 )
 1619         ret << redFsm->firstFinState->id;
 1620     else
 1621         ret << redFsm->nextStateId;
 1622     return ret.str();
 1623 }
 1624 
 1625 void JavaTabCodeGen::writeInit()
 1626 {
 1627     out << "    {\n";
 1628 
 1629     if ( !noCS )
 1630         out << "\t" << vCS() << " = " << START() << ";\n";
 1631     
 1632     /* If there are any calls, then the stack top needs initialization. */
 1633     if ( redFsm->anyActionCalls() || redFsm->anyActionRets() )
 1634         out << "\t" << TOP() << " = 0;\n";
 1635 
 1636     if ( hasLongestMatch ) {
 1637         out << 
 1638             "   " << TOKSTART() << " = " << NULL_ITEM() << ";\n"
 1639             "   " << TOKEND() << " = " << NULL_ITEM() << ";\n"
 1640             "   " << ACT() << " = 0;\n";
 1641     }
 1642     out << "    }\n";
 1643 }
 1644 
 1645 void JavaTabCodeGen::finishRagelDef()
 1646 {
 1647     /* The frontend will do this for us, but it may be a good idea to force it
 1648      * if the intermediate file is edited. */
 1649     redFsm->sortByStateId();
 1650 
 1651     /* Choose default transitions and the single transition. */
 1652     redFsm->chooseDefaultSpan();
 1653         
 1654     /* Maybe do flat expand, otherwise choose single. */
 1655     redFsm->chooseSingle();
 1656 
 1657     /* If any errors have occured in the input file then don't write anything. */
 1658     if ( gblErrorCount > 0 )
 1659         return;
 1660     
 1661     /* Anlayze Machine will find the final action reference counts, among
 1662      * other things. We will use these in reporting the usage
 1663      * of fsm directives in action code. */
 1664     analyzeMachine();
 1665 
 1666     /* Determine if we should use indicies. */
 1667     calcIndexSize();
 1668 }
 1669 
 1670 ostream &JavaTabCodeGen::source_warning( const InputLoc &loc )
 1671 {
 1672     cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": warning: ";
 1673     return cerr;
 1674 }
 1675 
 1676 ostream &JavaTabCodeGen::source_error( const InputLoc &loc )
 1677 {
 1678     gblErrorCount += 1;
 1679     assert( sourceFileName != 0 );
 1680     cerr << sourceFileName << ":" << loc.line << ":" << loc.col << ": ";
 1681     return cerr;
 1682 }
 1683 
 1684