Home | History | Annotate | Download | only in antlr
      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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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[%lu] = {",
    577 				name,
    578                 suffix,
    579 				NumWords(TokenNum-1)*sizeof(unsigned));
    580 	}
    581 	else {
    582 		fprintf(ErrFile, "SetWordType zzerr%d[%lu] = {",
    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
    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
    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[%lu];\n", name, suffix,
    645 				NumWords(TokenNum-1)*sizeof(unsigned));
    646 		fprintf(Parser_c, "SetWordType %s::%s%s[%lu] = {",
    647 				CurrentClassName,
    648 				name,
    649 				suffix,
    650 				NumWords(TokenNum-1)*sizeof(unsigned));
    651 	}
    652 	else {
    653 		fprintf(Parser_c, "SetWordType %s::err%d[%lu] = {",
    654 				CurrentClassName,
    655 				esetnum,
    656 				NumWords(TokenNum-1)*sizeof(unsigned));
    657 		fprintf(Parser_h, "\tstatic SetWordType err%d[%lu];\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
    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
    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,%lu)\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
    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
    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 %lu\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
    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
   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