Logo Search packages:      
Sourcecode: cccc version File versions

gen.c

/*
 * gen.c
 *
 * Generate C code (ANSI, K&R, C++)
 *
 * SOFTWARE RIGHTS
 *
 * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
 * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
 * company may do whatever they wish with source code distributed with
 * PCCTS or the code generated by PCCTS, including the incorporation of
 * PCCTS, or its output, into commerical software.
 *
 * We encourage users to develop software with PCCTS.  However, we do ask
 * that credit is given to us for developing PCCTS.  By "credit",
 * we mean that if you incorporate our source code into one of your
 * programs (commercial product, research project, or otherwise) that you
 * acknowledge this fact somewhere in the documentation, research report,
 * etc...  If you like PCCTS and have developed a nice tool with the
 * output, please mention that you developed it using PCCTS.  In
 * addition, we ask that this header remain intact in our source code.
 * As long as these guidelines are kept, we expect to continue enhancing
 * this system and expect to make other tools available as they are
 * completed.
 *
 * ANTLR 1.33
 * Terence Parr
 * Parr Research Corporation
 * with Purdue University and AHPCRC, University of Minnesota
 * 1989-1998
 */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "pcctscfg.h"
#include "set.h"
#include "syn.h"
#include "hash.h"
#include "generic.h"
#include "dlgdef.h"

#define NumExprPerLine  4
static int on1line=0;
static set tokensRefdInBlock;

                              /* T r a n s l a t i o n  T a b l e s */

/* C_Trans[node type] == pointer to function that knows how to translate that node. */
#ifdef __cplusplus
void (*C_Trans[NumNodeTypes+1])(...) = {
      NULL,
      NULL,                         /* See next table.
Junctions have many types */
      (void (*)(...)) genRuleRef,
      (void (*)(...)) genToken,
      (void (*)(...)) genAction
 };
#else
void (*C_Trans[NumNodeTypes+1])() = {
      NULL,
      NULL,                         /* See next table.
Junctions have many types */
      genRuleRef,
      genToken,
      genAction
 };
#endif

/* C_JTrans[Junction type] == pointer to function that knows how to translate that
 * kind of junction node.
 */
#ifdef __cplusplus
void (*C_JTrans[NumJuncTypes+1])(...) = {
      NULL,
      (void (*)(...)) genSubBlk,
      (void (*)(...)) genOptBlk,
      (void (*)(...)) genLoopBlk,
      (void (*)(...)) genEndBlk,
      (void (*)(...)) genRule,
      (void (*)(...)) genJunction,
      (void (*)(...)) genEndRule,
      (void (*)(...)) genPlusBlk,
      (void (*)(...)) genLoopBegin
 };
#else
void (*C_JTrans[NumJuncTypes+1])() = {
      NULL,
      genSubBlk,
      genOptBlk,
      genLoopBlk,
      genEndBlk,
      genRule,
      genJunction,
      genEndRule,
      genPlusBlk,
      genLoopBegin
 };
#endif

#define PastWhiteSpace(s)     while (*(s) == ' ' || *(s) == '\t') {s++;}

static int tabs = 0;

/* MR6      Got tired of text running off page when using standard tab stops */

#define TAB { int i;                                                    \
            if (TabWidth==0) {                                              \
               for (i=0; i<tabs; i++) fputc('\t', output);                        \
            } else {                                                    \
             for (i=0; i<tabs*TabWidth; i++) fputc(' ',output);                 \
            };                                                    \
          }

static void
#ifdef __USE_PROTOS
tab( void )
#else
tab( )
#endif
TAB

#ifdef __USE_PROTOS
static char *tokenFollowSet(TokNode *);
static ActionNode *findImmedAction( Node * );
static void dumpRetValAssign(char *, char *);
static void dumpAfterActions(FILE *output);
static set ComputeErrorSet(Junction *, int);
static void makeErrorClause(Junction *, set, int);
static void DumpFuncHeader( Junction *, RuleEntry * );
static int has_guess_block_as_first_item(Junction *);
static int genExprSets(set *, int);
static void genExprTree( Tree *t, int k );
static void genExprTreeOriginal( Tree *t, int k );                  /* MR10 */
static char * findOuterHandlerLabel(ExceptionGroup *eg);            /* MR7 */
static void OutLineInfo(FILE *file,int line,char *fileName);        /* MR14 */
#else
static char *tokenFollowSet();
static ActionNode *findImmedAction();
static void dumpRetValAssign();
static void dumpAfterActions();
static set ComputeErrorSet();
static void makeErrorClause();
static void DumpFuncHeader();
static int has_guess_block_as_first_item();
static int genExprSets();
static void genExprTree();
static void genExprTreeOriginal();                                  /* MR10 */
static char * findOuterHandlerLabel();                              /* MR7 */
static void OutLineInfo();                                          /* MR14 */
#endif

#define gen(s)                {tab(); fprintf(output, s);}
#define gen1(s,a)       {tab(); fprintf(output, s,a);}
#define gen2(s,a,b)           {tab(); fprintf(output, s,a,b);}
#define gen3(s,a,b,c)   {tab(); fprintf(output, s,a,b,c);}
#define gen4(s,a,b,c,d) {tab(); fprintf(output, s,a,b,c,d);}
#define gen5(s,a,b,c,d,e)     {tab(); fprintf(output, s,a,b,c,d,e);}
#define gen6(s,a,b,c,d,e,f)   {tab(); fprintf(output, s,a,b,c,d,e,f);}
#define gen7(s,a,b,c,d,e,f,g) {tab(); fprintf(output, s,a,b,c,d,e,f,g);}

#define _gen(s)               {fprintf(output, s);}
#define _gen1(s,a)            {fprintf(output, s,a);}
#define _gen2(s,a,b)    {fprintf(output, s,a,b);}
#define _gen3(s,a,b,c)  {fprintf(output, s,a,b,c);}
#define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);}
#define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);}
#define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}
#define _gen7(s,a,b,c,d,e,f,g){fprintf(output, s,a,b,c,d,e,f,g);}


/* MR11 a convenient place to set a break point */

#ifdef __USE_PROTOS
void MR_break(void) 
#else
void MR_break() 
#endif
{
  return;
}

/* MR10 genTraceOut(Junction *)      */

#ifdef __USE_PROTOS
static void genTraceOut(Junction *q)
#else
static void genTraceOut(q)
  Junction  *q;
#endif
{
  if ( TraceGen )
            if ( GenCC ) {gen1("zzTRACEOUT(\"%s\");\n", q->rname);}
            else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
}

static void
#ifdef __USE_PROTOS
warn_about_using_gk_option(void)
#else
warn_about_using_gk_option()
#endif
{
      static int warned_already=0;

      if ( !DemandLookahead || warned_already ) return;
      warned_already = 1;
      warnNoFL("-gk option could cause trouble for <<...>>? predicates");
}

void
#ifdef __USE_PROTOS
freeBlkFsets( Junction *q )
#else
freeBlkFsets( q )
Junction *q;
#endif
{
      int i;
      Junction *alt;
      require(q!=NULL, "freeBlkFsets: invalid node");

      for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
      {
            for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);
      }
}

/*
 * Generate a local variable allocation for each token references
 * in this block.
 */
static void
#ifdef __USE_PROTOS
genTokenPointers( Junction *q )
#else
genTokenPointers( q )
Junction *q;
#endif
{
      /* Rule refs are counted and can be referenced, but their
       * value is not set to anything useful ever.
       *
     * The ptrs are to be named _tij where i is the current level
       * and j is the element number within an alternative.
       */
      int first=1, t=0;
      set a;
      tokensRefdInBlock = q->tokrefs;

      if ( set_deg(q->tokrefs) == 0 ) return;
      a = set_dup(q->tokrefs);
      gen("ANTLRTokenPtr ");
      for (; !set_nil(a); set_rm(t, a))
      {
            t = set_int(a);
            if ( first ) first = 0;
            else _gen(",");
            if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t);
            _gen2("_t%d%d", BlkLevel, t);
            if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);}
            else _gen("=NULL");
      }
      _gen(";\n");
      set_free(a);
}

static int
#ifdef __USE_PROTOS
hasDefaultException(ExceptionGroup *eg)
#else
hasDefaultException(eg)
ExceptionGroup *eg;
#endif
{
    ListNode *q;

    for (q = eg->handlers->next; q!=NULL; q=q->next)
    {
        ExceptionHandler *eh = (ExceptionHandler *)q->elem;
        if ( strcmp("default", eh->signalname)==0 ) {
            return 1;
        }
    }
    return 0;
}
static void
#ifdef __USE_PROTOS
dumpException(ExceptionGroup *eg, int no_default_case)
#else
dumpException(eg, no_default_case)
ExceptionGroup *eg;
int no_default_case;
#endif
{
    char    *outerLabel;                                             /* MR7 */
    int     altHandler=0;                                            /* MR7 */
    int     namedHandler=0;                                          /* MR7 */

    outerLabel=findOuterHandlerLabel(eg);                            /* MR7 */

    if (eg->label != NULL) {                                         /* MR7 */
      namedHandler=1;                                                /* MR7 */
    } else if (eg->forRule) {                                        /* MR7 */
      /* nothing */                                                  /* MR20 */
    } else {                                                         /* MR7 */
      altHandler=1;                                                  /* MR7 */
    };                                                               /* MR7 */

#if 0
**     if (! eg->used) {                                             /* MR7 */
**          warnFL("exception group never used",                         /* MR7 */
**             FileStr[eg->altstart->file],eg->altstart->line);      /* MR7 */
**     };                                                            /* MR7 */
#endif

    if (namedHandler) {                                              /* MR7 */
        gen1("switch ( _signal ) {  /* [%s] */\n",eg->label);          /* MR7 */
    } else {                                                         /* MR7 */
        gen("switch ( _signal ) {\n");                                 /* MR7 */
      gen("case NoSignal: break;  /* MR7 */\n");                     /* MR7 */
    };                                                               /* MR7 */
      {
            ListNode *q;
            for (q = eg->handlers->next; q!=NULL; q=q->next)
            {
                  ExceptionHandler *eh = (ExceptionHandler *)q->elem;
                  if ( strcmp("default", eh->signalname)==0 ) {
                        gen("default :\n");
                        tabs++;
                        dumpAction(eh->action, output, tabs, -1, 1, 1);
                gen("_signal=NoSignal;  /* MR7 */\n");               /* MR7 */
                gen("break;  /* MR7 */\n");                          /* MR7 */
                        tabs--;
                        gen("}\n");

                /* copied from later code in dumpException              MR7 */

                if (namedHandler) {                                  /* MR7 */
                  gen("if (_signal != NoSignal)");                   /* MR7 */
                  _gen1(" goto %s_handler;  /* MR7 */\n",outerLabel);/* MR7 */
                } else if (altHandler) {                             /* MR7 */
                  gen1("goto %s_handler;  /* MR7 */\n",outerLabel);  /* MR7 */
                };
                        return;
                  }
                  gen1("case %s :\n", eh->signalname);
                  tabs++;
                  if ( eh->action != NULL )
                  {
                        dumpAction(eh->action, output, tabs, -1, 1, 1);
                gen("break;  /* MR7 */\n");                          /* MR7 */
                  }
                  tabs--;
            }
      }
      if ( no_default_case ) return;

      gen("default :\n");
    tabs++;                                                         /* MR7 */
    gen("break;  /* MR7 */\n");                                     /* MR7 */
    tabs--;                                                         /* MR7 */

      tabs++;
/*****      gen("*_retsignal = _signal;\n"); *****/

      tabs--;
      gen("}\n");

    if (namedHandler) {                                             /* MR7 */
      gen("if (_signal != NoSignal)");                              /* MR7 */
      _gen1(" goto %s_handler;  /* MR7 */\n",outerLabel);           /* MR7 */
    } else if (altHandler) {                                        /* MR7 */
      gen1("goto %s_handler;  /* MR7 */\n",outerLabel);             /* MR7 */
    };

}

static void
#ifdef __USE_PROTOS
dumpExceptions(ListNode *list)
#else
dumpExceptions(list)
ListNode *list;
#endif
{
      ListNode *p;

      for (p = list->next; p!=NULL; p=p->next)
      {
            ExceptionGroup *eg = (ExceptionGroup *) p->elem;
            _gen2("%s%s_handler:\n",
                    eg->label==NULL?"":eg->label,
                    eg->altID==NULL?"":eg->altID);
            if ( eg->altID!=NULL ) dumpException(eg, 0);
            else {
                  /* This must be the rule exception handler */
                  dumpException(eg, 1);
                  if ( !hasDefaultException(eg) )
            {
                gen("default :\n");
                tabs++;
                gen("zzdflthandlers(_signal,_retsignal);\n");
                tabs--;
                gen("}\n");
            }
            }
      }
}

/* For each element label that is found in a rule, generate a unique
 * Attribute (and AST pointer if GenAST) variable.
 */
void
#ifdef __USE_PROTOS
genElementLabels(ListNode *list)
#else
genElementLabels(list)
ListNode *list;
#endif
{
      int first=1;
      ListNode *p;

      if ( GenCC ) {gen("ANTLRTokenPtr");}
      else {gen("Attrib");}
      for (p = list->next; p!=NULL; p=p->next)
      {
            char *ep = (char *)p->elem;
            if ( first ) first = 0;
            else _gen(",");
            if ( GenCC ) {_gen1(" %s=NULL",ep);}
            else {_gen1(" %s",ep);}
      }
      _gen(";\n");

      if ( !GenAST ) return;

      first = 1;
      gen("AST");
      for (p = list->next; p!=NULL; p=p->next)
      {
            char *ep = (char *)p->elem;
            if ( first ) first = 0;
            else _gen(",");
            _gen1(" *%s_ast=NULL",ep);
      }
      _gen(";\n");
}

/*
 * Generate a local variable allocation for each token or rule reference
 * in this block.
 */
static void
#ifdef __USE_PROTOS
genASTPointers( Junction *q )
#else
genASTPointers( q )
Junction *q;
#endif
{
      int first=1, t;
      set a;

      a = set_or(q->tokrefs, q->rulerefs);
      if ( set_deg(a) > 0 )
      {
            gen("AST ");
            for (; !set_nil(a); set_rm(t, a))
            {
                  t = set_int(a);
                  if ( first ) first = 0;
                  else _gen(",");
                  _gen2("*_ast%d%d=NULL", BlkLevel, t);
            }
            set_free(a);
      }
      _gen(";\n");
}

static void
#ifdef __USE_PROTOS
BLOCK_Head( void )
#else
BLOCK_Head( )
#endif
{
      gen("{\n");
      tabs++;
      if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
}

static void
#ifdef __USE_PROTOS
BLOCK_Tail( void )
#else
BLOCK_Tail( )
#endif
{
      if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
      if ( !GenCC ) gen("}\n");
      tabs--;
      gen("}\n");
}

static void
#ifdef __USE_PROTOS
BLOCK_Preamble( Junction *q )
#else
BLOCK_Preamble( q )
Junction *q;
#endif
{
      ActionNode *a;
      Junction *begin;

      BLOCK_Head();
      if ( GenCC ) genTokenPointers(q);
      if ( GenCC&&GenAST ) genASTPointers(q);
      if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n");
      if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm)
      else if ( !GenCC ) gen("zzMake0;\n");
      if ( !GenCC ) gen("{\n");
      if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1);
      else begin = q;
      if ( has_guess_block_as_first_item(begin) )
      {
            gen("zzGUESS_BLOCK\n");
      }
      if ( q->jtype == aLoopBegin )
            a = findImmedAction( ((Junction *)q->p1)->p1 ); /* look at aLoopBlk */
      else
            a = findImmedAction( q->p1 );
      if ( a!=NULL && !a->is_predicate) {
            if (!a->noHoist) dumpAction(a->action, output, tabs, a->file, a->line, 1);
            a->done = 1;      /* remove action. We have already handled it */
      }
}

