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