1 /* bits.c -- manage creation and output of bit sets used by the parser.
2  *
3  * SOFTWARE RIGHTS
4  *
5  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
6  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
7  * company may do whatever they wish with source code distributed with
8  * PCCTS or the code generated by PCCTS, including the incorporation of
9  * PCCTS, or its output, into commerical software.
10  *
11  * We encourage users to develop software with PCCTS.  However, we do ask
12  * that credit is given to us for developing PCCTS.  By "credit",
13  * we mean that if you incorporate our source code into one of your
14  * programs (commercial product, research project, or otherwise) that you
15  * acknowledge this fact somewhere in the documentation, research report,
16  * etc...  If you like PCCTS and have developed a nice tool with the
17  * output, please mention that you developed it using PCCTS.  In
18  * addition, we ask that this header remain intact in our source code.
19  * As long as these guidelines are kept, we expect to continue enhancing
20  * this system and expect to make other tools available as they are
21  * completed.
22  *
23  * ANTLR 1.33
24  * Terence Parr
25  * Parr Research Corporation
26  * with Purdue University and AHPCRC, University of Minnesota
27  * 1989-2001
28  */
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include <assert.h>
34 #include "pcctscfg.h"
35 #include "set.h"
36 #include "syn.h"
37 #include "hash.h"
38 #include "generic.h"
39 #include "dlgdef.h"
40 
41 /* char is only thing that is pretty much always known == 8 bits
42  * This allows output of antlr (set stuff, anyway) to be androgynous (portable)
43  */
44 typedef unsigned char SetWordType;
45 #define BitsPerByte		8
46 #define BitsPerWord		BitsPerByte*sizeof(SetWordType)
47 
48 static SetWordType *setwd = NULL;
49 int setnum = -1;
50 int wordnum = 0;
51 
52 int esetnum = 0;
53 
54 /* Used to convert native wordsize, which ANTLR uses (via set.c) to manipulate sets,
55    to bytes that are most portable size-wise.
56    */
57 void
58 #ifdef __USE_PROTOS
DumpIntAsChars(FILE * f,char * format,unsigned wd)59 DumpIntAsChars( FILE *f, char *format, unsigned wd )
60 #else
61 DumpIntAsChars( f, format, wd )
62 FILE *f;
63 char *format;
64 unsigned wd;
65 #endif
66 {
67 	int i;
68 	/* uses max of 32 bit unsigned integer for the moment */
69 	static unsigned long byte_mask[sizeof(unsigned long)] =
70 				{ 0xFF, 0xFF00UL, 0xFF0000UL, 0xFF000000UL };  /* MR20 G. Hobbelt */
71 /*				  0xFF00000000, 0xFF0000000000, 0xFF000000000000, 0xFF00000000000000 };*/
72 
73 	/* for each byte in the word */
74 	assert(sizeof(unsigned) <= 4); /* M20 G. Hobbelt Sanity check */
75 	for (i=0; i<sizeof(unsigned); i++)
76 	{
77 		/* mask out the ith byte and shift down to the first 8 bits */
78 		fprintf(f, format, (wd&byte_mask[i])>>(i*BitsPerByte));
79 		if ( i<sizeof(unsigned)-1) fprintf(f, ",");
80 	}
81 }
82 
83 /* Create a new setwd (ignoring [Ep] token on end) */
84 void
85 #ifdef __USE_PROTOS
NewSetWd(void)86 NewSetWd( void )
87 #else
88 NewSetWd( )
89 #endif
90 {
91 	SetWordType *p;
92 
93 	if ( setwd == NULL )
94 	{
95 		setwd = (SetWordType *) calloc(TokenNum, sizeof(SetWordType));
96 		require(setwd!=NULL, "NewSetWd: cannot alloc set wd\n");
97 	}
98 	for (p = setwd; p<&(setwd[TokenNum]); p++)  {*p=0;}
99 	wordnum++;
100 }
101 
102 void
103 #ifdef __USE_PROTOS
DumpSetWd(void)104 DumpSetWd( void )
105 #else
106 DumpSetWd( )
107 #endif
108 {
109 	if ( GenCC ) DumpSetWdForCC();
110 	else DumpSetWdForC();
111 }
112 
113 /* Dump the current setwd to ErrFile. 0..MaxTokenVal */
114 void
115 #ifdef __USE_PROTOS
DumpSetWdForC(void)116 DumpSetWdForC( void )
117 #else
118 DumpSetWdForC( )
119 #endif
120 {
121 	int i,c=1;
122 
123 	if ( setwd==NULL ) return;
124 	fprintf(DefFile, "extern SetWordType setwd%d[];\n", wordnum);
125 	fprintf(ErrFile,
126 			"SetWordType setwd%d[%d] = {", wordnum, TokenNum-1);
127 	for (i=0; i<TokenNum-1; i++)
128 	{
129 		DAWDLE;
130 		if ( i!=0 ) fprintf(ErrFile, ",");
131 		if ( c == 8 ) {fprintf(ErrFile, "\n\t"); c=1;} else c++;
132 		fprintf(ErrFile, "0x%x", setwd[i]);
133 	}
134 	fprintf(ErrFile, "};\n");
135 }
136 
137 /* Dump the current setwd to Parser.C file. 0..MaxTokenVal;
138  * Only used if -CC on.
139  */
140 void
141 #ifdef __USE_PROTOS
DumpSetWdForCC(void)142 DumpSetWdForCC( void )
143 #else
144 DumpSetWdForCC( )
145 #endif
146 {
147 	int i,c=1;
148 
149 	if ( setwd==NULL ) return;
150 	fprintf(Parser_h, "\tstatic SetWordType setwd%d[%d];\n", wordnum, TokenNum-1);
151 	fprintf(Parser_c,
152 			"SetWordType %s::setwd%d[%d] = {", CurrentClassName, wordnum,
153 			TokenNum-1);
154 	for (i=0; i<TokenNum-1; i++)
155 	{
156 		DAWDLE;
157 		if ( i!=0 ) fprintf(Parser_c, ",");
158 		if ( c == 8 ) {fprintf(Parser_c, "\n\t"); c=1;} else c++;
159 		fprintf(Parser_c, "0x%x", setwd[i]);
160 	}
161 	fprintf(Parser_c, "};\n");
162 }
163 
164 /* Make a new set.  Dump old setwd and create new setwd if current setwd is full */
165 void
166 #ifdef __USE_PROTOS
NewSet(void)167 NewSet( void )
168 #else
169 NewSet( )
170 #endif
171 {
172 	setnum++;
173 	if ( setnum==BitsPerWord )		/* is current setwd full? */
174 	{
175 		DumpSetWd(); NewSetWd(); setnum = 0;
176 	}
177 }
178 
179 /* s is a set of tokens.  Turn on bit at each token position in set 'setnum' */
180 void
181 #ifdef __USE_PROTOS
FillSet(set s)182 FillSet( set s )
183 #else
184 FillSet( s )
185 set s;
186 #endif
187 {
188 	SetWordType mask=(((unsigned)1)<<setnum);
189 	unsigned int e;
190 
191 	while ( !set_nil(s) )
192 	{
193 		e = set_int(s);
194 		set_rm(e, s);
195 		setwd[e] |= mask;
196 	}
197 }
198 
199 					/* E r r o r  C l a s s  S t u f f */
200 
201 /* compute the FIRST of a rule for the error class stuff */
202 static set
203 #ifdef __USE_PROTOS
Efirst(char * rule,ECnode * eclass)204 Efirst( char *rule, ECnode *eclass )
205 #else
206 Efirst( rule, eclass )
207 char *rule;
208 ECnode *eclass;
209 #endif
210 {
211 	set rk, a;
212 	Junction *r;
213 	RuleEntry *q = (RuleEntry *) hash_get(Rname, rule);
214 
215 	if ( q == NULL )
216 	{
217 		warnNoFL(eMsg2("undefined rule '%s' referenced in errclass '%s'; ignored",
218 						rule, TokenString(eclass->tok)));
219 		return empty;
220 	}
221 	r = RulePtr[q->rulenum];
222 	r->end->halt = TRUE;		/* don't let reach fall off end of rule here */
223 	rk = empty;
224 	REACH(r, 1, &rk, a);
225 	r->end->halt = FALSE;
226 	return a;
227 }
228 
229 /*
230  * scan the list of tokens/eclasses/nonterminals filling the new eclass
231  * with the set described by the list.  Note that an eclass can be
232  * quoted to allow spaces etc... However, an eclass must not conflict
233  * with a reg expr found elsewhere.  The reg expr will be taken over
234  * the eclass name.
235  */
236 static void
237 #ifdef __USE_PROTOS
doEclass(char * eclass)238 doEclass( char *eclass )
239 #else
240 doEclass( eclass )
241 char *eclass;
242 #endif
243 {
244 	TermEntry *q;
245 	ECnode *p;
246 	TCnode *tcnode;
247 	ListNode *e;
248 	unsigned int t;
249 	unsigned deg=0;
250 	set a;
251 	require(eclass!=NULL, "doEclass: NULL eset");
252 
253 	p = (ECnode *) eclass;
254 	lexmode(p->lexclass);	/* switch to lexclass where errclass is defined */
255 	p->eset = empty;
256 	for (e = (p->elist)->next; e!=NULL; e=e->next)
257 	{
258 		q = NULL;								/* MR23 */
259 
260 		if ( islower( *((char *)e->elem) ) )	/* is it a rule ref? (alias FIRST request) */
261 		{
262 			a = Efirst((char *)e->elem, p);
263 			set_orin(&p->eset, a);
264 			deg += set_deg(a);
265 			set_free( a );
266 			continue;
267 		}
268 		else if ( *((char *)e->elem)=='"' )
269 		{
270 			t = 0;
271 			q = (TermEntry *) hash_get(Texpr, (char *) e->elem);
272 			if ( q == NULL )
273 			{
274 				/* if quoted and not an expr look for eclass name */
275 				q = (TermEntry *) hash_get(Tname, *((char **)&(e->elem))=StripQuotes((char *)e->elem));
276 				if ( q != NULL ) t = q->token;
277 			}
278 			else t = q->token;
279 		}
280 		else	/* labelled token/eclass/tokclass */
281 		{
282 			q = (TermEntry *) hash_get(Tname, (char *)e->elem);
283 			if ( q != NULL )
284 			{
285 				if ( strcmp((char *)e->elem, TokenString(p->tok))==0 )
286 				{
287 					warnNoFL(eMsg1("self-referential error class '%s'; ignored",
288 								   (char *)e->elem));
289 					continue;
290 				}
291 				else
292 					t = q->token;
293 			}
294 			else t=0;
295 		}
296 		if ( t!=0 )
297 		{
298 			if (isTermEntryTokClass(q))  {			/* MR23 */
299 			    tcnode = q->tclass;					/* MR23 */
300 				set_orin(&p->eset, tcnode->tset);	/* MR23 */
301 				deg = set_deg(p->eset);				/* MR23 */
302 			}										/* MR23 */
303 			else {
304 				set_orel(t, &p->eset);
305 				deg++;
306 			}
307 		}
308 		else warnNoFL(eMsg2("undefined token '%s' referenced in errclass '%s'; ignored",
309 							(char *)e->elem, TokenString(p->tok)));
310 	}
311 	p->setdeg = deg;
312 }
313 
314 void
315 #ifdef __USE_PROTOS
ComputeErrorSets(void)316 ComputeErrorSets( void )
317 #else
318 ComputeErrorSets( )
319 #endif
320 {
321 #ifdef __cplusplus
322     list_apply(eclasses, (void (*)(void *)) doEclass);
323 #else
324 #ifdef __USE_PROTOS
325     list_apply(eclasses, (void (*)(void *)) doEclass);
326 #else
327     list_apply(eclasses, doEclass);
328 #endif
329 #endif
330 }
331 
332 void
333 #ifdef __USE_PROTOS
ComputeTokSets(void)334 ComputeTokSets( void )
335 #else
336 ComputeTokSets( )
337 #endif
338 {
339 	ListNode *t, *e = NULL, *e1, *e2;
340 	int something_changed;
341     int i;
342 	TCnode *p;
343 	TermEntry *q, *q1, *q2;
344 
345 	if ( tclasses == NULL ) return;
346 
347 	/* turn lists of token/tokclass references into sets */
348 	for (t = tclasses->next; t!=NULL; t=t->next)
349 	{
350 		p = (TCnode *) t->elem;
351 
352 		/* if wild card, then won't have entries in tclass, assume all_tokens */
353 		if ( p->tok == WildCardToken )
354 		{
355 			p->tset = set_dup(all_tokens);
356 			continue;
357 		}
358 
359 		lexmode(p->lexclass);	/* switch to lexclass where tokclass is defined */
360 		p->tset = empty;
361 
362 		/* instantiate all tokens/token_classes into the tset */
363 		for (e = (p->tlist)->next; e!=NULL; e=e->next)
364 		{
365 			char *tokstr;
366 			tokstr = (char *)e->elem;
367 			if ( *tokstr == '"' ) {
368                 q = (TermEntry *) hash_get(Texpr, tokstr);
369     			require(q!=NULL, "ComputeTokSets: no token def");
370     			set_orel(q->token, &p->tset);
371 			} else if (tokstr[0] == '.') {
372                 e1=e->next;
373                 e2=e1->next;
374                 e=e2;
375                 q1= (TermEntry *) hash_get(Tname, (char *)e1->elem);
376     			require(q1!=NULL, "ComputeTokSets: no token def");
377                 q2= (TermEntry *) hash_get(Tname, (char *)e2->elem);
378     			require(q2!=NULL, "ComputeTokSets: no token def");
379 
380                 if (set_el(q1->token,imag_tokens)) {
381 errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s",
382                         TokenString(p->tok),(char *)e1->elem) );
383                 }
384                 if (set_el(q2->token,imag_tokens)) {
385 errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s",
386                         TokenString(p->tok),(char *)e2->elem) );
387                 }
388                 if (q1->token > q2->token) {
389 errNoFL(eMsg3("for #tokclass %s %s..%s - first token number > second token number",
390                         TokenString(p->tok),(char *)e1->elem,(char *)e2->elem) );
391                   for (i=q2->token; i<=q1->token; i++) { set_orel(i, &p->tset); }
392                 } else {
393                   for (i=q1->token; i<=q2->token; i++) { set_orel(i, &p->tset); }
394                 }
395             } else {
396                 q = (TermEntry *) hash_get(Tname, tokstr);
397     			require(q!=NULL, "ComputeTokSets: no token def");
398     			set_orel(q->token, &p->tset);
399             }
400 		}
401 	}
402 
403 	/* Go thru list of tokclasses again looking for tokclasses in sets */
404 again:
405 	something_changed = 0;
406 	for (t = tclasses->next; t!=NULL; t=t->next)
407 	{
408 		set tcl;
409 		p = (TCnode *) t->elem;
410 		tcl = set_and(p->tset, tokclasses);
411 		if ( !set_nil(tcl) )
412 		{
413 			int tk;
414 			/* replace refs to tokclasses with the associated set of tokens */
415 			something_changed = 1;
416 			while ( !set_nil(tcl) )
417 			{
418 				tk = set_int(tcl);		/* grab one of the tok class refs */
419 				set_rm(tk, tcl);
420 				if ( p->tok != tk )		/* tokclass ref to yourself? */
421 				{
422 					q = (TermEntry *) hash_get(Tname, TokenString(tk));
423 					require(q!=NULL, "#tokclass not in hash table");
424 					set_orin(&p->tset, q->tclass->tset);
425 				}
426 				set_rm(tk, p->tset);	/* remove ref that we replaced */
427 			}
428 		}
429 		set_free(tcl);
430 	}
431 	if ( something_changed ) goto again;
432 }
433 
434 void
435 #ifdef __USE_PROTOS
DumpRemainingTokSets(void)436 DumpRemainingTokSets(void)
437 #else
438 DumpRemainingTokSets()
439 #endif
440 {
441 	TCnode *p;
442 	ListNode *t;
443 
444 	/* Go thru tclasses (for the last time) and dump the sets not dumped
445 	 * during code gen; yes, this is a bogus way to do this, but ComputeTokSets()
446 	 * can't dump the defs as the error file and tok file has not been created
447 	 * yet etc...
448 	 */
449 	if ( tclasses==NULL ) return;
450 	for (t = tclasses->next; t!=NULL; t=t->next)
451 	{
452 		unsigned e;
453 		p = (TCnode *) t->elem;
454 		if ( p->dumped ) continue;
455 		e = DefErrSet(&(p->tset), 0, TokenString(p->tok));
456 		p->dumped = 1;
457 		p->setnum = e;
458 	}
459 }
460 
461 
462 /* replace a subset of an error set with an error class name if a subset is found
463  * repeat process until no replacements made
464  */
465 void
466 #ifdef __USE_PROTOS
SubstErrorClass(set * f)467 SubstErrorClass( set *f )
468 #else
469 SubstErrorClass( f )
470 set *f;
471 #endif
472 {
473 	int max, done = 0;
474 	ListNode *p;
475 	ECnode *ec, *maxclass = NULL;
476 	set a;
477 	require(f!=NULL, "SubstErrorClass: NULL eset");
478 
479 	if ( eclasses == NULL ) return;
480 	while ( !done )
481 	{
482 		max = 0;
483 		maxclass = NULL;
484 		for (p=eclasses->next; p!=NULL; p=p->next)	/* chk all error classes */
485 		{
486 			ec = (ECnode *) p->elem;
487 			if ( ec->setdeg > max )
488 			{
489 				if ( set_sub(ec->eset, *f) || set_equ(ec->eset, *f) )
490 					{maxclass = ec; max=ec->setdeg;}
491 			}
492 		}
493 		if ( maxclass != NULL )	/* if subset found, replace with token */
494 		{
495 			a = set_dif(*f, maxclass->eset);
496 			set_orel((unsigned)maxclass->tok, &a);
497 			set_free(*f);
498 			*f = a;
499 		}
500 		else done = 1;
501 	}
502 }
503 
504 int
505 #ifdef __USE_PROTOS
DefErrSet1(int nilOK,set * f,int subst,char * name)506 DefErrSet1(int nilOK, set *f, int subst, char *name )
507 #else
508 DefErrSet1(nilOK, f, subst, name )
509 int nilOK;
510 set *f;
511 int subst;			/* should be substitute error classes? */
512 char *name;
513 #endif
514 {
515 	if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, "_set");
516 	else return DefErrSetForC1(nilOK, f, subst, name, "_set");
517 }
518 
519 int
520 #ifdef __USE_PROTOS
DefErrSet(set * f,int subst,char * name)521 DefErrSet( set *f, int subst, char *name )
522 #else
523 DefErrSet( f, subst, name )
524 set *f;
525 int subst;			/* should be substitute error classes? */
526 char *name;
527 #endif
528 {
529     return DefErrSet1(0,f,subst,name);
530 }
531 
532 int
533 #ifdef __USE_PROTOS
DefErrSetWithSuffix(int nilOK,set * f,int subst,char * name,const char * suffix)534 DefErrSetWithSuffix(int nilOK, set *f, int subst, char *name, const char* suffix)
535 #else
536 DefErrSetWithSuffix(nilOK, f, subst, name, suffix )
537 int nilOK;
538 set *f;
539 int subst;			/* should be substitute error classes? */
540 char *name;
541 char *suffix;
542 #endif
543 {
544 	if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, suffix );
545 	else return DefErrSetForC1(nilOK, f, subst, name, suffix);
546 }
547 
548 /* Define a new error set.  WARNING...set-implementation dependent.
549  */
550 int
551 #ifdef __USE_PROTOS
DefErrSetForC1(int nilOK,set * f,int subst,char * name,const char * suffix)552 DefErrSetForC1(int nilOK, set *f, int subst, char * name, const char * suffix)
553 #else
554 DefErrSetForC1(nilOK, f, subst, name, suffix)
555 int nilOK;          /* MR13 */
556 set *f;
557 int subst;			/* should be substitute error classes? */
558 char *name;
559 const char *suffix;
560 #endif
561 {
562 	unsigned *p, *endp;
563 	int e=1;
564 
565     if (!nilOK)	require(!set_nil(*f), "DefErrSetForC1: nil set to dump?");
566 
567 	if ( subst ) SubstErrorClass(f);
568 	p = f->setword;
569 	endp = &(f->setword[f->n]);
570 	esetnum++;
571 	if ( name!=NULL )
572 		fprintf(DefFile, "extern SetWordType %s%s[];\n", name, suffix);
573 	else
574 		fprintf(DefFile, "extern SetWordType zzerr%d[];\n", esetnum);
575 	if ( name!=NULL ) {
576 		fprintf(ErrFile, "SetWordType %s%s[%d] = {",
577 				name,
578                 suffix,
579 				NumWords(TokenNum-1)*sizeof(unsigned));
580 	}
581 	else {
582 		fprintf(ErrFile, "SetWordType zzerr%d[%d] = {",
583 				esetnum,
584 				NumWords(TokenNum-1)*sizeof(unsigned));
585 	}
586 	while ( p < endp )
587 	{
588 		if ( e > 1 ) fprintf(ErrFile, ", ");
589 		DumpIntAsChars(ErrFile, "0x%x", *p++);
590 		if ( e == 3 )
591 		{
592 			DAWDLE;
593 			if ( p < endp ) fprintf(ErrFile, ",");
594 			fprintf(ErrFile, "\n\t");
595 			e=1;
596 		}
597 		else e++;
598 	}
599 	fprintf(ErrFile, "};\n");
600 
601 	return esetnum;
602 }
603 
604 int
605 #ifdef __USE_PROTOS
DefErrSetForC(set * f,int subst,char * name)606 DefErrSetForC( set *f, int subst, char *name )
607 #else
608 DefErrSetForC( f, subst, name )
609 set *f;
610 int subst;			/* should be substitute error classes? */
611 char *name;
612 #endif
613 {
614   return DefErrSetForC1(0,f,subst,name, "_set");
615 }
616 
617 /* Define a new error set.  WARNING...set-implementation dependent;
618  * Only used when -CC on.
619  */
620 
621 int
622 #ifdef __USE_PROTOS
DefErrSetForCC1(int nilOK,set * f,int subst,char * name,const char * suffix)623 DefErrSetForCC1(int nilOK, set *f, int subst, char *name, const char *suffix )
624 #else
625 DefErrSetForCC1(nilOK, f, subst, name, suffix )
626 int nilOK;          /* MR13 */
627 set *f;
628 int subst;			/* should be substitute error classes? */
629 char *name;
630 const char *suffix;
631 #endif
632 {
633 	unsigned *p, *endp;
634 	int e=1;
635 
636     if (!nilOK)	require(!set_nil(*f), "DefErrSetForCC1: nil set to dump?");
637 
638 	if ( subst ) SubstErrorClass(f);
639 	p = f->setword;
640 	endp = &(f->setword[f->n]);
641 	esetnum++;
642 
643 	if ( name!=NULL ) {
644 		fprintf(Parser_h, "\tstatic SetWordType %s%s[%d];\n", name, suffix,
645 				NumWords(TokenNum-1)*sizeof(unsigned));
646 		fprintf(Parser_c, "SetWordType %s::%s%s[%d] = {",
647 				CurrentClassName,
648 				name,
649 				suffix,
650 				NumWords(TokenNum-1)*sizeof(unsigned));
651 	}
652 	else {
653 		fprintf(Parser_c, "SetWordType %s::err%d[%d] = {",
654 				CurrentClassName,
655 				esetnum,
656 				NumWords(TokenNum-1)*sizeof(unsigned));
657 		fprintf(Parser_h, "\tstatic SetWordType err%d[%d];\n", esetnum,
658 				NumWords(TokenNum-1)*sizeof(unsigned));
659 	}
660 
661 	while ( p < endp )
662 	{
663 		if ( e > 1 ) fprintf(Parser_c, ", ");
664 		DumpIntAsChars(Parser_c, "0x%x", *p++);
665 		if ( e == 3 )
666 		{
667 			if ( p < endp ) fprintf(Parser_c, ",");
668 			fprintf(Parser_c, "\n\t");
669 			e=1;
670 		}
671 		else e++;
672 	}
673 	fprintf(Parser_c, "};\n");
674 
675 	return esetnum;
676 }
677 
678 int
679 #ifdef __USE_PROTOS
DefErrSetForCC(set * f,int subst,char * name)680 DefErrSetForCC( set *f, int subst, char *name )
681 #else
682 DefErrSetForCC( f, subst, name )
683 set *f;
684 int subst;			/* should be substitute error classes? */
685 char *name;
686 #endif
687 {
688   return DefErrSetForCC1(0,f,subst,name, "_set");
689 }
690 
691 void
692 #ifdef __USE_PROTOS
GenParser_c_Hdr(void)693 GenParser_c_Hdr(void)
694 #else
695 GenParser_c_Hdr()
696 #endif
697 {
698 	int i,j;
699     TermEntry   *te;
700     char * hasAkaName = NULL;									/* MR23 */
701 
702 	hasAkaName = (char *) malloc(TokenNum+1);					/* MR23 */
703 	require(hasAkaName!=NULL, "Cannot alloc hasAkaName\n");		/* MR23 */
704 	for (i = 0; i < TokenNum; i++) hasAkaName[i]='0';			/* MR23 */
705 	hasAkaName[TokenNum] = 0;                                   /* MR23 */
706 
707 	fprintf(Parser_c, "/*\n");
708 	fprintf(Parser_c, " * %s: P a r s e r  S u p p o r t\n", CurrentClassName);
709 	fprintf(Parser_c, " *\n");
710 	fprintf(Parser_c, " * Generated from:");
711 	for (i=0; i<NumFiles; i++) fprintf(Parser_c, " %s", FileStr[i]);
712 	fprintf(Parser_c, "\n");
713 	fprintf(Parser_c, " *\n");
714 	fprintf(Parser_c, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n");
715 	fprintf(Parser_c, " * Parr Research Corporation\n");
716 	fprintf(Parser_c, " * with Purdue University Electrical Engineering\n");
717 	fprintf(Parser_c, " * with AHPCRC, University of Minnesota\n");
718 	fprintf(Parser_c, " * ANTLR Version %s\n", Version);
719 	fprintf(Parser_c, " */\n\n");
720 
721   if ( FirstAction != NULL ) dumpAction(FirstAction,Parser_c, 0, -1, 0, 1);    /* MR11 MR15b */
722 
723 	fprintf(Parser_c, "#define ANTLR_VERSION	%s\n", VersionDef);
724 
725 	fprintf(Parser_c, "#include \"pcctscfg.h\"\n");
726 	fprintf(Parser_c, "#include \"pccts_stdio.h\"\n");
727 	fprintf(Parser_c, "#define ANTLR_SUPPORT_CODE\n");
728 	if ( UserTokenDefsFile != NULL )
729 	   fprintf(Parser_c, "#include %s\n", UserTokenDefsFile);
730 	else
731 	   fprintf(Parser_c, "#include \"%s\"\n", DefFileName);
732 
733 	fprintf(Parser_c, "#include \"%s.h\"\n\n", CurrentClassName);
734 
735 	fprintf(Parser_c, "const ANTLRChar *%s::tokenName(int tok) ",   /* MR1 */
736 					CurrentClassName);                  	        /* MR1 */
737 	fprintf(Parser_c, "  { return _token_tbl[tok]; }\n");	        /* MR1 */ /* MR10 */
738 	/* Dump a Parser::tokens for each automaton */
739 	fprintf(Parser_c, "\nconst ANTLRChar *%s::_token_tbl[]={\n",
740                                                  CurrentClassName); /* MR20 */
741 	fprintf(Parser_c, "\t/* 00 */\t\"Invalid\"");
742 
743 	for (i=1; i<TokenNum-1; i++)
744 	{
745 		DAWDLE;
746 		if ( i == EpToken ) continue;
747 		/* remapped to invalid token? */
748 		if ( TokenInd!=NULL && TokenInd[i]>=LastTokenCounted )
749 		{
750 			fprintf(Parser_c, ",\n\t/* %02d */\t\"invalid\"", i);
751 			continue;
752 		}
753 		if ( TokenString(i) != NULL ) {
754            te=(TermEntry *) hash_get(Tname,TokenString(i));                     /* MR11 */
755             if (te == NULL || te->akaString == NULL) {                          /* MR11 */
756   	   	      fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i));
757             } else {
758 			  hasAkaName[i] = '1';											    /* MR23 */
759   	   	      fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, te->akaString);   /* MR11 */
760             }
761         }
762 		else
763 		{
764 			/* look in all lexclasses for the reg expr */
765 			for (j=0; j<NumLexClasses; j++)
766 			{
767 				lexmode(j);
768 				if ( ExprString(i) != NULL )
769 				{
770 					fprintf(Parser_c, ",\n\t/* %02d */\t", i);
771 					dumpExpr(Parser_c, ExprString(i));
772 					break;
773 				}
774 			}
775 			if ( j>=NumLexClasses )
776 			{
777 				if ( UserDefdTokens )
778 				{
779 					fprintf(Parser_c, ",\n\t/* %02d */\t\"\"", i);
780 				}
781 				else
782 					fatal_internal(eMsgd("No label or expr for token %d",i));
783 			}
784 		}
785 	}
786 	fprintf(Parser_c, "\n};\n");
787 
788 	/* Build constructors */
789 	fprintf(Parser_c, "\n%s::", CurrentClassName);
790 	fprintf(Parser_c,	"%s(ANTLRTokenBuffer *input) : %s(input,%d,%d,%d,%d)\n",
791 						CurrentClassName,
792 						(BaseClassName == NULL ? "ANTLRParser" : BaseClassName),
793 						OutputLL_k,
794 						FoundGuessBlk,
795 						DemandLookahead,
796 						NumWords(TokenNum-1)*sizeof(unsigned));
797 	fprintf(Parser_c, "{\n");
798 	fprintf(Parser_c, "\ttoken_tbl = _token_tbl;\n");
799     if (TraceGen) {
800       fprintf(Parser_c, "\ttraceOptionValueDefault=1;\t\t// MR10 turn trace ON\n");
801     } else {
802       fprintf(Parser_c, "\ttraceOptionValueDefault=0;\t\t// MR10 turn trace OFF\n");
803     };
804 	fprintf(Parser_c, "}\n\n");
805 	free ( (void *) hasAkaName);
806 }
807 
808 void
809 #ifdef __USE_PROTOS
GenParser_h_Hdr(void)810 GenParser_h_Hdr(void)
811 #else
812 GenParser_h_Hdr()
813 #endif
814 {
815 	int i;
816 
817 	fprintf(Parser_h, "/*\n");
818 	fprintf(Parser_h, " * %s: P a r s e r  H e a d e r \n", CurrentClassName);
819 	fprintf(Parser_h, " *\n");
820 	fprintf(Parser_h, " * Generated from:");
821 	for (i=0; i<NumFiles; i++) fprintf(Parser_h, " %s", FileStr[i]);
822 	fprintf(Parser_h, "\n");
823 	fprintf(Parser_h, " *\n");
824 	fprintf(Parser_h, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n");
825 	fprintf(Parser_h, " * Parr Research Corporation\n");
826 	fprintf(Parser_h, " * with Purdue University Electrical Engineering\n");
827 	fprintf(Parser_h, " * with AHPCRC, University of Minnesota\n");
828 	fprintf(Parser_h, " * ANTLR Version %s\n", Version);
829 	fprintf(Parser_h, " */\n\n");
830 
831   if ( FirstAction != NULL ) dumpAction( FirstAction, Parser_h, 0, -1, 0, 1);         /* MR11 MR15b */
832 
833 	fprintf(Parser_h, "#ifndef %s_h\n", CurrentClassName);
834 	fprintf(Parser_h, "#define %s_h\n\n", CurrentClassName);
835 
836     fprintf(Parser_h, "#ifndef ANTLR_VERSION\n");
837     fprintf(Parser_h, "#define ANTLR_VERSION %s\n",VersionDef);
838     fprintf(Parser_h, "#endif\n\n");
839 
840 	if ( GenAST ) fprintf(Parser_h, "class ASTBase;\n");
841     if (TraceGen) {
842       fprintf(Parser_h,"#ifndef zzTRACE_RULES\n");  /* MR20 */
843       fprintf(Parser_h,"#define zzTRACE_RULES\n");  /* MR20 */
844       fprintf(Parser_h,"#endif\n");                 /* MR22 */
845     };
846 	fprintf(Parser_h, "#include \"%s\"\n\n", APARSER_H);
847 
848 	if ( HdrAction != NULL ) dumpAction( HdrAction, Parser_h, 0, -1, 0, 1);
849 
850 /* MR10 */    if (ClassDeclStuff == NULL) {
851 /* MR10 */  	fprintf(Parser_h, "class %s : public ANTLRParser {\n", CurrentClassName);
852 /* MR10 */    } else {
853 /* MR10 */      fprintf(Parser_h, "class %s %s {\n",CurrentClassName,ClassDeclStuff);
854 /* MR10 */    };
855 
856 	fprintf(Parser_h, "public:\n");					          /* MR1 */
857 	fprintf(Parser_h, "\tstatic  const ANTLRChar *tokenName(int tk);\n");/* MR1 */
858     fprintf(Parser_h, "\tenum { SET_SIZE = %i };\n",TokenNum-1);         /* MR21 */
859 	fprintf(Parser_h, "protected:\n");
860 	fprintf(Parser_h, "\tstatic const ANTLRChar *_token_tbl[];\n");     /* MR20 */
861 	fprintf(Parser_h, "private:\n");
862 }
863 
864 /* Currently, this is only used in !GenCC mode */
865 void
866 #ifdef __USE_PROTOS
GenErrHdr(void)867 GenErrHdr( void )
868 #else
869 GenErrHdr( )
870 #endif
871 {
872 	int i, j;
873     TermEntry   *te;
874 
875 	fprintf(ErrFile, "/*\n");
876 	fprintf(ErrFile, " * A n t l r  S e t s / E r r o r  F i l e  H e a d e r\n");
877 	fprintf(ErrFile, " *\n");
878 	fprintf(ErrFile, " * Generated from:");
879 	for (i=0; i<NumFiles; i++) fprintf(ErrFile, " %s", FileStr[i]);
880 	fprintf(ErrFile, "\n");
881 	fprintf(ErrFile, " *\n");
882 	fprintf(ErrFile, " * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001\n");
883 	fprintf(ErrFile, " * Parr Research Corporation\n");
884 	fprintf(ErrFile, " * with Purdue University Electrical Engineering\n");
885 	fprintf(ErrFile, " * With AHPCRC, University of Minnesota\n");
886 	fprintf(ErrFile, " * ANTLR Version %s\n", Version);
887 	fprintf(ErrFile, " */\n\n");
888 
889   if ( FirstAction != NULL ) dumpAction( FirstAction, ErrFile, 0, -1, 0, 1);         /* MR11 MR15b */
890 
891   fprintf(ErrFile, "#define ANTLR_VERSION	%s\n", VersionDef);
892 
893   fprintf(ErrFile, "#include \"pcctscfg.h\"\n");
894 	fprintf(ErrFile, "#include \"pccts_stdio.h\"\n");
895 	if ( strcmp(ParserName, DefaultParserName)!=0 )
896 		fprintf(ErrFile, "#define %s %s\n", DefaultParserName, ParserName);
897 	if ( strcmp(ParserName, DefaultParserName)!=0 )
898 		fprintf(ErrFile, "#include \"%s\"\n", RemapFileName);
899 	if ( HdrAction != NULL ) dumpAction( HdrAction, ErrFile, 0, -1, 0, 1 );
900 	if ( FoundGuessBlk )
901 	{
902 		fprintf(ErrFile, "#define ZZCAN_GUESS\n");
903 		fprintf(ErrFile, "#include \"pccts_setjmp.h\"\n");
904 	}
905     if (TraceGen) {
906       fprintf(ErrFile,"#ifndef zzTRACE_RULES\n");  /* MR20 */
907       fprintf(ErrFile,"#define zzTRACE_RULES\n");  /* MR20 */
908       fprintf(ErrFile,"#endif\n");                 /* MR22 */
909     };
910 
911 	if ( OutputLL_k > 1 ) fprintf(ErrFile, "#define LL_K %d\n", OutputLL_k);
912 #ifdef DUM
913 	if ( LexGen ) fprintf(ErrFile, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken));
914 #endif
915 	fprintf(ErrFile, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned));
916 	if ( DemandLookahead ) fprintf(ErrFile, "#define DEMAND_LOOK\n");
917 	fprintf(ErrFile, "#include \"antlr.h\"\n");
918 	if ( GenAST ) fprintf(ErrFile, "#include \"ast.h\"\n");
919 
920     if ( UserDefdTokens ) fprintf(ErrFile, "#include %s\n", UserTokenDefsFile);
921 	/* still need this one as it has the func prototypes */
922 	fprintf(ErrFile, "#include \"%s\"\n", DefFileName);
923 	fprintf(ErrFile, "#include \"dlgdef.h\"\n");
924 	fprintf(ErrFile, "#include \"err.h\"\n\n");
925 
926 	/* Dump a zztokens for each automaton */
927 	if ( strcmp(ParserName, DefaultParserName)!=0 )
928 	{
929 		fprintf(ErrFile, "ANTLRChar *%s_zztokens[%d]={\n", ParserName, TokenNum-1);
930 	}
931 	else
932 	{
933 		fprintf(ErrFile, "ANTLRChar *zztokens[%d]={\n", TokenNum-1);
934 	}
935 	fprintf(ErrFile, "\t/* 00 */\t\"Invalid\"");
936 	for (i=1; i<TokenNum-1; i++)
937 	{
938 		DAWDLE;
939 		if ( i == EpToken ) continue;
940 		/* remapped to invalid token? */
941 		if ( TokenInd!=NULL && TokenInd[i]>=LastTokenCounted )
942 		{
943 			fprintf(ErrFile, ",\n\t/* %02d */\t\"invalid\"", i);
944 			continue;
945 		}
946 		if ( TokenString(i) != NULL ) {
947             te=(TermEntry *) hash_get(Tname,TokenString(i));                     /* MR11 */
948             if (te == NULL || te->akaString == NULL) {                          /* MR11 */
949   			  fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i));
950             } else {
951   			  fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, te->akaString);    /* MR11 */
952             }
953         }
954 		else
955 		{
956 			/* look in all lexclasses for the reg expr */
957 			for (j=0; j<NumLexClasses; j++)
958 			{
959 				lexmode(j);
960 				if ( ExprString(i) != NULL )
961 				{
962 					fprintf(ErrFile, ",\n\t/* %02d */\t", i);
963 					dumpExpr(ErrFile, ExprString(i));
964 					break;
965 				}
966 			}
967 			if ( j>=NumLexClasses )
968 			{
969 				if ( UserDefdTokens )
970 				{
971 					fprintf(ErrFile, ",\n\t/* %02d */\t\"\"", i);
972 				}
973 				else
974 					fatal_internal(eMsgd("No label or expr for token %d",i));
975 			}
976 		}
977 	}
978 	fprintf(ErrFile, "\n};\n");
979 }
980 
981 void
982 #ifdef __USE_PROTOS
dumpExpr(FILE * f,char * e)983 dumpExpr( FILE *f, char *e )
984 #else
985 dumpExpr( f, e )
986 FILE *f;
987 char *e;
988 #endif
989 {
990 	while ( *e!='\0' )
991 	{
992 		if ( *e=='\\' && *(e+1)=='\\' )
993 			{putc('\\', f); putc('\\', f); e+=2;}
994 		else if ( *e=='\\' && *(e+1)=='"' )
995 			{putc('\\', f); putc('"', f); e+=2;}
996 		else if ( *e=='\\' ) {putc('\\', f); putc('\\', f); e++;}
997 		else {putc(*e, f); e++;}
998 	}
999 }
1000 
1001 int
1002 #ifdef __USE_PROTOS
isTermEntryTokClass(TermEntry * te)1003 isTermEntryTokClass(TermEntry *te)
1004 #else
1005 isTermEntryTokClass(te)
1006 TermEntry *te;
1007 #endif
1008 {
1009 	ListNode *t;
1010 	TCnode *p;
1011 	TermEntry *q;
1012 	char *tokstr;
1013 
1014 	if (tclasses == NULL) return 0;
1015 
1016 	for (t = tclasses->next; t!=NULL; t=t->next)
1017 	{
1018 		p = (TCnode *) t->elem;
1019 		tokstr = TokenString(p->tok);
1020 		lexmode(p->lexclass);	/* switch to lexclass where tokclass is defined */
1021         q = (TermEntry *) hash_get(Tname, tokstr);
1022 		if (q == te) return 1;
1023 	}
1024 	return 0;
1025 }
1026