void
#ifdef __USE_PROTOS
genCombinedPredTreeContextOrig( Predicate *p )
#else
genCombinedPredTreeContextOrig( p )
Predicate *p;
#endif
{
      static set *ctx=NULL;         /* genExprSets() is destructive, make copy*/
      require(p!=NULL, "can't make context tree for NULL pred tree");

#ifdef DBG_PRED
      fprintf(stderr, "enter genCombinedPredTreeContextOrig(%s,0x%x) with sets:\n", p->expr, p);
      s_fprT(stderr, p->scontext[1]);
      fprintf(stderr, "\n");
#endif
      if ( p->down == NULL )
      {
/***  if ( p->k>1 && p->tcontext!=NULL ) ***/
            if ( p->tcontext!=NULL )
            {
                  _gen("(");
                  genExprTree(p->tcontext, 1);
                  _gen(")");
            }
/***  else if ( p->k==1 && set_deg(p->scontext[1])>0 ) ***/
            else if ( set_deg(p->scontext[1])>0 )
            {
                  if ( ctx==NULL ) ctx = (set *)calloc(CLL_k+1, sizeof(set));
                  require(ctx!=NULL, "ctx cannot allocate");
                  ctx[0]=empty;
                  ctx[1]=set_dup(p->scontext[1]);
                  _gen("(");
                  genExprSets(&(ctx[0]), p->k);
                  _gen(")");
                  set_free(ctx[1]);
            }
            else if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) {
                  fatal_internal("pred tree is orphan OR or AND list");
            }
            else {
            if (! HoistPredicateContext) {
              _gen(" 1 /* no context: prc is off */ ");
            } else {
              fatal_internal("pred tree context is empty");
            };
            }
            return;
      }

/* MR10 - make AND just like OR */

      if ( p->expr == PRED_AND_LIST )
      {
        Predicate *list = p->down;
        for (; list!=NULL; list=list->right)
        {
           genCombinedPredTreeContextOrig(list);
                   if ( list->right!=NULL ) _gen("|| /* MR10 was wrong */ ");
        };
            return;
      }

      if ( p->expr == PRED_OR_LIST )
      {
        Predicate *list = p->down;
        for (; list!=NULL; list=list->right)
        {
           genCombinedPredTreeContextOrig(list);
           if ( list->right!=NULL ) _gen("||");
        };
        return;
     };

      fatal("pred tree is really wacked");
}

/* [genCombinedPredTreeContext] */

void
#ifdef __USE_PROTOS
genCombinedPredTreeContext( Predicate *p )
#else
genCombinedPredTreeContext( p )
Predicate *p;
#endif
{
  Tree  *t;
  int   predDepth=0;

  if (0 && ! MR_usingPredNames && ! MRhoisting) {
    genCombinedPredTreeContextOrig(p);
  } else {
/* MR13 */    MR_pred_depth(p,&predDepth);
/* MR13 */    if (predDepth == 1) {
/* MR13 */
/* MR13 */      set   scontext[2];
/* MR13 */      scontext[0]=empty;
/* MR13 */      scontext[1]=MR_compute_pred_set(p);
/* MR13 */      if (set_nil(scontext[1])) {
/* MR13 */        _gen(" 1 /* MR12 no context (-prc off) */ ");
/* MR13 */      } else {
/* MR13 */        _gen("(");
/* MR13 */        genExprSets(&scontext[0], 1);
/* MR13 */        set_free(scontext[1]);
/* MR13 */        _gen(")");
/* MR13 */      };

    } else {
      t=MR_compute_pred_tree_context(p);
      if (t == NULL) {
        _gen(" 1 /* MR12 no context (-prc off) */ ");
      } else {
        _gen("(");
        genExprTree(t, 1);
        Tfree(t);   /* MR10 */
        _gen(")");
      };
    };
  };
}

/* [genPredTreeGate] */

void
#ifdef __USE_PROTOS
genPredTreeGate( Predicate *p, int in_and_expr )
#else
genPredTreeGate( p, in_and_expr )
Predicate *p;
int in_and_expr;
#endif
{
      if ( in_and_expr )
      {
            _gen("!(");
            genCombinedPredTreeContext(p);
            _gen(")||");
            if ( p->down!=NULL ) _gen("\n");
      }
      else
      {
            _gen("(");
            genCombinedPredTreeContext(p);
            _gen(")&&");
            if ( p->down!=NULL ) _gen("\n");
      }
}

#ifdef __USE_PROTOS
void genPredEntry(Predicate *p,int outer)
#else
void genPredEntry(p,outer)
  Predicate     *p;
  int           outer;
#endif
{
    int         inverted=0;
    Predicate   *q;
    int         localOuter=outer;
    int         needRP=0;

    if (p == NULL) return;

    if (p->predEntry != NULL && p->predEntry->predLiteral != NULL) {
      if (p->inverted != p->predEntry->pred->inverted) {
        _gen("! /* inverted pred */ (");
        needRP=1;
      } else {
        if (!localOuter) _gen("(");
        needRP=1;
      };
      dumpAction(p->predEntry->predLiteral,output,0,p->source->file,p->source->line,0);
      if (needRP) _gen(")");
      return;
    };

    inverted=p->inverted;

    if (inverted) {
      _gen(" ! /* inverted pred */ (");
      localOuter=1;
    };

    if (p->expr == PRED_OR_LIST) {
      if (!localOuter) _gen("(");
      for (q=p->down; q != NULL ; q=q->right) {
        genPredEntry(q,0);
        if (q->right != NULL) _gen(" || ");
      };
      if (!localOuter) _gen(")");
    } else if (p->expr == PRED_AND_LIST) {
      if (!localOuter) _gen("(");
      for (q=p->down; q != NULL ; q=q->right) {
        genPredEntry(q,0);
        if (q->right != NULL) _gen(" && ");
      };
      if (!localOuter) _gen(")");
    } else {
      if (!localOuter) _gen("(");
      require (p->source != NULL,"predEntry->source == NULL");
      require (p->source->inverted == 0,"dumpPredEntry p->source->inverted != 0");
      dumpAction(p->source->action,output,0,p->source->file,p->source->line,0);
      if (!localOuter) _gen(")");
    };

    if (inverted) {
        _gen(")");
    }
}

void
#ifdef __USE_PROTOS
dumpPredAction(ActionNode *anode,
                    char *s,FILE *output,int tabs,int file,int line,int final_newline)
#else
dumpPredAction(anode,
                    s,output,tabs,file,line,final_newline)

    ActionNode  *anode;
    char        *s;
    FILE        *output;
    int         tabs;
    int         file;
    int         line;
    int         final_newline;
#endif
{
    PredEntry   *predEntry=anode->predEntry;
    int         inverted=anode->inverted;
    Predicate   *workPred;

    if (predEntry == NULL) {

      /* inline predicate literal */

      require(inverted == 0,"dumpPredAction action->inverted");
        dumpAction(s,output,tabs,file,line,final_newline);

    } else {

      /* a reference to a predicate - possibly with an inverted source */

      if (predEntry->predLiteral != NULL) {
        if (inverted) _gen("! /* inverted pred */ (");
        dumpAction(predEntry->predLiteral,output,0,anode->file,anode->line,0);
        if (inverted) _gen(")");
      } else {
        workPred=predicate_dup(predEntry->pred);
        if (inverted) workPred->inverted=!workPred->inverted;
        genPredEntry(workPred,1);
        predicate_free(workPred);
      };
    };
}

/* [genPred] */

void
#ifdef __USE_PROTOS
genPred(Predicate *p, Node *j,int suppress_sva)
#else
genPred(p,j,suppress_sva)
    Predicate   *p;
    Node        *j;
    int         suppress_sva;
#endif
{
      if ( FoundException && !suppress_sva) {_gen("(_sva=(");}    /* MR11 suppress_sva */
      else {_gen("(");}
      if ( GenLineInfo && j->file != -1 ) _gen("\n");
    if (p->source != NULL && p->source->ampersandPred != NULL) {
      if (p->source->ampersandPred->k == 1) {

            set     ctx[2];

                  ctx[0]=empty;
                  ctx[1]=set_dup(p->source->ampersandPred->scontext[1]);

                  _gen("(");
                  genExprSets(&(ctx[0]), p->k);
                  _gen(") && ");
                  set_free(ctx[1]);
      } else {
        _gen("( ");
        genExprTree(p->source->ampersandPred->tcontext,1);
            _gen(" ) && ");
      };
    };

    dumpPredAction((ActionNode *)p->source,
                p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0);

      if ( FoundException && !suppress_sva)   /* MR11 suppress_sva */
         {_gen("),_sva)");}    /* MR10 - get red of "meant ==" messages */
      else {_gen(")");}
}

void
#ifdef __USE_PROTOS
MR_distinctORcontextOpt(Predicate *p,Node *j,int in_and_expr)
#else
MR_distinctORcontextOpt(p,j,in_and_expr)
    Predicate   *p;
    Node        *j;
    int         in_and_expr;
#endif
{
    Predicate   *q;

    _gen(" /* MR10 Distinct OR context optimization */ \n");

    if (in_and_expr) {
      gen("zzpf=0,\n");
      for (q=p->down; q != NULL; q=q->right) {
        gen("(  ");
        genCombinedPredTreeContext(q);
        _gen(" && (zzpf=1, ");
        genPred(q,j,0);
        _gen("  )) ||\n");
      };
      gen("!zzpf)");
    } else {
      require (0,
            "MR_distinctORcontextOpt: can't get here when using MR_predSimplify");
#if 0
**      for (q=p->down; q != NULL; q=q->right) {
**        gen("(  ");
**        genCombinedPredTreeContext(q);
**        _gen(" && ");
**        genPred(q,j);
**        if (q->right != NULL) {
**          _gen("  ) ||\n");
**        };
**      };
**      gen(")");
#endif
   };
}

void
#ifdef __USE_PROTOS
genPredTreeOrig( Predicate *p, Node *j, int in_and_expr )
#else
genPredTreeOrig( p, j, in_and_expr )
Predicate *p;
Node *j;
int in_and_expr;
#endif
{

/* MR10 */  int     allHaveContext=1;
/* MR10 */  int     noneHaveContext=1;

/* MR10 */  MR_predContextPresent(p,&allHaveContext,&noneHaveContext);

      if ( ! noneHaveContext )                  /* MR10 context guards ignored when -prc off */
      {
            _gen("(");
            genPredTreeGate(p, in_and_expr);
      }

      /* if leaf node, just gen predicate */

      if ( p->down==NULL )
      {
            genPred(p,j,0);
            if ( ! noneHaveContext ) _gen(")");   /* MR10 context guards ignored when -prc off */
            return;
      }

      /* if AND list, do both preds (only two possible) */
      if ( p->expr == PRED_AND_LIST )
      {
#if 0
**          _gen("(");
**          genPredTreeOrig(p->down, j, 1);
**          _gen("&&");
**          genPredTreeOrig(p->down->right, j, 1);
**          _gen(")");
**          if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */
**          return;
#endif
        /* MR11 - make it work with AND with more than two children - like OR */

            Predicate *list;
            _gen("(");
            list = p->down;
            for (; list!=NULL; list=list->right)
            {
                  genPredTreeOrig(list, j, 1);
                  if ( list->right!=NULL ) _gen("&&");
            }
            _gen(")");
            if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */
            return;
    };

      if ( p->expr == PRED_OR_LIST )
      {
            Predicate *list;
            _gen("(");
            list = p->down;
            for (; list!=NULL; list=list->right)
            {
                  genPredTreeOrig(list, j, 0);
                  if ( list->right!=NULL ) _gen("||");
            }
            _gen(")");
            if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */
            return;
      }

      fatal_internal("genPredTreeOrig: predicate tree is wacked");
}

#if 0
**   Predicate member dummyPredDepth is no longer used in MR10
**     but we might need it again in the future
**
**   if (MRhoisting) {
**     if ( !noneHaveContext &&
**          ! in_and_expr &&
**          p->source != NULL &&
**          p->source->dummyPredicateDepth > 0 &&
**          p->down == NULL) {
**          _gen("(");
**          genCombinedPredTreeContext(p);
**          _gen("  )\n");
**          return;
**     };
**   };
#endif

/* [genPredTree] */

/* in_and_expr

   what to do if the context is wrong
   what to do if the context is correct but the predicate is false

   remember: if the context is wrong it's the same as if the
             predicate is true as far as enabling an alternative

        Consider (AND p q r)

        if in an ... && ... expression then you don't want
        the entire predicate chain to fail just because the
        context for one component is wrong: so return true

        Consider (OR p q r)

        if in an ... || ... expression then you don't want
        the entire predicate chain to succeed just because
        the context for one component is correct when the
        corresponding test is false: so return false when
        the context is correct but the test is false.
*/

void
#ifdef __USE_PROTOS
genPredTree( Predicate *p, Node *j, int in_and_expr, int suppress_sva )
#else
genPredTree( p, j, in_and_expr, suppress_sva)
  Predicate     *p;
  Node          *j;
  int           in_and_expr;
  int           suppress_sva;
#endif
{

    int         allHaveContext=1;
    int         noneHaveContext=1;
    Tree        *groupTree;
    Tree        *oneTree;
    Predicate   *q;
    int         identicalORcontextOptimization=0;
    int         identicalANDcontextOptimization=0;

    if (0 && !MR_usingPredNames && !MRhoisting) {
      genPredTreeOrig(p,j,in_and_expr);
      return;
    };

    MR_predContextPresent(p,&allHaveContext,&noneHaveContext);

      if ( ! noneHaveContext ) {                 /* MR10 context guards ignored when -prc off */

      _gen("(");

            /* MR10 optimize OR predicates which are all leaves */

      if (p->expr == PRED_OR_LIST && MR_allPredLeaves(p->down)) {
        groupTree=MR_compute_pred_tree_context(p);
        for (q=p->down ; q != NULL ; q=q->right) {
          oneTree=MR_compute_pred_tree_context(q);
          if (! MR_tree_equ(groupTree,oneTree)) {
            Tfree(oneTree);
            break;
          };
          Tfree(oneTree);
        };
        Tfree(groupTree);
        if (q == NULL) {
          _gen("/* MR10 individual OR gates suppressed when all predicates are leaves");
          _gen(" with identical context */\n");
          genPredTreeGate(p,in_and_expr);   /* use the parent's in_and_expr for this gate */
          identicalORcontextOptimization=1;
        } else {
          MR_distinctORcontextOpt(p,j,in_and_expr);
          return;
        };
      } else if (p->expr == PRED_AND_LIST && MR_allPredLeaves(p->down)) {

            /* MR12 optimize AND predicates which are all leaves */

        groupTree=MR_compute_pred_tree_context(p);
        for (q=p->down ; q != NULL ; q=q->right) {
          oneTree=MR_compute_pred_tree_context(q);
          if (! MR_tree_equ(groupTree,oneTree)) {
            Tfree(oneTree);
            break;
          };
          Tfree(oneTree);
        };
        Tfree(groupTree);
        if (q == NULL) {
          _gen("/* MR12 individual AND gates suppressed when all predicates are leaves");
          _gen(" with identical context */\n");
          genPredTreeGate(p,in_and_expr);   /* use the parent's in_and_expr for this gate */
          identicalANDcontextOptimization=1;
        } else {
          genPredTreeGate(p, in_and_expr);
        };
      } else {
          genPredTreeGate(p, in_and_expr);
      };
      }

      /* if leaf node, just gen predicate */

      if ( p->down==NULL )
      {
            genPred(p,j,suppress_sva);
            if ( ! noneHaveContext ) _gen(")");   /* MR10 context guards ignored when -prc off */
            return;
      }

      /* if AND list, do both preds (only two possible) */
    /* MR10    not any more ! */

      if ( p->expr == PRED_AND_LIST )
      {
            Predicate *list;
            _gen("(");
            list = p->down;
        for (; list != NULL; list=list->right) {
          if (identicalANDcontextOptimization) {
            genPred(list, j,suppress_sva);
          } else {
                genPredTree(list, j, 1, suppress_sva);  /* in and context */
          };
          if ( list->right!=NULL ) _gen("&&");
        };
            _gen(")");
            if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */
            return;
      }

      if ( p->expr == PRED_OR_LIST )
      {
            Predicate *list;
            _gen("(");
            list = p->down;
            for (; list!=NULL; list=list->right)
            {
            if (identicalORcontextOptimization) {
                genPred(list, j,suppress_sva);
            } else {
                  genPredTree(list, j, 0, suppress_sva);
            };
                  if ( list->right!=NULL ) _gen("||");
            }
            _gen(")");
            if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */
            return;
      }

      fatal_internal("predicate tree is wacked");
}

