Home | History | Annotate | Download | only in antlr
      1 /*
      2  * gen.c
      3  *
      4  * Generate C code (ANSI, K&R, C++)
      5  *
      6  * SOFTWARE RIGHTS
      7  *
      8  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
      9  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
     10  * company may do whatever they wish with source code distributed with
     11  * PCCTS or the code generated by PCCTS, including the incorporation of
     12  * PCCTS, or its output, into commerical software.
     13  *
     14  * We encourage users to develop software with PCCTS.  However, we do ask
     15  * that credit is given to us for developing PCCTS.  By "credit",
     16  * we mean that if you incorporate our source code into one of your
     17  * programs (commercial product, research project, or otherwise) that you
     18  * acknowledge this fact somewhere in the documentation, research report,
     19  * etc...  If you like PCCTS and have developed a nice tool with the
     20  * output, please mention that you developed it using PCCTS.  In
     21  * addition, we ask that this header remain intact in our source code.
     22  * As long as these guidelines are kept, we expect to continue enhancing
     23  * this system and expect to make other tools available as they are
     24  * completed.
     25  *
     26  * ANTLR 1.33
     27  * Terence Parr
     28  * Parr Research Corporation
     29  * with Purdue University and AHPCRC, University of Minnesota
     30  * 1989-2001
     31  */
     32 
     33 #include <stdio.h>
     34 #include <stdlib.h>
     35 #include <ctype.h>
     36 #include "pcctscfg.h"
     37 #include "set.h"
     38 #include "syn.h"
     39 #include "hash.h"
     40 #include "generic.h"
     41 #include "dlgdef.h"
     42 
     43 #define NumExprPerLine	4
     44 static int on1line=0;
     45 static set tokensRefdInBlock;
     46 
     47 					/* T r a n s l a t i o n  T a b l e s */
     48 
     49 /* C_Trans[node type] == pointer to function that knows how to translate that node. */
     50 #ifdef __cplusplus
     51 void (*C_Trans[NumNodeTypes+1])(...) = {
     52 	NULL,
     53 	NULL,					/* See next table.
     54 Junctions have many types */
     55 	(void (*)(...)) genRuleRef,
     56 	(void (*)(...)) genToken,
     57 	(void (*)(...)) genAction
     58  };
     59 #else
     60 void (*C_Trans[NumNodeTypes+1])() = {
     61 	NULL,
     62 	NULL,					/* See next table.
     63 Junctions have many types */
     64 	genRuleRef,
     65 	genToken,
     66 	genAction
     67  };
     68 #endif
     69 
     70 /* C_JTrans[Junction type] == pointer to function that knows how to translate that
     71  * kind of junction node.
     72  */
     73 #ifdef __cplusplus
     74 void (*C_JTrans[NumJuncTypes+1])(...) = {
     75 	NULL,
     76 	(void (*)(...)) genSubBlk,
     77 	(void (*)(...)) genOptBlk,
     78 	(void (*)(...)) genLoopBlk,
     79 	(void (*)(...)) genEndBlk,
     80 	(void (*)(...)) genRule,
     81 	(void (*)(...)) genJunction,
     82 	(void (*)(...)) genEndRule,
     83 	(void (*)(...)) genPlusBlk,
     84 	(void (*)(...)) genLoopBegin
     85  };
     86 #else
     87 void (*C_JTrans[NumJuncTypes+1])() = {
     88 	NULL,
     89 	genSubBlk,
     90 	genOptBlk,
     91 	genLoopBlk,
     92 	genEndBlk,
     93 	genRule,
     94 	genJunction,
     95 	genEndRule,
     96 	genPlusBlk,
     97 	genLoopBegin
     98  };
     99 #endif
    100 
    101 #define PastWhiteSpace(s)	while (*(s) == ' ' || *(s) == '\t') {s++;}
    102 
    103 static int tabs = 0;
    104 
    105 /* MR6	Got tired of text running off page when using standard tab stops */
    106 
    107 #define TAB { int i; 					                		\
    108 	      if (TabWidth==0) { 					                \
    109 	         for (i=0; i<tabs; i++) fputc('\t', output);		                \
    110 	      } else {           							\
    111 		 for (i=0; i<tabs*TabWidth; i++) fputc(' ',output);     	        \
    112 	      };	                						\
    113 	    }
    114 
    115 static void
    116 #ifdef __USE_PROTOS
    117 tab( void )
    118 #else
    119 tab( )
    120 #endif
    121 TAB
    122 
    123 #ifdef __USE_PROTOS
    124 static char *tokenFollowSet(TokNode *);
    125 static ActionNode *findImmedAction( Node * );
    126 static void dumpRetValAssign(char *, char *, RuleRefNode *);		/* MR30 */
    127 static void dumpAfterActions(FILE *output);
    128 static set ComputeErrorSet(Junction *, int, int);
    129 static void makeErrorClause(Junction *, set, int, int);
    130 static void DumpFuncHeader( Junction *, RuleEntry * );
    131 static int has_guess_block_as_first_item(Junction *);
    132 static int genExprSets(set *, int);
    133 static void genExprTree( Tree *t, int k );
    134 static void genExprTreeOriginal( Tree *t, int k );                  /* MR10 */
    135 static char * findOuterHandlerLabel(ExceptionGroup *eg);            /* MR7 */
    136 static void OutLineInfo(FILE *file,int line,char *fileName);        /* MR14 */
    137 #else
    138 static char *tokenFollowSet();
    139 static ActionNode *findImmedAction();
    140 static void dumpRetValAssign();
    141 static void dumpAfterActions();
    142 static set ComputeErrorSet();
    143 static void makeErrorClause();
    144 static void DumpFuncHeader();
    145 static int has_guess_block_as_first_item();
    146 static int genExprSets();
    147 static void genExprTree();
    148 static void genExprTreeOriginal();                                  /* MR10 */
    149 static char * findOuterHandlerLabel();                              /* MR7 */
    150 static void OutLineInfo();                                          /* MR14 */
    151 #endif
    152 
    153 #define gen(s)			{tab(); fprintf(output, s);}
    154 #define gen1(s,a)		{tab(); fprintf(output, s,a);}
    155 #define gen2(s,a,b)		{tab(); fprintf(output, s,a,b);}
    156 #define gen3(s,a,b,c)	{tab(); fprintf(output, s,a,b,c);}
    157 #define gen4(s,a,b,c,d)	{tab(); fprintf(output, s,a,b,c,d);}
    158 #define gen5(s,a,b,c,d,e)	{tab(); fprintf(output, s,a,b,c,d,e);}
    159 #define gen6(s,a,b,c,d,e,f)	{tab(); fprintf(output, s,a,b,c,d,e,f);}
    160 #define gen7(s,a,b,c,d,e,f,g)	{tab(); fprintf(output, s,a,b,c,d,e,f,g);}
    161 
    162 #define _gen(s)			{fprintf(output, s);}
    163 #define _gen1(s,a)		{fprintf(output, s,a);}
    164 #define _gen2(s,a,b)	{fprintf(output, s,a,b);}
    165 #define _gen3(s,a,b,c)	{fprintf(output, s,a,b,c);}
    166 #define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);}
    167 #define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);}
    168 #define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}
    169 #define _gen7(s,a,b,c,d,e,f,g){fprintf(output, s,a,b,c,d,e,f,g);}
    170 
    171 
    172 /* MR11 a convenient place to set a break point */
    173 
    174 #ifdef __USE_PROTOS
    175 void MR_break(void)
    176 #else
    177 void MR_break()
    178 #endif
    179 {
    180   return;
    181 }
    182 
    183 /* MR10 genTraceOut(Junction *)      */
    184 
    185 #ifdef __USE_PROTOS
    186 static void genTraceOut(Junction *q)
    187 #else
    188 static void genTraceOut(q)
    189   Junction  *q;
    190 #endif
    191 {
    192   if ( TraceGen ) {
    193 		if ( GenCC ) {gen1("zzTRACEOUT(\"%s\");\n", q->rname);}
    194     		else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);
    195   }
    196 }
    197 
    198 static void
    199 #ifdef __USE_PROTOS
    200 warn_about_using_gk_option(void)
    201 #else
    202 warn_about_using_gk_option()
    203 #endif
    204 {
    205 	static int warned_already=0;
    206 
    207 	if ( !DemandLookahead || warned_already ) return;
    208 	warned_already = 1;
    209 	warnNoFL("-gk option could cause trouble for <<...>>? predicates");
    210 }
    211 
    212 void
    213 #ifdef __USE_PROTOS
    214 freeBlkFsets( Junction *q )
    215 #else
    216 freeBlkFsets( q )
    217 Junction *q;
    218 #endif
    219 {
    220 	int i;
    221 	Junction *alt;
    222 	require(q!=NULL, "freeBlkFsets: invalid node");
    223 
    224 	for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
    225 	{
    226 		for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]);
    227 	}
    228 }
    229 
    230 /*
    231  * Generate a local variable allocation for each token references
    232  * in this block.
    233  */
    234 static void
    235 #ifdef __USE_PROTOS
    236 genTokenPointers( Junction *q )
    237 #else
    238 genTokenPointers( q )
    239 Junction *q;
    240 #endif
    241 {
    242 	/* Rule refs are counted and can be referenced, but their
    243 	 * value is not set to anything useful ever.
    244 	 *
    245      * The ptrs are to be named _tij where i is the current level
    246 	 * and j is the element number within an alternative.
    247 	 */
    248 	int first=1, t=0;
    249 	set a;
    250 	tokensRefdInBlock = q->tokrefs;
    251 
    252 	if ( set_deg(q->tokrefs) == 0 ) return;
    253 	a = set_dup(q->tokrefs);
    254 	gen("ANTLRTokenPtr ");
    255 	for (; !set_nil(a); set_rm(t, a))
    256 	{
    257 		t = set_int(a);
    258 		if ( first ) first = 0;
    259 		else _gen(",");
    260 		if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t);
    261 		_gen2("_t%d%d", BlkLevel, t);
    262 		if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);}
    263 		else _gen("=NULL");
    264 	}
    265 	_gen(";\n");
    266 	set_free(a);
    267 }
    268 
    269 static int
    270 #ifdef __USE_PROTOS
    271 hasDefaultException(ExceptionGroup *eg)
    272 #else
    273 hasDefaultException(eg)
    274 ExceptionGroup *eg;
    275 #endif
    276 {
    277     ListNode *q;
    278 
    279     for (q = eg->handlers->next; q!=NULL; q=q->next)
    280     {
    281         ExceptionHandler *eh = (ExceptionHandler *)q->elem;
    282         if ( strcmp("default", eh->signalname)==0 ) {
    283             return 1;
    284         }
    285     }
    286     return 0;
    287 }
    288 static void
    289 #ifdef __USE_PROTOS
    290 dumpException(ExceptionGroup *eg, int no_default_case)
    291 #else
    292 dumpException(eg, no_default_case)
    293 ExceptionGroup *eg;
    294 int no_default_case;
    295 #endif
    296 {
    297     char    *outerLabel;                                             /* MR7 */
    298     int     altHandler=0;                                            /* MR7 */
    299     int     namedHandler=0;                                          /* MR7 */
    300 
    301     outerLabel=findOuterHandlerLabel(eg);                            /* MR7 */
    302 
    303     if (eg->label != NULL) {                                         /* MR7 */
    304       namedHandler=1;                                                /* MR7 */
    305     } else if (eg->forRule) {                                        /* MR7 */
    306       /* nothing */                                                  /* MR20 */
    307     } else {                                                         /* MR7 */
    308       altHandler=1;                                                  /* MR7 */
    309     };                                                               /* MR7 */
    310 
    311 #if 0
    312 **     if (! eg->used) {                                             /* MR7 */
    313 **     	warnFL("exception group never used",                         /* MR7 */
    314 **             FileStr[eg->altstart->file],eg->altstart->line);      /* MR7 */
    315 **     };                                                            /* MR7 */
    316 #endif
    317 
    318     if (namedHandler) {                                              /* MR7 */
    319 	  gen1("switch ( _signal ) {  /* [%s] */\n",eg->label);          /* MR7 */
    320     } else {                                                         /* MR7 */
    321 	  gen("switch ( _signal ) {\n");                                 /* MR7 */
    322       gen("case NoSignal: break;  /* MR7 */\n");                     /* MR7 */
    323     };                                                               /* MR7 */
    324 	{
    325 		ListNode *q;
    326 		for (q = eg->handlers->next; q!=NULL; q=q->next)
    327 		{
    328 			ExceptionHandler *eh = (ExceptionHandler *)q->elem;
    329 			if ( strcmp("default", eh->signalname)==0 ) {
    330 				gen("default :\n");
    331 				tabs++;
    332 				dumpAction(eh->action, output, tabs, -1, 1, 1);
    333                 gen("_signal=NoSignal;  /* MR7 */\n");                  /* MR7 */
    334                 gen("break;  /* MR7 */\n");                             /* MR7 */
    335 				tabs--;
    336 				gen("}\n");
    337 
    338                 /* copied from later code in dumpException */        /* MR7 */
    339 
    340                 if (namedHandler) {                                  /* MR7 */
    341                   gen("if (_signal != NoSignal)");                   /* MR7 */
    342                   _gen1(" goto %s_handler;  /* MR7 */\n",outerLabel);/* MR7 */
    343                 } else if (altHandler) {                             /* MR7 */
    344                   gen1("goto %s_handler;  /* MR7 */\n",outerLabel);  /* MR7 */
    345                 };
    346 				return;
    347 			}
    348 			gen1("case %s :\n", eh->signalname);
    349 			tabs++;
    350 			if ( eh->action != NULL )
    351 			{
    352 				dumpAction(eh->action, output, tabs, -1, 1, 1);
    353                 gen("break;  /* MR7 */\n");                          /* MR7 */
    354 			}
    355 			tabs--;
    356 		}
    357 	}
    358 	if ( no_default_case ) return;
    359 
    360 	gen("default :\n");
    361     tabs++;                                                         /* MR7 */
    362     gen("break;  /* MR7 */\n");                                     /* MR7 */
    363     tabs--;                                                         /* MR7 */
    364 
    365 	tabs++;
    366 /*****	gen("*_retsignal = _signal;\n"); *****/
    367 
    368 	tabs--;
    369 	gen("}\n");
    370 
    371     if (namedHandler) {                                             /* MR7 */
    372       gen("if (_signal != NoSignal)");                              /* MR7 */
    373       _gen1(" goto %s_handler;  /* MR7 */\n",outerLabel);           /* MR7 */
    374     } else if (altHandler) {                                        /* MR7 */
    375       gen1("goto %s_handler;  /* MR7 */\n",outerLabel);             /* MR7 */
    376     };
    377 
    378 }
    379 
    380 static void
    381 #ifdef __USE_PROTOS
    382 dumpExceptions(ListNode *list)
    383 #else
    384 dumpExceptions(list)
    385 ListNode *list;
    386 #endif
    387 {
    388 	ListNode *p;
    389 
    390 	for (p = list->next; p!=NULL; p=p->next)
    391 	{
    392 		ExceptionGroup *eg = (ExceptionGroup *) p->elem;
    393 		_gen2("%s%s_handler:\n",
    394 			  eg->label==NULL?"":eg->label,
    395 			  eg->altID==NULL?"":eg->altID);
    396 		if ( eg->altID!=NULL ) dumpException(eg, 0);
    397 		else {
    398 			/* This must be the rule exception handler */
    399 			dumpException(eg, 1);
    400 			if ( !hasDefaultException(eg) )
    401             {
    402                 gen("default :\n");
    403                 tabs++;
    404                 gen("zzdflthandlers(_signal,_retsignal);\n");
    405                 tabs--;
    406                 gen("}\n");
    407             }
    408 		}
    409 	}
    410 }
    411 
    412 /* For each element label that is found in a rule, generate a unique
    413  * Attribute (and AST pointer if GenAST) variable.
    414  */
    415 void
    416 #ifdef __USE_PROTOS
    417 genElementLabels(ListNode *list)
    418 #else
    419 genElementLabels(list)
    420 ListNode *list;
    421 #endif
    422 {
    423 	int first=1;
    424 	ListNode *p;
    425 
    426 	if ( GenCC ) {gen("ANTLRTokenPtr");}
    427 	else {gen("Attrib");}
    428 	for (p = list->next; p!=NULL; p=p->next)
    429 	{
    430 		char *ep = (char *)p->elem;
    431 		if ( first ) first = 0;
    432 		else _gen(",");
    433 		if ( GenCC ) {_gen1(" %s=NULL",ep);}
    434 		else {_gen1(" %s",ep);}
    435 	}
    436 	_gen(";\n");
    437 
    438 	if ( !GenAST ) return;
    439 
    440 	first = 1;
    441 	gen("AST");
    442 	for (p = list->next; p!=NULL; p=p->next)
    443 	{
    444 		char *ep = (char *)p->elem;
    445 		if ( first ) first = 0;
    446 		else _gen(",");
    447 		_gen1(" *%s_ast=NULL",ep);
    448 	}
    449 	_gen(";\n");
    450 }
    451 
    452 /*
    453  * Generate a local variable allocation for each token or rule reference
    454  * in this block.
    455  */
    456 static void
    457 #ifdef __USE_PROTOS
    458 genASTPointers( Junction *q )
    459 #else
    460 genASTPointers( q )
    461 Junction *q;
    462 #endif
    463 {
    464 	int first=1, t;
    465 	set a;
    466 
    467 	a = set_or(q->tokrefs, q->rulerefs);
    468 	if ( set_deg(a) > 0 )
    469 	{
    470 		gen("AST ");
    471 		for (; !set_nil(a); set_rm(t, a))
    472 		{
    473 			t = set_int(a);
    474 			if ( first ) first = 0;
    475 			else _gen(",");
    476 			_gen2("*_ast%d%d=NULL", BlkLevel, t);
    477 		}
    478 		set_free(a);
    479 	}
    480 	_gen(";\n");
    481 }
    482 
    483 static void
    484 #ifdef __USE_PROTOS
    485 BLOCK_Head( void )
    486 #else
    487 BLOCK_Head( )
    488 #endif
    489 {
    490 	gen("{\n");
    491 	tabs++;
    492 	if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
    493 }
    494 
    495 static void
    496 #ifdef __USE_PROTOS
    497 BLOCK_Tail( void )
    498 #else
    499 BLOCK_Tail( )
    500 #endif
    501 {
    502 	if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
    503 	if ( !GenCC ) gen("}\n");
    504 	tabs--;
    505 	gen("}\n");
    506 }
    507 
    508 static void
    509 #ifdef __USE_PROTOS
    510 BLOCK_Preamble( Junction *q )
    511 #else
    512 BLOCK_Preamble( q )
    513 Junction *q;
    514 #endif
    515 {
    516 	ActionNode *a;
    517 	Junction *begin;
    518 
    519 	BLOCK_Head();
    520 	if ( GenCC ) genTokenPointers(q);
    521 	if ( GenCC&&GenAST ) genASTPointers(q);
    522 	if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n");
    523 	if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm)
    524 	else if ( !GenCC ) gen("zzMake0;\n");
    525 	if ( !GenCC ) gen("{\n");
    526 	if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1);
    527 	else begin = q;
    528 	if ( has_guess_block_as_first_item(begin) )
    529 	{
    530 		gen("zzGUESS_BLOCK\n");
    531 	}
    532 	if ( q->jtype == aLoopBegin )
    533 		a = findImmedAction( ((Junction *)q->p1)->p1 );	/* look at aLoopBlk */
    534 	else
    535 		a = findImmedAction( q->p1 );
    536 	if ( a!=NULL && !a->is_predicate) {
    537 /* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1);
    538 		   a->done = 1;	/* remove action. We have already handled it */
    539 	}
    540 }
    541 
    542 void
    543 #ifdef __USE_PROTOS
    544 genCombinedPredTreeContextOrig( Predicate *p )
    545 #else
    546 genCombinedPredTreeContextOrig( p )
    547 Predicate *p;
    548 #endif
    549 {
    550 	static set *ctx=NULL;		/* genExprSets() is destructive, make copy*/
    551 	require(p!=NULL, "can't make context tree for NULL pred tree");
    552 
    553 #ifdef DBG_PRED
    554 	fprintf(stderr, "enter genCombinedPredTreeContextOrig(%s,0x%x) with sets:\n", p->expr, p);
    555 	s_fprT(stderr, p->scontext[1]);
    556 	fprintf(stderr, "\n");
    557 #endif
    558 	if ( p->down == NULL )
    559 	{
    560 /***	if ( p->k>1 && p->tcontext!=NULL ) ***/
    561 		if ( p->tcontext!=NULL )
    562 		{
    563 			_gen("(");
    564 			genExprTree(p->tcontext, 1);
    565 			_gen(")");
    566 		}
    567 /***	else if ( p->k==1 && set_deg(p->scontext[1])>0 ) ***/
    568 		else if ( set_deg(p->scontext[1])>0 )
    569 		{
    570 			if ( ctx==NULL ) ctx = (set *)calloc(CLL_k+1, sizeof(set));
    571 			require(ctx!=NULL, "ctx cannot allocate");
    572 			ctx[0]=empty;
    573 			ctx[1]=set_dup(p->scontext[1]);
    574 			_gen("(");
    575 			genExprSets(&(ctx[0]), p->k);
    576 			_gen(")");
    577 			set_free(ctx[1]);
    578 		}
    579 		else if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) {
    580 			fatal_internal("pred tree is orphan OR or AND list");
    581 		}
    582 		else {
    583             if (! HoistPredicateContext) {
    584               _gen(" 1 /* no context: prc is off */ ");
    585             } else {
    586               fatal_internal("pred tree context is empty");
    587             };
    588 		}
    589 		return;
    590 	}
    591 
    592 /* MR10 - make AND just like OR */
    593 
    594 	if ( p->expr == PRED_AND_LIST )
    595 	{
    596         Predicate *list = p->down;
    597         for (; list!=NULL; list=list->right)
    598         {
    599      	     genCombinedPredTreeContextOrig(list);
    600        		 if ( list->right!=NULL ) _gen("|| /* MR10 was wrong */ ");
    601         };
    602 		return;
    603 	}
    604 
    605 	if ( p->expr == PRED_OR_LIST )
    606 	{
    607         Predicate *list = p->down;
    608         for (; list!=NULL; list=list->right)
    609         {
    610            genCombinedPredTreeContextOrig(list);
    611            if ( list->right!=NULL ) _gen("||");
    612         };
    613         return;
    614      };
    615 
    616 	fatal("pred tree is really wacked");
    617 }
    618 
    619 /* [genCombinedPredTreeContext] */
    620 
    621 void
    622 #ifdef __USE_PROTOS
    623 genCombinedPredTreeContext( Predicate *p )
    624 #else
    625 genCombinedPredTreeContext( p )
    626 Predicate *p;
    627 #endif
    628 {
    629   Tree  *t;
    630   int   predDepth=0;
    631 
    632   if (0 && ! MR_usingPredNames && ! MRhoisting) {
    633     genCombinedPredTreeContextOrig(p);
    634   } else {
    635 /* MR13 */    MR_pred_depth(p,&predDepth);
    636 /* MR13 */    if (predDepth == 1) {
    637 /* MR13 */
    638 /* MR13 */      set   scontext[2];
    639 /* MR13 */      scontext[0]=empty;
    640 /* MR13 */      scontext[1]=MR_compute_pred_set(p);
    641 /* MR13 */      if (set_nil(scontext[1])) {
    642 /* MR13 */        _gen(" 1 /* MR12 no context (-prc off) */ ");
    643 /* MR13 */      } else {
    644 /* MR13 */        _gen("(");
    645 /* MR13 */        genExprSets(&scontext[0], 1);
    646 /* MR13 */        set_free(scontext[1]);
    647 /* MR13 */        _gen(")");
    648 /* MR13 */      };
    649 
    650     } else {
    651       t=MR_compute_pred_tree_context(p);
    652       if (t == NULL) {
    653         _gen(" 1 /* MR12 no context (-prc off) */ ");
    654       } else {
    655         _gen("(");
    656         genExprTree(t, 1);
    657         Tfree(t);   /* MR10 */
    658         _gen(")");
    659       };
    660     };
    661   };
    662 }
    663 
    664 /* [genPredTreeGate] */
    665 
    666 void
    667 #ifdef __USE_PROTOS
    668 genPredTreeGate( Predicate *p, int in_and_expr )
    669 #else
    670 genPredTreeGate( p, in_and_expr )
    671 Predicate *p;
    672 int in_and_expr;
    673 #endif
    674 {
    675 	if ( in_and_expr )
    676 	{
    677 		_gen("!(");
    678 		genCombinedPredTreeContext(p);
    679 		_gen(")||");
    680 		if ( p->down!=NULL ) _gen("\n");
    681 	}
    682 	else
    683 	{
    684 		_gen("(");
    685 		genCombinedPredTreeContext(p);
    686 		_gen(")&&");
    687 		if ( p->down!=NULL ) _gen("\n");
    688 	}
    689 }
    690 
    691 #ifdef __USE_PROTOS
    692 void genPredEntry(Predicate *p,int outer)
    693 #else
    694 void genPredEntry(p,outer)
    695   Predicate     *p;
    696   int           outer;
    697 #endif
    698 {
    699     int         inverted=0;
    700     Predicate   *q;
    701     int         localOuter=outer;
    702     int         needRP=0;
    703 
    704     if (p == NULL) return;
    705 
    706     if (p->predEntry != NULL && p->predEntry->predLiteral != NULL) {
    707       if (p->inverted != p->predEntry->pred->inverted) {
    708         _gen("! /* inverted pred */ (");
    709         needRP=1;
    710       } else {
    711         if (!localOuter) _gen("(");
    712         needRP=1;
    713       };
    714       dumpAction(p->predEntry->predLiteral,output,0,p->source->file,p->source->line,0);
    715       if (needRP) _gen(")");
    716       return;
    717     };
    718 
    719     inverted=p->inverted;
    720 
    721     if (inverted) {
    722       _gen(" ! /* inverted pred */ (");
    723       localOuter=1;
    724     };
    725 
    726     if (p->expr == PRED_OR_LIST) {
    727       if (!localOuter) _gen("(");
    728       for (q=p->down; q != NULL ; q=q->right) {
    729         genPredEntry(q,0);
    730         if (q->right != NULL) _gen(" || ");
    731       };
    732       if (!localOuter) _gen(")");
    733     } else if (p->expr == PRED_AND_LIST) {
    734       if (!localOuter) _gen("(");
    735       for (q=p->down; q != NULL ; q=q->right) {
    736         genPredEntry(q,0);
    737         if (q->right != NULL) _gen(" && ");
    738       };
    739       if (!localOuter) _gen(")");
    740     } else {
    741       if (!localOuter) _gen("(");
    742       require (p->source != NULL,"predEntry->source == NULL");
    743       require (p->source->inverted == 0,"dumpPredEntry p->source->inverted != 0");
    744       dumpAction(p->source->action,output,0,p->source->file,p->source->line,0);
    745       if (!localOuter) _gen(")");
    746     };
    747 
    748     if (inverted) {
    749         _gen(")");
    750     }
    751 }
    752 
    753 void
    754 #ifdef __USE_PROTOS
    755 dumpPredAction(ActionNode *anode,
    756                     char *s,FILE *output,int tabs,int file,int line,int final_newline)
    757 #else
    758 dumpPredAction(anode,
    759                     s,output,tabs,file,line,final_newline)
    760 
    761     ActionNode  *anode;
    762     char        *s;
    763     FILE        *output;
    764     int         tabs;
    765     int         file;
    766     int         line;
    767     int         final_newline;
    768 #endif
    769 {
    770     PredEntry   *predEntry=anode->predEntry;
    771     int         inverted=anode->inverted;
    772     Predicate   *workPred;
    773 
    774     if (predEntry == NULL) {
    775 
    776       /* inline predicate literal */
    777 
    778       require(inverted == 0,"dumpPredAction action->inverted");
    779   	  dumpAction(s,output,tabs,file,line,final_newline);
    780 
    781     } else {
    782 
    783       /* a reference to a predicate - possibly with an inverted source */
    784 
    785       if (predEntry->predLiteral != NULL) {
    786         if (inverted) _gen("! /* inverted pred */ (");
    787         dumpAction(predEntry->predLiteral,output,0,anode->file,anode->line,0);
    788         if (inverted) _gen(")");
    789       } else {
    790         workPred=predicate_dup(predEntry->pred);
    791         if (inverted) workPred->inverted=!workPred->inverted;
    792         genPredEntry(workPred,1);
    793         predicate_free(workPred);
    794       };
    795     };
    796 }
    797 
    798 /* [genPred] */
    799 
    800 void
    801 #ifdef __USE_PROTOS
    802 genPred(Predicate *p, Node *j,int suppress_sva)
    803 #else
    804 genPred(p,j,suppress_sva)
    805     Predicate   *p;
    806     Node        *j;
    807     int         suppress_sva;
    808 #endif
    809 {
    810 	if ( FoundException && !suppress_sva) {_gen("(_sva=(");}    /* MR11 suppress_sva */
    811 	else {_gen("(");}
    812 	if ( GenLineInfo && j->file != -1 ) _gen("\n");
    813     if (p->source != NULL && p->source->ampersandPred != NULL) {
    814       if (p->source->ampersandPred->k == 1) {
    815 
    816             set     ctx[2];
    817 
    818 			ctx[0]=empty;
    819 			ctx[1]=set_dup(p->source->ampersandPred->scontext[1]);
    820 
    821 			_gen("(");
    822 			genExprSets(&(ctx[0]), p->k);
    823 			_gen(") && ");
    824 			set_free(ctx[1]);
    825       } else {
    826         _gen("( ");
    827         genExprTree(p->source->ampersandPred->tcontext,1);
    828 		_gen(" ) && ");
    829       };
    830     };
    831 
    832     dumpPredAction((ActionNode *)p->source,
    833                 p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0);
    834 
    835 	if ( FoundException && !suppress_sva)   /* MR11 suppress_sva */
    836          {_gen("),_sva)");}    /* MR10 - get red of "meant ==" messages */
    837 	else {_gen(")");}
    838 }
    839 
    840 void
    841 #ifdef __USE_PROTOS
    842 MR_distinctORcontextOpt(Predicate *p,Node *j,int in_and_expr)
    843 #else
    844 MR_distinctORcontextOpt(p,j,in_and_expr)
    845     Predicate   *p;
    846     Node        *j;
    847     int         in_and_expr;
    848 #endif
    849 {
    850     Predicate   *q;
    851 
    852     _gen(" /* MR10 Distinct OR context optimization */ \n");
    853 
    854     if (in_and_expr) {
    855       gen("zzpf=0,\n");
    856       for (q=p->down; q != NULL; q=q->right) {
    857         gen("(  ");
    858         genCombinedPredTreeContext(q);
    859         _gen(" && (zzpf=1, ");
    860         genPred(q,j,0);
    861         _gen("  )) ||\n");
    862       };
    863       gen("!zzpf)");
    864     } else {
    865       require (0,
    866             "MR_distinctORcontextOpt: can't get here when using MR_predSimplify");
    867 #if 0
    868 **      for (q=p->down; q != NULL; q=q->right) {
    869 **        gen("(  ");
    870 **        genCombinedPredTreeContext(q);
    871 **        _gen(" && ");
    872 **        genPred(q,j);
    873 **        if (q->right != NULL) {
    874 **          _gen("  ) ||\n");
    875 **        };
    876 **      };
    877 **      gen(")");
    878 #endif
    879    };
    880 }
    881 
    882 void
    883 #ifdef __USE_PROTOS
    884 genPredTreeOrig( Predicate *p, Node *j, int in_and_expr )
    885 #else
    886 genPredTreeOrig( p, j, in_and_expr )
    887 Predicate *p;
    888 Node *j;
    889 int in_and_expr;
    890 #endif
    891 {
    892 
    893 /* MR10 */  int     allHaveContext=1;
    894 /* MR10 */  int     noneHaveContext=1;
    895 
    896 /* MR10 */  MR_predContextPresent(p,&allHaveContext,&noneHaveContext);
    897 
    898 	if ( ! noneHaveContext )                  /* MR10 context guards ignored when -prc off */
    899 	{
    900 		_gen("(");
    901 		genPredTreeGate(p, in_and_expr);
    902 	}
    903 
    904 	/* if leaf node, just gen predicate */
    905 
    906 	if ( p->down==NULL )
    907 	{
    908 		genPred(p,j,0);
    909 		if ( ! noneHaveContext ) _gen(")");   /* MR10 context guards ignored when -prc off */
    910 		return;
    911 	}
    912 
    913 	/* if AND list, do both preds (only two possible) */
    914 	if ( p->expr == PRED_AND_LIST )
    915 	{
    916 #if 0
    917 **		_gen("(");
    918 **		genPredTreeOrig(p->down, j, 1);
    919 **		_gen("&&");
    920 **		genPredTreeOrig(p->down->right, j, 1);
    921 **		_gen(")");
    922 **		if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */
    923 **		return;
    924 #endif
    925         /* MR11 - make it work with AND with more than two children - like OR */
    926 
    927 		Predicate *list;
    928 		_gen("(");
    929 		list = p->down;
    930 		for (; list!=NULL; list=list->right)
    931 		{
    932 			genPredTreeOrig(list, j, 1);
    933 			if ( list->right!=NULL ) _gen("&&");
    934 		}
    935 		_gen(")");
    936 		if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */
    937 		return;
    938     };
    939 
    940 	if ( p->expr == PRED_OR_LIST )
    941 	{
    942 		Predicate *list;
    943 		_gen("(");
    944 		list = p->down;
    945 		for (; list!=NULL; list=list->right)
    946 		{
    947 			genPredTreeOrig(list, j, 0);
    948 			if ( list->right!=NULL ) _gen("||");
    949 		}
    950 		_gen(")");
    951 		if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */
    952 		return;
    953 	}
    954 
    955 	fatal_internal("genPredTreeOrig: predicate tree is wacked");
    956 }
    957 
    958 #if 0
    959 **   Predicate member dummyPredDepth is no longer used in MR10
    960 **     but we might need it again in the future
    961 **
    962 **   if (MRhoisting) {
    963 **     if ( !noneHaveContext &&
    964 **          ! in_and_expr &&
    965 **          p->source != NULL &&
    966 **          p->source->dummyPredicateDepth > 0 &&
    967 **          p->down == NULL) {
    968 ** 		_gen("(");
    969 ** 		genCombinedPredTreeContext(p);
    970 ** 		_gen("  )\n");
    971 ** 		return;
    972 **     };
    973 **   };
    974 #endif
    975 
    976 /* [genPredTree] */
    977 
    978 /* in_and_expr
    979 
    980    what to do if the context is wrong
    981    what to do if the context is correct but the predicate is false
    982 
    983    remember: if the context is wrong it's the same as if the
    984              predicate is true as far as enabling an alternative
    985 
    986         Consider (AND p q r)
    987 
    988         if in an ... && ... expression then you don't want
    989         the entire predicate chain to fail just because the
    990         context for one component is wrong: so return true
    991 
    992         Consider (OR p q r)
    993 
    994         if in an ... || ... expression then you don't want
    995         the entire predicate chain to succeed just because
    996         the context for one component is correct when the
    997         corresponding test is false: so return false when
    998         the context is correct but the test is false.
    999 */
   1000 
   1001 void
   1002 #ifdef __USE_PROTOS
   1003 genPredTree( Predicate *p, Node *j, int in_and_expr, int suppress_sva )
   1004 #else
   1005 genPredTree( p, j, in_and_expr, suppress_sva)
   1006   Predicate     *p;
   1007   Node          *j;
   1008   int           in_and_expr;
   1009   int           suppress_sva;
   1010 #endif
   1011 {
   1012 
   1013     int         allHaveContext=1;
   1014     int         noneHaveContext=1;
   1015     Tree        *groupTree;
   1016     Tree        *oneTree;
   1017     Predicate   *q;
   1018     int         identicalORcontextOptimization=0;
   1019     int         identicalANDcontextOptimization=0;
   1020 
   1021     if (0 && !MR_usingPredNames && !MRhoisting) {
   1022       genPredTreeOrig(p,j,in_and_expr);
   1023       return;
   1024     };
   1025 
   1026     MR_predContextPresent(p,&allHaveContext,&noneHaveContext);
   1027 
   1028 	if ( ! noneHaveContext ) {                 /* MR10 context guards ignored when -prc off */
   1029 
   1030       _gen("(");
   1031 
   1032             /* MR10 optimize OR predicates which are all leaves */
   1033 
   1034       if (p->expr == PRED_OR_LIST && MR_allPredLeaves(p->down)) {
   1035         groupTree=MR_compute_pred_tree_context(p);
   1036         for (q=p->down ; q != NULL ; q=q->right) {
   1037           oneTree=MR_compute_pred_tree_context(q);
   1038           if (! MR_tree_equ(groupTree,oneTree)) {
   1039             Tfree(oneTree);
   1040             break;
   1041           };
   1042           Tfree(oneTree);
   1043         };
   1044         Tfree(groupTree);
   1045         if (q == NULL) {
   1046           _gen("/* MR10 individual OR gates suppressed when all predicates are leaves");
   1047           _gen(" with identical context */\n");
   1048           genPredTreeGate(p,in_and_expr);   /* use the parent's in_and_expr for this gate */
   1049           identicalORcontextOptimization=1;
   1050         } else {
   1051           MR_distinctORcontextOpt(p,j,in_and_expr);
   1052           return;
   1053         };
   1054       } else if (p->expr == PRED_AND_LIST && MR_allPredLeaves(p->down)) {
   1055 
   1056             /* MR12 optimize AND predicates which are all leaves */
   1057 
   1058         groupTree=MR_compute_pred_tree_context(p);
   1059         for (q=p->down ; q != NULL ; q=q->right) {
   1060           oneTree=MR_compute_pred_tree_context(q);
   1061           if (! MR_tree_equ(groupTree,oneTree)) {
   1062             Tfree(oneTree);
   1063             break;
   1064           };
   1065           Tfree(oneTree);
   1066         };
   1067         Tfree(groupTree);
   1068         if (q == NULL) {
   1069           _gen("/* MR12 individual AND gates suppressed when all predicates are leaves");
   1070           _gen(" with identical context */\n");
   1071           genPredTreeGate(p,in_and_expr);   /* use the parent's in_and_expr for this gate */
   1072           identicalANDcontextOptimization=1;
   1073         } else {
   1074           genPredTreeGate(p, in_and_expr);
   1075         };
   1076       } else {
   1077   	    genPredTreeGate(p, in_and_expr);
   1078       };
   1079 	}
   1080 
   1081 	/* if leaf node, just gen predicate */
   1082 
   1083 	if ( p->down==NULL )
   1084 	{
   1085 		genPred(p,j,suppress_sva);
   1086 		if ( ! noneHaveContext ) _gen(")");   /* MR10 context guards ignored when -prc off */
   1087 		return;
   1088 	}
   1089 
   1090 	/* if AND list, do both preds (only two possible) */
   1091     /* MR10    not any more ! */
   1092 
   1093 	if ( p->expr == PRED_AND_LIST )
   1094 	{
   1095 		Predicate *list;
   1096 		_gen("(");
   1097 		list = p->down;
   1098         for (; list != NULL; list=list->right) {
   1099           if (identicalANDcontextOptimization) {
   1100             genPred(list, j,suppress_sva);
   1101           } else {
   1102 	   	    genPredTree(list, j, 1, suppress_sva);  /* in and context */
   1103           };
   1104           if ( list->right!=NULL ) _gen("&&");
   1105         };
   1106 		_gen(")");
   1107 		if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */
   1108 		return;
   1109 	}
   1110 
   1111 	if ( p->expr == PRED_OR_LIST )
   1112 	{
   1113 		Predicate *list;
   1114 		_gen("(");
   1115 		list = p->down;
   1116 		for (; list!=NULL; list=list->right)
   1117 		{
   1118             if (identicalORcontextOptimization) {
   1119 	          genPred(list, j,suppress_sva);
   1120             } else {
   1121 	   	      genPredTree(list, j, 0, suppress_sva);
   1122             };
   1123 			if ( list->right!=NULL ) _gen("||");
   1124 		}
   1125 		_gen(")");
   1126 		if ( ! noneHaveContext ) _gen(")");    /* MR10 context guards ignored when -prc off */
   1127 		return;
   1128 	}
   1129 
   1130 	fatal_internal("predicate tree is wacked");
   1131 }
   1132 
   1133 /* [genPredTreeMainXX] */
   1134 
   1135 Predicate *     /* MR10 */
   1136 #ifdef __USE_PROTOS
   1137 genPredTreeMainXX( Predicate *p, Node *j ,int in_and_expr)
   1138 #else
   1139 genPredTreeMainXX( p, j ,in_and_expr)
   1140     Predicate   *p;
   1141     Node        *j;
   1142     int         in_and_expr;
   1143 #endif
   1144 {
   1145 
   1146     int     allHaveContext=1;
   1147     int     noneHaveContext=1;
   1148 
   1149 #if 0
   1150     fprintf(stderr,"Pred before\n");
   1151     dumppred(p);
   1152     fprintf(stderr,"\n");
   1153     fprintf(stderr,"Pred after\n");
   1154     dumppred(p);
   1155     fprintf(stderr,"\n");
   1156 #endif
   1157 
   1158     p=MR_predSimplifyALL(p);    /* MR10 */
   1159 
   1160     require (MR_predicate_context_completed(p),"predicate context is not complete");
   1161 
   1162     MR_cleanup_pred_trees(p);   /* MR10 */
   1163 
   1164     MR_predContextPresent(p,&allHaveContext,&noneHaveContext);
   1165     if (!noneHaveContext & !allHaveContext) {
   1166       warnFL("predicate contains elements both with and without context",
   1167                 FileStr[j->file],j->line);
   1168     };
   1169 
   1170     if (InfoP) {
   1171        _gen("\n#if 0\n\n");
   1172        MR_dumpPred(p,1);
   1173        _gen("#endif\n");
   1174     };
   1175 	genPredTree(p,j,in_and_expr,0);
   1176     return p;
   1177 }
   1178 
   1179 Predicate *     /* MR10 */
   1180 #ifdef __USE_PROTOS
   1181 genPredTreeMain( Predicate *p, Node *j)
   1182 #else
   1183 genPredTreeMain( p, j)
   1184     Predicate   *p;
   1185     Node        *j;
   1186 #endif
   1187 {
   1188   return genPredTreeMainXX(p,j,1);
   1189 }
   1190 
   1191 static void
   1192 #ifdef __USE_PROTOS
   1193 genExprTreeOriginal( Tree *t, int k )
   1194 #else
   1195 genExprTreeOriginal( t, k )
   1196 Tree *t;
   1197 int k;
   1198 #endif
   1199 {
   1200 	require(t!=NULL, "genExprTreeOriginal: NULL tree");
   1201 
   1202 	if ( t->token == ALT )
   1203 	{
   1204 		_gen("("); genExprTreeOriginal(t->down, k); _gen(")");
   1205 		if ( t->right!=NULL )
   1206 		{
   1207 			_gen("||");
   1208 			on1line++;
   1209 			if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
   1210 			_gen("("); genExprTreeOriginal(t->right, k); _gen(")");
   1211 		}
   1212 		return;
   1213 	}
   1214 	if ( t->down!=NULL ) _gen("(");
   1215 	_gen1("LA(%d)==",k);
   1216 	if ( TokenString(t->token) == NULL ) _gen1("%d", t->token)
   1217 	else _gen1("%s", TokenString(t->token));
   1218 	if ( t->down!=NULL )
   1219 	{
   1220 		_gen("&&");
   1221 		on1line++;
   1222 		if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
   1223 		_gen("("); genExprTreeOriginal(t->down, k+1); _gen(")");
   1224 	}
   1225 	if ( t->down!=NULL ) _gen(")");
   1226 	if ( t->right!=NULL )
   1227 	{
   1228 		_gen("||");
   1229 		on1line++;
   1230 		if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
   1231 		_gen("("); genExprTreeOriginal(t->right, k); _gen(")");
   1232 	}
   1233 }
   1234 
   1235 #ifdef __USE_PROTOS
   1236 static void MR_LAtokenString(int k,int token)
   1237 #else
   1238 static void MR_LAtokenString(k,token)
   1239   int   k;
   1240   int   token;
   1241 #endif
   1242 {
   1243     char    *ts;
   1244 
   1245     ts=TokenString(token);
   1246     if (ts == NULL) {
   1247       _gen2(" LA(%d)==%d",k,token);
   1248     } else {
   1249       _gen2(" LA(%d)==%s",k,ts);
   1250     };
   1251 }
   1252 
   1253 
   1254 #ifdef __USE_PROTOS
   1255 static int MR_countLeaves(Tree *t)
   1256 #else
   1257 static int MR_countLeaves(t)
   1258   Tree  *t;
   1259 #endif
   1260 {
   1261   if (t == NULL) return 0;
   1262   if (t->token == ALT) {
   1263     return MR_countLeaves(t->down)+MR_countLeaves(t->right);
   1264   } else {
   1265     return 1+MR_countLeaves(t->down)+MR_countLeaves(t->right);
   1266   };
   1267 }
   1268 
   1269 #ifdef __USE_PROTOS
   1270 static void MR_genOneLine(Tree *tree,int k)
   1271 #else
   1272 static void MR_genOneLine(tree,k)
   1273   Tree      *tree;
   1274   int       k;
   1275 #endif
   1276 {
   1277     if (tree == NULL) return;
   1278     if (tree->token == ALT) {
   1279        MR_genOneLine(tree->down,k);
   1280     } else {
   1281        MR_LAtokenString(k,tree->token);
   1282        if (tree->down != NULL &&
   1283            tree->down->right == NULL) {
   1284           _gen(" &&");
   1285           MR_genOneLine(tree->down,k+1);
   1286        } else if (tree->down != NULL) {
   1287          _gen(" && (");
   1288          MR_genOneLine(tree->down,k+1);
   1289          _gen(")");
   1290        };
   1291     };
   1292     if (tree->right != NULL) {
   1293       _gen(" ||");
   1294       MR_genOneLine(tree->right,k);
   1295     };
   1296 }
   1297 
   1298 static int across;
   1299 static int depth;
   1300 static int lastkonline;
   1301 
   1302 #ifdef __USE_PROTOS
   1303 static void MR_genMultiLine(Tree *tree,int k)
   1304 #else
   1305 static void MR_genMultiLine(tree,k)
   1306   Tree  *tree;
   1307   int   k;
   1308 #endif
   1309 {
   1310     int     i;
   1311 
   1312     if (tree == NULL) return;
   1313     if (tree->token == ALT) {
   1314       MR_genMultiLine(tree,k);
   1315     } else {
   1316       MR_LAtokenString(k,tree->token);
   1317       lastkonline=k;
   1318       across++;
   1319       if (tree->down != NULL && tree->down->right == NULL) {
   1320         if (across > 3) {
   1321           _gen("\n");
   1322           across=0;
   1323           lastkonline=0;
   1324           for (i=0 ; i < depth+k ; i++) _gen("   ");
   1325           _gen("&&");
   1326         } else {
   1327           _gen(" &&");
   1328         };
   1329         MR_genMultiLine(tree->down,k+1);
   1330       } else if (tree->down != NULL) {
   1331         _gen("\n");
   1332         lastkonline=0;
   1333         across=0;
   1334         for (i=0 ; i < depth+k ; i++) _gen("   ");
   1335         _gen("&& (");
   1336         MR_genMultiLine(tree->down,k+1);
   1337         _gen(")");
   1338       };
   1339     };
   1340     if (tree->right != NULL) {
   1341       if (k < lastkonline) {
   1342         _gen("\n");
   1343         across=0;
   1344         lastkonline=0;
   1345         for (i=0; i < depth+k-1 ; i++) _gen("   ");
   1346         _gen("||");
   1347       } else if (across > 3 ) {
   1348         _gen("\n");
   1349         across=0;
   1350         lastkonline=0;
   1351         for (i=0; i < depth+k ; i++) _gen("   ");
   1352         _gen("||");
   1353       } else {
   1354         _gen(" ||");
   1355       };
   1356       MR_genMultiLine(tree->right,k);
   1357     };
   1358 }
   1359 
   1360 #ifdef __USE_PROTOS
   1361 static void genExprTree(Tree *tree,int k)
   1362 #else
   1363 static void genExprTree(tree,k)
   1364   Tree  *tree;
   1365   int   k;
   1366 #endif
   1367 {
   1368     int     count;
   1369 
   1370 #if 0
   1371     /* MR20 THM This was probably an error.
   1372             The routine should probably reference that static
   1373             "across" and this declaration hides it.
   1374     */
   1375 
   1376     int     across;
   1377 #endif
   1378 
   1379     require (tree != NULL,"genExprTree: tree is NULL");
   1380     require (k > 0,"genExprTree: k <= 0");
   1381 
   1382     if (0 && !MRhoisting) {   /* MR11 make new version standard */
   1383       genExprTreeOriginal(tree,k);
   1384     } else {
   1385       count=MR_countLeaves(tree);
   1386       if (count < 5) {
   1387         MR_genOneLine(tree,k);
   1388       } else {
   1389         _gen("\n");
   1390         across=0;
   1391         depth=0;
   1392         lastkonline=0;
   1393         MR_genMultiLine(tree,k);
   1394         _gen("\n");
   1395       };
   1396     };
   1397 }
   1398 
   1399 
   1400 /*
   1401  * Generate LL(k) type expressions of the form:
   1402  *
   1403  *		 (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) &&
   1404  *		 (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) &&
   1405  *			.....
   1406  *		 (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn)
   1407  *
   1408  * If GenExprSetsOpt generate:
   1409  *
   1410  *		(setwdi[LA(1)]&(1<<j)) && (setwdi[LA(2)]&(1<<j)) ...
   1411  *
   1412  * where n is set_deg(expr) and Ti is some random token and k is the last nonempty
   1413  * set in fset <=CLL_k.
   1414  * k=1..CLL_k where CLL_k >= 1.
   1415  *
   1416  * This routine is visible only to this file and cannot answer a TRANS message.
   1417  *
   1418  */
   1419 
   1420 /*  [genExpr] */
   1421 
   1422 static int
   1423 #ifdef __USE_PROTOS
   1424 genExpr( Junction *j )
   1425 #else
   1426 genExpr( j )
   1427 Junction *j;
   1428 #endif
   1429 {
   1430 	int max_k;
   1431 
   1432 	/* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead
   1433 	 * from CLL_k..LL_k
   1434 	 */
   1435 	{
   1436 		int limit;
   1437 		if ( j->ftree!=NULL ) limit = LL_k;
   1438 		else limit = CLL_k;
   1439 		max_k = genExprSets(j->fset, limit);
   1440 	}
   1441 
   1442 	/* Do tests for real tuples from other productions that conflict with
   1443 	 * artificial tuples generated by compression (using sets of tokens
   1444 	 * rather than k-trees).
   1445 	 */
   1446 	if ( j->ftree != NULL )
   1447 	{
   1448 		_gen(" && !("); genExprTree(j->ftree, 1); _gen(")");
   1449 	}
   1450 
   1451 	if ( ParseWithPredicates && j->predicate!=NULL )
   1452 	{
   1453 		Predicate *p = j->predicate;
   1454 		warn_about_using_gk_option();
   1455 		_gen("&&");
   1456 		j->predicate=genPredTreeMain(p, (Node *)j);     /* MR10 */
   1457 	}
   1458 
   1459 	return max_k;
   1460 }
   1461 
   1462 static int
   1463 #ifdef __USE_PROTOS
   1464 genExprSets( set *fset, int limit )
   1465 #else
   1466 genExprSets( fset, limit )
   1467 set *fset;
   1468 int limit;
   1469 #endif
   1470 {
   1471 	int k = 1;
   1472 	int max_k = 0;
   1473 	unsigned *e, *g, firstTime=1;
   1474 
   1475     if (set_nil(fset[1])) {
   1476       _gen(" 0 /* MR13 empty set expression  - undefined rule ? infinite left recursion ? */ ");
   1477       MR_BadExprSets++;
   1478     };
   1479 
   1480 	if ( GenExprSetsOpt )
   1481 	{
   1482 		while ( k <= limit && !set_nil(fset[k]) )   /* MR11 */
   1483 		{
   1484 			if ( set_deg(fset[k])==1 )	/* too simple for a set? */
   1485 			{
   1486 				int e;
   1487 				_gen1("(LA(%d)==",k);
   1488 				e = set_int(fset[k]);
   1489 				if ( TokenString(e) == NULL ) _gen1("%d)", e)
   1490 				else _gen1("%s)", TokenString(e));
   1491 			}
   1492 			else
   1493 			{
   1494 				NewSet();
   1495 				FillSet( fset[k] );
   1496 				_gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<<setnum);
   1497 			}
   1498 			if ( k>max_k ) max_k = k;
   1499 			if ( k == CLL_k ) break;
   1500 			k++;
   1501 			if ( k<=limit && !set_nil(fset[k]) ) _gen(" && ");  /* MR11 */
   1502 			on1line++;
   1503 			if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
   1504 		}
   1505 		return max_k;
   1506 	}
   1507 
   1508 	while ( k<= limit &&  !set_nil(fset[k]) )       /* MR11 */
   1509 	{
   1510 		if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set");
   1511 		for (; *e!=nil; e++)
   1512 		{
   1513 			if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; }
   1514 			on1line++;
   1515 			if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
   1516 			_gen1("LA(%d)==",k);
   1517 			if ( TokenString(*e) == NULL ) _gen1("%d", *e)
   1518 			else _gen1("%s", TokenString(*e));
   1519 		}
   1520 		free( (char *)g );
   1521 		_gen(")");
   1522 		if ( k>max_k ) max_k = k;
   1523 		if ( k == CLL_k ) break;
   1524 		k++;
   1525 		if ( k <= limit && !set_nil(fset[k]) ) { firstTime=1; _gen(" && "); }   /* MR11 */
   1526 		on1line++;
   1527 		if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); }
   1528 	}
   1529 	return max_k;
   1530 }
   1531 
   1532 /*
   1533  * Generate code for any type of block.  If the last alternative in the block is
   1534  * empty (not even an action) don't bother doing it.  This permits us to handle
   1535  * optional and loop blocks as well.
   1536  *
   1537  * Only do this block, return after completing the block.
   1538  * This routine is visible only to this file and cannot answer a TRANS message.
   1539  */
   1540 static set
   1541 #ifdef __USE_PROTOS
   1542 genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly, int * lastAltEmpty /* MR23 */)
   1543 #else
   1544 genBlk( q, jtype, max_k, need_right_curly, lastAltEmpty /* MR23 */)
   1545 Junction *q;
   1546 int jtype;
   1547 int *max_k;
   1548 int *need_right_curly;
   1549 int *lastAltEmpty; /* MR23 */
   1550 #endif
   1551 {
   1552 	set f;
   1553 	Junction *alt;
   1554 	int a_guess_in_block = 0;
   1555 	require(q!=NULL,				"genBlk: invalid node");
   1556 	require(q->ntype == nJunction,	"genBlk: not junction");
   1557 	*need_right_curly=0;
   1558 	*lastAltEmpty = 0;		/* MR23 */
   1559 	if ( q->p2 == NULL )	/* only one alternative?  Then don't need if */
   1560 	{
   1561 		if (first_item_is_guess_block((Junction *)q->p1)!=NULL )
   1562 		{
   1563             if (jtype != aLoopBlk && jtype != aOptBlk && jtype != aPlusBlk) {
   1564   			  warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line);
   1565             };
   1566    	   	    gen("zzGUESS\n");	/* guess anyway to make output code consistent */
   1567 /* MR10 disable */  /**** gen("if ( !zzrv )\n"); ****/
   1568 /* MR10 */          gen("if ( !zzrv ) {\n"); tabs++; (*need_right_curly)++;
   1569         };
   1570 		TRANS(q->p1);
   1571 		return empty;		/* no decision to be made-->no error set */
   1572 	}
   1573 
   1574 	f = First(q, 1, jtype, max_k);
   1575 	for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
   1576 	{
   1577 		if ( alt->p2 == NULL )					/* chk for empty alt */
   1578 		{
   1579 			Node *p = alt->p1;
   1580 			if ( p->ntype == nJunction )
   1581 			{
   1582 				/* we have empty alt */
   1583 /* MR23
   1584    There is a conflict between giving good error information for non-exceptions
   1585    and making life easy for those using parser exception handling.  Consider:
   1586 
   1587          r: { A } b;
   1588 		 b: B;
   1589 
   1590 		   with input "C"
   1591 
   1592    Before MR21 the error message would be "expecting B - found C".  After MR21
   1593    the error message would be "expcect A, B - found C".  This was good, but it
   1594    caused problems for those using parser exceptions because the reference to
   1595    B was generated inside the {...} where B really wasn't part of the block.
   1596 
   1597    In MR23 this has been changed for the case where exceptions are in use to
   1598    not generate the extra check in the tail of the {A} block.
   1599 */
   1600 
   1601 
   1602 /* MR23 */	if (isEmptyAlt( ((Junction *)p)->p1, (Node *)q->end)) {
   1603 /* MR23 */      *lastAltEmpty = 1;
   1604 /* MR23 */		if (FoundException) {
   1605 /* MR23 */			/* code to restore state if a prev alt didn't follow guess */
   1606 /* MR23 */			if ( a_guess_in_block && jtype != aPlusBlk) {
   1607 /* MR23 */				gen("if ( !zzrv ) zzGUESS_DONE; /* MR28 */\n");
   1608 /* MR23 */			}
   1609 /* MR23 */			break;
   1610 /* MR23 */		};
   1611 /* MR28 */      if (jtype == aPlusBlk) {
   1612 /* MR28 */          break;
   1613 /* MR28 */      }
   1614 /* MR23 */	}
   1615 		}
   1616 	} /* end of for loop on alt */
   1617 
   1618 /* MR10 */        if (alt->p2 == NULL &&
   1619 /* MR10 */               ( q->jtype == aSubBlk || q->jtype == RuleBlk) ) {
   1620 /* MR10 */          if (first_item_is_guess_block(alt)) {
   1621 /* MR10 */               warnFL("(...)? as last alternative of block is unnecessary",
   1622 /* MR10 */                                FileStr[alt->file],alt->line);
   1623 /* MR10 */          };
   1624 /* MR10 */        };
   1625 
   1626 		if ( alt != q ) gen("else ")
   1627 		else
   1628 		{
   1629 			if ( DemandLookahead ) {
   1630 				if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);}
   1631 				else gen1("look(%d);\n", *max_k);
   1632 			}
   1633 		}
   1634 
   1635 		if ( alt!=q )
   1636 		{
   1637 			_gen("{\n");
   1638 			tabs++;
   1639 			(*need_right_curly)++;
   1640 			/* code to restore state if a prev alt didn't follow guess */
   1641 			if ( a_guess_in_block )
   1642 				gen("if ( !zzrv ) zzGUESS_DONE;\n");
   1643 		}
   1644 		if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL )
   1645 		{
   1646 			a_guess_in_block = 1;
   1647 			gen("zzGUESS\n");
   1648 		}
   1649 		gen("if ( ");
   1650 		if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && ");
   1651 		genExpr(alt);
   1652 		_gen(" ) ");
   1653 		_gen("{\n");
   1654 		tabs++;
   1655 		TRANS(alt->p1);
   1656 		--tabs;
   1657 		gen("}\n");
   1658 /* MR10 */        if (alt->p2 == NULL) {
   1659 /* MR10 */          if (first_item_is_guess_block(alt)) {
   1660 /* MR10 */            gen("/* MR10 */ else {\n");
   1661 /* MR10 */            tabs++;
   1662 /* MR10 */  		  (*need_right_curly)++;
   1663 /* MR10 */  		  /* code to restore state if a prev alt didn't follow guess */
   1664 /* MR10 */            gen("/* MR10 */ if ( !zzrv ) zzGUESS_DONE;\n");
   1665 /* MR10 */            gen("/* MR10 */ if (0) {}     /* last alternative of block is guess block */\n");
   1666 /* MR10 */          };
   1667 /* MR10 */        };
   1668 	}
   1669 	return f;
   1670 }
   1671 
   1672 static int
   1673 #ifdef __USE_PROTOS
   1674 has_guess_block_as_first_item( Junction *q )
   1675 #else
   1676 has_guess_block_as_first_item( q )
   1677 Junction *q;
   1678 #endif
   1679 {
   1680 	Junction *alt;
   1681 
   1682 	for (alt=q; alt != NULL; alt= (Junction *) alt->p2 )
   1683 	{
   1684 		if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1;
   1685 	}
   1686 	return 0;
   1687 }
   1688 
   1689 static int
   1690 #ifdef __USE_PROTOS
   1691 has_guess_block_as_last_item( Junction *q )
   1692 #else
   1693 has_guess_block_as_last_item( q )
   1694 Junction *q;
   1695 #endif
   1696 {
   1697 	Junction *alt;
   1698 
   1699     if (q == NULL) return 0;
   1700 	for (alt=q; alt->p2 != NULL && !( (Junction *) alt->p2)->ignore; alt= (Junction *) alt->p2 ) {};
   1701     return first_item_is_guess_block( (Junction *) alt->p1) != NULL;
   1702 }
   1703 
   1704 /* MR30 See description of first_item_is_guess_block for background */
   1705 
   1706 Junction *
   1707 #ifdef __USE_PROTOS
   1708 first_item_is_guess_block_extra(Junction *q )
   1709 #else
   1710 first_item_is_guess_block_extra(q)
   1711 Junction *q;
   1712 #endif
   1713 {
   1714 	while ( q!=NULL &&
   1715             (  ( q->ntype==nAction ) ||
   1716                ( q->ntype==nJunction &&
   1717                     (q->jtype==Generic || q->jtype == aLoopBlk)
   1718                )
   1719             )
   1720           )
   1721 	{
   1722 		if ( q->ntype==nJunction ) q = (Junction *)q->p1;
   1723 		else q = (Junction *) ((ActionNode *)q)->next;
   1724 	}
   1725 
   1726 	if ( q==NULL ) return NULL;
   1727 	if ( q->ntype!=nJunction ) return NULL;
   1728 	if ( q->jtype!=aSubBlk ) return NULL;
   1729 	if ( !q->guess ) return NULL;
   1730 
   1731 	return q;
   1732 }
   1733 
   1734 /* return NULL if 1st item of alt is NOT (...)? block; else return ptr to aSubBlk node
   1735  * of (...)?;  This function ignores actions and predicates.
   1736  */
   1737 
   1738 Junction *
   1739 #ifdef __USE_PROTOS
   1740 first_item_is_guess_block( Junction *q )
   1741 #else
   1742 first_item_is_guess_block( q )
   1743 Junction *q;
   1744 #endif
   1745 {
   1746 	Junction * qOriginal = q;	/* DEBUG */
   1747 
   1748     /* MR14  Couldn't find aSubBlock which was a guess block when it lay
   1749              behind aLoopBlk.  The aLoopBlk only appear in conjunction with
   1750              aLoopBegin, but the routine didn't know that.  I think.
   1751 
   1752        MR14a Added extra parentheses to clarify precedence
   1753 
   1754 	   MR30  This appears to have been a mistake.  The First set was then
   1755 	         computed incorrectly for:
   1756 
   1757 					r : ( (A)? B
   1758 					    | C
   1759 						)*
   1760 
   1761 			 The routine analysis_point was seeing the guess block when
   1762 			 it was still analyzing the loopBegin block.  As a consequence,
   1763 			 when it looked for the analysis_point it was processing the B, but
   1764 			 skipping over the C alternative altogether because it thought
   1765 			 it was looking at a guess block, not realizing there was a loop
   1766 			 block in front of the loopBegin.
   1767 
   1768              loopBegin  loopBlk  subBlk/guess  A  G  EB  G  B EB EB  EB  ER
   1769 			    |          |          |                     ^   ^
   1770 				|		   |                                |   |
   1771                 |          +-> G  C G ----------------------+   |
   1772                 |                                               |
   1773 				+--- G G G -------------------------------------+
   1774 
   1775 			 Reported by Arpad Beszedes (beszedes (at) inf.u-szeged.hu).
   1776 
   1777 		MR30  This is still more complicated.  This fix caused ambiguity messages
   1778 		to be reported for "( (A B)? )* A B" but not for "( (A B)? )+".  Why is
   1779 		there a difference when these are outwardly identical ?  It is because the
   1780 		start of a (...)* block is represented by two nodes: a loopBegin block
   1781 		followed by a loopBlock whereas the start of a (...)+ block is
   1782 		represented as a single node: a plusBlock.  So if first_item_is_guess_block
   1783 		is called when the current node is a loopBegin it starts with the
   1784 		loop block rather than the the sub block which follows the loop block.
   1785 		However, we can't just skip past the loop block because some routines
   1786 		depend on the old implementation.  So, we provide a new implementation
   1787 		which does skip the loopBlock.  However, which should be called when ?
   1788 		I'm not sure, but my guess is that first_item_is_guess_block_extra (the
   1789 		new one) should only be called for the ambiguity routines.
   1790 
   1791     */
   1792 
   1793 	while ( q!=NULL &&
   1794             (  ( q->ntype==nAction ) ||
   1795                ( q->ntype==nJunction &&
   1796                     (q->jtype==Generic /*** || q->jtype == aLoopBlk ***/ ) /*** MR30 Undo MR14 change ***/
   1797                )
   1798             )
   1799           )
   1800 	{
   1801 		if ( q->ntype==nJunction ) q = (Junction *)q->p1;
   1802 		else q = (Junction *) ((ActionNode *)q)->next;
   1803 	}
   1804 
   1805 	if ( q==NULL ) return NULL;
   1806 	if ( q->ntype!=nJunction ) return NULL;
   1807 	if ( q->jtype!=aSubBlk ) return NULL;
   1808 	if ( !q->guess ) return NULL;
   1809 
   1810 	return q;
   1811 }
   1812 
   1813 /* MR1				                 					    */
   1814 /* MR1  10-Apr-97 MR1 Routine to stringize failed semantic predicates msgs  */
   1815 /* MR1				                                                        */
   1816 
   1817 #define STRINGIZEBUFSIZE 1024
   1818 
   1819 static char stringizeBuf[STRINGIZEBUFSIZE];
   1820 char *
   1821 #ifdef __USE_PROTOS
   1822 stringize(char * s)
   1823 #else
   1824 stringize(s)
   1825 char *s;
   1826 #endif
   1827 
   1828 {
   1829   char		*p;
   1830   char		*stop;
   1831 
   1832   p=stringizeBuf;
   1833   stop=&stringizeBuf[1015];
   1834 
   1835   if (s != 0) {
   1836     while (*s != 0) {
   1837       if (p >= stop) {
   1838 	goto stringizeStop;
   1839       } else if (*s == '\n') {
   1840         *p++='\\';
   1841         *p++='n';
   1842         *p++='\\';
   1843 	*p++=*s++;
   1844       } else if (*s == '\\') {
   1845 	*p++=*s;
   1846 	*p++=*s++;
   1847       } else if (*s == '\"') {
   1848         *p++='\\';
   1849 	*p++=*s++;
   1850         while (*s != 0) {
   1851           if (p >= stop) {
   1852 	     goto stringizeStop;
   1853 	  } else if (*s == '\n') {
   1854 	    *p++='\\';
   1855 	    *p++=*s++;
   1856 	  } else if (*s == '\\') {
   1857 	    *p++=*s++;
   1858 	    *p++=*s++;
   1859 	  } else if (*s == '\"') {
   1860 	    *p++='\\';
   1861 	    *p++=*s++;
   1862 	    break;
   1863 	  } else {
   1864 	    *p++=*s++;
   1865           };
   1866         };
   1867       } else if (*s == '\'') {
   1868 	*p++=*s++;
   1869         while (*s != 0) {
   1870           if (p >= stop) {
   1871 	     goto stringizeStop;
   1872 	  } else if (*s == '\'') {
   1873 	    *p++=*s++;
   1874 	    break;
   1875 	  } else if (*s == '\\') {
   1876 	    *p++=*s++;
   1877 	    *p++=*s++;
   1878 	  } else if (*s == '\"') {
   1879 	    *p++='\\';
   1880 	    *p++=*s++;
   1881 	    break;
   1882 	  } else {
   1883 	    *p++=*s++;
   1884           };
   1885         };
   1886       } else {
   1887         *p++=*s++;
   1888       };
   1889     };
   1890   };
   1891   goto stringizeExit;
   1892 stringizeStop:
   1893   *p++='.';
   1894   *p++='.';
   1895   *p++='.';
   1896 stringizeExit:
   1897   *p=0;
   1898   return stringizeBuf;
   1899 }
   1900 
   1901 #ifdef __USE_PROTOS
   1902 int isNullAction(char *s)
   1903 #else
   1904 int isNullAction(s)
   1905   char  *s;
   1906 #endif
   1907 {
   1908   char  *p;
   1909   for (p=s; *p != '\0' ; p++) {
   1910     if (*p != ';' && *p !=' ') return 0;
   1911   };
   1912   return 1;
   1913 }
   1914 /* MR1									                                    */
   1915 /* MR1	End of Routine to stringize code for failed predicates msgs         */
   1916 /* MR1				                                                        */
   1917 
   1918 /* Generate an action.  Don't if action is NULL which means that it was already
   1919  * handled as an init action.
   1920  */
   1921 void
   1922 #ifdef __USE_PROTOS
   1923 genAction( ActionNode *p )
   1924 #else
   1925 genAction( p )
   1926 ActionNode *p;
   1927 #endif
   1928 {
   1929 	require(p!=NULL,			"genAction: invalid node and/or rule");
   1930 	require(p->ntype==nAction,	"genAction: not action");
   1931 
   1932 	if ( !p->done )  /* MR10 */ /* MR11 */
   1933 	{
   1934 		if ( p->is_predicate)
   1935 		{
   1936 			if ( p->guardpred != NULL )
   1937 			{
   1938                 Predicate *guardDup=predicate_dup(p->guardpred); /* MR10 */
   1939                 gen("if (!");
   1940        			guardDup=genPredTreeMain(guardDup, (Node *)p);
   1941                 predicate_free(guardDup);
   1942 			}
   1943 /* MR10 */  else if (p->ampersandPred != NULL) {
   1944 /* MR10 */      gen("if (!");
   1945 /* MR10 */      p->ampersandPred=genPredTreeMain(p->ampersandPred, (Node *)p);
   1946 /* MR10 */  }
   1947 			else
   1948 			{
   1949 				gen("if (!(");
   1950 				/* make sure that '#line n' is on front of line */
   1951 				if ( GenLineInfo && p->file != -1 ) _gen("\n");
   1952 				dumpPredAction(p,p->action, output, 0, p->file, p->line, 0);
   1953 				_gen(")");
   1954 			}
   1955 
   1956 /* MR23 Change failed predicate macro to have three arguments:
   1957 
   1958         macro arg 1: The stringized predicate itself
   1959         macro arg 2: 0 => no user-defined error action
   1960                      1 => user-defined error action
   1961         macro arg 3: The user-defined error action
   1962 
   1963    This gives the user more control of the error action.
   1964 */
   1965 			tabs++;
   1966 			gen3(") {zzfailed_pred(\"%s\",%s, { %s } );}\n",         /* MR23 */
   1967 					stringize(p->action),	                         /* MR23 */
   1968                     (p->pred_fail == NULL ?                          /* MR23/MR27 */
   1969                        	"0 /* report */" : "1 /* user action */"),   /* MR23/MR27 */
   1970                     (p->pred_fail == NULL ?                          /* MR23 */
   1971                         "0; /* no user action */" : p->pred_fail));  /* MR23 */
   1972 			tabs--;
   1973 		}
   1974 		else    /* not a predicate */
   1975 		{
   1976             if (! isNullAction(p->action) && !p->noHoist) {
   1977   	  		  if ( FoundGuessBlk ) {
   1978 				if ( GenCC ) {
   1979                   gen("if ( !guessing ) {\n");
   1980                 } else {
   1981 				  gen("zzNON_GUESS_MODE {\n");
   1982                 };
   1983               };
   1984 			  dumpActionPlus(p, p->action, output, tabs, p->file, p->line, 1); /* MR21 */
   1985 			  if ( FoundGuessBlk ) gen("}\n");
   1986             };
   1987 		}
   1988 	}
   1989 	TRANS(p->next)
   1990 }
   1991 
   1992 /*
   1993  *		if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in
   1994  *		else pass addr of temp root ptr (&_ast) (don't zzlink it in).
   1995  *
   1996  *		if ! modifies rule-ref, then never link it in and never pass zzSTR.
   1997  *		Always pass address of temp root ptr.
   1998  */
   1999 void
   2000 #ifdef __USE_PROTOS
   2001 genRuleRef( RuleRefNode *p )
   2002 #else
   2003 genRuleRef( p )
   2004 RuleRefNode *p;
   2005 #endif
   2006 {
   2007 	Junction *q;
   2008 	char *handler_id = "";
   2009 	RuleEntry *r, *r2;
   2010 	char *parm = "", *exsig = "";
   2011 
   2012     int     genRuleRef_emittedGuessGuard=0;     /* MR10 */
   2013 
   2014 	require(p!=NULL,			"genRuleRef: invalid node and/or rule");
   2015 	require(p->ntype==nRuleRef, "genRuleRef: not rule reference");
   2016 
   2017 	if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
   2018 		handler_id = p->altstart->exception_label;
   2019 
   2020 	r = (RuleEntry *) hash_get(Rname, p->text);
   2021 	if ( r == NULL )
   2022 	{
   2023 		warnFL( eMsg1("rule %s not defined",
   2024 					  p->text), FileStr[p->file], p->line );
   2025 		return;
   2026 	}
   2027 
   2028 /* MR8 5-Aug-97     Reported by S.Bochnak (at) microtool.com.pl                  */
   2029 /*                  Don't do assign when no return values declared          */
   2030 /*                  Move definition of q up and use it to guard p->assign   */
   2031 
   2032 	q = RulePtr[r->rulenum];	/* find definition of ref'd rule */  /* MR8 */
   2033 
   2034 	r2 = (RuleEntry *) hash_get(Rname, p->rname);
   2035 	if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
   2036 
   2037     OutLineInfo(output,p->line,FileStr[p->file]);
   2038 
   2039 	if ( GenCC && GenAST ) {
   2040 		gen("_ast = NULL;\n");
   2041 	}
   2042 
   2043 	if ( FoundGuessBlk && p->assign!=NULL && q->ret != NULL ) {      /* MR8 */
   2044 		if ( GenCC ) {
   2045           gen("if ( !guessing ) {\n");
   2046         } else {
   2047           gen("zzNON_GUESS_MODE {\n");
   2048         };
   2049         tabs++;                                                      /* MR11 */
   2050         genRuleRef_emittedGuessGuard=1;                              /* MR11 */
   2051     };
   2052 
   2053 	if ( FoundException ) exsig = "&_signal";
   2054 
   2055 	tab();
   2056 	if ( GenAST )
   2057 	{
   2058 		if ( GenCC ) {
   2059 /****			if ( r2->noAST || p->astnode==ASTexclude )
   2060 ****/
   2061 			{
   2062 /****				_gen("_ast = NULL;\n");
   2063 ****/
   2064 				parm = "&_ast";
   2065 			}
   2066 /*** we always want to set just a pointer now, then set correct
   2067 pointer after
   2068 
   2069 			else {
   2070 				_gen("_astp =
   2071 (_tail==NULL)?(&_sibling):(&(_tail->_right));\n");
   2072 				parm = "_astp";
   2073 			}
   2074 ****/
   2075 		}
   2076 		else {
   2077 			if ( r2->noAST || p->astnode==ASTexclude )
   2078 			{
   2079 				_gen("_ast = NULL; ");
   2080 				parm = "&_ast";
   2081 			}
   2082 			else parm = "zzSTR";
   2083 		}
   2084 		if ( p->assign!=NULL && q->ret!=NULL )                       /* MR8 */
   2085 		{
   2086 			if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */
   2087 			else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
   2088 		}
   2089 		if ( FoundException ) {
   2090 			_gen5("%s%s(%s,&_signal%s%s); ",
   2091 				  RulePrefix,
   2092 				  p->text,
   2093 				  parm,
   2094 				  (p->parms!=NULL)?",":"",
   2095 				  (p->parms!=NULL)?p->parms:"");
   2096 			if ( p->ex_group!=NULL ) {
   2097 				_gen("\n");
   2098 				gen("if (_signal) {\n");
   2099 				tabs++;
   2100 				dumpException(p->ex_group, 0);
   2101 				tabs--;
   2102 				gen("}");
   2103 			}
   2104 			else {
   2105 				_gen1("if (_signal) goto %s_handler;", handler_id);
   2106 			}
   2107 		}
   2108 		else {
   2109 			_gen5("%s%s(%s%s%s);",
   2110 				  RulePrefix,
   2111 				  p->text,
   2112 				  parm,
   2113 				  (p->parms!=NULL)?",":"",
   2114 				  (p->parms!=NULL)?p->parms:"");
   2115 		}
   2116 		if ( GenCC && (r2->noAST || p->astnode==ASTexclude) )
   2117 		{
   2118 			/* rule has a ! or element does */
   2119 			/* still need to assign to #i so we can play with it */
   2120 			_gen("\n");
   2121 			gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum);
   2122 		}
   2123 		else if ( !r2->noAST && p->astnode == ASTinclude )
   2124 		{
   2125 			/* rule doesn't have a ! and neither does element */
   2126 /* MR10 */  if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) {
   2127 /* MR10 */    _gen("\n");
   2128 /* MR10 */    if (GenCC) gen ("if (!guessing) {    /* MR10 */")
   2129 /* MR10 */          else gen ("if (!zzguessing) {    /* MR10 */\n");
   2130 /* MR10 */    tabs++;
   2131 /* MR10 */  };
   2132 			if ( GenCC ) {
   2133 				_gen("\n");
   2134 				gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n");
   2135 				gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum);
   2136 				tab();
   2137 			}
   2138 			else _gen(" ");
   2139             if ( GenCC ) {
   2140                 _gen("ASTBase::"); }
   2141                 else _gen("zz");
   2142 			_gen("link(_root, &_sibling, &_tail);");
   2143 
   2144 /* MR10 */  if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) {     /* MR10 */
   2145 /* MR10 */    _gen("\n");
   2146 /* MR10 */    tabs--;
   2147 /* MR10 */    if (GenCC) gen ("};    /* MR10 */")
   2148 /* MR10 */          else gen ("};    /* MR10 */");
   2149 /* MR10 */  };
   2150 		}
   2151 	}
   2152 	else
   2153 	{
   2154 		if ( p->assign!=NULL && q->ret!=NULL )                       /* MR8 */
   2155 		{
   2156 			if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */
   2157 			else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum);
   2158 		}
   2159 		if ( FoundException ) {
   2160 			_gen4("%s%s(&_signal%s%s); ",
   2161 				  RulePrefix,
   2162 				  p->text,
   2163 				  (p->parms!=NULL)?",":"",
   2164 				  (p->parms!=NULL)?p->parms:"");
   2165 			if ( p->ex_group!=NULL ) {
   2166 				_gen("\n");
   2167 				gen("if (_signal) {\n");
   2168 				tabs++;
   2169 				dumpException(p->ex_group, 0);
   2170 				tabs--;
   2171 				gen("}");
   2172 			}
   2173 			else {
   2174 				_gen1("if (_signal) goto %s_handler;", handler_id);
   2175 			}
   2176 		}
   2177 		else {
   2178 			_gen3("%s%s(%s);",
   2179 				  RulePrefix,
   2180 				  p->text,
   2181 				  (p->parms!=NULL)?p->parms:"");
   2182 		}
   2183 		if ( p->assign!=NULL && q->ret!=NULL ) _gen("\n");           /* MR8 */
   2184 	}
   2185 
   2186 	if ( p->assign!=NULL && q->ret!=NULL) {                          /* MR8 */
   2187 		if ( hasMultipleOperands(p->assign) )                        /* MR23 */
   2188 		{
   2189 			_gen("\n");
   2190 			dumpRetValAssign(p->assign, q->ret, p);                  /* MR30 */
   2191 			_gen("}");
   2192 		}
   2193 	}
   2194 	_gen("\n");
   2195 
   2196 	/* Handle element labels now */
   2197 	if ( p->el_label!=NULL )
   2198 	{
   2199 		if ( GenAST )
   2200 		{
   2201 			if ( GenCC ) {
   2202 				gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
   2203 			}
   2204 			else {gen1("%s_ast = zzastCur;\n", p->el_label);}
   2205 		}
   2206        	else if (!GenCC ) {
   2207 			gen1("%s = zzaCur;\n", p->el_label);
   2208         }
   2209 	}
   2210 
   2211 	if ( FoundGuessBlk && p->assign!=NULL && q->ret!=NULL ) {       /* MR8 */
   2212 		/* in guessing mode, don't branch to handler upon error */
   2213         tabs--;                                                     /* MR11 */
   2214 		gen("} else {\n");
   2215         tabs++;                                                     /* MR11 */
   2216 		if ( FoundException ) {
   2217 			gen6("%s%s(%s%s&_signal%s%s);\n",
   2218 				 RulePrefix,
   2219 				 p->text,
   2220 				 parm,
   2221                  (*parm!='\0')?",":"",
   2222                  (p->parms!=NULL)?",":"",
   2223 				 (p->parms!=NULL)?p->parms:"");
   2224 		}
   2225 		else {
   2226 			gen5("%s%s(%s%s%s);\n",
   2227 				 RulePrefix,
   2228 				 p->text,
   2229 				 parm,
   2230 				 (p->parms!=NULL && *parm!='\0')?",":"",
   2231 				 (p->parms!=NULL)?p->parms:"");
   2232 		}
   2233         tabs--;                                                     /* MR11 */
   2234 		gen("}\n");
   2235 	}
   2236 	TRANS(p->next)
   2237 }
   2238 
   2239 /*
   2240  * Generate code to match a token.
   2241  *
   2242  * Getting the next token is tricky.  We want to ensure that any action
   2243  * following a token is executed before the next GetToken();
   2244  */
   2245 void
   2246 #ifdef __USE_PROTOS
   2247 genToken( TokNode *p )
   2248 #else
   2249 genToken( p )
   2250 TokNode *p;
   2251 #endif
   2252 {
   2253 	RuleEntry *r;
   2254 	char *handler_id = "";
   2255 	ActionNode *a;
   2256 	char *set_name;
   2257 	char *set_nameErrSet;
   2258 	int complement;
   2259 	int ast_label_in_action = 0;	/* MR27 */
   2260 	int pushedCmodeAST = 0;			/* MR27 */
   2261 
   2262 	require(p!=NULL,			"genToken: invalid node and/or rule");
   2263 	require(p->ntype==nToken,	"genToken: not token");
   2264 	if ( p->altstart!=NULL && p->altstart->exception_label!=NULL )
   2265 		handler_id = p->altstart->exception_label;
   2266 
   2267 	r = (RuleEntry *) hash_get(Rname, p->rname);
   2268 	if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;}
   2269 
   2270 /*
   2271  * MR27 Has the element label been referenced as an AST (with the # operator) ?
   2272  *      If so, then we'll want to build the AST even though the user has used
   2273  *      the ! operator.
   2274  */
   2275 /* MR27 */	if (GenAST && p->el_label != NULL) {
   2276 /* MR27 */		ast_label_in_action = list_search_cstring(r->ast_labels_in_actions,
   2277 /* MR27 */		                                          p->el_label);
   2278 /* MR27 */	}
   2279 
   2280     OutLineInfo(output,p->line,FileStr[p->file]);
   2281 
   2282 	if ( !set_nil(p->tset) )	/* implies '.', ~Tok, or tokenclass */
   2283 	{
   2284 		unsigned e;
   2285 		unsigned eErrSet = 0;
   2286 		set b;
   2287 		set bErrSet;					/* MR23 */
   2288 		b = set_dup(p->tset);
   2289 		bErrSet = set_dup(p->tset);	    /* MR23 */
   2290 		complement = p->complement; /* MR23 */
   2291 		if ( p->tclass!=NULL  && complement == 0 /* MR23 */) { /* token class not complemented*/
   2292 			static char buf[MaxRuleName+20];	    /* MR23 */
   2293 			static char bufErrSet[MaxRuleName+20];	/* MR23 */
   2294 			if ( p->tclass->dumped ) {
   2295 				e = p->tclass->setnum;
   2296 				eErrSet = p->tclass->setnumErrSet;
   2297 			}
   2298 			else {
   2299 				e = DefErrSet(&b, 0, TokenString(p->token));
   2300 				eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errset");
   2301 				p->tclass->dumped = 1;	/* indicate set has been created */
   2302 				p->tclass->setnum = e;
   2303 				p->tclass->setnumErrSet = eErrSet;					/* MR23 */
   2304 			}
   2305 			sprintf(buf, "%s_set", TokenString(p->token));
   2306 			sprintf(bufErrSet, "%s_errset", TokenString(p->token));	/* MR23 */
   2307 			set_name = buf;
   2308 			set_nameErrSet = bufErrSet;								/* MR23 */
   2309 		}
   2310 
   2311 		/* MR23 - Forgot about the case of ~TOKCLASS. */
   2312 
   2313 		else if ( p->tclass!=NULL  && complement != 0 /* MR23 */)
   2314 		{
   2315 			static char buf[MaxRuleName+20];	    /* MR23 */
   2316 			static char bufErrSet[MaxRuleName+20];	/* MR23 */
   2317 			if ( p->tclass->dumpedComplement ) {
   2318 				e = p->tclass->setnumComplement;
   2319 				eErrSet = p->tclass->setnumErrSetComplement;
   2320 			}
   2321 			else {
   2322 				e = DefErrSetWithSuffix(0, &b, 0, TokenString(p->token), "_setbar");
   2323 				eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errsetbar");
   2324 				p->tclass->dumpedComplement = 1;	/* indicate set has been created */
   2325 				p->tclass->setnumComplement = e;
   2326 				p->tclass->setnumErrSetComplement = eErrSet;					/* MR23 */
   2327 			}
   2328 			sprintf(buf, "%s_setbar", TokenString(p->token));
   2329 			sprintf(bufErrSet, "%s_errsetbar", TokenString(p->token));	/* MR23 */
   2330 			set_name = buf;
   2331 			set_nameErrSet = bufErrSet;								/* MR23 */
   2332 		}
   2333 		else {					/* wild card */
   2334 			static char buf[sizeof("zzerr")+10];
   2335 			static char bufErrSet[sizeof("zzerr")+10];
   2336 			int n = DefErrSet( &b, 0, NULL );
   2337 			int nErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, NULL, "_set");
   2338 			if ( GenCC ) sprintf(buf, "err%d", n);
   2339 			else sprintf(buf, "zzerr%d", n);
   2340 			if ( GenCC ) sprintf(bufErrSet, "err%d", nErrSet);
   2341 			else sprintf(bufErrSet, "zzerr%d", nErrSet);
   2342 			set_name = buf;
   2343 			set_nameErrSet = bufErrSet;
   2344 		}
   2345 
   2346 		if ( !FoundException ) {
   2347 /* MR23 */		gen2("zzsetmatch(%s, %s);", set_name, set_nameErrSet);
   2348 		}
   2349 		else if ( p->ex_group==NULL ) {
   2350             if ( p->use_def_MT_handler )
   2351                 gen3("zzsetmatch_wdfltsig(%s,(ANTLRTokenType)%d,%s);",
   2352                      set_name,
   2353                      p->token,
   2354                      tokenFollowSet(p))
   2355             else
   2356                 gen2("zzsetmatch_wsig(%s, %s_handler);",
   2357                      set_name,
   2358                      handler_id);
   2359 		}
   2360 		else
   2361 		{
   2362 			gen1("if ( !_setmatch_wsig(%s) ) {\n", set_name);
   2363 			tabs++;
   2364 /* MR6 */	if (FoundGuessBlk) {
   2365 /* MR6 */	  if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
   2366 /* MR6 */	  else gen("if ( zzguessing ) goto fail;\n");
   2367 /* MR6 */	};
   2368 			gen("_signal=MismatchedToken;\n");
   2369 			dumpException(p->ex_group, 0);
   2370 			tabs--;
   2371 			gen("}\n");
   2372 		}
   2373 		set_free(b);
   2374 		set_free(bErrSet);
   2375 	}
   2376 	else if ( TokenString(p->token)!=NULL )
   2377 	{
   2378 		if ( FoundException ) {
   2379 			if ( p->use_def_MT_handler )
   2380 				gen2("zzmatch_wdfltsig(%s,%s);",TokenString(p->token),tokenFollowSet(p))
   2381 			else if ( p->ex_group==NULL )
   2382 			{
   2383 				gen2("zzmatch_wsig(%s, %s_handler);",
   2384 					 TokenString(p->token),
   2385 					 handler_id);
   2386 			}
   2387 			else
   2388 			{
   2389 /* MR6 */		if (GenCC) {
   2390 /* MR6 */		  gen1("if ( !_match_wsig(%s) ) {\n", TokenString(p->token));
   2391 /* MR6 */		} else {
   2392 /* MR6 */		  gen1("if ( !_zzmatch_wsig(%s) ) {\n", TokenString(p->token));
   2393 /* MR6 */		};
   2394 				tabs++;
   2395 /* MR6 */		if (FoundGuessBlk) {
   2396 /* MR6 */	  	  if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
   2397 /* MR6 */		  else gen("if ( zzguessing ) goto fail;\n");
   2398 /* MR6 */		};
   2399 				gen("_signal=MismatchedToken;\n");
   2400 				dumpException(p->ex_group, 0);
   2401 				tabs--;
   2402 				gen("}\n");
   2403 			}
   2404 		}
   2405 		else gen1("zzmatch(%s);", TokenString(p->token));
   2406 	}
   2407 	else {
   2408         if ( FoundException ) {
   2409             if ( p->use_def_MT_handler )
   2410 				gen2("zzmatch_wdfltsig((ANTLRTokenType)%d,%s);",
   2411 					 p->token,tokenFollowSet(p))
   2412             else
   2413                 gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id);
   2414         }
   2415 		else {gen1("zzmatch(%d);", p->token);}
   2416 	}
   2417 
   2418 	a = findImmedAction( p->next );
   2419 	/* generate the token labels */
   2420 	if ( GenCC && p->elnum>0 )
   2421 	{
   2422 		/* If building trees in C++, always gen the LT() assigns */
   2423 		if ( set_el(p->elnum, tokensRefdInBlock) || GenAST )
   2424 		{
   2425 /* MR10 */	if ( FoundGuessBlk ) {
   2426 /* MR10 */    gen("\n");
   2427 /* MR10 */    if (p->label_used_in_semantic_pred) {
   2428 /* MR10 */		gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);  /* MR10 */\n", BlkLevel-1, p->elnum);
   2429 /* MR10 */    } else {
   2430 /* MR10 */		gen("if ( !guessing ) {\n"); tab();
   2431 /* MR10 */		_gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);\n", BlkLevel-1, p->elnum);
   2432 /* MR10 */      gen("}\n");
   2433 /* MR10 */    };
   2434 /* MR10 */  } else {
   2435 /* MR10 */	  _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);", BlkLevel-1, p->elnum);
   2436 /* MR10 */  };
   2437 /* MR10 */
   2438 		}
   2439 
   2440 /*
   2441  *  MR23 labase is never used in the C++ runtime library.
   2442  *       and this code is generated only in C++ mode
   2443  */
   2444 
   2445 /***		if ( LL_k>1 )                                    / * MR23 disabled */
   2446 /***			if ( !DemandLookahead ) _gen(" labase++;");  / * MR23 disabled */
   2447 /***		_gen("\n");                                      / * MR23 disabled */
   2448 /***		tab();                                           / * MR23 disabled */
   2449 	}
   2450 	if ( GenAST )
   2451 	{
   2452 		if ( FoundGuessBlk &&
   2453 				(ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) )
   2454 		{
   2455 			if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();}
   2456 			else {_gen("zzNON_GUESS_MODE {\n"); tab();}
   2457 		}
   2458 
   2459 /* MR27 addition when labels referenced when operator ! used */
   2460 
   2461 		pushedCmodeAST = 0; /* MR27 */
   2462 		if (ast_label_in_action && (p->astnode == ASTexclude || r->noAST)) {
   2463 			_gen("\n");
   2464 			if (GenCC) {
   2465 /* MR13 */      if (NewAST) {
   2466 /* MR13 */    	    gen4("_ast%d%d = newAST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
   2467 /* MR13 */      } else {
   2468 /* MR13 */    	    gen4("_ast%d%d = new AST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
   2469 /* MR13 */      }
   2470 			}
   2471 			else {
   2472 				pushedCmodeAST = 1;
   2473 				gen("zzastPush(zzmk_ast(zzastnew(),zzaCur)); /* MR27 */");
   2474 			}
   2475 		}
   2476 
   2477 /* end MR27 addition for labels referenced when operator ! used */
   2478 
   2479 		if (!r->noAST )
   2480 		{
   2481 			if (GenCC && !(p->astnode == ASTexclude) ) {
   2482 				_gen("\n");
   2483 /* MR13 */      if (NewAST) {
   2484 /* MR13 */    	    gen4("_ast%d%d = newAST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
   2485 /* MR13 */      } else {
   2486 /* MR13 */    	    gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum);
   2487 /* MR13 */      }
   2488 				tab();
   2489 			}
   2490 			if ( GenCC && !(p->astnode == ASTexclude) )
   2491 				{_gen2("_ast%d%d->", BlkLevel-1, p->elnum);}
   2492 			else _gen(" ");
   2493 			if ( p->astnode==ASTchild ) {
   2494 				if ( !GenCC ) _gen("zz");
   2495 				_gen("subchild(_root, &_sibling, &_tail);");
   2496 			}
   2497 			else if ( p->astnode==ASTroot ) {
   2498 				if ( !GenCC ) _gen("zz");
   2499 				_gen("subroot(_root, &_sibling, &_tail);");
   2500 			}
   2501 			if ( GenCC && !(p->astnode == ASTexclude) ) {
   2502 				_gen("\n");
   2503 				tab();
   2504 			}
   2505 		}
   2506 		else if ( !GenCC ) {
   2507 			if (! pushedCmodeAST) _gen(" zzastDPush;");
   2508 		}
   2509 		if ( FoundGuessBlk &&
   2510 				(ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) )
   2511 			{gen("}\n"); tab();}
   2512 	}
   2513 
   2514 	/* Handle element labels now */
   2515 	if ( p->el_label!=NULL )
   2516 	{
   2517         int     done_NON_GUESSMODE=0;
   2518 
   2519 		_gen("\n");
   2520 
   2521 /* MR10 */    /* do Attrib / Token ptr for token label used in semantic pred */
   2522 /* MR10 */    /* for these cases do assign even in guess mode                */
   2523 /* MR10 */
   2524 /* MR10 */    if (p->label_used_in_semantic_pred) {
   2525 /* MR10 */      if ( GenCC ) {
   2526 /* MR10 */        if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {
   2527 /* MR10 */          gen3("%s = _t%d%d;", p->el_label, BlkLevel-1, p->elnum);
   2528 /* MR10 */        } else {
   2529 /* MR10 */          gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);
   2530 /* MR10 */        };
   2531 /* MR10 */      } else {
   2532 /* MR10 */		  gen1("%s = zzaCur;", p->el_label);
   2533 /* MR10 */      };
   2534 /* MR10 */      if (FoundGuessBlk) _gen("  /* MR10 */");
   2535 /* MR10 */      _gen("\n");
   2536 /* MR10 */    };
   2537 
   2538 		/* Do Attrib / Token ptr */
   2539 
   2540 /* MR10 */  if (! p->label_used_in_semantic_pred) {
   2541 /* MR10 */
   2542 /* MR10 */      if ( FoundGuessBlk ) {
   2543 /* MR10 */        if (! done_NON_GUESSMODE) {
   2544 /* MR10 */          done_NON_GUESSMODE=1;
   2545 /* MR10 */          if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
   2546 /* MR10 */          else {gen("zzNON_GUESS_MODE {\n"); tab();}
   2547 /* MR10 */        };
   2548 /* MR10 */      };
   2549 /* MR10 */
   2550 /* MR10 */      if ( GenCC ) {
   2551 /* MR10 */        if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) {
   2552 /* MR10 */          gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
   2553 /* MR10 */        } else {
   2554 /* MR10 */          gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label);
   2555 /* MR10 */        };
   2556 /* MR10 */      } else {
   2557 /* MR10 */        gen1("%s = zzaCur;\n", p->el_label);
   2558 /* MR10 */      };
   2559 /* MR10 */  };
   2560 
   2561 		/* Do AST ptr */
   2562 
   2563 		if (GenAST && (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST) )) /* MR27 */
   2564 		{
   2565 
   2566 /* MR10 */      if ( FoundGuessBlk ) {
   2567 /* MR10 */        if (! done_NON_GUESSMODE) {
   2568 /* MR10 */          done_NON_GUESSMODE=1;
   2569 /* MR10 */          if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();}
   2570 /* MR10 */          else {gen("zzNON_GUESS_MODE {\n"); tab();}
   2571 /* MR10 */        };
   2572 /* MR10 */      };
   2573 
   2574 			if ( GenCC ) {
   2575 				gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum);
   2576 			}
   2577 			else {gen1("%s_ast = zzastCur;\n", p->el_label);}
   2578 		}
   2579 
   2580 /* MR10 */  if (done_NON_GUESSMODE) {
   2581 /* MR10 */    gen("}\n"); tab();
   2582 /* MR10 */  };
   2583 
   2584 	}
   2585 
   2586 	/* Handle any actions immediately following action */
   2587 	if ( a != NULL )  /* MR10 */ /* MR11 */
   2588     {
   2589     	/* delay next token fetch until after action */
   2590 		_gen("\n");
   2591 		if ( a->is_predicate)
   2592 		{
   2593 #if 0
   2594 /* Disabled in MR30 ************************************************************
   2595    And moved into genAction
   2596    *****************************************************************************
   2597 */
   2598 
   2599     	    gen("if (!(");
   2600 
   2601 			/* make sure that '#line n' is on front of line */  /* MR14 */
   2602 			if ( GenLineInfo && p->file != -1 ) _gen("\n");     /* MR14 */
   2603 			dumpPredAction(a,a->action, output, 0, a->file, a->line, 0);
   2604 
   2605 /* MR23 Change failed predicate macro to have three arguments:
   2606 
   2607         macro arg 1: The stringized predicate itself
   2608         macro arg 2: 0 => no user-defined error action
   2609                      1 => user-defined error action
   2610         macro arg 3: The user-defined error action
   2611 
   2612    This gives the user more control of the error action.
   2613 */
   2614 			_gen(")) \n");
   2615 			tabs++;
   2616 			gen3(" {zzfailed_pred(\"%s\",%s,{ %s } );}\n",           /* MR23 */
   2617 					stringize(a->action),	                         /* MR23 */
   2618                     (a->pred_fail == NULL ?                          /* MR23/MR27 */
   2619                        	"0 /* report */" : "1 /* user action */"),   /* MR23/MR27 */
   2620                     (a->pred_fail == NULL ?                          /* MR23 */
   2621                         "0; /* no user action */" : a->pred_fail));  /* MR23 */
   2622 			tabs--;
   2623 /* Disabled in MR30 ************************************************************
   2624    And moved into genAction
   2625    *****************************************************************************
   2626 */
   2627 #endif
   2628 		}
   2629 		else    /* MR9 a regular action - not a predicate action */
   2630 		{
   2631 
   2632 /* MR23: Search an action which is not a predicate for LT(i),
   2633          LA(i), or LATEXT(i) in order to warn novice users that
   2634          it refers to the previous matched token, not the next
   2635          one.  This is different than the case for semantic
   2636          predicates.
   2637 */
   2638 
   2639 /* MR23 */    if (GenCC) {
   2640 /* MR23 */	    if (strstr(a->action, "LT(") != NULL) LTinTokenAction = 1;
   2641 /* MR23 */    }
   2642 /* MR23 */    else {
   2643 /* MR23 */      if (strstr(a->action, "LA(") != NULL) LTinTokenAction = 1;
   2644 /* MR23 */      if (strstr(a->action, "LATEXT(") != NULL) LTinTokenAction = 1;
   2645 /* MR23 */    }
   2646 
   2647 			if ( FoundGuessBlk ) {
   2648    				if ( GenCC ) {gen("if ( !guessing ) {\n");}
   2649    				else gen("zzNON_GUESS_MODE {\n");
   2650 			}
   2651    			dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1); /* MR21 */
   2652        		if ( FoundGuessBlk ) gen("}\n");
   2653 			a->done = 1; /* MR30 */
   2654  		}
   2655 /***    a->done = 1;  MR30 Moved up into then branch for true actions, but not predicates ***/
   2656 		if ( !DemandLookahead ) {
   2657 			if ( GenCC ) {
   2658 				if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)");
   2659 				_gen(" consume();")
   2660                 if ( FoundException && p->use_def_MT_handler )
   2661                     _gen(" _signal=NoSignal;");
   2662                 _gen("\n");
   2663 			}
   2664             else
   2665             {
   2666                 if ( FoundException && p->use_def_MT_handler ) _gen("if (!_signal)");
   2667 					_gen(" zzCONSUME;\n");
   2668                 if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
   2669                 _gen("\n");
   2670             }
   2671 		}
   2672 		else gen("\n");
   2673 		if (a->done) {			/* MR30 */
   2674 			TRANS( a->next );   /* MR30 */
   2675 		}						/* MR30 */
   2676 		else {					/* MR30 */
   2677 			TRANS( p->next );	/* MR30 */
   2678 		}						/* MR30 */
   2679 	}
   2680 	else
   2681 	{
   2682         if ( !DemandLookahead ) {
   2683 			if ( GenCC ) {
   2684 				if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
   2685 				_gen(" consume();")
   2686 				if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;");
   2687 				_gen("\n");
   2688 			}
   2689 			else {
   2690 				if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)");
   2691 				_gen(" zzCONSUME;");
   2692 				if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;");
   2693 				_gen("\n");
   2694 			}
   2695 		}
   2696 		else _gen("\n");
   2697 		TRANS(p->next);
   2698 	}
   2699 }
   2700 
   2701 /*  MR21
   2702  *
   2703  *  There was a bug in the code generation for {...} which causes it
   2704  *  to omit the optional tokens from the error messages.  The easiest
   2705  *  way to fix this was to make the opt block look like a sub block:
   2706  *
   2707  *          { a | b | c }
   2708  *
   2709  *  becomes (internally):
   2710  *
   2711  *          ( a | b | c | )
   2712  *
   2713  *  The code for genOptBlk is now identical to genSubBlk except for
   2714  *  cosmetic changes.
   2715  */
   2716 
   2717 void
   2718 #ifdef __USE_PROTOS
   2719 genOptBlk( Junction *q )
   2720 #else
   2721 genOptBlk( q )
   2722 Junction *q;
   2723 #endif
   2724 {
   2725 	int max_k;
   2726 	set f;
   2727 	int need_right_curly;
   2728 	set savetkref;
   2729 	int lastAltEmpty;			/* MR23 */
   2730 	savetkref = tokensRefdInBlock;
   2731 	require(q->ntype == nJunction,	"genOptBlk: not junction");
   2732 	require(q->jtype == aOptBlk,	"genOptBlk: not opt block");
   2733 
   2734     OutLineInfo(output,q->line,FileStr[q->file]);
   2735 	BLOCK_Preamble(q);
   2736 	BlkLevel++;
   2737     BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */
   2738 	f = genBlk(q, aOptBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
   2739 /* MR23
   2740    Bypass error clause generation when exceptions are used in {...} block
   2741    See multi-line note in genBlk near call to isEmptyAlt.
   2742 */
   2743 	if (! FoundException) {
   2744 	    if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}
   2745 	}
   2746 	else {
   2747 		gen("/* MR23 skip error clause for {...} when exceptions in use */\n");
   2748 	}
   2749 	{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
   2750 	freeBlkFsets(q);
   2751 	--BlkLevel;
   2752 	BLOCK_Tail();
   2753 
   2754 	if ( q->guess )
   2755 	{
   2756 		gen("zzGUESS_DONE\n");
   2757 	}
   2758 
   2759 	/* must duplicate if (alpha)?; one guesses (validates), the
   2760 	 * second pass matches */
   2761 	if ( q->guess && analysis_point(q)==q )
   2762 	{
   2763         OutLineInfo(output,q->line,FileStr[q->file]);
   2764 		BLOCK_Preamble(q);
   2765 		BlkLevel++;
   2766 		f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
   2767 		if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}
   2768 		{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
   2769 		freeBlkFsets(q);
   2770 		--BlkLevel;
   2771 		BLOCK_Tail();
   2772 	}
   2773 
   2774 	tokensRefdInBlock = savetkref;
   2775 	if (q->end->p1 != NULL) TRANS(q->end->p1);
   2776 }
   2777 
   2778 /*
   2779  * Generate code for a loop blk of form:
   2780  *
   2781  *				 |---|
   2782  *				 v   |
   2783  *			   --o-G-o-->o--
   2784  */
   2785 void
   2786 #ifdef __USE_PROTOS
   2787 genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k )
   2788 #else
   2789 genLoopBlk( begin, q, start, max_k )
   2790 Junction *begin;
   2791 Junction *q;
   2792 Junction *start;	/* where to start generating code from */
   2793 int max_k;
   2794 #endif
   2795 {
   2796 	set         f;
   2797 	int         need_right_curly;
   2798 	set         savetkref;
   2799     Junction    *guessBlock;    /* MR10 */
   2800     int         singleAlt;      /* MR10 */
   2801 	int			lastAltEmpty;	/* MR23 */
   2802 
   2803 	savetkref = tokensRefdInBlock;
   2804 	require(q->ntype == nJunction,	"genLoopBlk: not junction");
   2805 	require(q->jtype == aLoopBlk,	"genLoopBlk: not loop block");
   2806 
   2807 	if ( q->visited ) return;
   2808 	q->visited = TRUE;
   2809 
   2810     /* first_item_is_guess_block doesn't care what kind of node it is */
   2811 
   2812     guessBlock=first_item_is_guess_block( (Junction *) q->p1);  /* MR10 */
   2813     singleAlt=q->p2==NULL;                                      /* MR10 */
   2814 
   2815 	if (singleAlt && !guessBlock)	    /* MR10 */ /* only one alternative? */
   2816 	{
   2817 		if ( DemandLookahead ) {
   2818 			if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
   2819 			else gen1("look(%d);\n", max_k);
   2820 		}
   2821 		gen("while ( ");
   2822 		if ( begin!=NULL ) genExpr(begin);
   2823 		else genExpr(q);
   2824 		/* if no predicates have been hoisted for this single alt (..)*
   2825 		 * do so now
   2826 		 */
   2827         require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
   2828 		if ( ParseWithPredicates && begin->predicate==NULL )
   2829 		{
   2830 			Predicate *a = MR_find_predicates_and_supp((Node *)q->p1);
   2831             require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
   2832 
   2833 			if ( a!=NULL )
   2834 			{
   2835 				_gen("&&");
   2836 				a=genPredTreeMain(a, (Node *)q);    /* MR10 */
   2837 			}
   2838 /* MR10 */  if (MRhoisting) {
   2839 /* MR10 */    predicate_free(a);
   2840 /* MR10 */  };
   2841 		}
   2842 		_gen(" ) {\n");
   2843 		tabs++;
   2844 		TRANS(q->p1);
   2845 		if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
   2846 		if ( DemandLookahead ) {
   2847 			if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
   2848 			else gen1("look(%d);\n", max_k);
   2849 		}
   2850 		--tabs;
   2851 		gen("}\n");
   2852 		freeBlkFsets(q);
   2853 		q->visited = FALSE;
   2854 		tokensRefdInBlock = savetkref;
   2855 		return;
   2856 	}
   2857 	gen("for (;;) {\n");        /* MR20 G. Hobbelt */
   2858 	tabs++;
   2859 /* MR6				                					*/
   2860 /* MR6 	   "begin" can never be null when called from genLoopBegin	*/
   2861 /* MR6     because q==(Junction *)begin->p1 and we know q is valid	*/
   2862 /* MR6								                            	*/
   2863 /* MR6	   from genLoopBegin:						                */
   2864 /* MR6			                						            */
   2865 /* MR6		 if ( LL_k>1 && !set_nil(q->fset[2]) )			        */
   2866 /* MR6	 	   genLoopBlk( q, (Junction *)q->p1, q, max_k );	    */
   2867 /* MR6		else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );	*/
   2868 /* MR6				                				            	*/
   2869 	if ( begin!=NULL )
   2870 	{
   2871 		if ( DemandLookahead )
   2872 		{
   2873 			if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
   2874 			else gen1("look(%d);\n", max_k);
   2875 		}
   2876 		/* The bypass arc of the (...)* predicts what to do when you fail, but
   2877 		 * ONLY after having tested the loop start expression.  To avoid this,
   2878 		 * we simply break out of the (...)* loop when we find something that
   2879 		 * is not in the prediction of the loop (all alts thereof).
   2880 		 */
   2881 		gen("if ( !(");
   2882 
   2883 /***	TJP says: It used to use the prediction expression for the bypass arc
   2884      	of the (...)*.  HOWEVER, if a non LL^1(k) decision was found, this
   2885     	thing would miss the ftree stored in the aLoopBegin node and generate
   2886     	an LL^1(k) decision anyway.
   2887 
   2888  ***		genExpr((Junction *)begin->p2);
   2889  ***/
   2890 
   2891             genExpr((Junction *)begin);
   2892             _gen(")) break;\n");
   2893 
   2894 	}
   2895 
   2896 	/* generate code for terminating loop (this is optional branch) */
   2897 
   2898 	f = genBlk(q, aLoopBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
   2899 	set_free(f);
   2900 	freeBlkFsets(q);
   2901 
   2902 	/* generate code for terminating loop (this is optional branch) */
   2903 
   2904 /* MR6 						                    			            */
   2905 /* MR6  30-May-97 Bug reported by Manuel Ornato				            */
   2906 /* MR6            A definite bug involving the exit from a loop block   */
   2907 /* MR6 		  In 1.23 and later versions (including 1.33) Instead       */
   2908 /* MR6              exiting the block and reporting a syntax error the  */
   2909 /* MR6		    code loops forever.     				                */
   2910 /* MR6	          Looking at 1.20 which generates proper code it is not */
   2911 /* MR6		    clear which of two changes should be undone.            */
   2912 /* MR6		  This is my best guess.                                    */
   2913 /* MR6		  From earlier MR6 note we know that begin can never be     */
   2914 /* MR6		    null when genLoopBlk called from genLoopBegin           */
   2915 /* MR6 */
   2916 /* MR6 */ if ( begin==NULL) {
   2917 /* MR6 */   /* code for exiting loop "for sure" */
   2918 /* MR6 */   gen("/* Suppressed by MR6 */ /*** else break; ***/\n");
   2919 /* MR6 */ };
   2920 
   2921 /* MR10 */if (singleAlt && guessBlock) {
   2922 /* MR10 */  tabs--;
   2923 /* MR6 */   gen("} else break; /* MR6 code for exiting loop \"for sure\" */\n");
   2924 /* MR10 */  need_right_curly--;
   2925 /* MR10 */ } else {
   2926 /* MR6 */   gen("else break; /* MR6 code for exiting loop \"for sure\" */\n");
   2927 /* MR10 */ };
   2928 
   2929 	{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
   2930 	if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
   2931 	--tabs;
   2932 	gen("}\n");
   2933 	q->visited = FALSE;
   2934 	tokensRefdInBlock = savetkref;
   2935 }
   2936 
   2937 /*
   2938  * Generate code for a loop blk of form:
   2939  *
   2940  * 				         |---|
   2941  *					     v   |
   2942  *			   --o-->o-->o-G-o-->o--
   2943  *                   |           ^
   2944  *                   v           |
   2945  *					 o-----------o
   2946  *
   2947  * q->end points to the last node (far right) in the blk.
   2948  *
   2949  * Note that q->end->jtype must be 'EndBlk'.
   2950  *
   2951  * Generate code roughly of the following form:
   2952  *
   2953  *	do {
   2954  *		... code for alternatives ...
   2955  *  } while ( First Set of aLoopBlk );
   2956  *
   2957  *	OR if > 1 alternative
   2958  *
   2959  *	do {
   2960  *		... code for alternatives ...
   2961  *		else break;
   2962  *  } while ( 1 );
   2963  */
   2964 void
   2965 #ifdef __USE_PROTOS
   2966 genLoopBegin( Junction *q )
   2967 #else
   2968 genLoopBegin( q )
   2969 Junction *q;
   2970 #endif
   2971 {
   2972 	set f;
   2973 	int i;
   2974 	int max_k;
   2975 	set savetkref;
   2976 	savetkref = tokensRefdInBlock;
   2977 	require(q!=NULL,				"genLoopBegin: invalid node and/or rule");
   2978 	require(q->ntype == nJunction,	"genLoopBegin: not junction");
   2979 	require(q->jtype == aLoopBegin,	"genLoopBegin: not loop block");
   2980 	require(q->p2!=NULL,			"genLoopBegin: invalid Loop Graph");
   2981 
   2982     OutLineInfo(output,q->line,FileStr[q->file]);
   2983 
   2984 	BLOCK_Preamble(q);
   2985 	BlkLevel++;
   2986     BlockPreambleOption(q,q->pFirstSetSymbol);       /* MR21 */
   2987 	f = First(q, 1, aLoopBegin, &max_k);
   2988 	/* If not simple LL(1), must specify to start at LoopBegin, not LoopBlk */
   2989 	if ( LL_k>1 && !set_nil(q->fset[2]) )
   2990 		genLoopBlk( q, (Junction *)q->p1, q, max_k );
   2991 	else genLoopBlk( q, (Junction *)q->p1, NULL, max_k );
   2992 
   2993 	for (i=1; i<=CLL_k; i++) set_free(q->fset[i]);
   2994 	for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]);
   2995 	--BlkLevel;
   2996 	BLOCK_Tail();
   2997 	set_free(f);
   2998 	tokensRefdInBlock = savetkref;
   2999 /* MR21 */	if (MR_BlkErr) {
   3000 /* MR21 */		set f, fArray[2];
   3001 /* MR21 */		f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ );
   3002 /* MR21 */      fArray[0]= empty;
   3003 /* MR21 */		fArray[1]= set_dup(f);
   3004 /* MR21 */      gen("if (");
   3005 /* MR21 */      genExprSets(fArray,1);  /* note: destroys set arguments */
   3006 /* MR21 */      _gen(") { /* MR21 option -mrblksynerr */\n");
   3007 /* MR21 */      tabs++;
   3008 /* MR21 */      tab();
   3009 /* MR21 */      _gen("/* nothing */ }\n");
   3010 /* MR21 */      tab();
   3011 /* MR21 */      makeErrorClause(q,f,1,0 /* use plus block bypass ? */ );  /* frees set */
   3012 /* MR21 */      tabs--;
   3013 /* MR21 */	};
   3014 	if (q->end->p1 != NULL) TRANS(q->end->p1);
   3015 }
   3016 
   3017 /*
   3018  * Generate code for a loop blk of form:
   3019  *
   3020  * 					 |---|
   3021  *					 v   |
   3022  *			       --o-G-o-->o--
   3023  *
   3024  * q->end points to the last node (far right) in the blk.
   3025  * Note that q->end->jtype must be 'EndBlk'.
   3026  *
   3027  * Generate code roughly of the following form:
   3028  *
   3029  *	do {
   3030  *		... code for alternatives ...
   3031  *  } while ( First Set of aPlusBlk );
   3032  *
   3033  *	OR if > 1 alternative
   3034  *
   3035  *	do {
   3036  *		... code for alternatives ...
   3037  *		else if not 1st time through, break;
   3038  *  } while ( 1 );
   3039  */
   3040 void
   3041 #ifdef __USE_PROTOS
   3042 genPlusBlk( Junction *q )
   3043 #else
   3044 genPlusBlk( q )
   3045 Junction *q;
   3046 #endif
   3047 {
   3048 	int         max_k;
   3049 	set         f;
   3050 	int         need_right_curly;
   3051 	int			lastAltEmpty;	/* MR23 */
   3052 	set         savetkref;
   3053     Junction    *guessBlock;    /* MR10 */
   3054     int         singleAlt;      /* MR10 */
   3055 
   3056 	savetkref = tokensRefdInBlock;
   3057 	require(q!=NULL,				"genPlusBlk: invalid node and/or rule");
   3058 	require(q->ntype == nJunction,	"genPlusBlk: not junction");
   3059 	require(q->jtype == aPlusBlk,	"genPlusBlk: not Plus block");
   3060 	require(q->p2 != NULL,			"genPlusBlk: not a valid Plus block");
   3061 
   3062 	if ( q->visited ) return;
   3063 	q->visited = TRUE;
   3064     OutLineInfo(output,q->line,FileStr[q->file]);
   3065 	BLOCK_Preamble(q);
   3066 	BlkLevel++;
   3067 
   3068     BlockPreambleOption((Junction *)q, q->pFirstSetSymbol);       /* MR21 */
   3069 
   3070     /* first_item_is_guess_block  doesn't care what kind of node it is */
   3071 
   3072     guessBlock=first_item_is_guess_block( (Junction *)q->p1);   /* MR10 */
   3073 
   3074 	/* if the ignore flag is set on the 2nd alt and that alt is empty,
   3075 	 * then it is the implied optional alternative that we added for (...)+
   3076 	 * and, hence, only 1 alt.
   3077 	 */
   3078 
   3079 /* MR10  Reported by Pulkkinen Esa (esap (at) cs.tut.fi)
   3080  *       Outer code for guess blocks ignored when there is only one alt
   3081  *         for a (...)+ block.
   3082  *       Force use of regular code rather than "optimized" code for that case
   3083  */
   3084 
   3085     singleAlt=( ( (Junction *) q->p2)->p2 == NULL) &&
   3086         	  ( ( (Junction *) q->p2)->ignore );			/* only one alternative? */
   3087 
   3088     if (singleAlt && !guessBlock)   /* MR10 */
   3089 	{
   3090 
   3091 		Predicate *a=NULL;
   3092 		/* if the only alt has a semantic predicate, hoist it; must test before
   3093 		 * entering loop.
   3094 		 */
   3095 		if ( ParseWithPredicates )
   3096 		{
   3097             require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
   3098 			a = MR_find_predicates_and_supp((Node *)q);
   3099             require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty");
   3100 
   3101 			if ( a!=NULL ) {
   3102 				gen("if (");
   3103 				a=genPredTreeMain(a, (Node *)q);    /* MR10 */
   3104 				_gen(") {\n");
   3105 			}
   3106 		}
   3107 		gen("do {\n");
   3108 		tabs++;
   3109 		TRANS(q->p1);
   3110 		if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1);
   3111 		f = First(q, 1, aPlusBlk, &max_k);
   3112 		if ( DemandLookahead ) {
   3113 			if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
   3114 			else gen1("look(%d);\n", max_k);
   3115 		}
   3116 		--tabs;
   3117 		gen("} while ( ");
   3118 		if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm);
   3119 		genExpr(q);
   3120 		if ( ParseWithPredicates && a!=NULL )
   3121 		{
   3122             if (! MR_comparePredicates(q->predicate,a)) {
   3123     			_gen("&&");
   3124     			a=genPredTreeMain(a, (Node *)q);    /* MR10 */
   3125             };
   3126 		}
   3127 		_gen(" );\n");
   3128 		if ( ParseWithPredicates && a!=NULL ) gen("}\n");
   3129 		--BlkLevel;
   3130 		BLOCK_Tail();
   3131 		q->visited = FALSE;
   3132 		freeBlkFsets(q);
   3133 		set_free(f);
   3134 		tokensRefdInBlock = savetkref;
   3135 /* MR21 */	if (MR_BlkErr) {
   3136 /* MR21 */		set f, fArray[2];
   3137 /* MR21 */		f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ );
   3138 /* MR21 */      fArray[0]= empty;
   3139 /* MR21 */		fArray[1]= set_dup(f);
   3140 /* MR21 */      gen("if (");
   3141 /* MR21 */      genExprSets(fArray,1);  /* note: destroys set arguments */
   3142 /* MR21 */      _gen(") { /* MR21 option -mrblksynerr */\n");
   3143 /* MR21 */      tabs++;
   3144 /* MR21 */      tab();
   3145 /* MR21 */      _gen("/* nothing */ }\n");
   3146 /* MR21 */      tab();
   3147 /* MR21 */      makeErrorClause(q,f,1,1 /* use plus block bypass ? */ );  /* frees set */
   3148 /* MR21 */      tabs--;
   3149 /* MR21 */	};
   3150 		if (q->end->p1 != NULL) TRANS(q->end->p1);
   3151 /* MR10 */  if (MRhoisting) {
   3152 /* MR10 */    predicate_free(a);
   3153 /* MR10 */  };
   3154 		return;
   3155 	}
   3156 	gen("do {\n");
   3157 	tabs++;
   3158 	f = genBlk(q, aPlusBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
   3159 /* MR6              									        */
   3160 /* MR6	Sinan Karasu	(sinan (at) tardis.ds.boeing.com)			*/
   3161 /* MR6    Failed to turn off guess mode when leaving block		*/
   3162 /* MR6				                           					*/
   3163 /* MR6  */ if ( has_guess_block_as_last_item(q) ) {
   3164 /* MR10 */   gen("/* MR10 ()+ */ else {\n");
   3165 /* MR10 */   tabs++;
   3166 /* MR10 */   need_right_curly++;
   3167 /* MR10 */   gen("/* MR10 ()+ */ if ( !zzrv ) zzGUESS_DONE;\n");
   3168 /* MR6  */   gen("/* MR10 ()+ */ if ( zzcnt > 1 ) break;\n");
   3169 /* MR10 */ } else {
   3170 /* MR10 */   gen("/* MR10 ()+ */ else {\n");
   3171 /* MR10 */   tabs++;
   3172 /* MR10 */   need_right_curly++;
   3173 /* MR10 */   gen("if ( zzcnt > 1 ) break;\n");
   3174 /* MR10 */ };
   3175 
   3176 /* MR21 */	if (MR_BlkErr && 1 >= max_k) {
   3177 /* MR21 */		set f;
   3178 /* MR21 */		f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ );
   3179 /* MR21 */      tabs++;
   3180 /* MR21 */      tab();
   3181 /* MR21 */      makeErrorClause(q,f,1,0 /* use plus block bypass ? */ );  /* frees set */
   3182 /* MR21 */      tabs--;
   3183 /* MR21 */	}
   3184 /* MR21 */  else {
   3185 				tab();
   3186                 makeErrorClause(q,f,max_k,1 /* use plus block bypass ? */);
   3187 										    /* MR21 I think this generates the wrong set ? */
   3188                                             /* MR21 because it includes the plus block bypass ? */
   3189 										    /* MR21 but I'm afraid to change it without additional checking */
   3190             }
   3191 
   3192 	{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
   3193 	freeBlkFsets(q);
   3194 	gen("zzcnt++;");
   3195 	if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1);
   3196 	_gen("\n");
   3197 	if ( DemandLookahead ) {
   3198 		if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);}
   3199 		else gen1("look(%d);\n", max_k);
   3200 	}
   3201 	--tabs;
   3202 	if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);}
   3203 	else gen("} while ( 1 );\n");
   3204 	--BlkLevel;
   3205 	BLOCK_Tail();
   3206 	q->visited = FALSE;
   3207 	tokensRefdInBlock = savetkref;
   3208 /* MR21 */	if (MR_BlkErr) {
   3209 /* MR21 */		set f, fArray[2];
   3210 /* MR21 */		f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ );
   3211 /* MR21 */      fArray[0]= empty;
   3212 /* MR21 */		fArray[1]= set_dup(f);
   3213 /* MR21 */      gen("if (");
   3214 /* MR21 */      genExprSets(fArray,1);  /* note: destroys set arguments */
   3215 /* MR21 */      _gen(") { /* MR21 option -mrblksynerr */\n");
   3216 /* MR21 */      tabs++;
   3217 /* MR21 */      tab();
   3218 /* MR21 */      _gen("/* nothing */ }\n");
   3219 /* MR21 */      tab();
   3220 /* MR21 */      makeErrorClause(q,f,1,1 /* use plus block bypass ? */ );  /* frees set */
   3221 /* MR21 */      tabs--;
   3222 /* MR21 */	};
   3223 	if (q->end->p1 != NULL) TRANS(q->end->p1);
   3224 }
   3225 
   3226 /*
   3227  * Generate code for a sub blk of alternatives of form:
   3228  *
   3229  *			       --o-G1--o--
   3230  *					 |     ^
   3231  *					 v    /|
   3232  *			         o-G2-o|
   3233  *					 |     ^
   3234  *					 v     |
   3235  *				   ..........
   3236  *					 |     ^
   3237  *					 v    /
   3238  *			         o-Gn-o
   3239  *
   3240  * q points to the 1st junction of blk (upper-left).
   3241  * q->end points to the last node (far right) in the blk.
   3242  * Note that q->end->jtype must be 'EndBlk'.
   3243  * The last node in every alt points to q->end.
   3244  *
   3245  * Generate code of the following form:
   3246  *	if ( First(G1) ) {
   3247  *		...code for G1...
   3248  *	}
   3249  *	else if ( First(G2) ) {
   3250  *		...code for G2...
   3251  *	}
   3252  *	...
   3253  *	else {
   3254  *		...code for Gn...
   3255  *	}
   3256  */
   3257 
   3258 void
   3259 #ifdef __USE_PROTOS
   3260 genSubBlk( Junction *q )
   3261 #else
   3262 genSubBlk( q )
   3263 Junction *q;
   3264 #endif
   3265 {
   3266 	int max_k;
   3267 	set f;
   3268 	int need_right_curly;
   3269 	int lastAltEmpty;		/* MR23 */
   3270 	set savetkref;
   3271 	savetkref = tokensRefdInBlock;
   3272 	require(q->ntype == nJunction,	"genSubBlk: not junction");
   3273 	require(q->jtype == aSubBlk,	"genSubBlk: not subblock");
   3274 
   3275     OutLineInfo(output,q->line,FileStr[q->file]);
   3276 	BLOCK_Preamble(q);
   3277 	BlkLevel++;
   3278     BlockPreambleOption(q,q->pFirstSetSymbol);       /* MR21 */
   3279 	f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
   3280 
   3281 /* MR23
   3282    Bypass error clause generation when exceptions are used in a sub block
   3283    in which the last alternative is epsilon.  Example: "(A | B | )".
   3284    See multi-line note in genBlk near call to isEmptyAlt.
   3285 */
   3286 	if (FoundException && lastAltEmpty) {
   3287 		gen("/* MR23 skip error clause for (...| epsilon) when exceptions in use */\n");
   3288 	}
   3289 	else {
   3290 		if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );}
   3291 	}
   3292 
   3293 	{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
   3294 	freeBlkFsets(q);
   3295 	--BlkLevel;
   3296 	BLOCK_Tail();
   3297 
   3298 	if ( q->guess )
   3299 	{
   3300 		gen("zzGUESS_DONE\n");
   3301 	}
   3302 
   3303 	/* must duplicate if (alpha)?; one guesses (validates), the
   3304 	 * second pass matches */
   3305 	if ( q->guess && analysis_point(q)==q )
   3306 	{
   3307         OutLineInfo(output,q->line,FileStr[q->file]);
   3308 		BLOCK_Preamble(q);
   3309 		BlkLevel++;
   3310 		f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
   3311 		if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */);}
   3312 		{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
   3313 		freeBlkFsets(q);
   3314 		--BlkLevel;
   3315 		BLOCK_Tail();
   3316 	}
   3317 
   3318 	tokensRefdInBlock = savetkref;
   3319 	if (q->end->p1 != NULL) TRANS(q->end->p1);
   3320 }
   3321 
   3322 static int TnodesAllocatedPrevRule=0;
   3323 
   3324 /*
   3325  * Generate code for a rule.
   3326  *
   3327  *		rule--> o-->o-Alternatives-o-->o
   3328  * Or,
   3329  *		rule--> o-->o-Alternative-o-->o
   3330  *
   3331  * The 1st junction is a RuleBlk.  The second can be a SubBlk or just a junction
   3332  * (one alternative--no block), the last is EndRule.
   3333  * The second to last is EndBlk if more than one alternative exists in the rule.
   3334  *
   3335  * To get to the init-action for a rule, we must bypass the RuleBlk,
   3336  * and possible SubBlk.
   3337  * Mark any init-action as generated so genBlk() does not regenerate it.
   3338  */
   3339 void
   3340 #ifdef __USE_PROTOS
   3341 genRule( Junction *q )
   3342 #else
   3343 genRule( q )
   3344 Junction *q;
   3345 #endif
   3346 {
   3347 
   3348 	const char * returnValueInitializer;
   3349 
   3350 do {    /* MR10     Change recursion into iteration         */
   3351 
   3352 	int max_k;
   3353 	set follow, rk, f;
   3354 	ActionNode *a;
   3355 	RuleEntry *r;
   3356 	int lastAltEmpty;		/* MR23 */
   3357 	static int file = -1;
   3358 	int need_right_curly;
   3359 	require(q->ntype == nJunction,	"genRule: not junction");
   3360 	require(q->jtype == RuleBlk,	"genRule: not rule");
   3361 
   3362 /* MR14 */    require (MR_BackTraceStack.count == 0,"-alpha MR_BackTraceStack.count != 0");
   3363 /* MR14 */    MR_pointerStackReset(&MR_BackTraceStack);
   3364 /* MR14 */    if (AlphaBetaTrace) MR_MaintainBackTrace=1;
   3365 
   3366     CurRule=q->rname;                               /* MR11 */
   3367 
   3368 	r = (RuleEntry *) hash_get(Rname, q->rname);
   3369 	if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief");
   3370 	if ( q->file != file )		/* open new output file if need to */
   3371 	{
   3372 /* MR6              									*/
   3373 /* MR6  Simpler to debug when output goes to stdout rather than a file 	*/
   3374 /* MR6				                					*/
   3375 /* MR6 */	if (UseStdout) {
   3376 /* MR6 */	  output = stdout;
   3377 /* MR6 */	} else {
   3378 /* MR6 */  	  if ( output != NULL) fclose( output );
   3379 /* MR6 */	  output = fopen(OutMetaName(outname(FileStr[q->file])), "w");
   3380 /* MR6 */	};
   3381 		require(output != NULL, "genRule: can't open output file");
   3382 
   3383 #ifdef SPECIAL_FOPEN
   3384        special_fopen_actions(OutMetaName(outname(FileStr[q->file]))); /* MR1 */
   3385 #endif
   3386 		if ( file == -1 ) genHdr1(q->file);
   3387 		else genHdr(q->file);
   3388 		file = q->file;
   3389 	}
   3390 
   3391     if (InfoM) {
   3392       fprintf(stderr,"    rule %s\n",q->rname);
   3393       fflush(output);
   3394     };
   3395 
   3396 #if 0
   3397     if (strcmp(q->rname,"***debug***") == 0) {
   3398       fprintf(stderr,"***debug*** %s reached\n",q->rname);
   3399       MR_break();
   3400     };
   3401 #endif
   3402 
   3403 	DumpFuncHeader(q,r);
   3404 	tabs++;
   3405 
   3406 	/* MR23
   3407 
   3408 	   If there is a single return value then it can be initialized in
   3409 	   the declaration using assignment syntax.  If there are multiple
   3410 	   return values then antlr creates a struct and initialization takes
   3411 	   place element by element for each element of the struct.  For
   3412        multiple elements the initialization is by assignment so we have
   3413        to wait until all declarations are done before emitting that code -
   3414        because of restrictions in C which don't exist in C++.
   3415 
   3416        In the past (before MR23) the only kind of initialization was
   3417 	   the PURIFY macro which was just a memset() of 0.  Now we allow
   3418 	   the user to specify an initial value.  PURIFY is still used in C
   3419 	   mode because C does not have constructors.  However, PURIFY is
   3420 	   not used in C++ mode because it might overwrite information created
   3421 	   by elements which have their own ctor.
   3422 
   3423 	*/
   3424 
   3425 	if ( q->ret!=NULL )
   3426 	{
   3427 		if ( hasMultipleOperands(q->ret) )                         /* MR23 */
   3428 		{
   3429 
   3430             /* Emit initialization code later. */
   3431 
   3432 			gen1("struct _rv%d _retv;\n",r->rulenum);
   3433 		}
   3434 		else
   3435 		{
   3436             /* Emit initialization code now. */
   3437 
   3438 			tab();
   3439 			DumpType(q->ret, output);
   3440             returnValueInitializer = getInitializer(q->ret);
   3441             if (returnValueInitializer == NULL) {                  /* MR23 */
   3442       			gen(" _retv;\n");                     		    /* MR1 MR3 */
   3443             }                                                      /* MR23 */
   3444             else {                                                 /* MR23 */
   3445                 gen1(" _retv = %s;\n", returnValueInitializer);    /* MR23 */
   3446             }                                                      /* MR23 */
   3447 		}
   3448 	}
   3449 
   3450     OutLineInfo(output,q->line,FileStr[q->file]);
   3451 
   3452     if (InfoM) {
   3453       fflush(output);
   3454     };
   3455 
   3456 	gen("zzRULE;\n");
   3457 	if ( FoundException )
   3458 	{
   3459 		gen("int _sva=1;\n");
   3460 	}
   3461 	if ( GenCC && GenAST )
   3462 		gen("ASTBase *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n");
   3463 	if ( GenCC ) genTokenPointers(q);
   3464 	if ( GenCC&&GenAST ) genASTPointers(q);
   3465 	if ( q->el_labels!=NULL ) genElementLabels(q->el_labels);
   3466 	if ( FoundException ) gen("int _signal=NoSignal;\n");
   3467 
   3468 	if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);
   3469 
   3470 /* MR10 */  /* move zzTRACEIN to before init action */
   3471 
   3472 /* MR10 */	if ( TraceGen ) {
   3473 /* MR10 */		if ( GenCC ) {gen1("zzTRACEIN(\"%s\");\n", q->rname);}
   3474 /* MR10 */		else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname);
   3475 /* MR10 */	}
   3476 
   3477 /* MR7      Moved PURIFY() to after all local variables have been declared */
   3478 /* MR7      so that the generated code is valid C as well as C++           */
   3479 /* MR7        Jan Mikkelsen 10-June-1997                                   */
   3480 
   3481 
   3482      /*
   3483        MR23    Do the PURIFY macro only for C mode.
   3484                C++ users should use constructors or initialization expressions.
   3485      */
   3486 
   3487 	if ( q->ret != NULL )                                            /* MR7 */
   3488 	{                                                                /* MR7 */
   3489 		if (hasMultipleOperands(q->ret)) {                           /* MR23 */
   3490 			if (PURIFY == TRUE) {
   3491                 gen1("PCCTS_PURIFY(_retv,sizeof(struct _rv%d))\n",r->rulenum); /* MR23 */
   3492             }
   3493         }                                                            /* MR7 */
   3494 		else {                                                       /* MR7 */
   3495 
   3496 			/* MR23
   3497 			   If there were only one return value operand and
   3498 			   it had an initializer then it would have been
   3499 			   initiailized in the declaration.
   3500 			*/
   3501 
   3502 			returnValueInitializer = getInitializer(q->ret);         /* MR23 */
   3503 			if (returnValueInitializer == NULL) {                    /* MR23 */
   3504     			if (PURIFY == TRUE) {
   3505         			gen("PCCTS_PURIFY(_retv,sizeof(");               /* MR23 */
   3506 	    			DumpType(q->ret, output);                        /* MR7 */
   3507 					gen("))\n");                                     /* MR7 */
   3508 				}
   3509 			}                                                        /* MR23 */
   3510 		}                                                            /* MR7 */
   3511 
   3512         if (hasMultipleOperands(q->ret)) {                           /* MR23 */
   3513           DumpInitializers(output, r, q->ret);                       /* MR23 */
   3514         }
   3515 
   3516 	}
   3517 	if ( !GenCC ) gen("zzMake0;\n");
   3518 	if ( FoundException ) gen("*_retsignal = NoSignal;\n");
   3519 
   3520 	if ( !GenCC ) gen("{\n");
   3521 
   3522 	if ( has_guess_block_as_first_item((Junction *)q->p1) )
   3523 	{
   3524 		gen("zzGUESS_BLOCK\n");
   3525 	}
   3526 
   3527 	/* L o o k  F o r  I n i t  A c t i o n */
   3528 	if ( ((Junction *)q->p1)->jtype == aSubBlk )
   3529 		a = findImmedAction( ((Junction *)q->p1)->p1 );
   3530 	else
   3531 		a = findImmedAction( q->p1 );	/* only one alternative in rule */
   3532 	if ( a!=NULL && !a->is_predicate)
   3533 	{
   3534  /* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1);
   3535   		    a->done = 1;	/* ignore action. We have already handled it */
   3536 	}
   3537 
   3538 	BlkLevel++;
   3539 	q->visited = TRUE;				/* mark RULE as visited for FIRST/FOLLOW */
   3540     BlockPreambleOption((Junction *)q->p1, NULL);   /* MR21 */
   3541 	f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */);
   3542 	if ( q->p1 != NULL )
   3543 		if ( ((Junction *)q->p1)->p2 != NULL )
   3544 			{tab(); makeErrorClause((Junction *)q->p1,f,max_k,0 /* use plus block bypass ? */);}
   3545 	{ int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} }
   3546 	freeBlkFsets((Junction *)q->p1);
   3547 	q->visited = FALSE;
   3548 	--BlkLevel;
   3549 	if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel);
   3550 
   3551     genTraceOut(q);
   3552 
   3553 	if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n");
   3554 	/* E r r o r  R e c o v e r y */
   3555 	NewSet();
   3556 	rk = empty;
   3557 
   3558 /* MR14 */    if (r->dontComputeErrorSet) {
   3559 /* MR14 */      follow=empty;
   3560               } else {
   3561                 MR_pointerStackReset(&MR_BackTraceStack);   /* MR14 */
   3562                 MR_ErrorSetComputationActive=1;
   3563                 REACH(q->end, 1, &rk, follow);
   3564                 MR_ErrorSetComputationActive=0;
   3565                 require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0");
   3566               }
   3567 
   3568   FillSet( follow );
   3569 	set_free( follow );
   3570 
   3571   /* MR20 G. Hobbelt
   3572      Isn't it so that "fail:" is ONLY referenced when:
   3573 
   3574       	 !FoundException || FoundGuessBlk ?
   3575 
   3576      Therefore add the "if" around this piece of code generation...
   3577 
   3578      Should guessing mode also use _handler label instead of "fail"
   3579      when exception handling is active? gen can automatically put
   3580      "if (guessing)" there so as to skip all kinds of user code.
   3581 
   3582    */
   3583 
   3584 	if ( !FoundException || FoundGuessBlk )  /* MR20 G. Hobbelt */
   3585   {                                          /* MR20 G. Hobbelt */
   3586 	_gen("fail:\n");
   3587 	if ( !GenCC ) gen("zzEXIT(zztasp1);\n");
   3588 	if ( FoundGuessBlk ) {
   3589 	   	if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");}
   3590 		else gen("if ( guessing ) zzGUESS_FAIL;\n");
   3591 	}
   3592 	if ( q->erraction!=NULL )
   3593 		dumpAction(q->erraction, output, tabs, q->file, q->line, 1);
   3594 	if ( GenCC )
   3595 	{
   3596 		gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n",
   3597 			 r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
   3598 	}
   3599 	else
   3600 	{
   3601 		gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n",
   3602 			 r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup);
   3603 	}
   3604 	gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<<setnum);
   3605 
   3606 	if ( q->ret!=NULL ) {
   3607       genTraceOut(q);
   3608       gen("return _retv;\n");
   3609     } else if ( q->exceptions!=NULL ) {
   3610       genTraceOut(q);
   3611       gen("return;\n");
   3612     } else if (!FoundException) {       /* MR10 */
   3613       genTraceOut(q);                   /* MR10 */
   3614     };
   3615 
   3616   }                                        /* MR20 G. Hobbelt */
   3617 
   3618 	if ( !GenCC ) gen("}\n");
   3619 
   3620 	/* Gen code for exception handlers */
   3621     /* make sure each path out contains genTraceOut() */
   3622 
   3623 	if ( q->exceptions!=NULL )
   3624 	{
   3625 
   3626 		gen("/* exception handlers */\n");
   3627 
   3628 		dumpExceptions(q->exceptions);
   3629 
   3630         if ( !r->has_rule_exception )
   3631         {
   3632             _gen("_handler:\n");
   3633             gen("zzdflthandlers(_signal,_retsignal);\n");
   3634         }
   3635 /*  MR20 G. Gobbelt   The label "adios" is never referenced */
   3636 
   3637 #if 0
   3638 	_gen("_adios:\n");
   3639 #endif
   3640     if ( q->ret!=NULL ) {
   3641             genTraceOut(q);
   3642             gen("return _retv;\n");
   3643         }
   3644 		else {
   3645             genTraceOut(q);
   3646             gen("return;\n");
   3647         }
   3648 	}
   3649 	else if ( FoundException )
   3650 	{
   3651       _gen("_handler:\n");
   3652       gen("zzdflthandlers(_signal,_retsignal);\n");
   3653 
   3654 /* MR1                                                                      */
   3655 /* MR1	 7-Apr-97 Fix suggested by: John Bair (jbair (at) iftime.com)            */
   3656 /* MR1							                                            */
   3657 
   3658    	  if ( q->ret != NULL) {			                             /* MR1 */
   3659             genTraceOut(q);                                          /* MR10 */
   3660             gen("return _retv;\n");			                         /* MR1 */
   3661       } else {					                                     /* MR1 */
   3662             genTraceOut(q);                                          /* MR10 */
   3663             gen("return;\n")    ;				                     /* MR1 */
   3664       };						                                     /* MR1 */
   3665 	}
   3666 
   3667 	tabs--;
   3668 	gen("}\n");
   3669 
   3670 /* MR10     Tired of looking at stacks that are as deep as the number of    */
   3671 /* MR10       rules.  Changes recursion to iteration.                       */
   3672 
   3673     MR_releaseResourcesUsedInRule( (Node *) q );      /* MR10 */
   3674 
   3675     if (InfoT) {
   3676       fprintf(output,"\n/* tnodes created for rule %s:  %d */\n",
   3677                 q->rname, (TnodesAllocated-TnodesAllocatedPrevRule) );
   3678     };
   3679 
   3680     TnodesAllocatedPrevRule=TnodesAllocated;
   3681 
   3682     if (q->p2 == NULL) dumpAfterActions( output );
   3683     q=(Junction *)q->p2;
   3684     require(q==NULL || q->jtype==RuleBlk,"RuleBlk p2 does not point to another RuleBlk");
   3685 
   3686 } while (q != NULL);
   3687 
   3688 /**** The old code                           ****/
   3689 /****	if ( q->p2 != NULL ) {TRANS(q->p2);} ****/ /* generate code for next rule too */
   3690 /****	else dumpAfterActions( output );     ****/
   3691 
   3692 }
   3693 
   3694 
   3695 /* This is for the function definition, not the declaration. */
   3696 
   3697 static void
   3698 #ifdef __USE_PROTOS
   3699 DumpFuncHeader( Junction *q, RuleEntry *r )
   3700 #else
   3701 DumpFuncHeader( q, r )
   3702 Junction *q;
   3703 RuleEntry *r;
   3704 #endif
   3705 {
   3706 /*								                                            */
   3707 /*  MR1 10-Apr-97  MR1  Simplify insertion of commas in function header     */
   3708 /*								                                            */
   3709 	int	needComma;					                                 /* MR1 */
   3710 
   3711 
   3712 	/* A N S I */
   3713 	_gen("\n");
   3714 	if ( q->ret!=NULL )
   3715 	{
   3716 		if ( hasMultipleOperands(q->ret) )                            /* MR23 */
   3717 		{
   3718 			if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum)
   3719 			else gen1("struct _rv%d\n",r->rulenum);
   3720 		}
   3721 		else
   3722 		{
   3723 			DumpType(q->ret, output);
   3724 			gen("\n");
   3725 		}
   3726 	}
   3727 	else
   3728 	{
   3729 		_gen("void\n");
   3730 	}
   3731 /*  MR1			                                                            */
   3732 /*  MR1	10-Apr-97  133MR1	Replace __STDC__ with __USE_PROTOS              */
   3733 /*  MR1								                                        */
   3734 	if ( !GenCC ) _gen("#ifdef __USE_PROTOS\n");		     /* MR1 */
   3735 	if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname)
   3736 	else gen3("%s::%s%s(", CurrentClassName, RulePrefix,q->rname);
   3737 
   3738     	/* If we generate C++ method names, we must hide default arguments */
   3739         /* which can appear in the parameter declaration list.             */
   3740         /* NOTICE: this is done only here, for the method definition, but  */
   3741         /*         not for the method declaration inside the class         */
   3742         /*         definition. This is exactly the behaviour defined in    */
   3743         /*         C++ standard for default paramters.                     */
   3744 
   3745 	DumpANSIFunctionArgDef(output,q, 0 /* emit initializers ? */);
   3746 	_gen("\n");
   3747 
   3748 	if ( GenCC ) {
   3749       gen("{\n");
   3750       return;
   3751     }
   3752 
   3753 	/* K & R */
   3754 	gen("#else\n");
   3755 	gen2("%s%s(", RulePrefix, q->rname);
   3756 	needComma=0;						                             /* MR1 */
   3757 	if ( GenAST )						                             /* MR1 */
   3758 	{							                                     /* MR1 */
   3759 		_gen("_root");					                             /* MR1 */
   3760 		needComma=1;					                             /* MR1 */
   3761 	}							                                     /* MR1 */
   3762 	if ( FoundException )					                         /* MR1 */
   3763 	{							                                     /* MR1 */
   3764 		if (needComma) {_gen(",");needComma=0;};	                 /* MR1 */
   3765 		_gen("_retsignal");				                             /* MR1 */
   3766 		needComma=1;					                             /* MR1 */
   3767 	}							                                     /* MR1 */
   3768 /* MR5	Change below by Jan Mikkelsen (janm (at) zeta.org.au) 26-May-97      MR5 */
   3769 	DumpListOfParmNames( q->pdecl, output, needComma );	             /* MR5 */
   3770 	gen(")\n");
   3771 	if ( GenAST ) gen("AST **_root;\n");
   3772 	if ( FoundException ) gen("int *_retsignal;\n");
   3773 	DumpOldStyleParms( q->pdecl, output );
   3774 	gen("#endif\n");
   3775     gen("{\n");
   3776 }
   3777 
   3778 void
   3779 #ifdef __USE_PROTOS
   3780 DumpANSIFunctionArgDef(FILE *f, Junction *q, int bInitializer)
   3781 #else
   3782 DumpANSIFunctionArgDef(f,q,bInitializer)
   3783 FILE *f;
   3784 Junction *q;
   3785 int bInitializer;
   3786 #endif
   3787 {
   3788 	if ( GenAST )
   3789 	{
   3790 		if ( GenCC ) {fprintf(f,"ASTBase **_root");}
   3791 		else fprintf(f,"AST**_root");
   3792 		if ( !FoundException && q->pdecl!=NULL ) fprintf(f,",");
   3793 	}
   3794 	if ( FoundException )
   3795 	{
   3796 		if ( GenAST ) fprintf(f,",");
   3797 		fprintf(f,"int *_retsignal");
   3798 		if ( q->pdecl!=NULL ) {
   3799             fprintf(f,",");
   3800         }
   3801 	}
   3802 	if ( q->pdecl!=NULL ) {
   3803         DumpFormals(f, q->pdecl, bInitializer);     /* MR23 */
   3804     }
   3805 	else {
   3806         if ( !GenAST && !FoundException ) {
   3807             fprintf(f,"void");
   3808         }
   3809     }
   3810 	fprintf(f,")");
   3811 }
   3812 
   3813 void
   3814 #ifdef __USE_PROTOS
   3815 genJunction( Junction *q )
   3816 #else
   3817 genJunction( q )
   3818 Junction *q;
   3819 #endif
   3820 {
   3821 	require(q->ntype == nJunction,	"genJunction: not junction");
   3822 	require(q->jtype == Generic,	"genJunction: not generic junction");
   3823 
   3824 	if ( q->p1 != NULL ) TRANS(q->p1);
   3825 	if ( q->p2 != NULL ) TRANS(q->p2);
   3826 }
   3827 
   3828 void
   3829 #ifdef __USE_PROTOS
   3830 genEndBlk( Junction *q )
   3831 #else
   3832 genEndBlk( q )
   3833 Junction *q;
   3834 #endif
   3835 {
   3836 }
   3837 
   3838 void
   3839 #ifdef __USE_PROTOS
   3840 genEndRule( Junction *q )
   3841 #else
   3842 genEndRule( q )
   3843 Junction *q;
   3844 #endif
   3845 {
   3846 }
   3847 
   3848 void
   3849 #ifdef __USE_PROTOS
   3850 genHdr( int file )
   3851 #else
   3852 genHdr( file )
   3853 int file;
   3854 #endif
   3855 {
   3856     int     i;
   3857 
   3858 	_gen("/*\n");
   3859 	_gen(" * A n t l r  T r a n s l a t i o n  H e a d e r\n");
   3860 	_gen(" *\n");
   3861 	_gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");
   3862 	_gen(" * Purdue University Electrical Engineering\n");
   3863 	_gen(" * With AHPCRC, University of Minnesota\n");
   3864 	_gen1(" * ANTLR Version %s\n", Version);
   3865 	_gen(" *\n");
   3866 /* MR10 */    _gen(" *  ");
   3867 /* MR10 */    for (i=0 ; i < Save_argc ; i++) {
   3868 /* MR10 */      _gen(" ");
   3869 /* MR10 */      _gen1("%s", Save_argv[i]);
   3870 /* MR10 */    };
   3871 	_gen("\n");
   3872 	_gen(" *\n");
   3873     _gen(" */\n\n");
   3874 	if (FirstAction != NULL ) dumpAction( FirstAction, output, 0, -1, 0, 1);    /* MR11 MR15b */
   3875 	_gen1("#define ANTLR_VERSION	%s\n", VersionDef);
   3876 	_gen("#include \"pcctscfg.h\"\n");
   3877 	_gen("#include \"pccts_stdio.h\"\n");
   3878 	if ( strcmp(ParserName, DefaultParserName)!=0 )
   3879 		_gen2("#define %s %s\n", DefaultParserName, ParserName);
   3880    	if ( strcmp(ParserName, DefaultParserName)!=0 )
   3881 		{_gen1("#include \"%s\"\n", RemapFileName);}
   3882     OutLineInfo(output,1,FileStr[file]);
   3883 	if ( GenCC ) {
   3884 		if ( UserTokenDefsFile != NULL )
   3885 			fprintf(output, "#include %s\n", UserTokenDefsFile);
   3886 		else
   3887 			fprintf(output, "#include \"%s\"\n", DefFileName);
   3888 	}
   3889 
   3890 	if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1);
   3891 	if ( !GenCC && FoundGuessBlk )
   3892 	{
   3893 		_gen("#define ZZCAN_GUESS\n");
   3894 		_gen("#include \"pccts_setjmp.h\"\n");  /* MR15 K.J. Cummings (cummings (at) peritus.com) */
   3895 	}
   3896 	if ( FoundException )
   3897 	{
   3898 		_gen("#define EXCEPTION_HANDLING\n");
   3899 		_gen1("#define NUM_SIGNALS %d\n", NumSignals);
   3900 	}
   3901 	if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k);
   3902 	if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n");
   3903 	if ( GenAST ) {
   3904 		if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);}
   3905 		else _gen("#include \"ast.h\"\n\n");
   3906 	}
   3907 	if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n");
   3908 #ifdef DUM
   3909 	if ( !GenCC && LexGen ) {
   3910 		_gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
   3911 	}
   3912 #endif
   3913 	/* ###WARNING: This will have to change when SetWordSize changes */
   3914 	if ( !GenCC ) _gen1("#define zzSET_SIZE %lu\n", NumWords(TokenNum-1)*sizeof(unsigned));
   3915     if (TraceGen) {
   3916       _gen("#ifndef zzTRACE_RULES\n");  /* MR20 */
   3917       _gen("#define zzTRACE_RULES\n");  /* MR20 */
   3918       _gen("#endif\n");                 /* MR22 */
   3919     };
   3920 	if ( !GenCC ) {_gen("#include \"antlr.h\"\n");}
   3921 	else {
   3922 		_gen1("#include \"%s\"\n", APARSER_H);
   3923 		_gen1("#include \"%s.h\"\n", CurrentClassName);
   3924 	}
   3925 	if ( !GenCC ) {
   3926 		if ( UserDefdTokens )
   3927 			{_gen1("#include %s\n", UserTokenDefsFile);}
   3928 		/* still need this one as it has the func prototypes */
   3929 		_gen1("#include \"%s\"\n", DefFileName);
   3930 	}
   3931 	/* still need this one as it defines the DLG interface */
   3932 	if ( !GenCC ) _gen("#include \"dlgdef.h\"\n");
   3933 	if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H);
   3934 	if ( GenCC ) _gen1("#include \"%s\"\n", ATOKPTR_H);
   3935 	if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName);
   3936 
   3937 /* MR10  Ofer Ben-Ami (gremlin (at) cs.huji.ac.il)           */
   3938 /* MR10    Finally, a definition of the Purify macro    */
   3939 
   3940     if (PURIFY == TRUE) {                                                   /* MR23 */
   3941         _gen("\n/* MR23 In order to remove calls to PURIFY use the antlr"); /* MR23 */
   3942         _gen(" -nopurify option */\n\n");                                   /* MR23 */
   3943     	_gen("#ifndef PCCTS_PURIFY\n");
   3944         _gen("#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\\0',(s));\n");
   3945         _gen("#endif\n\n");
   3946     }                                                                       /* MR23 */
   3947 }
   3948 
   3949 void
   3950 #ifdef __USE_PROTOS
   3951 genHdr1( int file )
   3952 #else
   3953 genHdr1( file )
   3954 int file;
   3955 #endif
   3956 {
   3957 	ListNode *p;
   3958 
   3959 	genHdr(file);
   3960 	if ( GenAST )
   3961 	{
   3962 		if ( !GenCC ) {
   3963 			_gen("#include \"ast.c\"\n");
   3964 			_gen("zzASTgvars\n\n");
   3965 		}
   3966 	}
   3967 	if ( !GenCC ) _gen("ANTLR_INFO\n");
   3968 	if ( BeforeActions != NULL )
   3969 	{
   3970 		for (p = BeforeActions->next; p!=NULL; p=p->next)
   3971 		{
   3972 			UserAction *ua = (UserAction *)p->elem;
   3973 			dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
   3974 		}
   3975 	}
   3976 
   3977 	if ( !FoundException ) return;
   3978 
   3979 	if ( GenCC )
   3980 	{
   3981 		_gen1("\nvoid %s::\n", CurrentClassName);
   3982 		_gen("zzdflthandlers( int _signal, int *_retsignal )\n");
   3983 		_gen("{\n");
   3984 	}
   3985 	else
   3986 	{
   3987 		_gen("\nvoid\n");
   3988 /*  MR1				                                                        */
   3989 /*  MR1	10-Apr-97  133MR1	Replace __STDC__ with __USE_PROTOS              */
   3990 /*  MR1	                                                                    */
   3991 	    _gen("#ifdef __USE_PROTOS\n");                               /* MR1 */
   3992 		_gen("zzdflthandlers( int _signal, int *_retsignal )\n");
   3993 		_gen("#else\n");
   3994 		_gen("zzdflthandlers( _signal, _retsignal )\n");
   3995 		_gen("int _signal;\n");
   3996 		_gen("int *_retsignal;\n");
   3997 		_gen("#endif\n");
   3998 		_gen("{\n");
   3999 	}
   4000 	tabs++;
   4001 	if ( DefaultExGroup!=NULL )
   4002 	{
   4003 		dumpException(DefaultExGroup, 1);
   4004 		if ( !hasDefaultException(DefaultExGroup) )
   4005 		{
   4006 			gen("default :\n");
   4007 			tabs++;
   4008 			gen("*_retsignal = _signal;\n");
   4009 			tabs--;
   4010 			gen("}\n");
   4011 		}
   4012 	}
   4013 	else {
   4014 		gen("*_retsignal = _signal;\n");
   4015 	}
   4016 
   4017 	tabs--;
   4018 	_gen("}\n\n");
   4019 }
   4020 
   4021 void
   4022 #ifdef __USE_PROTOS
   4023 genStdPCCTSIncludeFile( FILE *f,char *gate )    /* MR10 */
   4024 #else
   4025 genStdPCCTSIncludeFile( f , gate)               /* MR10 */
   4026 FILE *f;
   4027 char * gate;                                    /* MR10 */
   4028 #endif
   4029 {
   4030 /* MR10 Ramanathan Santhanam (ps (at) kumaran.com)           */
   4031 /* MR10 Same preprocessor symbol use to gate stdpccts.h */
   4032 /* MR10   even when two grammars are in use.            */
   4033 /* MR10 Derive gate symbol from -fh filename            */
   4034 
   4035     if (gate == NULL) {
   4036       fprintf(f,"#ifndef STDPCCTS_H\n");          /* MR10 */
   4037       fprintf(f,"#define STDPCCTS_H\n");          /* MR10 */
   4038     } else {
   4039       fprintf(f,"#ifndef STDPCCTS_%s_H\n",gate);  /* MR10 */
   4040       fprintf(f,"#define STDPCCTS_%s_H\n",gate);  /* MR10 */
   4041     };
   4042 	fprintf(f,"/*\n");
   4043     if (gate == NULL) {
   4044 	  fprintf(f," * %s -- P C C T S  I n c l u d e\n", stdpccts);
   4045     } else {
   4046 	  fprintf(f," * Standard PCCTS include file with -fh %s -- P C C T S  I n c l u d e\n", stdpccts);
   4047     }
   4048 	fprintf(f," *\n");
   4049 	fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");
   4050 	fprintf(f," * Purdue University Electrical Engineering\n");
   4051 	fprintf(f," * With AHPCRC, University of Minnesota\n");
   4052 	fprintf(f," * ANTLR Version %s\n", Version);
   4053 	fprintf(f," */\n\n");
   4054 
   4055     fprintf(f,"#ifndef ANTLR_VERSION\n");
   4056 	fprintf(f,"#define ANTLR_VERSION	%s\n", VersionDef);
   4057     fprintf(f,"#endif\n\n");
   4058 
   4059     if (FirstAction != NULL ) dumpAction(FirstAction, f, 0, -1, 0, 1);  /* MR11 */
   4060 
   4061 	fprintf(f,"#include \"pcctscfg.h\"\n");
   4062 	fprintf(f,"#include \"pccts_stdio.h\"\n");
   4063 	if ( GenCC )
   4064 	{
   4065 		if ( UserDefdTokens )
   4066 			fprintf(f, "#include %s\n", UserTokenDefsFile);
   4067 		else {
   4068 			fprintf(f, "#include \"%s\"\n", DefFileName);
   4069 		}
   4070 
   4071 		fprintf(f, "#include \"%s\"\n", ATOKEN_H);
   4072 
   4073 		if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
   4074 
   4075 		fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H);
   4076 
   4077 		if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k);
   4078 		if ( GenAST ) {
   4079 			fprintf(f, "#include \"%s\"\n", ASTBASE_H);
   4080 		}
   4081 
   4082         if (TraceGen) {
   4083           fprintf(f,"#ifndef zzTRACE_RULES\n");  /* MR20 */
   4084           fprintf(f,"#define zzTRACE_RULES\n");  /* MR20 */
   4085           fprintf(f,"#endif\n");                 /* MR22 */
   4086         };
   4087 
   4088 		fprintf(f,"#include \"%s\"\n", APARSER_H);
   4089 		fprintf(f,"#include \"%s.h\"\n", CurrentClassName);
   4090 		if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H);
   4091 		fprintf(f, "#endif\n");
   4092 		return;
   4093 	}
   4094 
   4095 	if ( strcmp(ParserName, DefaultParserName)!=0 )
   4096 		fprintf(f, "#define %s %s\n", DefaultParserName, ParserName);
   4097 	if ( strcmp(ParserName, DefaultParserName)!=0 )
   4098 		fprintf(f, "#include \"%s\"\n", RemapFileName);
   4099 	if ( UserTokenDefsFile != NULL )
   4100 	   fprintf(f, "#include %s\n", UserTokenDefsFile);
   4101 	if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1);
   4102 	if ( FoundGuessBlk )
   4103 	{
   4104 		fprintf(f,"#define ZZCAN_GUESS\n");
   4105 		fprintf(f,"#include \"pccts_setjmp.h\"\n");
   4106 	}
   4107     if (TraceGen) {
   4108       fprintf(f,"#ifndef zzTRACE_RULES\n");  /* MR20 */
   4109       fprintf(f,"#define zzTRACE_RULES\n");  /* MR20 */
   4110       fprintf(f,"#endif\n");                 /* MR22 */
   4111     };
   4112 	if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k);
   4113 	if ( GenAST ) fprintf(f,"#define GENAST\n");
   4114 	if ( FoundException )
   4115 	{
   4116 /* MR1	 7-Apr-97  1.33MR1					                           */
   4117 /* MR1	 	   Fix suggested by:				                   */
   4118 /* MR1		   Francois-Xavier Fontaine (fontaine_f (at) istvax.ist.lu)         */
   4119 
   4120 		fprintf(f,"#define EXCEPTION_HANDLING\n");	            /* MR1 */
   4121 		fprintf(f,"#define NUM_SIGNALS %d\n", NumSignals);          /* MR1 */
   4122 	}
   4123 	if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n");
   4124 #ifdef DUM
   4125 	if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
   4126 #endif
   4127 	/* ###WARNING: This will have to change when SetWordSize changes */
   4128 	fprintf(f, "#define zzSET_SIZE %lu\n", NumWords(TokenNum-1)*sizeof(unsigned));
   4129     if (TraceGen) {
   4130       fprintf(f,"#ifndef zzTRACE_RULES\n");  /* MR20 */
   4131       fprintf(f,"#define zzTRACE_RULES\n");  /* MR20 */
   4132       fprintf(f,"#endif\n");                 /* MR22 */
   4133     };
   4134 	fprintf(f,"#include \"antlr.h\"\n");
   4135 	if ( GenAST ) fprintf(f,"#include \"ast.h\"\n");
   4136 	if ( UserDefdTokens )
   4137 		fprintf(f, "#include %s\n", UserTokenDefsFile);
   4138 	/* still need this one as it has the func prototypes */
   4139 	fprintf(f, "#include \"%s\"\n", DefFileName);
   4140 	/* still need this one as it defines the DLG interface */
   4141 	fprintf(f,"#include \"dlgdef.h\"\n");
   4142 	/* don't need this one unless DLG is used */
   4143 	if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName);
   4144 	fprintf(f,"#endif\n");
   4145 }
   4146 
   4147 /* dump action 's' to file 'output' starting at "local" tab 'tabs'
   4148    Dump line information in front of action if GenLineInfo is set
   4149    If file == -1 then GenLineInfo is ignored.
   4150    The user may redefine the LineInfoFormatStr to his/her liking
   4151    most compilers will like the default, however.
   4152 
   4153    June '93; changed so that empty lines are left alone so that
   4154    line information is correct for the compiler/debuggers.
   4155 */
   4156 void
   4157 #ifdef __USE_PROTOS
   4158 dumpAction( char *s, FILE *output, int tabs, int file, int line,
   4159 int final_newline )
   4160 #else
   4161 dumpAction( s, output, tabs, file, line, final_newline )
   4162 char *s;
   4163 FILE *output;
   4164 int tabs;
   4165 int file;
   4166 int line;
   4167 int final_newline;
   4168 #endif
   4169 {
   4170     int inDQuote, inSQuote;
   4171     require(s!=NULL, 		"dumpAction: NULL action");
   4172     require(output!=NULL,	eMsg1("dumpAction: output FILE is NULL for %s",s));
   4173 
   4174 	if ( GenLineInfo && file != -1 )
   4175 	{
   4176         OutLineInfo(output,line,FileStr[file]);
   4177 	}
   4178     PastWhiteSpace( s );
   4179 	/* don't print a tab if first non-white char is a # (preprocessor command) */
   4180 	if ( *s!='#' ) {TAB;}
   4181     inDQuote = inSQuote = FALSE;
   4182     while ( *s != '\0' )
   4183     {
   4184         if ( *s == '\\' )
   4185         {
   4186             fputc( *s++, output ); /* Avoid '"' Case */
   4187             if ( *s == '\0' ) return;
   4188             if ( *s == '\'' ) fputc( *s++, output );
   4189             if ( *s == '\"' ) fputc( *s++, output );
   4190         }
   4191         if ( *s == '\'' )
   4192         {
   4193             if ( !inDQuote ) inSQuote = !inSQuote;
   4194         }
   4195         if ( *s == '"' )
   4196         {
   4197             if ( !inSQuote ) inDQuote = !inDQuote;
   4198         }
   4199         if ( *s == '\n' )
   4200         {
   4201             fputc('\n', output);
   4202 			s++;
   4203             PastWhiteSpace( s );
   4204             if ( *s == '}' )
   4205             {
   4206                 --tabs;
   4207 				TAB;
   4208                 fputc( *s++, output );
   4209                 continue;
   4210             }
   4211             if ( *s == '\0' ) return;
   4212 			if ( *s != '#' )	/* #define, #endif etc.. start at col 1 */
   4213             {
   4214 				TAB;
   4215 			}
   4216         }
   4217         if ( *s == '}' && !(inSQuote || inDQuote) )
   4218         {
   4219             --tabs;            /* Indent one fewer */
   4220         }
   4221         if ( *s == '{' && !(inSQuote || inDQuote) )
   4222         {
   4223             tabs++;            /* Indent one more */
   4224         }
   4225         fputc( *s, output );
   4226         s++;
   4227     }
   4228     if ( final_newline ) fputc('\n', output);
   4229 }
   4230 
   4231 static void
   4232 #ifdef __USE_PROTOS
   4233 dumpAfterActions( FILE *output )
   4234 #else
   4235 dumpAfterActions( output )
   4236 FILE *output;
   4237 #endif
   4238 {
   4239 	ListNode *p;
   4240 	require(output!=NULL, "dumpAfterActions: output file was NULL for some reason");
   4241 	if ( AfterActions != NULL )
   4242 	{
   4243 		for (p = AfterActions->next; p!=NULL; p=p->next)
   4244 		{
   4245 			UserAction *ua = (UserAction *)p->elem;
   4246 			dumpAction( ua->action, output, 0, ua->file, ua->line, 1);
   4247 		}
   4248 	}
   4249 	fclose( output );
   4250 }
   4251 
   4252 /*
   4253  * Find the next action in the stream of execution.  Do not pass
   4254  * junctions with more than one path leaving them.
   4255  * Only pass generic junctions.
   4256  *
   4257  *	Scan forward while (generic junction with p2==NULL)
   4258  *	If we stop on an action, return ptr to the action
   4259  *	else return NULL;
   4260  */
   4261 static ActionNode *
   4262 #ifdef __USE_PROTOS
   4263 findImmedAction( Node *q )
   4264 #else
   4265 findImmedAction( q )
   4266 Node *q;
   4267 #endif
   4268 {
   4269 	Junction *j;
   4270 	require(q!=NULL, "findImmedAction: NULL node");
   4271 	require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node");
   4272 
   4273 	while ( q->ntype == nJunction )
   4274 	{
   4275 		j = (Junction *)q;
   4276 		if ( j->jtype != Generic || j->p2 != NULL ) return NULL;
   4277 		q = j->p1;
   4278 		if ( q == NULL ) return NULL;
   4279 	}
   4280 	if ( q->ntype == nAction ) return (ActionNode *)q;
   4281 	return NULL;
   4282 }
   4283 
   4284 static void
   4285 #ifdef __USE_PROTOS
   4286 dumpRetValAssign( char *retval, char *ret_def, RuleRefNode * ruleRef /* MR30 */)
   4287 #else
   4288 dumpRetValAssign( retval, ret_def, ruleRef /* MR30 */)
   4289 char *retval;
   4290 char *ret_def;
   4291 RuleRefNode *ruleRefNode;
   4292 #endif
   4293 {
   4294 	char *q = ret_def;
   4295 
   4296 	tab();
   4297 	while ( *retval != '\0' && *q != '\0')
   4298 	{
   4299 		while ( isspace((*retval)) ) retval++;
   4300 		while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output);
   4301 		fprintf(output, " = _trv.");
   4302 
   4303 		DumpNextNameInDef(&q, output);
   4304 		while ( isspace(*q) ) q++;
   4305 		fputc(';', output); fputc(' ', output);
   4306 		if ( *retval == ',' ) retval++;
   4307 	}
   4308 	if (*retval == '\0' && *q != '\0') {
   4309 /* MR30 */    errFL("Fewer output values than output formals for rule reference",
   4310 /* MR30 */                 FileStr[ruleRef->file],ruleRef->line);
   4311 	}
   4312 	if (*retval != '\0' && *q == '\0') {
   4313 /* MR30 */    errFL("More output actuals than output formals for rule reference",
   4314 /* MR30 */                 FileStr[ruleRef->file],ruleRef->line);
   4315 	}
   4316 }
   4317 
   4318 /* This function computes the set of tokens that can possibly be seen k
   4319  * tokens in the future from point j
   4320  */
   4321 
   4322 static set
   4323 #ifdef __USE_PROTOS
   4324 ComputeErrorSet( Junction *j, int k, int usePlusBlockBypass)
   4325 #else
   4326 ComputeErrorSet( j, k, usePlusBlockBypass )
   4327 Junction *j;
   4328 int k;
   4329 int usePlusBlockBypass;
   4330 #endif
   4331 {
   4332 	Junction *alt1;
   4333 	set a, rk, f;
   4334 	require(j->ntype==nJunction, "ComputeErrorSet: non junction passed");
   4335 
   4336 	f = rk = empty;
   4337 	for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2)
   4338 	{
   4339         if (alt1->ignore && ! usePlusBlockBypass) continue;     /* MR21 - Ignore aPlusBlk forward p2 */
   4340 		REACH(alt1->p1, k, &rk, a);
   4341 		require(set_nil(rk), "ComputeErrorSet: rk != nil");
   4342 		set_free(rk);
   4343 		set_orin(&f, a);
   4344 		set_free(a);
   4345 	}
   4346 	return f;
   4347 }
   4348 
   4349 static char *
   4350 #ifdef __USE_PROTOS
   4351 tokenFollowSet(TokNode *p)
   4352 #else
   4353 tokenFollowSet(p)
   4354 TokNode *p;
   4355 #endif
   4356 {
   4357     static char buf[100];
   4358     set rk, a;
   4359     int n;
   4360     rk = empty;
   4361 
   4362     REACH(p->next, 1, &rk, a);
   4363     require(set_nil(rk), "rk != nil");
   4364     set_free(rk);
   4365     n = DefErrSet( &a, 0, NULL );
   4366     set_free(a);
   4367     if ( GenCC )
   4368         sprintf(buf, "err%d", n);
   4369     else
   4370         sprintf(buf, "zzerr%d", n);
   4371     return buf;
   4372 }
   4373 
   4374 static void
   4375 #ifdef __USE_PROTOS
   4376 makeErrorClause( Junction *q, set f, int max_k, int usePlusBlockBypass )
   4377 #else
   4378 makeErrorClause( q, f, max_k, usePlusBlockBypass )
   4379 Junction *q;
   4380 set f;
   4381 int max_k;
   4382 int usePlusBlockBypass;
   4383 #endif
   4384 {
   4385     char *  handler_id="";                                           /* MR7 */
   4386     int     nilf=0;                                                  /* MR13 */
   4387     RuleEntry *ruleEntry;                                            /* MR14 */
   4388 
   4389 	if ( FoundException )
   4390 	{
   4391 		_gen("else {\n");
   4392 		tabs++;
   4393 		if ( FoundGuessBlk )
   4394 		{
   4395 			if ( GenCC ) {gen("if ( guessing ) goto fail;\n");}
   4396 			else gen("if ( zzguessing ) goto fail;\n");
   4397 		}
   4398 		gen("if (_sva) _signal=NoViableAlt;\n");
   4399 		gen("else _signal=NoSemViableAlt;\n");
   4400         if (q->outerEG != NULL) {
   4401           handler_id=q->outerEG->altID;
   4402 #if 0
   4403         } else {
   4404           printf("q->curAltNum=%d q->exception_label=%s\n",q->curAltNum,q->exception_label);
   4405           gen("*** DEBUG *** outerEG==NULL\n");
   4406 #endif
   4407         };
   4408 		gen1("goto %s_handler;  /* MR7 */\n",handler_id);    /* MR7 */
   4409 		tabs--;
   4410 		gen("}\n");
   4411 		return;
   4412 	}
   4413 
   4414 	if ( max_k == 1 )
   4415 	{
   4416 /* MR13 */  nilf=set_nil(f);
   4417     	  	if ( GenCC ) {
   4418               _gen1("else {FAIL(1,err%d", DefErrSet1(1,&f,1,NULL));
   4419             } else {
   4420                _gen1("else {zzFAIL(1,zzerr%d", DefErrSet1(1,&f,1,NULL));
   4421             };
   4422     		set_free(f);
   4423 	}
   4424 	else
   4425 	{
   4426 		int i;
   4427 		set_free(f);
   4428 		if ( GenCC ) {_gen1("else {FAIL(%d", max_k);}
   4429 		else _gen1("else {zzFAIL(%d", max_k);
   4430 
   4431     ruleEntry = (RuleEntry *) hash_get(Rname,q->rname);
   4432 
   4433 		for (i=1; i<=max_k; i++)
   4434 		{
   4435 /* MR14 */  if (ruleEntry->dontComputeErrorSet) {
   4436 /* MR14 */    f=empty;
   4437             } else {
   4438       	      f = ComputeErrorSet(q, i, usePlusBlockBypass /* use plus block bypass ? */ );
   4439             }
   4440 
   4441       if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));}
   4442 			else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL ));
   4443 
   4444 			set_free(f);
   4445 		}
   4446 	}
   4447 	_gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n");
   4448 /* MR13 */  if (nilf) {
   4449 /* MR13 */    errFL("empty error set for alt - probably because of undefined rule or infinite left recursion",
   4450 /* MR13 */                 FileStr[q->file],q->line);
   4451 /* MR13 */    gen(" /* MR13 empty error set for this alt - undef rule ? infinite left recursion ? */");
   4452 /* MR13 */  };
   4453 }
   4454 
   4455 static                                                               /* MR7 */
   4456 #ifdef __USE_PROTOS
   4457 char * findOuterHandlerLabel(ExceptionGroup *eg)                     /* MR7 */
   4458 #else
   4459 char * findOuterHandlerLabel(eg)                                     /* MR7 */
   4460 ExceptionGroup *eg;                                                  /* MR7 */
   4461 #endif
   4462 {
   4463   char              *label=NULL;                                     /* MR7 */
   4464   ExceptionGroup    *outerEG;                                        /* MR7 */
   4465 
   4466   if (eg->forRule == 0) {                                            /* MR7 */
   4467     if (eg->labelEntry != NULL) {                                    /* MR7 */
   4468       outerEG=eg->labelEntry->outerEG;                               /* MR7 */
   4469       if (outerEG != NULL) {                                         /* MR7 */
   4470         label=outerEG->altID;                                        /* MR7 */
   4471         outerEG->used=1;                                             /* MR7 */
   4472       };                                                             /* MR7 */
   4473     } else if (eg->outerEG != NULL) {                                /* MR7 */
   4474       outerEG=eg->outerEG;                                           /* MR7 */
   4475       label=outerEG->altID;                                          /* MR7 */
   4476       outerEG->used=1;                                               /* MR7 */
   4477     };                                                               /* MR7 */
   4478   };                                                                 /* MR7 */
   4479   return (label==NULL ? "" : label);                                 /* MR7 */
   4480 }                                                                    /* MR7 */
   4481 
   4482 /*** debug ***/
   4483 #if 0
   4484 ** static                                                               /* MR7 */
   4485 ** #ifdef __USE_PROTOS
   4486 ** char * findOuterAltHandlerLabel(Junction *startJ)                    /* MR7 */
   4487 ** #else
   4488 ** char * findOuterAltHandlerLabel(startJ)                              /* MR7 */
   4489 ** Junction *startJ;                                                    /* MR7 */
   4490 ** #endif
   4491 ** {                                                                    /* MR7 */
   4492 **   char      *label=NULL;                                             /* MR7 */
   4493 **   Junction  *alt;                                                    /* MR7 */
   4494 **                                                                      /* MR7 */
   4495 **   for (alt=startJ; alt != NULL; alt=alt->outerAltstart) {            /* MR7 */
   4496 **     label=alt->exception_label;                                      /* MR7 */
   4497 **     if (label != NULL) break;                                        /* MR7 */
   4498 **   };                                                                 /* MR7 */
   4499 **   return (label==NULL ? "" : label);                                 /* MR7 */
   4500 ** }                                                                    /* MR7 */
   4501 #endif
   4502 
   4503 #ifdef __USE_PROTOS
   4504 static void OutLineInfo(FILE *file,int line,char *fileName)
   4505 #else
   4506 static void OutLineInfo(file,line,fileName)
   4507   FILE *    file;
   4508   int       line;
   4509   char *    fileName;
   4510 #endif
   4511 {
   4512     static  char * prevFileName=NULL;
   4513     static  char * prevFileNameMS=NULL;
   4514 
   4515     char *  p;
   4516     char *  q;
   4517 
   4518     if (! GenLineInfo) return;
   4519 
   4520     if (!GenLineInfoMS) {
   4521 	    fprintf(file, LineInfoFormatStr,line,fileName);
   4522     } else {
   4523       if (fileName == prevFileName) {
   4524 	    fprintf(file, LineInfoFormatStr,line,prevFileNameMS);
   4525       } else {
   4526         if (prevFileNameMS != NULL) free (prevFileNameMS);
   4527         prevFileNameMS=(char *)calloc(1,strlen(fileName)+1);
   4528         require(prevFileNameMS != NULL,"why not do this in calloc wrapper");
   4529         q=prevFileNameMS;
   4530         for (p=fileName; *p != 0; p++) {
   4531             *q=*p;
   4532             if (*q == '\\') *q='/';
   4533             q++;
   4534         }
   4535       }
   4536       prevFileName=fileName;
   4537     };
   4538 }
   4539 
   4540 #if 0
   4541 
   4542 /* MR21 */
   4543 
   4544 #ifdef __USE_PROTOS
   4545 void OutFirstSetSymbol(Junction *q, char * pSymbol)
   4546 #else
   4547 void OutFirstSetSymbol(q, pSymbol)
   4548     Junction* q;
   4549 	char * pSymbol
   4550 #endif
   4551 {
   4552 
   4553 	set f;
   4554     if (pSymbol == NULL) return;
   4555 	gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol);
   4556     f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */);
   4557     DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, "");
   4558     set_free(f);
   4559 }
   4560 #endif
   4561 
   4562 /* MR21 */
   4563 
   4564 #ifdef __USE_PROTOS
   4565 void BlockPreambleOption(Junction *q, char * pSymbol)
   4566 #else
   4567 void BlockPreambleOption(q, pSymbol)
   4568     Junction* q;
   4569 	char * pSymbol;
   4570 #endif
   4571 {
   4572 	set f = empty;
   4573     if (pSymbol != NULL) {
   4574         f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */);
   4575     	gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol);
   4576         DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, "");
   4577     }
   4578     set_free(f);
   4579 }
   4580 
   4581 /* MR21 */
   4582 
   4583 void
   4584 #ifdef __USE_PROTOS
   4585 dumpActionPlus(ActionNode *a, char *s, FILE *output, int tabs, int file, int line,
   4586 int final_newline )
   4587 #else
   4588 dumpActionPlus(a, s, output, tabs, file, line, final_newline )
   4589 ActionNode *a;
   4590 char *s;
   4591 FILE *output;
   4592 int tabs;
   4593 int file;
   4594 int line;
   4595 int final_newline;
   4596 #endif
   4597 {
   4598     dumpAction(s,output,tabs,file,line,final_newline);
   4599 }
   4600 
   4601 
   4602 #if 0
   4603 ** #ifdef __USE_PROTOS
   4604 ** void MR_ErrorSets(Junction *q, int max_k, int usePlusBlockBypass)
   4605 ** #else
   4606 ** void MR_ErrorSets(q, max_k, usePlusBlockBypass)
   4607 ** Junction *q;
   4608 ** int max_k;
   4609 ** int usePlusBlockBypass;
   4610 ** #endif
   4611 ** {
   4612 **     int k;
   4613 **     set setResult;
   4614 ** 	Junction* alt1;
   4615 ** 	Junction* p;
   4616 ** 	set rk;
   4617 **
   4618 **     require (max_k <= CLL_k, "k > CLL_k");
   4619 **
   4620 **
   4621 **     for (k = 1; k <= CLL_k; k++) {set_clr(q->fset[k]); }
   4622 **
   4623 **     for (k = 1; k <= max_k; k++) {
   4624 **         for (alt1=q; alt1 != NULL; alt1 = (Junction *)alt1->p2)
   4625 **     	{
   4626 **             if (alt1->ignore && ! usePlusBlockBypass) continue;
   4627 **         	p = analysis_point((Junction *)alt1->p1);
   4628 **     		REACH(p, k, &rk, setResult);
   4629 **     		require(set_nil(rk), "rk != nil");
   4630 **             set_orin(&q->fset[k], setResult);
   4631 **     	}
   4632 **     }
   4633 ** }
   4634 #endif
   4635 
   4636 
   4637 #ifdef __USE_PROTOS
   4638 void DumpInitializers(FILE* output, RuleEntry *r, char * pReturn)
   4639 #else
   4640 void DumpInitializers(output, r, pReturn)
   4641 FILE* output;
   4642 RuleEntry *r;
   4643 char * pReturn;
   4644 #endif
   4645 {
   4646 	char *p = pReturn;
   4647 	char *pDataType;
   4648 	char *pSymbol;
   4649 	char *pEqualSign;
   4650 	char *pValue;
   4651 	char *pSeparator;
   4652 	int nest = 0;
   4653     char *q;
   4654 
   4655 	require(pReturn!=NULL, "DumpInitializer: invalid string");
   4656 
   4657     while (*p != 0) {
   4658     	p = endFormal(p,
   4659     			      &pDataType,
   4660     				  &pSymbol,
   4661     				  &pEqualSign,
   4662     				  &pValue,
   4663     				  &pSeparator,
   4664     				  &nest);
   4665         if (nest != 0) return;
   4666         if (pValue != NULL) {
   4667 			tab();
   4668             q = strBetween(pSymbol, pEqualSign, pSeparator);
   4669             fprintf(output, "_retv.%s", q);
   4670             q = strBetween(pValue, NULL, pSeparator);
   4671             fprintf(output, " = %s;\n", q);
   4672         }
   4673     }
   4674 }
   4675 
   4676 #ifdef __USE_PROTOS
   4677 void DumpFormals(FILE* output, char * pReturn, int bInitializer)
   4678 #else
   4679 void DumpFormals(output, pReturn, bInitializer)
   4680 FILE* output;
   4681 char * pReturn;
   4682 int bInitializer;
   4683 #endif
   4684 {
   4685 	char *p = pReturn;
   4686 	char *pDataType;
   4687 	char *pSymbol;
   4688 	char *pEqualSign;
   4689 	char *pValue;
   4690 	char *pSeparator;
   4691 	int nest = 0;
   4692     char *q;
   4693     int count = 0;
   4694 
   4695 	require(pReturn!=NULL, "DumpFormals: invalid string");
   4696 
   4697     while (*p != 0) {
   4698     	p = endFormal(p,
   4699     			      &pDataType,
   4700     				  &pSymbol,
   4701     				  &pEqualSign,
   4702     				  &pValue,
   4703     				  &pSeparator,
   4704     				  &nest);
   4705         if (nest != 0) return;
   4706         if (count > 0) fprintf(output,",");
   4707         if (pDataType != NULL && pSymbol != NULL) {
   4708             q = strBetween(pDataType, pSymbol, pSeparator);
   4709             fprintf(output, "%s", q);
   4710             q = strBetween(pSymbol, pEqualSign, pSeparator);
   4711             fprintf(output," %s",q);
   4712             if (pValue != NULL) {
   4713                 q = strBetween(pValue, NULL, pSeparator);
   4714                 if (bInitializer != 0) {
   4715                     fprintf(output, " = %s", q);
   4716                 }
   4717             }
   4718         }
   4719         count++;
   4720     }
   4721 }
   4722 
   4723 /* MR23 Check for empty alt in a more intelligent way.
   4724         Previously, an empty alt for genBlk had to point directly
   4725 		to the endBlock.  This did not work once I changed {...}
   4726 		blocks to look like (...|...| epsilon) since there were
   4727 		intervening generics.  This fixes the problem for this
   4728 		particular case.  Things like actions or empty blocks of
   4729 		various kinds will still cause problems, but I wasnt't
   4730 		prepared to handle pathological cases like (A|()*). It
   4731 		does handle (A | ()), which is a recommended idiom for
   4732 		epsilon.
   4733 
   4734         Actually, this isn't quite correct since it doesn't handle
   4735 		the case of the ignore bit in the plus block bypass, but
   4736 		I'm too tired to figure out the correct fix, and will just
   4737 		work around it.
   4738 */
   4739 
   4740 #ifdef __USE_PROTOS
   4741 int isEmptyAlt(Node * alt, Node * endBlock)
   4742 #else
   4743 int isEmptyAlt(alt, endBlock)
   4744 Node * alt;
   4745 Node * endBlock;
   4746 #endif
   4747 {
   4748 	Node * n = alt;
   4749 	Junction * j;
   4750 	while (n != endBlock) {
   4751 		switch (n->ntype) {
   4752 
   4753 			case nRuleRef:
   4754 				return 0;
   4755 
   4756 			case nToken:
   4757 				return 0;
   4758 
   4759 			case nAction:
   4760 				return 0;
   4761 
   4762 			case nJunction:
   4763 				goto JUNCTION;
   4764 
   4765 			default:
   4766 				fatal_internal("Invalid node type");
   4767 				return 0;
   4768 		}
   4769 JUNCTION:
   4770 		j = (Junction *) n;
   4771 
   4772 		switch (j->jtype) {
   4773 			case Generic:
   4774 				{
   4775 					n = j->p1;
   4776 					goto NEXT;
   4777 				}
   4778 
   4779 			case aSubBlk:
   4780 				{
   4781 					n = j->p1;	/* MR26 */
   4782 					goto NEXT;	/* MR26 */
   4783 				}
   4784 
   4785 			case EndBlk:
   4786 					return 0;
   4787 
   4788 			case EndRule:
   4789 					return 1;
   4790 
   4791 			default:
   4792 					return 0;
   4793 		}
   4794 NEXT: continue;
   4795 	}
   4796 	return 1;
   4797 }
   4798