/* [genPredTreeMainXX] */

Predicate *     /* MR10 */
#ifdef __USE_PROTOS
genPredTreeMainXX( Predicate *p, Node *j ,int in_and_expr)
#else
genPredTreeMainXX( p, j ,in_and_expr)
    Predicate   *p;
    Node        *j;
    int         in_and_expr;
#endif
{

    int     allHaveContext=1;
    int     noneHaveContext=1;

#if 0
    fprintf(stderr,"Pred before\n");
    dumppred(p);
    fprintf(stderr,"\n");
    fprintf(stderr,"Pred after\n");
    dumppred(p);
    fprintf(stderr,"\n");
#endif

    p=MR_predSimplifyALL(p);    /* MR10 */

    require (MR_predicate_context_completed(p),"predicate context is not complete");

    MR_cleanup_pred_trees(p);   /* MR10 */

    MR_predContextPresent(p,&allHaveContext,&noneHaveContext);
    if (!noneHaveContext & !allHaveContext) {
      warnFL("predicate contains elements both with and without context",
                FileStr[j->file],j->line);
    };

    if (InfoP) {
       _gen("\n#if 0\n\n");
       MR_dumpPred(p,1);
       _gen("#endif\n");
    };
      genPredTree(p,j,in_and_expr,0);
    return p;
}

Predicate *     /* MR10 */
#ifdef __USE_PROTOS
genPredTreeMain( Predicate *p, Node *j)
#else
genPredTreeMain( p, j)
    Predicate   *p;
    Node        *j;
#endif
{
  return genPredTreeMainXX(p,j,1);
}

static void
#ifdef __USE_PROTOS
genExprTreeOriginal( Tree *t, int k )
#else
genExprTreeOriginal( t, k )
Tree *t;
int k;
#endif
{
      require(t!=NULL, "genExprTreeOriginal: NULL tree");
      
      if ( t->token == ALT )
      {
            _gen("("); genExprTreeOriginal(t->down, k); _gen(")");
            if ( t->right!=NULL )
            {
                  _gen("||");
                  on1line++;
                  if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
                  _gen("("); genExprTreeOriginal(t->right, k); _gen(")");
            }
            return;
      }
      if ( t->down!=NULL ) _gen("(");
      _gen1("LA(%d)==",k);
      if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)
      else _gen1("%s", TokenString(t->token));
      if ( t->down!=NULL )
      {
            _gen("&&");
            on1line++;
            if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
            _gen("("); genExprTreeOriginal(t->down, k+1); _gen(")");
      }
      if ( t->down!=NULL ) _gen(")");
      if ( t->right!=NULL )
      {
            _gen("||");
            on1line++;
            if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
            _gen("("); genExprTreeOriginal(t->right, k); _gen(")");
      }
}

#ifdef __USE_PROTOS
static void MR_LAtokenString(int k,int token)
#else
static void MR_LAtokenString(k,token)
  int   k;
  int   token;
#endif
{
    char    *ts;

    ts=TokenString(token);
    if (ts == NULL) {
      _gen2(" LA(%d)==%d",k,token);
    } else {
      _gen2(" LA(%d)==%s",k,ts);
    };
}


#ifdef __USE_PROTOS
static int MR_countLeaves(Tree *t)
#else
static int MR_countLeaves(t)
  Tree  *t;
#endif
{
  if (t == NULL) return 0;
  if (t->token == ALT) {
    return MR_countLeaves(t->down)+MR_countLeaves(t->right);
  } else {
    return 1+MR_countLeaves(t->down)+MR_countLeaves(t->right);
  };
}

#ifdef __USE_PROTOS
static void MR_genOneLine(Tree *tree,int k)
#else
static void MR_genOneLine(tree,k)
  Tree      *tree;
  int       k;
#endif
{
    if (tree == NULL) return;
    if (tree->token == ALT) {
       MR_genOneLine(tree->down,k);
    } else {
       MR_LAtokenString(k,tree->token);
       if (tree->down != NULL &&
           tree->down->right == NULL) {
          _gen(" &&");
          MR_genOneLine(tree->down,k+1);
       } else if (tree->down != NULL) {
         _gen(" && (");
         MR_genOneLine(tree->down,k+1);
         _gen(")");
       };
    };
    if (tree->right != NULL) {
      _gen(" ||");
      MR_genOneLine(tree->right,k);
    };
}

static int across;
static int depth;
static int lastkonline;

#ifdef __USE_PROTOS
static void MR_genMultiLine(Tree *tree,int k)
#else
static void MR_genMultiLine(tree,k)
  Tree  *tree;
  int   k;
#endif
{
    int     i;

    if (tree == NULL) return;
    if (tree->token == ALT) {
      MR_genMultiLine(tree,k);
    } else {
      MR_LAtokenString(k,tree->token);
      lastkonline=k;
      across++;
      if (tree->down != NULL && tree->down->right == NULL) {
        if (across > 3) {
          _gen("\n");
          across=0;
          lastkonline=0;
          for (i=0 ; i < depth+k ; i++) _gen("   ");
          _gen("&&");
        } else {
          _gen(" &&");
        };
        MR_genMultiLine(tree->down,k+1);
      } else if (tree->down != NULL) {
        _gen("\n");
        lastkonline=0;
        across=0;
        for (i=0 ; i < depth+k ; i++) _gen("   ");
        _gen("&& (");
        MR_genMultiLine(tree->down,k+1);
        _gen(")");
      };
    };
    if (tree->right != NULL) {
      if (k < lastkonline) {
        _gen("\n");
        across=0;
        lastkonline=0;
        for (i=0; i < depth+k-1 ; i++) _gen("   ");
        _gen("||");
      } else if (across > 3 ) {
        _gen("\n");
        across=0;
        lastkonline=0;
        for (i=0; i < depth+k ; i++) _gen("   ");
        _gen("||");
      } else {
        _gen(" ||");
      };
      MR_genMultiLine(tree->right,k);
    };
}

#ifdef __USE_PROTOS
static void genExprTree(Tree *tree,int k)
#else
static void genExprTree(tree,k)
  Tree  *tree;
  int   k;
#endif
{
    int     count;

#if 0
    /* MR20 THM This was probably an error.
            The routine should probably reference that static 
            "across" and this declaration hides it.
    */

    int     across;
#endif
  
    require (tree != NULL,"genExprTree: tree is NULL");
    require (k > 0,"genExprTree: k <= 0");

    if (0 && !MRhoisting) {   /* MR11 make new version standard */
      genExprTreeOriginal(tree,k);
    } else {
      count=MR_countLeaves(tree);
      if (count < 5) {
        MR_genOneLine(tree,k);
      } else {
        _gen("\n");
        across=0;
        depth=0;
        lastkonline=0;
        MR_genMultiLine(tree,k);
        _gen("\n");
      };
    };
}


/*
 * Generate LL(k) type expressions of the form:
 *
 *           (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&
 *           (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&
 *                .....
 *           (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)
 *
 * If GenExprSetsOpt generate:
 *
 *          (setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...
 *
 * where n is set_deg(expr) and Ti is some random token and k is the last nonempty
 * set in fset <=CLL_k.
 * k=1..CLL_k where CLL_k >= 1.
 *
 * This routine is visible only to this file and cannot answer a TRANS message.
 *
 */

/*  [genExpr] */

static int
#ifdef __USE_PROTOS
genExpr( Junction *j )
#else
genExpr( j )
Junction *j;
#endif
{
      int max_k;

      /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead
       * from CLL_k..LL_k
       */
      {
            int limit;
            if ( j->ftree!=NULL ) limit = LL_k;
            else limit = CLL_k;
            max_k = genExprSets(j->fset, limit);
      }

      /* Do tests for real tuples from other productions that conflict with
       * artificial tuples generated by compression (using sets of tokens
       * rather than k-trees).
       */
      if ( j->ftree != NULL )
      {
            _gen(" && !("); genExprTree(j->ftree, 1); _gen(")");
      }

      if ( ParseWithPredicates && j->predicate!=NULL )
      {
            Predicate *p = j->predicate;
            warn_about_using_gk_option();
            _gen("&&");
            j->predicate=genPredTreeMain(p, (Node *)j);     /* MR10 */
      }

      return max_k;
}

static int
#ifdef __USE_PROTOS
genExprSets( set *fset, int limit )
#else
genExprSets( fset, limit )
set *fset;
int limit;
#endif
{
      int k = 1;
      int max_k = 0;
      unsigned *e, *g, firstTime=1;

    if (set_nil(fset[1])) {
      _gen(" 0 /* MR13 empty set expression  - undefined rule ? infinite left recursion ? */ ");
      MR_BadExprSets++;
    };

      if ( GenExprSetsOpt )
      {
            while ( k <= limit && !set_nil(fset[k]) )   /* MR11 */
            {
                  if ( set_deg(fset[k])==1 )    /* too simple for a set? */
                  {
                        int e;
                        _gen1("(LA(%d)==",k);
                        e = set_int(fset[k]);
                        if ( TokenString(e) == NULL ) _gen1("%d)", e)
                        else _gen1("%s)", TokenString(e));
                  }
                  else
                  {
                        NewSet();
                        FillSet( fset[k] );
                        _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);
                  }
                  if ( k>max_k ) max_k = k;
                  if ( k == CLL_k ) break;
                  k++;
                  if ( k<=limit && !set_nil(fset[k]) ) _gen(" && ");  /* MR11 */
                  on1line++;
                  if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
            }
            return max_k;
      }

      while ( k<= limit &&  !set_nil(fset[k]) )       /* MR11 */
      {
            if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set");
            for (; *e!=nil; e++)
            {
                  if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }
                  on1line++;
                  if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
                  _gen1("LA(%d)==",k);
                  if ( TokenString(*e) == NULL ) _gen1("%d", *e)
                  else _gen1("%s", TokenString(*e));
            }
            free( (char *)g );
            _gen(")");
            if ( k>max_k ) max_k = k;
            if ( k == CLL_k ) break;
            k++;
            if ( k <= limit && !set_nil(fset[k]) ) { firstTime=1; _gen(" && "); }   /* MR11 */
            on1line++;
            if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
      }
      return max_k;
}

/*
 * Generate code for any type of block.  If the last alternative in the block is
 * empty (not even an action) don't bother doing it.  This permits us to handle
 * optional and loop blocks as well.
 *
 * Only do this block, return after completing the block.
 * This routine is visible only to this file and cannot answer a TRANS message.
 */
static set
#ifdef __USE_PROTOS
genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly )
#else
genBlk( q, jtype, max_k, need_right_curly )
Junction *q;
int jtype;
int *max_k;
int *need_right_curly;
#endif
{
      set f;
      Junction *alt;
      int a_guess_in_block = 0;
      require(q!=NULL,                    "genBlk: invalid node");
      require(q->ntype == nJunction,      "genBlk: not junction");

      *need_right_curly=0;
      if ( q->p2 == NULL )    /* only one alternative?  Then don't need if */
      {     
            if (first_item_is_guess_block((Junction *)q->p1)!=NULL )
            {
            if (jtype != aLoopBlk && jtype != aOptBlk && jtype != aPlusBlk) {
                    warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line);
            };
                gen("zzGUESS\n");   /* guess anyway to make output code consistent */
/* MR10 disable */  /**** gen("if ( !zzrv )\n"); ****/
/* MR10 */          gen("if ( !zzrv ) {\n"); tabs++; (*need_right_curly)++;
        };
            TRANS(q->p1);
            return empty;           /* no decision to be made-->no error set */
      }

      f = First(q, 1, jtype, max_k);
      for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
      {
            if ( alt->p2 == NULL )                          /* chk for empty alt */
            {     
                  Node *p = alt->p1;
                  if ( p->ntype == nJunction )
                  {
                        /* we have empty alt */
                        if ( ((Junction *)p)->p1 == (Node *)q->end )
                        {
                              break;                                    /* don't do this one, quit */
                        }
                  }
            }
/* MR10 */        if (alt->p2 == NULL &&
/* MR10 */               ( q->jtype == aSubBlk || q->jtype == RuleBlk) ) {
/* MR10 */          if (first_item_is_guess_block(alt)) {
/* MR10 */               warnFL("(...)? as last alternative of block is unnecessary",
/* MR10 */                                FileStr[alt->file],alt->line);
/* MR10 */          };
/* MR10 */        };

            if ( alt != q ) gen("else ")
            else
            {
                  if ( DemandLookahead )
                        if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}
                        else gen1("look(%d);\n", *max_k);
            }

            if ( alt!=q )
            {
                  _gen("{\n");
                  tabs++;
                  (*need_right_curly)++;
                  /* code to restore state if a prev alt didn't follow guess */
                  if ( a_guess_in_block )
                        gen("if ( !zzrv ) zzGUESS_DONE;\n");
            }
            if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )
            {
                  a_guess_in_block = 1;
                  gen("zzGUESS\n");
            }
            gen("if ( ");
            if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");
            genExpr(alt);
            _gen(" ) ");
            _gen("{\n");
            tabs++;
            TRANS(alt->p1);
            --tabs;
            gen("}\n");
/* MR10 */        if (alt->p2 == NULL) {
/* MR10 */          if (first_item_is_guess_block(alt)) {
/* MR10 */            gen("/* MR10 */ else {\n");
/* MR10 */            tabs++;
/* MR10 */                (*need_right_curly)++;
/* MR10 */                /* code to restore state if a prev alt didn't follow guess */
/* MR10 */            gen("/* MR10 */ if ( !zzrv ) zzGUESS_DONE;\n");
/* MR10 */            gen("/* MR10 */ if (0) {}     /* last alternative of block is guess block */\n");
/* MR10 */          };
/* MR10 */        };
      }
      return f;
}

static int
#ifdef __USE_PROTOS
has_guess_block_as_first_item( Junction *q )
#else
has_guess_block_as_first_item( q )
Junction *q;
#endif
{
      Junction *alt;

      for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
      {
            if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;
      }
      return 0;
}

static int
#ifdef __USE_PROTOS
has_guess_block_as_last_item( Junction *q )
#else
has_guess_block_as_last_item( q )
Junction *q;
#endif
{
      Junction *alt;

    if (q == NULL) return 0;
      for (alt=q; alt->p2 != NULL && !( (Junction *) alt->p2)->ignore; alt= (Junction *) alt->p2 ) {};
    return first_item_is_guess_block( (Junction *) alt->p1) != NULL;
}

/* return NULL if 1st item of alt is NOT (...)? block; else return ptr to aSubBlk node
 * of (...)?;  This function ignores actions and predicates.
 */
Junction *
#ifdef __USE_PROTOS
first_item_is_guess_block( Junction *q )
#else
first_item_is_guess_block( q )
Junction *q;
#endif
{
    /* MR14  Couldnt' find aSubBlock which was a guess block when it lay
             behind aLoopBlk.  The aLoopBlk only appear in conjunction with
             aLoopBegin, but the routine didn't know that.  I think.

       MR14a Added extra parentheses to clarify precedence
    */

      while ( q!=NULL &&
            (  ( q->ntype==nAction ) ||
               ( q->ntype==nJunction &&
                    (q->jtype==Generic || q->jtype == aLoopBlk)
               )
            )
          )
      {
            if ( q->ntype==nJunction ) q = (Junction *)q->p1;
            else q = (Junction *) ((ActionNode *)q)->next;
      }

      if ( q==NULL ) return NULL;
      if ( q->ntype!=nJunction ) return NULL;
      if ( q->jtype!=aSubBlk ) return NULL;
      if ( !q->guess ) return NULL;
      return q;
}

/* MR1                                                                      */
/* MR1  10-Apr-97 MR1 Routine to stringize failed semantic predicates msgs  */
/* MR1                                                                                */

#define STRINGIZEBUFSIZE 1024

static char stringizeBuf[STRINGIZEBUFSIZE];
char *
#ifdef __USE_PROTOS
stringize(char * s)
#else
stringize(s)
char *s;
#endif

{
  char            *p;
  char            *stop;

  p=stringizeBuf;
  stop=&stringizeBuf[1015];

  if (s != 0) {
    while (*s != 0) {
      if (p >= stop) {
      goto stringizeStop;
      } else if (*s == '\n') {
        *p++='\\';
        *p++='n';
        *p++='\\';
      *p++=*s++;
      } else if (*s == '\\') {
      *p++=*s;
      *p++=*s++;
      } else if (*s == '\"') {
        *p++='\\';
      *p++=*s++;
        while (*s != 0) {
          if (p >= stop) {
           goto stringizeStop;
        } else if (*s == '\n') {
          *p++='\\';
          *p++=*s++;
        } else if (*s == '\\') {
          *p++=*s++;
          *p++=*s++;
        } else if (*s == '\"') {
          *p++='\\';
          *p++=*s++;
          break;
        } else {
          *p++=*s++;
          };
        };
      } else if (*s == '\'') {
      *p++=*s++;
        while (*s != 0) {
          if (p >= stop) {
           goto stringizeStop;
        } else if (*s == '\'') {
          *p++=*s++;
          break;
        } else if (*s == '\\') {
          *p++=*s++;
          *p++=*s++;
        } else if (*s == '\"') {
          *p++='\\';
          *p++=*s++;
          break;
        } else {
          *p++=*s++;
          };
        };
      } else {
        *p++=*s++;
      };
    };
  };
  goto stringizeExit;
stringizeStop:
  *p++='.';             
  *p++='.';             
  *p++='.';             
stringizeExit:
  *p=0;
  return stringizeBuf;
}

#ifdef __USE_PROTOS
int isNullAction(char *s)
#else
int isNullAction(s)
  char  *s;
#endif
{
  char  *p;
  for (p=s; *p != '\0' ; p++) {
    if (*p != ';' && *p !=' ') return 0;
  };
  return 1;
}
/* MR1                                                                                          */
/* MR1      End of Routine to stringize code for failed predicates msgs         */
/* MR1                                                                                */

/* Generate an action.  Don't if action is NULL which means that it was already
 * handled as an init action.
 */
void
#ifdef __USE_PROTOS
genAction( ActionNode *p )
#else
genAction( p )
ActionNode *p;
#endif
{
      require(p!=NULL,              "genAction: invalid node and/or rule");
      require(p->ntype==nAction,    "genAction: not action");
      
      if ( !p->done )  /* MR10 */ /* MR11 */
      {
            if ( p->is_predicate)
            {
                  if ( p->guardpred != NULL )
                  {
                Predicate *guardDup=predicate_dup(p->guardpred); /* MR10 */
                gen("if (!");
                        guardDup=genPredTreeMain(guardDup, (Node *)p);
                predicate_free(guardDup);
                  }
/* MR10 */  else if (p->ampersandPred != NULL) {
/* MR10 */      gen("if (!");
/* MR10 */      p->ampersandPred=genPredTreeMain(p->ampersandPred, (Node *)p);
/* MR10 */  }
                  else
                  {
                        gen("if (!(");
                        /* make sure that '#line n' is on front of line */
                        if ( GenLineInfo && p->file != -1 ) _gen("\n");
                        dumpPredAction(p,p->action, output, 0, p->file, p->line, 0);
                        _gen(")");
                  }
                  if ( p->pred_fail != NULL )
                  {
                        _gen(")\n");
                        tabs++;
/* MR1                                                                                */
/* MR1  10-Apr-97 MR1  Put {...} envelope around failed semantic predicates */
/* MR1                                                                                */
                        gen1("{%s};\n", p->pred_fail);                           /* MR1 */
                        tabs--;
                  }
/* MR1                                                                                    */
/* MR1  10-Apr-97 MR1   Properly stringize failed semantic predicates       */
/* MR1                                                                                */
                  else _gen1(") {zzfailed_pred(\"%s\");}\n",               /* MR1 */
                              stringize(p->action));                       /* MR1 */
            }
            else    /* not a predicate */
            {
            if (! isNullAction(p->action) && !p->noHoist) {
                    if ( FoundGuessBlk ) {
                        if ( GenCC ) {
                  gen("if ( !guessing ) {\n");
                } else {
                          gen("zzNON_GUESS_MODE {\n");
                };
              };
                    dumpAction(p->action, output, tabs, p->file, p->line, 1);
                    if ( FoundGuessBlk ) gen("}\n");
            };
            }
      }
      TRANS(p->next)
}

/*
 *          if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in
 *          else pass addr of temp root ptr (&_ast) (don't zzlink it in).
 *
 *          if ! modifies rule-ref, then never link it in and never pass zzSTR.
 *          Always pass address of temp root ptr.
 */
void
#ifdef __USE_PROTOS
genRuleRef( RuleRefNode *p )
#else
genRuleRef( p )
RuleRefNode *p;
#endif
{
      Junction *q;
      char *handler_id = "";
      RuleEntry *r, *r2;
      char *parm = "", *exsig = "";

    int     genRuleRef_emittedGuessGuard=0;     /* MR10 */

      require(p!=NULL,              "genRuleRef: invalid node and/or rule");
      require(p->ntype==nRuleRef, "genRuleRef: not rule reference");
      
      if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
            handler_id = p->altstart->exception_label;

      r = (RuleEntry *) hash_get(Rname, p->text);
      if ( r == NULL )
      {
            warnFL( eMsg1("rule %s not defined",
                                p->text), FileStr[p->file], p->line );
            return;
      }

/* MR8 5-Aug-97     Reported by S.Bochnak@microtool.com.pl                  */
/*                  Don't do assign when no return values declared          */
/*                  Move definition of q up and use it to guard p->assign   */

      q = RulePtr[r->rulenum];      /* find definition of ref'd rule */  /* MR8 */

      r2 = (RuleEntry *) hash_get(Rname, p->rname);
      if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}

    OutLineInfo(output,p->line,FileStr[p->file]);

      if ( GenCC && GenAST ) {
            gen("_ast = NULL;\n");
      }

      if ( FoundGuessBlk && p->assign!=NULL && q->ret != NULL ) {      /* MR8 */
            if ( GenCC ) {
          gen("if ( !guessing ) {\n");
        } else {
          gen("zzNON_GUESS_MODE {\n");
        };
        tabs++;                                                      /* MR11 */
        genRuleRef_emittedGuessGuard=1;                              /* MR11 */
    };

      if ( FoundException ) exsig = "&_signal";

      tab();
      if ( GenAST )
      {
            if ( GenCC ) {
/****             if ( r2->noAST || p->astnode==ASTexclude )
****/
                  {
/****                   _gen("_ast = NULL;\n");
****/
                        parm = "&_ast";
                  }
/*** we always want to set just a pointer now, then set correct
pointer after

                  else {
                        _gen("_astp =
(_tail==NULL)?(&_sibling):(&(_tail->_right));\n");
                        parm = "_astp";
                  }
****/
            }
            else {
                  if ( r2->noAST || p->astnode==ASTexclude )
                  {
                        _gen("_ast = NULL; ");
                        parm = "&_ast";
                  }
                  else parm = "zzSTR";
            }
            if ( p->assign!=NULL && q->ret!=NULL )                       /* MR8 */
            {
                  if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
                  else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
            }
            if ( FoundException ) {
                  _gen5("%s%s(%s,&_signal%s%s); ",
                          RulePrefix,
                          p->text,
                          parm,
                          (p->parms!=NULL)?",":"",
                          (p->parms!=NULL)?p->parms:"");
                  if ( p->ex_group!=NULL ) {
                        _gen("\n");
                        gen("if (_signal) {\n");
                        tabs++;
                        dumpException(p->ex_group, 0);
                        tabs--;
                        gen("}");
                  }
                  else {
                        _gen1("if (_signal) goto %s_handler;", handler_id);
                  }
            }
            else {
                  _gen5("%s%s(%s%s%s);",
                          RulePrefix,
                          p->text,
                          parm,
                          (p->parms!=NULL)?",":"",
                          (p->parms!=NULL)?p->parms:"");
            }
            if ( GenCC && (r2->noAST || p->astnode==ASTexclude) )
            {
                  /* rule has a ! or element does */
                  /* still need to assign to #i so we can play with it */
                  _gen("\n");
                  gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum);
            }
            else if ( !r2->noAST && p->astnode == ASTinclude )
            {
                  /* rule doesn't have a ! and neither does element */
/* MR10 */  if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) {
/* MR10 */    _gen("\n");
/* MR10 */    if (GenCC) gen ("if (!guessing) {    /* MR10 */")
/* MR10 */          else gen ("if (!zzguessing) {    /* MR10 */\n");
/* MR10 */    tabs++;
/* MR10 */  };
                  if ( GenCC ) {
                        _gen("\n");
                        gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n");
                        gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum);
                        tab();
                  }
                  else _gen(" ");
            if ( GenCC ) {
                _gen("ASTBase::"); }
                else _gen("zz");
                  _gen("link(_root, &_sibling, &_tail);");

/* MR10 */  if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) {     /* MR10 */
/* MR10 */    _gen("\n");
/* MR10 */    tabs--;
/* MR10 */    if (GenCC) gen ("};    /* MR10 */")
/* MR10 */          else gen ("};    /* MR10 */");
/* MR10 */  };
            }
      }
      else
      {
            if ( p->assign!=NULL && q->ret!=NULL )                       /* MR8 */
            {
                  if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);}
                  else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
            }
            if ( FoundException ) {
                  _gen4("%s%s(&_signal%s%s); ",
                          RulePrefix,
                          p->text,
                          (p->parms!=NULL)?",":"",
                          (p->parms!=NULL)?p->parms:"");
                  if ( p->ex_group!=NULL ) {
                        _gen("\n");
                        gen("if (_signal) {\n");
                        tabs++;
                        dumpException(p->ex_group, 0);
                        tabs--;
                        gen("}");
                  }
                  else {
                        _gen1("if (_signal) goto %s_handler;", handler_id);
                  }
            }
            else {
                  _gen3("%s%s(%s);",
                          RulePrefix,
                          p->text,
                          (p->parms!=NULL)?p->parms:"");
            }
            if ( p->assign!=NULL && q->ret!=NULL ) _gen("\n");           /* MR8 */
      }

      if ( p->assign!=NULL && q->ret!=NULL) {                          /* MR8 */
            if ( HasComma(p->assign) )
            {
                  _gen("\n");
                  dumpRetValAssign(p->assign, q->ret);
                  _gen("}");
            }
      }
      _gen("\n");

      /* Handle element labels now */
      if ( p->el_label!=NULL )
      {
            if ( GenAST )
            {
                  if ( GenCC ) {
                        gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
                  }
                  else {gen1("%s_ast = zzastCur;\n", p->el_label);}
            }
            else if (!GenCC ) {
                  gen1("%s = zzaCur;\n", p->el_label);
        }
      }

      if ( FoundGuessBlk && p->assign!=NULL && q->ret!=NULL ) {       /* MR8 */
            /* in guessing mode, don't branch to handler upon error */
        tabs--;                                                     /* MR11 */
            gen("} else {\n");
        tabs++;                                                     /* MR11 */
            if ( FoundException ) {
                  gen6("%s%s(%s%s&_signal%s%s);\n",
                         RulePrefix,
                         p->text,
                         parm,
                 (*parm!='\0')?",":"",
                 (p->parms!=NULL)?",":"",
                         (p->parms!=NULL)?p->parms:"");
            }
            else {
                  gen5("%s%s(%s%s%s);\n",
                         RulePrefix,
                         p->text,
                         parm,
                         (p->parms!=NULL && *parm!='\0')?",":"",
                         (p->parms!=NULL)?p->parms:"");
            }
        tabs--;                                                     /* MR11 */
            gen("}\n");
      }
      TRANS(p->next)
}

/*
 * Generate code to match a token.
 *
 * Getting the next token is tricky.  We want to ensure that any action
 * following a token is executed before the next GetToken();
 */
void
#ifdef __USE_PROTOS
genToken( TokNode *p )
#else
genToken( p )
TokNode *p;
#endif
{
      RuleEntry *r;
      char *handler_id = "";
      ActionNode *a;
      char *set_name;
      require(p!=NULL,              "genToken: invalid node and/or rule");
      require(p->ntype==nToken,     "genToken: not token");
      
      if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
            handler_id = p->altstart->exception_label;

      r = (RuleEntry *) hash_get(Rname, p->rname);
      if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}

    OutLineInfo(output,p->line,FileStr[p->file]);

      if ( !set_nil(p->tset) )      /* implies '.', ~Tok, or tokenclass */
      {
            unsigned e;
            set b;
            b = set_dup(p->tset);
            if ( p->tclass!=NULL )              /* token class? */
            {
                  static char buf[MaxRuleName+1];
                  if ( p->tclass->dumped )
                        e = p->tclass->setnum;
                  else {
                        e = DefErrSet(&b, 0, TokenString(p->token));
                        p->tclass->dumped = 1;  /* indicate set has been created */
                        p->tclass->setnum = e;
                  }
                  sprintf(buf, "%s_set", TokenString(p->token));
                  set_name = buf;
            }
            else {                              /* wild card to ~ operator */
                  static char buf[sizeof("zzerr")+10];
                  int n = DefErrSet( &b, 0, NULL );
                  if ( GenCC ) sprintf(buf, "err%d", n);
                  else sprintf(buf, "zzerr%d", n);
                  set_name = buf;
            }

            if ( !FoundException )
                  {gen1("zzsetmatch(%s);", set_name);}
            else if ( p->ex_group==NULL ) {
            if ( p->use_def_MT_handler )
                gen3("zzsetmatch_wdfltsig(%s,(ANTLRTokenType)%d,%s);",
                     set_name,
                     p->token,
                     tokenFollowSet(p))
            else
                gen2("zzsetmatch_wsig(%s, %s_handler);",
                     set_name,
                     handler_id);
            }
            else
            {
                  gen1("if ( !_setmatch_wsig(%s) ) {\n", set_name);
                  tabs++;
/* MR6 */   if (FoundGuessBlk) {
/* MR6 */     if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
/* MR6 */     else gen("if ( zzguessing ) goto fail;\n");
/* MR6 */   };
                  gen("_signal=MismatchedToken;\n");
                  dumpException(p->ex_group, 0);
                  tabs--;
                  gen("}\n");
            }
            set_free(b);
      }
      else if ( TokenString(p->token)!=NULL )
      {
            if ( FoundException ) {
                  if ( p->use_def_MT_handler )
                        gen2("zzmatch_wdfltsig(%s,%s);",TokenString(p->token),tokenFollowSet(p))
                  else if ( p->ex_group==NULL )
                  {
                        gen2("zzmatch_wsig(%s, %s_handler);",
                               TokenString(p->token),
                               handler_id);
                  }
                  else
                  {
/* MR6 */         if (GenCC) {
/* MR6 */           gen1("if ( !_match_wsig(%s) ) {\n", TokenString(p->token));
/* MR6 */         } else {
/* MR6 */           gen1("if ( !_zzmatch_wsig(%s) ) {\n", TokenString(p->token));
/* MR6 */         };
                        tabs++;
/* MR6 */         if (FoundGuessBlk) {
/* MR6 */           if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
/* MR6 */           else gen("if ( zzguessing ) goto fail;\n");
/* MR6 */         };
                        gen("_signal=MismatchedToken;\n");
                        dumpException(p->ex_group, 0);
                        tabs--;
                        gen("}\n");
                  }
            }
            else gen1("zzmatch(%s);", TokenString(p->token));
      }
      else {
        if ( FoundException ) {
            if ( p->use_def_MT_handler )
                        gen2("zzmatch_wdfltsig((ANTLRTokenType)%d,%s);",
                               p->token,tokenFollowSet(p))
            else
                gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id);
        }
            else {gen1("zzmatch(%d);", p->token);}
      }

      a = findImmedAction( p->next );
      /* generate the token labels */
      if ( GenCC && p->elnum>0 )
      {
            /* If building trees in C++, always gen the LT() assigns */
            if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )
            {
/* MR10 */  if ( FoundGuessBlk ) {
/* MR10 */    gen("\n");
/* MR10 */    if (p->label_used_in_semantic_pred) {
/* MR10 */        gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);  /* MR10 */\n", BlkLevel-1, p->elnum);
/* MR10 */    } else {
/* MR10 */        gen("if ( !guessing ) {\n"); tab();
/* MR10 */        _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);\n", BlkLevel-1, p->elnum);
/* MR10 */      _gen("}\n");
/* MR10 */    };
/* MR10 */  } else {
/* MR10 */    _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);", BlkLevel-1, p->elnum);
/* MR10 */  };
/* MR10 */
            }

            if ( LL_k>1 )
                  if ( !DemandLookahead ) _gen(" labase++;");
            _gen("\n");
            tab();
      }
      if ( GenAST )
      {
            if ( FoundGuessBlk && !(p->astnode == ASTexclude || r->noAST) )
            {
                  if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}
                  else {_gen("zzNON_GUESS_MODE {\n"); tab();}
            }
            if ( !r->noAST )
            {
                  if ( GenCC && !(p->astnode == ASTexclude || r->noAST) ) {
                        _gen("\n");
/* MR13 */      if (NewAST) {
/* MR13 */            gen4("_ast%d%d = newAST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
/* MR13 */      } else {
/* MR13 */            gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
/* MR13 */      }
                        tab();
                  }
                  if ( GenCC && !(p->astnode == ASTexclude || r->noAST) )
                        {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}
                  else _gen(" ");
                  if ( p->astnode==ASTchild ) {
                        if ( !GenCC ) _gen("zz");
                        _gen("subchild(_root, &_sibling, &_tail);");
                  }
                  else if ( p->astnode==ASTroot ) {
                        if ( !GenCC ) _gen("zz");
                        _gen("subroot(_root, &_sibling, &_tail);");
                  }
                  if ( GenCC && !(p->astnode == ASTexclude || r->noAST) ) {
                        _gen("\n");
                        tab();
                  }
            }
            else if ( !GenCC ) _gen(" zzastDPush;");
            if ( FoundGuessBlk && !(p->astnode == ASTexclude || r->noAST) )
                  {_gen("}\n"); tab();}
      }

      /* Handle element labels now */
      if ( p->el_label!=NULL )
      {
        int     done_NON_GUESSMODE=0;

            _gen("\n");

/* MR10 */    /* do Attrib / Token ptr for token label used in semantic pred */
/* MR10 */    /* for these cases do assign even in guess mode                */
/* MR10 */
/* MR10 */    if (p->label_used_in_semantic_pred) {
/* MR10 */      if ( GenCC ) {
/* MR10 */        if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {
/* MR10 */          gen3("%s = _t%d%d;", p->el_label, BlkLevel-1, p->elnum);
/* MR10 */        } else {
/* MR10 */          gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);
/* MR10 */        };
/* MR10 */      } else {
/* MR10 */          gen1("%s = zzaCur;", p->el_label);
/* MR10 */      };
/* MR10 */      if (FoundGuessBlk) _gen("  /* MR10 */");
/* MR10 */      _gen("\n");
/* MR10 */    };

            /* Do Attrib / Token ptr */

/* MR10 */  if (! p->label_used_in_semantic_pred) {
/* MR10 */
/* MR10 */      if ( FoundGuessBlk ) {
/* MR10 */        if (! done_NON_GUESSMODE) {
/* MR10 */          done_NON_GUESSMODE=1;
/* MR10 */          if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
/* MR10 */          else {gen("zzNON_GUESS_MODE {\n"); tab();}
/* MR10 */        };
/* MR10 */      };
/* MR10 */
/* MR10 */      if ( GenCC ) {
/* MR10 */        if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {
/* MR10 */          gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
/* MR10 */        } else {
/* MR10 */          gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);
/* MR10 */        };
/* MR10 */      } else {
/* MR10 */        gen1("%s = zzaCur;\n", p->el_label);
/* MR10 */      };
/* MR10 */  };

            /* Do AST ptr */
            if ( GenAST && !(p->astnode == ASTexclude || r->noAST) )
            {

/* MR10 */      if ( FoundGuessBlk ) {
/* MR10 */        if (! done_NON_GUESSMODE) {
/* MR10 */          done_NON_GUESSMODE=1;
/* MR10 */          if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
/* MR10 */          else {gen("zzNON_GUESS_MODE {\n"); tab();}
/* MR10 */        };
/* MR10 */      };

                  if ( GenCC ) {
                        gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
                  }
                  else {gen1("%s_ast = zzastCur;\n", p->el_label);}
            }

/* MR10 */  if (done_NON_GUESSMODE) {
/* MR10 */    gen("}\n"); tab();
/* MR10 */  };

      }

      /* Handle any actions immediately following action */
      if ( a != NULL )  /* MR10 */ /* MR11 */
    {
      /* delay next token fetch until after action */
            _gen("\n");
            if ( a->is_predicate)
            {
            gen("if (!(");
                  /* make sure that '#line n' is on front of line */  /* MR14 */
                  if ( GenLineInfo && p->file != -1 ) _gen("\n");     /* MR14 */
                  dumpPredAction(a,a->action, output, 0, a->file, a->line, 0);
                  if ( a->pred_fail != NULL )
                  {
                        _gen(")) {\n");
/**************   if ( FoundGuessBlk ) gen("zzNON_GUESS_MODE {\n"); *****/
                        tabs++;
/* MR1                                                                                */
/* MR1  10-Apr-97 MR1  Put {...} envelope around failed semantic predicates */
/* MR1                                                                                */
                        gen1("{%s};\n", a->pred_fail);
                        tabs--;
                        gen("}\n");
/**************   if ( FoundGuessBlk ) gen("}\n"); *****/
                  }
/* MR1                                                                            */
/* MR1  10-Apr-97 MR1   Properly stringize failed semantic predicates       */
/* MR1                                                                                    */
                  else
            {
                 _gen1(")) {zzfailed_pred(\"%s\");}\n",              /* MR1 */
                              stringize(a->action));                       /* MR1 */
            }
            }
            else    /* MR9 a regular action - not a predicate action */
            {
                  if ( FoundGuessBlk )
                        if ( GenCC ) {gen("if ( !guessing ) {\n");}
                        else gen("zzNON_GUESS_MODE {\n");
                  dumpAction(a->action, output, tabs, a->file, a->line, 1);
                  if ( FoundGuessBlk ) gen("}\n");
            }
            a->done = 1;
            if ( !DemandLookahead ) {
                  if ( GenCC ) {
                        if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)");
                        _gen(" consume();")
                if ( FoundException && p->use_def_MT_handler )
                    _gen(" _signal=NoSignal;");
                _gen("\n");
                  }
            else
            {
                if ( FoundException && p->use_def_MT_handler ) _gen("if (!_signal)");
                              _gen(" zzCONSUME;\n");
                if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
                _gen("\n");
            }
            }
            else gen("\n");
            TRANS( a->next );
      }
      else
      {
        if ( !DemandLookahead ) {
                  if ( GenCC ) {
                        if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
                        _gen(" consume();")
                        if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;");
                        _gen("\n");
                  }
                  else {
                        if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
                        _gen(" zzCONSUME;");
                        if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
                        _gen("\n");
                  }
            }
            else _gen("\n");
            TRANS(p->next);
      }
}

void
#ifdef __USE_PROTOS
genOptBlk( Junction *q )
#else
genOptBlk( q )
Junction *q;
#endif
{
      int max_k;
      set f;
      int need_right_curly;
      set savetkref;
      savetkref = tokensRefdInBlock;
      require(q!=NULL,                    "genOptBlk: invalid node and/or rule");
      require(q->ntype == nJunction,      "genOptBlk: not junction");
      require(q->jtype == aOptBlk,  "genOptBlk: not optional block");

    OutLineInfo(output,q->line,FileStr[q->file]);

      BLOCK_Preamble(q);
      BlkLevel++;
      f = genBlk(q, aOptBlk, &max_k, &need_right_curly);
      set_free(f);
      freeBlkFsets(q);
      BlkLevel--;
    if ( first_item_is_guess_block((Junction *)q->p1)!=NULL )
      {
            gen("else if ( !zzrv ) zzGUESS_DONE;\n");
      }
      { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
      BLOCK_Tail();
      tokensRefdInBlock = savetkref;
      if (q->end->p1 != NULL) TRANS(q->end->p1);
}

/*
 * Generate code for a loop blk of form:
 *
 *                       |---|
 *                       v   |
 *                   --o-G-o-->o--
 */
void
#ifdef __USE_PROTOS
genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )
#else
genLoopBlk( begin, q, start, max_k )
Junction *begin;
Junction *q;
Junction *start;  /* where to start generating code from */
int max_k;
#endif
{
      set         f;
      int         need_right_curly;
      set         savetkref;
    Junction    *guessBlock;    /* MR10 */
    int         singleAlt;      /* MR10 */

      savetkref = tokensRefdInBlock;
      require(q->ntype == nJunction,      "genLoopBlk: not junction");
      require(q->jtype == aLoopBlk, "genLoopBlk: not loop block");

      if ( q->visited ) return;
      q->visited = TRUE;

    /* first_item_is_guess_block doesn't care what kind of node it is */

    guessBlock=first_item_is_guess_block( (Junction *) q->p1);  /* MR10 */
    singleAlt=q->p2==NULL;                                      /* MR10 */

      if (singleAlt && !guessBlock)     /* MR10 */ /* only one alternative? */
      {
            if ( DemandLookahead )
                  if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
                  else gen1("look(%d);\n", max_k);
            gen("while ( ");
            if ( begin!=NULL ) genExpr(begin);
            else genExpr(q);
            /* if no predicates have been hoisted for this single alt (..)*
             * do so now
             */
        require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
            if ( ParseWithPredicates && begin->predicate==NULL )
            {
                  Predicate *a = MR_find_predicates_and_supp((Node *)q->p1);
            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

                  if ( a!=NULL )
                  {
                        _gen("&&");
                        a=genPredTreeMain(a, (Node *)q);    /* MR10 */
                  }
/* MR10 */  if (MRhoisting) {
/* MR10 */    predicate_free(a);
/* MR10 */  };
            }
            _gen(" ) {\n");
            tabs++;
            TRANS(q->p1);
            if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
            if ( DemandLookahead )
                  if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
                  else gen1("look(%d);\n", max_k);
            --tabs;
            gen("}\n");
            freeBlkFsets(q);
            q->visited = FALSE;
            tokensRefdInBlock = savetkref;
            return;
      }
      gen("for (;;) {\n");        /* MR20 G. Hobbelt */
      tabs++;
/* MR6                                                                  */
/* MR6         "begin" can never be null when called from genLoopBegin  */
/* MR6     because q==(Junction *)begin->p1 and we know q is valid      */
/* MR6                                                                              */
/* MR6         from genLoopBegin:                                                 */
/* MR6                                                                              */
/* MR6             if ( LL_k>1 && !set_nil(q->fset[2]) )                        */
/* MR6               genLoopBlk( q, (Junction *)q->p1, q, max_k );          */
/* MR6            else genLoopBlk( q, (Junction *)q->p1, NULL, max_k ); */
/* MR6                                                                              */
      if ( begin!=NULL )
      {
            if ( DemandLookahead )
            {
                  if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
                  else gen1("look(%d);\n", max_k);
            }
            /* The bypass arc of the (...)* predicts what to do when you fail, but
             * ONLY after having tested the loop start expression.  To avoid this,
             * we simply break out of the (...)* loop when we find something that
             * is not in the prediction of the loop (all alts thereof).
             */
            gen("if ( !(");

/***  TJP says: It used to use the prediction expression for the bypass arc
      of the (...)*.  HOWEVER, if a non LL^1(k) decision was found, this
      thing would miss the ftree stored in the aLoopBegin node and generate
      an LL^1(k) decision anyway.

 ***        genExpr((Junction *)begin->p2);
 ***/

            genExpr((Junction *)begin);
            _gen(")) break;\n");

      }

      /* generate code for terminating loop (this is optional branch) */

      f = genBlk(q, aLoopBlk, &max_k, &need_right_curly);
      set_free(f);
      freeBlkFsets(q);

      /* generate code for terminating loop (this is optional branch) */

/* MR6                                                                                    */
/* MR6  30-May-97 Bug reported by Manuel Ornato                               */
/* MR6            A definite bug involving the exit from a loop block   */
/* MR6              In 1.23 and later versions (including 1.33) Instead       */
/* MR6              exiting the block and reporting a syntax error the  */
/* MR6                code loops forever.                                         */
/* MR6                Looking at 1.20 which generates proper code it is not */
/* MR6                clear which of two changes should be undone.            */
/* MR6              This is my best guess.                                    */
/* MR6              From earlier MR6 note we know that begin can never be     */
/* MR6                null when genLoopBlk called from genLoopBegin           */
/* MR6 */
/* MR6 */ if ( begin==NULL) {
/* MR6 */   /* code for exiting loop "for sure" */
/* MR6 */   gen("/* Suppressed by MR6 */ /*** else break; ***/\n");
/* MR6 */ };

/* MR10 */if (singleAlt && guessBlock) {
/* MR10 */  tabs--;
/* MR6 */   gen("} else break; /* MR6 code for exiting loop \"for sure\" */\n");
/* MR10 */  need_right_curly--;
/* MR10 */ } else {
/* MR6 */   gen("else break; /* MR6 code for exiting loop \"for sure\" */\n");
/* MR10 */ };

      { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
      if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
      --tabs;
      gen("}\n");
      q->visited = FALSE;
      tokensRefdInBlock = savetkref;
}

/*
 * Generate code for a loop blk of form:
 *
 *                               |---|
 *                                 v   |
 *                   --o-->o-->o-G-o-->o--
 *                   |           ^
 *                   v           |
 *                             o-----------o
 *
 * q->end points to the last node (far right) in the blk.
 *
 * Note that q->end->jtype must be 'EndBlk'.
 *
 * Generate code roughly of the following form:
 *
 *    do {
 *          ... code for alternatives ...
 *  } while ( First Set of aLoopBlk );
 *
 *    OR if > 1 alternative
 *
 *    do {
 *          ... code for alternatives ...
 *          else break;
 *  } while ( 1 );
 */
void
#ifdef __USE_PROTOS
genLoopBegin( Junction *q )
#else
genLoopBegin( q )
Junction *q;
#endif
{
      set f;
      int i;
      int max_k;
      set savetkref;
      savetkref = tokensRefdInBlock;
      require(q!=NULL,                    "genLoopBegin: invalid node and/or rule");
      require(q->ntype == nJunction,      "genLoopBegin: not junction");
      require(q->jtype == aLoopBegin,     "genLoopBegin: not loop block");
      require(q->p2!=NULL,                "genLoopBegin: invalid Loop Graph");

    OutLineInfo(output,q->line,FileStr[q->file]);

      BLOCK_Preamble(q);
      BlkLevel++;
      f = First(q, 1, aLoopBegin, &max_k);
      /* If not simple LL(1), must specify to start at LoopBegin, not LoopBlk */
      if ( LL_k>1 && !set_nil(q->fset[2]) )
            genLoopBlk( q, (Junction *)q->p1, q, max_k );
      else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );

      for (i=1; i<=CLL_k; i++) set_free(q->fset[i]);
      for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]);
      --BlkLevel;
      BLOCK_Tail();
      set_free(f);
      tokensRefdInBlock = savetkref;
      if (q->end->p1 != NULL) TRANS(q->end->p1);
}

/*
 * Generate code for a loop blk of form:
 *
 *                             |---|
 *                             v   |
 *                       --o-G-o-->o--
 *
 * q->end points to the last node (far right) in the blk.
 * Note that q->end->jtype must be 'EndBlk'.
 *
 * Generate code roughly of the following form:
 *
 *    do {
 *          ... code for alternatives ...
 *  } while ( First Set of aPlusBlk );
 *
 *    OR if > 1 alternative
 *
 *    do {
 *          ... code for alternatives ...
 *          else if not 1st time through, break;
 *  } while ( 1 );
 */
void
#ifdef __USE_PROTOS
genPlusBlk( Junction *q )
#else
genPlusBlk( q )
Junction *q;
#endif
{
      int         max_k;
      set         f;
      int         need_right_curly;
      set         savetkref;
    Junction    *guessBlock;    /* MR10 */
    int         singleAlt;      /* MR10 */

      savetkref = tokensRefdInBlock;
      require(q!=NULL,                    "genPlusBlk: invalid node and/or rule");
      require(q->ntype == nJunction,      "genPlusBlk: not junction");
      require(q->jtype == aPlusBlk, "genPlusBlk: not Plus block");
      require(q->p2 != NULL,              "genPlusBlk: not a valid Plus block");

      if ( q->visited ) return;
      q->visited = TRUE;
    OutLineInfo(output,q->line,FileStr[q->file]);
      BLOCK_Preamble(q);
      BlkLevel++;

    /* first_item_is_guess_block  doesn't care what kind of node it is */

    guessBlock=first_item_is_guess_block( (Junction *)q->p1);   /* MR10 */

      /* if the ignore flag is set on the 2nd alt and that alt is empty,
       * then it is the implied optional alternative that we added for (...)+
       * and, hence, only 1 alt.
       */

/* MR10  Reported by Pulkkinen Esa (esap@cs.tut.fi)
 *       Outer code for guess blocks ignored when there is only one alt
 *         for a (...)+ block.
 *       Force use of regular code rather than "optimized" code for that case
 */

    singleAlt=( ( (Junction *) q->p2)->p2 == NULL) &&
              ( ( (Junction *) q->p2)->ignore );                  /* only one alternative? */

    if (singleAlt && !guessBlock)   /* MR10 */
      {

            Predicate *a=NULL;
            /* if the only alt has a semantic predicate, hoist it; must test before
             * entering loop.
             */
            if ( ParseWithPredicates )
            {
            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
                  a = MR_find_predicates_and_supp((Node *)q);
            require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");

                  if ( a!=NULL ) {
                        gen("if (");
                        a=genPredTreeMain(a, (Node *)q);    /* MR10 */
                        _gen(") {\n");
                  }
            }
            gen("do {\n");
            tabs++;
            TRANS(q->p1);
            if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
            f = First(q, 1, aPlusBlk, &max_k);
            if ( DemandLookahead )
                  if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
                  else gen1("look(%d);\n", max_k);
            --tabs;
            gen("} while ( ");
            if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);
            genExpr(q);
            if ( ParseWithPredicates && a!=NULL )
            {
            if (! MR_comparePredicates(q->predicate,a)) {
                  _gen("&&");
                  a=genPredTreeMain(a, (Node *)q);    /* MR10 */
            };
            }
            _gen(" );\n");
            if ( ParseWithPredicates && a!=NULL ) gen("}\n");
            --BlkLevel;
            BLOCK_Tail();
            q->visited = FALSE;
            freeBlkFsets(q);
            set_free(f);
            tokensRefdInBlock = savetkref;
            if (q->end->p1 != NULL) TRANS(q->end->p1);
/* MR10 */  if (MRhoisting) {
/* MR10 */    predicate_free(a);
/* MR10 */  };
            return;
      }
      gen("do {\n");
      tabs++;
      f = genBlk(q, aPlusBlk, &max_k, &need_right_curly);
/* MR6                                                                          */
/* MR6      Sinan Karasu      (sinan@tardis.ds.boeing.com)              */
/* MR6    Failed to turn off guess mode when leaving block        */
/* MR6                                                                              */
/* MR6  */ if ( has_guess_block_as_last_item(q) ) {
/* MR10 */   gen("/* MR10 ()+ */ else {\n");
/* MR10 */   tabs++;
/* MR10 */   need_right_curly++;
/* MR10 */   gen("/* MR10 ()+ */ if ( !zzrv ) zzGUESS_DONE;\n");
/* MR6  */   gen("/* MR10 ()+ */ if ( zzcnt > 1 ) break;\n");
/* MR10 */ } else {
/* MR10 */   gen("/* MR10 ()+ */ else {\n");
/* MR10 */   tabs++;
/* MR10 */   need_right_curly++;
/* MR10 */   gen("if ( zzcnt > 1 ) break;\n");
/* MR10 */ };

      tab();
      makeErrorClause(q,f,max_k);
      { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
      freeBlkFsets(q);
      gen("zzcnt++;");
      if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);
      _gen("\n");
      if ( DemandLookahead )
            if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
            else gen1("look(%d);\n", max_k);
      --tabs;
      if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}
      else gen("} while ( 1 );\n");
      --BlkLevel;
      BLOCK_Tail();
      q->visited = FALSE;
      tokensRefdInBlock = savetkref;
      if (q->end->p1 != NULL) TRANS(q->end->p1);
}

/*
 * Generate code for a sub blk of alternatives of form:
 *
 *                       --o-G1--o--
 *                             |     ^
 *                             v    /|
 *                         o-G2-o|
 *                             |     ^
 *                             v     |
 *                         ..........
 *                             |     ^
 *                             v    /
 *                         o-Gn-o
 *
 * q points to the 1st junction of blk (upper-left).
 * q->end points to the last node (far right) in the blk.
 * Note that q->end->jtype must be 'EndBlk'.
 * The last node in every alt points to q->end.
 *
 * Generate code of the following form:
 *    if ( First(G1) ) {
 *          ...code for G1...
 *    }
 *    else if ( First(G2) ) {
 *          ...code for G2...
 *    }
 *    ...
 *    else {
 *          ...code for Gn...
 *    }
 */
void
#ifdef __USE_PROTOS
genSubBlk( Junction *q )
#else
genSubBlk( q )
Junction *q;
#endif
{
      int max_k;
      set f;
      int need_right_curly;
      set savetkref;
      savetkref = tokensRefdInBlock;
      require(q->ntype == nJunction,      "genSubBlk: not junction");
      require(q->jtype == aSubBlk,  "genSubBlk: not subblock");

    OutLineInfo(output,q->line,FileStr[q->file]);
      BLOCK_Preamble(q);
      BlkLevel++;
      f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
      if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
      { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
      freeBlkFsets(q);
      --BlkLevel;
      BLOCK_Tail();

      if ( q->guess )
      {
            gen("zzGUESS_DONE\n");
      }

      /* must duplicate if (alpha)?; one guesses (validates), the
       * second pass matches */
      if ( q->guess && analysis_point(q)==q )
      {
        OutLineInfo(output,q->line,FileStr[q->file]);
            BLOCK_Preamble(q);
            BlkLevel++;
            f = genBlk(q, aSubBlk, &max_k, &need_right_curly);
            if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);}
            { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
            freeBlkFsets(q);
            --BlkLevel;
            BLOCK_Tail();
      }

      tokensRefdInBlock = savetkref;
      if (q->end->p1 != NULL) TRANS(q->end->p1);
}

static int TnodesAllocatedPrevRule=0;

/*
 * Generate code for a rule.
 *
 *          rule--> o-->o-Alternatives-o-->o
 * Or,
 *          rule--> o-->o-Alternative-o-->o
 *
 * The 1st junction is a RuleBlk.  The second can be a SubBlk or just a junction
 * (one alternative--no block), the last is EndRule.
 * The second to last is EndBlk if more than one alternative exists in the rule.
 *
 * To get to the init-action for a rule, we must bypass the RuleBlk,
 * and possible SubBlk.
 * Mark any init-action as generated so genBlk() does not regenerate it.
 */
void
#ifdef __USE_PROTOS
genRule( Junction *q )
#else
genRule( q )
Junction *q;
#endif
{


do {    /* MR10     Change recursion into iteration         */

      int max_k;
      set follow, rk, f;
      ActionNode *a;
      RuleEntry *r;
      static int file = -1;
      int need_right_curly;
      require(q->ntype == nJunction,      "genRule: not junction");
      require(q->jtype == RuleBlk,  "genRule: not rule");

/* MR14 */    require (MR_BackTraceStack.count == 0,"-alpha MR_BackTraceStack.count != 0");
/* MR14 */    MR_pointerStackReset(&MR_BackTraceStack);
/* MR14 */    if (AlphaBetaTrace) MR_MaintainBackTrace=1;

    CurRule=q->rname;                               /* MR11 */

      r = (RuleEntry *) hash_get(Rname, q->rname);
      if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief");
      if ( q->file != file )        /* open new output file if need to */
      {
/* MR6                                                                  */
/* MR6  Simpler to debug when output goes to stdout rather than a file  */
/* MR6                                                                  */
/* MR6 */   if (UseStdout) {
/* MR6 */     output = stdout;
/* MR6 */   } else {
/* MR6 */     if ( output != NULL) fclose( output );
/* MR6 */     output = fopen(OutMetaName(outname(FileStr[q->file])), "w");
/* MR6 */   };
            require(output != NULL, "genRule: can't open output file");

#ifdef SPECIAL_FOPEN
       special_fopen_actions(OutMetaName(outname(FileStr[q->file]))); /* MR1 */
#endif
            if ( file == -1 ) genHdr1(q->file);
            else genHdr(q->file);
            file = q->file;
      }

    if (InfoM) {
      fprintf(stderr,"    rule %s\n",q->rname);
      fflush(output);
    };

#if 0
    if (strcmp(q->rname,"***debug***") == 0) {
      fprintf(stderr,"***debug*** %s reached\n",q->rname);
      MR_break();
    };
#endif

      DumpFuncHeader(q,r);
      tabs++;
      if ( q->ret!=NULL )
      {
            /* Declare the return value - and PURIFY it -ATG 6/5/95 */

/* MR7      Moved PURIFY() to after all local variables have been declared */
/* MR7      so that the generated code is valid C as well as C++           */
/* MR7        Jan Mikkelsen 10-June-1997                                   */

            if ( HasComma(q->ret) )
            {
                  gen1("struct _rv%d _retv;\n",r->rulenum);
            }
            else
            {
                  tab();
                  DumpType(q->ret, output);

/* MR3  17-May-97  Undo change since _retv is of unpredictable type        */
/* MR3               If an object it may not be possible to assign 0 or NULL     */
/* MR3               Reported by Cortland Starrett (cort@shay.ecn.purdue.edu     */
/* MR1  10-Apr-97  Get rid of annoying Possibly ref'd before use msgs      */

                  gen(" _retv;\n");                   /* MR1 MR3         */
            }
      }

    OutLineInfo(output,q->line,FileStr[q->file]);

    if (InfoM) {
      fflush(output);
    };

      gen("zzRULE;\n");
      if ( FoundException )
      {
            gen("int _sva=1;\n");
      }
      if ( GenCC && GenAST )
            gen("ASTBase *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n");
      if ( GenCC ) genTokenPointers(q);
      if ( GenCC&&GenAST ) genASTPointers(q);
      if ( q->el_labels!=NULL ) genElementLabels(q->el_labels);
      if ( FoundException ) gen("int _signal=NoSignal;\n");

      if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);

/* MR10 */  /* move zzTRACEIN to before init action */

/* MR10 */  if ( TraceGen )
/* MR10 */        if ( GenCC ) {gen1("zzTRACEIN(\"%s\");\n", q->rname);}
/* MR10 */        else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);

/* MR7      Moved PURIFY() to after all local variables have been declared */
/* MR7      so that the generated code is valid C as well as C++           */
/* MR7        Jan Mikkelsen 10-June-1997                                   */

      if ( q->ret != NULL )                                            /* MR7 */
      {                                                                /* MR7 */
            if ( HasComma(q->ret) )                                      /* MR7 */
            {                                                            /* MR7 */
                  gen1("PURIFY(_retv,sizeof(struct _rv%d))\n",r->rulenum); /* MR7 */
            }                                                            /* MR7 */
            else                                                         /* MR7 */
            {                                                            /* MR7 */
                  gen("PURIFY(_retv,sizeof(");                             /* MR7 */
                  DumpType(q->ret, output);                                /* MR7 */
                  gen("))\n");                                             /* MR7 */
            }                                                            /* MR7 */
      }                                                                /* MR7 */
      if ( !GenCC ) gen("zzMake0;\n");
      if ( FoundException ) gen("*_retsignal = NoSignal;\n");

      if ( !GenCC ) gen("{\n");

      if ( has_guess_block_as_first_item((Junction *)q->p1) )
      {
            gen("zzGUESS_BLOCK\n");
      }

      /* L o o k  F o r  I n i t  A c t i o n */
      if ( ((Junction *)q->p1)->jtype == aSubBlk )
            a = findImmedAction( ((Junction *)q->p1)->p1 );
      else
            a = findImmedAction( q->p1 ); /* only one alternative in rule */
      if ( a!=NULL && !a->is_predicate)
      {
            if (!a->noHoist) dumpAction(a->action, output, tabs, a->file, a->line, 1);
            a->done = 1;      /* ignore action. We have already handled it */
      }

      BlkLevel++;
      q->visited = TRUE;                        /* mark RULE as visited for FIRST/FOLLOW */
      f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly);
      if ( q->p1 != NULL )
            if ( ((Junction *)q->p1)->p2 != NULL )
                  {tab(); makeErrorClause((Junction *)q->p1,f,max_k);}
      { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
      freeBlkFsets((Junction *)q->p1);
      q->visited = FALSE;
      --BlkLevel;
      if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);

    genTraceOut(q);

      if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n");
      /* E r r o r  R e c o v e r y */
      NewSet();
      rk = empty;

/* MR14 */    if (r->dontComputeErrorSet) {
/* MR14 */      follow=empty;
              } else {
                MR_pointerStackReset(&MR_BackTraceStack);   /* MR14 */
                MR_ErrorSetComputationActive=1;
                REACH(q->end, 1, &rk, follow);
                MR_ErrorSetComputationActive=0;
                require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0");
              }

  FillSet( follow );
      set_free( follow );

  /* MR20 G. Hobbelt 
     Isn't it so that "fail:" is ONLY referenced when:

             !FoundException || FoundGuessBlk ?

     Therefore add the "if" around this piece of code generation...

     Should guessing mode also use _handler label instead of "fail"
     when exception handling is active? gen can automatically put 
     "if (guessing)" there so as to skip all kinds of user code.

   */

      if ( !FoundException || FoundGuessBlk )  /* MR20 G. Hobbelt */
  {                                          /* MR20 G. Hobbelt */
      _gen("fail:\n");
      if ( !GenCC ) gen("zzEXIT(zztasp1);\n");
      if ( FoundGuessBlk )
            if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");}
            else gen("if ( guessing ) zzGUESS_FAIL;\n");
      if ( q->erraction!=NULL )
            dumpAction(q->erraction, output, tabs, q->file, q->line, 1);
      if ( GenCC )
      {
            gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",
                   r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
      }
      else
      {
            gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",
                   r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
      }
      gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);

      if ( q->ret!=NULL ) {
      genTraceOut(q);
      gen("return _retv;\n");
    } else if ( q->exceptions!=NULL ) {
      genTraceOut(q);
      gen("return;\n");
    } else if (!FoundException) {       /* MR10 */
      genTraceOut(q);                   /* MR10 */
    };

  }                                        /* MR20 G. Hobbelt */

      if ( !GenCC ) gen("}\n");

      /* Gen code for exception handlers */
    /* make sure each path out contains genTraceOut() */

      if ( q->exceptions!=NULL )
      {

            gen("/* exception handlers */\n");

            dumpExceptions(q->exceptions);

        if ( !r->has_rule_exception )
        {
            _gen("_handler:\n");
            gen("zzdflthandlers(_signal,_retsignal);\n");
        }
/*  MR20 G. Gobbelt   The label "adios" is never referenced */

#if 0
      _gen("_adios:\n");
#endif
    if ( q->ret!=NULL ) {
            genTraceOut(q);
            gen("return _retv;\n");
        }
            else {
            genTraceOut(q);
            gen("return;\n");
        }
      }
      else if ( FoundException )
      {
      _gen("_handler:\n");
      gen("zzdflthandlers(_signal,_retsignal);\n");

/* MR1                                                                      */
/* MR1       7-Apr-97 Fix suggested by: John Bair (jbair@iftime.com)            */
/* MR1                                                                                      */

        if ( q->ret != NULL) {                                               /* MR1 */
            genTraceOut(q);                                          /* MR10 */
            gen("return _retv;\n");                                      /* MR1 */
      } else {                                                                 /* MR1 */
            genTraceOut(q);                                          /* MR10 */
            gen("return;\n")    ;                                          /* MR1 */
      };                                                                       /* MR1 */
      }

      tabs--;
      gen("}\n");

/* MR10     Tired of looking at stacks that are as deep as the number of    */
/* MR10       rules.  Changes recursion to iteration.                       */

    MR_releaseResourcesUsedInRule( (Node *) q );      /* MR10 */

    if (InfoT) {
      fprintf(output,"\n/* tnodes created for rule %s:  %d */\n",
                q->rname, (TnodesAllocated-TnodesAllocatedPrevRule) );
    };

    TnodesAllocatedPrevRule=TnodesAllocated;

    if (q->p2 == NULL) dumpAfterActions( output );
    q=(Junction *)q->p2;
    require(q==NULL || q->jtype==RuleBlk,"RuleBlk p2 does not point to another RuleBlk");

} while (q != NULL);

/**** The old code                           ****/
/**** if ( q->p2 != NULL ) {TRANS(q->p2);} ****/ /* generate code for next rule too */
/**** else dumpAfterActions( output );     ****/

}

static void
#ifdef __USE_PROTOS
DumpFuncHeader( Junction *q, RuleEntry *r )
#else
DumpFuncHeader( q, r )
Junction *q;
RuleEntry *r;
#endif
{
/*                                                                                          */
/*  MR1 10-Apr-97  MR1  Simplify insertion of commas in function header     */
/*                                                                                          */
      int   needComma;                                                           /* MR1 */

      /* A N S I */
      _gen("\n");
      if ( q->ret!=NULL )
      {
            if ( HasComma(q->ret) )
            {
                  if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum)
                  else gen1("struct _rv%d\n",r->rulenum);
            }
            else
            {
                  DumpType(q->ret, output);
                  gen("\n");
            }
      }
      else
      {
            _gen("void\n");
      }
/*  MR1                                                                             */
/*  MR1     10-Apr-97  133MR1 Replace __STDC__ with __USE_PROTOS              */
/*  MR1                                                                                       */
      if ( !GenCC ) _gen("#ifdef __USE_PROTOS\n");               /* MR1 */
      if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname)
      else gen3("%s::%s%s(", CurrentClassName, RulePrefix,q->rname);
      DumpANSIFunctionArgDef(output,q);
      _gen("\n");

      if ( GenCC ) {
      gen("{\n");
      return;
    }

      /* K & R */
      gen("#else\n");
      gen2("%s%s(", RulePrefix, q->rname);
      needComma=0;                                                                 /* MR1 */
      if ( GenAST )                                                                /* MR1 */
      {                                                                              /* MR1 */
            _gen("_root");                                                         /* MR1 */
            needComma=1;                                                           /* MR1 */
      }                                                                              /* MR1 */
      if ( FoundException )                                                    /* MR1 */
      {                                                                              /* MR1 */
            if (needComma) {_gen(",");needComma=0;};                   /* MR1 */
            _gen("_retsignal");                                                    /* MR1 */
            needComma=1;                                                           /* MR1 */
      }                                                                              /* MR1 */
/* MR5      Change below by Jan Mikkelsen (janm@zeta.org.au) 26-May-97      MR5 */
      DumpListOfParmNames( q->pdecl, output, needComma );                /* MR5 */
      gen(")\n");
      if ( GenAST ) gen("AST **_root;\n");
      if ( FoundException ) gen("int *_retsignal;\n");
      DumpOldStyleParms( q->pdecl, output );
      gen("#endif\n");
    gen("{\n");
}

void
#ifdef __USE_PROTOS
DumpANSIFunctionArgDef(FILE *f, Junction *q)
#else
DumpANSIFunctionArgDef(f,q)
FILE *f;
Junction *q;
#endif
{
      if ( GenAST )
      {
            if ( GenCC ) {fprintf(f,"ASTBase **_root");}
            else fprintf(f,"AST**_root");
            if ( !FoundException && q->pdecl!=NULL ) fprintf(f,",");
      }
      if ( FoundException )
      {
            if ( GenAST ) fprintf(f,",");
            fprintf(f,"int *_retsignal");
            if ( q->pdecl!=NULL ) fprintf(f,",");
      }
      if ( q->pdecl!=NULL ) {fprintf(f,"%s", q->pdecl);}
      else if ( !GenAST && !FoundException ) fprintf(f,"void");
      fprintf(f,")");
}

void
#ifdef __USE_PROTOS
genJunction( Junction *q )
#else
genJunction( q )
Junction *q;
#endif
{
      require(q->ntype == nJunction,      "genJunction: not junction");
      require(q->jtype == Generic,  "genJunction: not generic junction");

      if ( q->p1 != NULL ) TRANS(q->p1);
      if ( q->p2 != NULL ) TRANS(q->p2);
}

void
#ifdef __USE_PROTOS
genEndBlk( Junction *q )
#else
genEndBlk( q )
Junction *q;
#endif
{
}

void
#ifdef __USE_PROTOS
genEndRule( Junction *q )
#else
genEndRule( q )
Junction *q;
#endif
{
}

void
#ifdef __USE_PROTOS
genHdr( int file )
#else
genHdr( file )
int file;
#endif
{
    int     i;

      _gen("/*\n");
      _gen(" * A n t l r  T r a n s l a t i o n  H e a d e r\n");
      _gen(" *\n");
      _gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-1999\n");
      _gen(" * Purdue University Electrical Engineering\n");
      _gen(" * With AHPCRC, University of Minnesota\n");
      _gen1(" * ANTLR Version %s\n", Version);
      _gen(" *\n");
/* MR10 */    _gen(" *  ");
/* MR10 */    for (i=0 ; i < Save_argc ; i++) {
/* MR10 */      _gen(" ");
/* MR10 */      _gen(Save_argv[i]);
/* MR10 */    };
      _gen("\n");
      _gen(" *\n");
    _gen(" */\n\n");
      if (FirstAction != NULL ) dumpAction( FirstAction, output, 0, -1, 0, 1);    /* MR11 MR15b */
      _gen1("#define ANTLR_VERSION  %s\n", VersionDef);
      _gen("#include \"pcctscfg.h\"\n");
      _gen("#include \"pccts_stdio.h\"\n");
      if ( strcmp(ParserName, DefaultParserName)!=0 )
            _gen2("#define %s %s\n", DefaultParserName, ParserName);
      if ( strcmp(ParserName, DefaultParserName)!=0 )
            {_gen1("#include \"%s\"\n", RemapFileName);}
    OutLineInfo(output,1,FileStr[file]);
      if ( GenCC ) {
            if ( UserTokenDefsFile != NULL )
                  fprintf(output, "#include %s\n", UserTokenDefsFile);
            else
                  fprintf(output, "#include \"%s\"\n", DefFileName);
      }

      if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);
      if ( !GenCC && FoundGuessBlk )
      {
            _gen("#define ZZCAN_GUESS\n");
            _gen("#include \"pccts_setjmp.h\"\n");  /* MR15 K.J. Cummings (cummings@peritus.com) */
      }
      if ( FoundException )
      {
            _gen("#define EXCEPTION_HANDLING\n");
            _gen1("#define NUM_SIGNALS %d\n", NumSignals);
      }
      if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);
      if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");
      if ( GenAST ) {
            if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);}
            else _gen("#include \"ast.h\"\n\n");
      }
      if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");
#ifdef DUM
      if ( !GenCC && LexGen ) {
            _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
      }
#endif
      /* ###WARNING: This will have to change when SetWordSize changes */
      if ( !GenCC ) _gen1("#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
    if (TraceGen) {
      _gen("#ifndef zzTRACE_RULES\n");  /* MR20 */
      _gen("#define zzTRACE_RULES\n");  /* MR20 */
      // zzTRACE_RULES removed from #endif by TL because it causes
      // a warning under GCC 3.0.2
      // _gen("#endif  zzTRACE_RULES\n");  /* MR20 */
      _gen("#endif\n");  /* MR20 */
    };
      if ( !GenCC ) {_gen("#include \"antlr.h\"\n");}
      else {
            _gen1("#include \"%s\"\n", APARSER_H);
            _gen1("#include \"%s.h\"\n", CurrentClassName);
      }
      if ( !GenCC ) {
            if ( UserDefdTokens )
                  {_gen1("#include %s\n", UserTokenDefsFile);}
            /* still need this one as it has the func prototypes */
            _gen1("#include \"%s\"\n", DefFileName);
      }
      /* still need this one as it defines the DLG interface */
      if ( !GenCC ) _gen("#include \"dlgdef.h\"\n");
      if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H);
      if ( GenCC ) _gen1("#include \"%s\"\n", ATOKPTR_H);
      if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName);

/* MR10  Ofer Ben-Ami (gremlin@cs.huji.ac.il)           */
/* MR10    Finally, a definition of the Purify macro    */

      _gen("#ifndef PURIFY\n");
    _gen("#define PURIFY(r,s) memset((char *) &(r),'\\0',(s));\n");
    _gen("#endif\n");
}

void
#ifdef __USE_PROTOS
genHdr1( int file )
#else
genHdr1( file )
int file;
#endif
{
      ListNode *p;

      genHdr(file);
      if ( GenAST )
      {
            if ( !GenCC ) {
                  _gen("#include \"ast.c\"\n");
                  _gen("zzASTgvars\n\n");
            }
      }
      if ( !GenCC ) _gen("ANTLR_INFO\n");
      if ( BeforeActions != NULL )
      {
            for (p = BeforeActions->next; p!=NULL; p=p->next)
            {
                  UserAction *ua = (UserAction *)p->elem;
                  dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
            }
      }

      if ( !FoundException ) return;

      if ( GenCC )
      {
            _gen1("\nvoid %s::\n", CurrentClassName);
            _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
            _gen("{\n");
      }
      else
      {
            _gen("\nvoid\n");
/*  MR1                                                                               */
/*  MR1     10-Apr-97  133MR1 Replace __STDC__ with __USE_PROTOS              */
/*  MR1                                                                         */
          _gen("#ifdef __USE_PROTOS\n");                               /* MR1 */
            _gen("zzdflthandlers( int _signal, int *_retsignal )\n");
            _gen("#else\n");
            _gen("zzdflthandlers( _signal, _retsignal )\n");
            _gen("int _signal;\n");
            _gen("int *_retsignal;\n");
            _gen("#endif\n");
            _gen("{\n");
      }
      tabs++;
      if ( DefaultExGroup!=NULL )
      {
            dumpException(DefaultExGroup, 1);
            if ( !hasDefaultException(DefaultExGroup) )
            {
                  gen("default :\n");
                  tabs++;
                  gen("*_retsignal = _signal;\n");
                  tabs--;
                  gen("}\n");
            }
      }
      else {
            gen("*_retsignal = _signal;\n");
      }

      tabs--;
      _gen("}\n\n");
}

void
#ifdef __USE_PROTOS
genStdPCCTSIncludeFile( FILE *f,char *gate )    /* MR10 */
#else
genStdPCCTSIncludeFile( f , gate)               /* MR10 */
FILE *f;
char * gate;                                    /* MR10 */
#endif
{
/* MR10 Ramanathan Santhanam (ps@kumaran.com)           */
/* MR10 Same preprocessor symbol use to gate stdpccts.h */
/* MR10   even when two grammars are in use.            */
/* MR10 Derive gate symbol from -fh filename            */

    if (gate == NULL) {
      fprintf(f,"#ifndef STDPCCTS_H\n");          /* MR10 */
      fprintf(f,"#define STDPCCTS_H\n");          /* MR10 */
    } else {
      fprintf(f,"#ifndef STDPCCTS_%s_H\n",gate);  /* MR10 */
      fprintf(f,"#define STDPCCTS_%s_H\n",gate);  /* MR10 */
    };
      fprintf(f,"/*\n");
    if (gate == NULL) {
        fprintf(f," * %s -- P C C T S  I n c l u d e\n", stdpccts);
    } else {
        fprintf(f," * Standard PCCTS include file with -fh %s -- P C C T S  I n c l u d e\n", stdpccts);
    }
      fprintf(f," *\n");
      fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-1999\n");
      fprintf(f," * Purdue University Electrical Engineering\n");
      fprintf(f," * With AHPCRC, University of Minnesota\n");
      fprintf(f," * ANTLR Version %s\n", Version);
      fprintf(f," */\n\n");

    fprintf(f,"#ifndef ANTLR_VERSION\n");
      fprintf(f,"#define ANTLR_VERSION    %s\n", VersionDef);
    fprintf(f,"#endif\n\n");

    if (FirstAction != NULL ) dumpAction(FirstAction, f, 0, -1, 0, 1);  /* MR11 */

      fprintf(f,"#include \"pcctscfg.h\"\n");
      fprintf(f,"#include \"pccts_stdio.h\"\n");
      if ( GenCC )
      {
            if ( UserDefdTokens )
                  fprintf(f, "#include %s\n", UserTokenDefsFile);
            else {
                  fprintf(f, "#include \"%s\"\n", DefFileName);
            }

            fprintf(f, "#include \"%s\"\n", ATOKEN_H);

            if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);

            fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H);

            if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);
            if ( GenAST ) {
                  fprintf(f, "#include \"%s\"\n", ASTBASE_H);
            }

        if (TraceGen) {
          fprintf(f,"#ifndef zzTRACE_RULES\n");  /* MR20 */
          fprintf(f,"#define zzTRACE_RULES\n");  /* MR20 */
          // zzTRACE_RULES removed from #endif by TL because it causes
          // a warning under GCC 3.0.2
          // fprintf(f,"#endif  zzTRACE_RULES\n");  /* MR20 */
          fprintf(f,"#endif\n");  /* MR20 */
        };

            fprintf(f,"#include \"%s\"\n", APARSER_H);
            fprintf(f,"#include \"%s.h\"\n", CurrentClassName);
            if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H);
            fprintf(f, "#endif\n");
            return;
      }

      if ( strcmp(ParserName, DefaultParserName)!=0 )
            fprintf(f, "#define %s %s\n", DefaultParserName, ParserName);
      if ( strcmp(ParserName, DefaultParserName)!=0 )
            fprintf(f, "#include \"%s\"\n", RemapFileName);
      if ( UserTokenDefsFile != NULL )
         fprintf(f, "#include %s\n", UserTokenDefsFile);
      if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
      if ( FoundGuessBlk )
      {
            fprintf(f,"#define ZZCAN_GUESS\n");
            fprintf(f,"#include \"pccts_setjmp.h\"\n");
      }
    if (TraceGen) {
      fprintf(f,"#ifndef zzTRACE_RULES\n");  /* MR20 */
      fprintf(f,"#define zzTRACE_RULES\n");  /* MR20 */
      // zzTRACE_RULES removed from #endif by TL because it causes
      // a warning under GCC 3.0.2
      // fprintf(f,"#endif  zzTRACE_RULES\n");  /* MR20 */
      fprintf(f,"#endif\n");  /* MR20 */
    };
      if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k);
      if ( GenAST ) fprintf(f,"#define GENAST\n");
      if ( FoundException )
      {
/* MR1       7-Apr-97  1.33MR1                                                         */
/* MR1               Fix suggested by:                                         */
/* MR1               Francois-Xavier Fontaine (fontaine_f@istvax.ist.lu)         */

            fprintf(f,"#define EXCEPTION_HANDLING\n");                  /* MR1 */
            fprintf(f,"#define NUM_SIGNALS %d\n", NumSignals);          /* MR1 */
      }
      if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");
#ifdef DUM
      if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
#endif
      /* ###WARNING: This will have to change when SetWordSize changes */
      fprintf(f, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
    if (TraceGen) {
      fprintf(f,"#ifndef zzTRACE_RULES\n");  /* MR20 */
      fprintf(f,"#define zzTRACE_RULES\n");  /* MR20 */
      // zzTRACE_RULES removed from #endif by TL because it causes
      // a warning under GCC 3.0.2
      // fprintf(f,"#endif  zzTRACE_RULES\n");  /* MR20 */
      fprintf(f,"#endif\n");  /* MR20 */
    };
      fprintf(f,"#include \"antlr.h\"\n");
      if ( GenAST ) fprintf(f,"#include \"ast.h\"\n");
      if ( UserDefdTokens )
            fprintf(f, "#include %s\n", UserTokenDefsFile);
      /* still need this one as it has the func prototypes */
      fprintf(f, "#include \"%s\"\n", DefFileName);
      /* still need this one as it defines the DLG interface */
      fprintf(f,"#include \"dlgdef.h\"\n");
      /* don't need this one unless DLG is used */
      if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName);
      fprintf(f,"#endif\n");
}

/* dump action 's' to file 'output' starting at "local" tab 'tabs'
   Dump line information in front of action if GenLineInfo is set
   If file == -1 then GenLineInfo is ignored.
   The user may redefine the LineInfoFormatStr to his/her liking
   most compilers will like the default, however.

   June '93; changed so that empty lines are left alone so that
   line information is correct for the compiler/debuggers.
*/
void
#ifdef __USE_PROTOS
dumpAction( char *s, FILE *output, int tabs, int file, int line,
int final_newline )
#else
dumpAction( s, output, tabs, file, line, final_newline )
char *s;
FILE *output;
int tabs;
int file;
int line;
int final_newline;
#endif
{
    int inDQuote, inSQuote;
    require(s!=NULL,          "dumpAction: NULL action");
    require(output!=NULL,     eMsg1("dumpAction: output FILE is NULL for %s",s));

      if ( GenLineInfo && file != -1 )
      {
        OutLineInfo(output,line,FileStr[file]);
      }
    PastWhiteSpace( s );
      /* don't print a tab if first non-white char is a # (preprocessor command) */
      if ( *s!='#' ) {TAB;}
    inDQuote = inSQuote = FALSE;
    while ( *s != '\0' )
    {
        if ( *s == '\\' )
        {
            fputc( *s++, output ); /* Avoid '"' Case */
            if ( *s == '\0' ) return;
            if ( *s == '\'' ) fputc( *s++, output );
            if ( *s == '\"' ) fputc( *s++, output );
        }
        if ( *s == '\'' )
        {
            if ( !inDQuote ) inSQuote = !inSQuote;
        }
        if ( *s == '"' )
        {
            if ( !inSQuote ) inDQuote = !inDQuote;
        }
        if ( *s == '\n' )
        {
            fputc('\n', output);
                  s++;
            PastWhiteSpace( s );
            if ( *s == '}' )
            {
                --tabs;
                        TAB;
                fputc( *s++, output );
                continue;
            }
            if ( *s == '\0' ) return;
                  if ( *s != '#' )  /* #define, #endif etc.. start at col 1 */
            {
                        TAB;
                  }
        }
        if ( *s == '}' && !(inSQuote || inDQuote) )
        {
            --tabs;            /* Indent one fewer */
        }
        if ( *s == '{' && !(inSQuote || inDQuote) )
        {
            tabs++;            /* Indent one more */
        }
        fputc( *s, output );
        s++;
    }
    if ( final_newline ) fputc('\n', output);
}

static void
#ifdef __USE_PROTOS
dumpAfterActions( FILE *output )
#else
dumpAfterActions( output )
FILE *output;
#endif
{
      ListNode *p;
      require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");
      if ( AfterActions != NULL )
      {
            for (p = AfterActions->next; p!=NULL; p=p->next)
            {
                  UserAction *ua = (UserAction *)p->elem;
                  dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
            }
      }
      fclose( output );
}

/*
 * Find the next action in the stream of execution.  Do not pass
 * junctions with more than one path leaving them.
 * Only pass generic junctions.
 *
 *    Scan forward while (generic junction with p2==NULL)
 *    If we stop on an action, return ptr to the action
 *    else return NULL;
 */
static ActionNode *
#ifdef __USE_PROTOS
findImmedAction( Node *q )
#else
findImmedAction( q )
Node *q;
#endif
{
      Junction *j;
      require(q!=NULL, "findImmedAction: NULL node");
      require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");
      
      while ( q->ntype == nJunction )
      {
            j = (Junction *)q;
            if ( j->jtype != Generic || j->p2 != NULL ) return NULL;
            q = j->p1;
            if ( q == NULL ) return NULL;
      }
      if ( q->ntype == nAction ) return (ActionNode *)q;
      return NULL;
}

static void
#ifdef __USE_PROTOS
dumpRetValAssign( char *retval, char *ret_def )
#else
dumpRetValAssign( retval, ret_def )
char *retval;
char *ret_def;
#endif
{
      char *q = ret_def;
      
      tab();
      while ( *retval != '\0' )
      {
            while ( isspace((*retval)) ) retval++;
            while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output);
            fprintf(output, " = _trv.");
            
            DumpNextNameInDef(&q, output);
            fputc(';', output); fputc(' ', output);
            if ( *retval == ',' ) retval++;
      }
}

/* This function computes the set of tokens that can possibly be seen k
 * tokens in the future from point j
 */
static set
#ifdef __USE_PROTOS
ComputeErrorSet( Junction *j, int k )
#else
ComputeErrorSet( j, k )
Junction *j;
int k;
#endif
{
      Junction *alt1;
      set a, rk, f;
      require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");

      f = rk = empty;
      for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)
      {
            REACH(alt1->p1, k, &rk, a);
            require(set_nil(rk), "ComputeErrorSet: rk != nil");
            set_free(rk);
            set_orin(&f, a);
            set_free(a);
      }
      return f;
}

static char *
#ifdef __USE_PROTOS
tokenFollowSet(TokNode *p)
#else
tokenFollowSet(p)
TokNode *p;
#endif
{
    static char buf[100];
    set rk, a;
    int n;
    rk = empty;

    REACH(p->next, 1, &rk, a);
    require(set_nil(rk), "rk != nil");
    set_free(rk);
    n = DefErrSet( &a, 0, NULL );
    set_free(a);
    if ( GenCC )
        sprintf(buf, "err%d", n);
    else
        sprintf(buf, "zzerr%d", n);
    return buf;
}

static void
#ifdef __USE_PROTOS
makeErrorClause( Junction *q, set f, int max_k )
#else
makeErrorClause( q, f, max_k )
Junction *q;
set f;
int max_k;
#endif
{
    char *  handler_id="";                                           /* MR7 */
    int     nilf=0;                                                  /* MR13 */
    RuleEntry *ruleEntry;                                            /* MR14 */

      if ( FoundException )
      {
            _gen("else {\n");
            tabs++;
            if ( FoundGuessBlk )
            {
                  if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
                  else gen("if ( zzguessing ) goto fail;\n");
            }
            gen("if (_sva) _signal=NoViableAlt;\n");
            gen("else _signal=NoSemViableAlt;\n");
        if (q->outerEG != NULL) {
          handler_id=q->outerEG->altID;
#if 0
        } else {
          printf("q->curAltNum=%d q->exception_label=%s\n",q->curAltNum,q->exception_label);
          gen("*** DEBUG *** outerEG==NULL\n");
#endif
        };
            gen1("goto %s_handler;  /* MR7 */\n",handler_id);    /* MR7 */
            tabs--;
            gen("}\n");
            return;
      }

      if ( max_k == 1 )
      {
/* MR13 */  nilf=set_nil(f);
            if ( GenCC ) {
              _gen1("else {FAIL(1,err%d", DefErrSet1(1,&f,1,NULL));
            } else {
               _gen1("else {zzFAIL(1,zzerr%d", DefErrSet1(1,&f,1,NULL));
            };
            set_free(f);
      }
      else
      {
            int i;
            set_free(f);
            if ( GenCC ) {_gen1("else {FAIL(%d", max_k);}
            else _gen1("else {zzFAIL(%d", max_k);

    ruleEntry = (RuleEntry *) hash_get(Rname,q->rname);

            for (i=1; i<=max_k; i++)
            {
/* MR14 */  if (ruleEntry->dontComputeErrorSet) {
/* MR14 */    f=empty;
            } else {
                  f = ComputeErrorSet(q, i);
            }

      if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));}
                  else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL ));
                  
                  set_free(f);
            }
      }
      _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");
/* MR13 */  if (nilf) {
/* MR13 */    errFL("empty error set for alt - probably because of undefined rule or infinite left recursion",
/* MR13 */                 FileStr[q->file],q->line);
/* MR13 */    gen(" /* MR13 empty error set for this alt - undef rule ? infinite left recursion ? */");
/* MR13 */  };
}

static                                                               /* MR7 */
#ifdef __USE_PROTOS
char * findOuterHandlerLabel(ExceptionGroup *eg)                     /* MR7 */
#else
char * findOuterHandlerLabel(eg)                                     /* MR7 */
ExceptionGroup *eg;                                                  /* MR7 */
#endif
{
  char              *label=NULL;                                     /* MR7 */
  ExceptionGroup    *outerEG;                                        /* MR7 */

  if (eg->forRule == 0) {                                            /* MR7 */
    if (eg->labelEntry != NULL) {                                    /* MR7 */
      outerEG=eg->labelEntry->outerEG;                               /* MR7 */
      if (outerEG != NULL) {                                         /* MR7 */
        label=outerEG->altID;                                        /* MR7 */
        outerEG->used=1;                                             /* MR7 */
      };                                                             /* MR7 */
    } else if (eg->outerEG != NULL) {                                /* MR7 */
      outerEG=eg->outerEG;                                           /* MR7 */
      label=outerEG->altID;                                          /* MR7 */
      outerEG->used=1;                                               /* MR7 */
    };                                                               /* MR7 */
  };                                                                 /* MR7 */
  return (label==NULL ? "" : label);                                 /* MR7 */
}                                                                    /* MR7 */

/*** debug ***/
#if 0
** static                                                               /* MR7 */
** #ifdef __USE_PROTOS
** char * findOuterAltHandlerLabel(Junction *startJ)                    /* MR7 */
** #else
** char * findOuterAltHandlerLabel(startJ)                              /* MR7 */
** Junction *startJ;                                                    /* MR7 */
** #endif
** {                                                                    /* MR7 */
**   char      *label=NULL;                                             /* MR7 */
**   Junction  *alt;                                                    /* MR7 */
**                                                                      /* MR7 */
**   for (alt=startJ; alt != NULL; alt=alt->outerAltstart) {            /* MR7 */
**     label=alt->exception_label;                                      /* MR7 */
**     if (label != NULL) break;                                        /* MR7 */
**   };                                                                 /* MR7 */
**   return (label==NULL ? "" : label);                                 /* MR7 */
** }                                                                    /* MR7 */
#endif

#ifdef __USE_PROTOS
static void OutLineInfo(FILE *file,int line,char *fileName)
#else
static void OutLineInfo(file,line,fileName)
  FILE *    file;
  int       line;
  char *    fileName;
#endif
{
    static  char * prevFileName=NULL;
    static  char * prevFileNameMS=NULL;

    char *  p;
    char *  q;

    if (! GenLineInfo) return;

    if (!GenLineInfoMS) {
          fprintf(file, LineInfoFormatStr,line,fileName);
    } else {
      if (fileName == prevFileName) {
          fprintf(file, LineInfoFormatStr,line,prevFileNameMS);
      } else {
        if (prevFileNameMS != NULL) free (prevFileNameMS);
        prevFileNameMS=(char *)calloc(1,strlen(fileName)+1);
        require(prevFileNameMS != NULL,"why not do this in calloc wrapper");
        q=prevFileNameMS;
        for (p=fileName; *p != 0; p++) {
            *q=*p;
            if (*q == '\\') *q='/';
            q++;
        }
      }
      prevFileName=fileName;
    };
}

Generated by  Doxygen 1.6.0   Back to index