Home | History | Annotate | Download | only in antlr
      1 /*
      2  * lex.c	--	Generate all of the lexical type files: parser.dlg tokens.h
      3  *
      4  * SOFTWARE RIGHTS
      5  *
      6  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
      7  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
      8  * company may do whatever they wish with source code distributed with
      9  * PCCTS or the code generated by PCCTS, including the incorporation of
     10  * PCCTS, or its output, into commerical software.
     11  *
     12  * We encourage users to develop software with PCCTS.  However, we do ask
     13  * that credit is given to us for developing PCCTS.  By "credit",
     14  * we mean that if you incorporate our source code into one of your
     15  * programs (commercial product, research project, or otherwise) that you
     16  * acknowledge this fact somewhere in the documentation, research report,
     17  * etc...  If you like PCCTS and have developed a nice tool with the
     18  * output, please mention that you developed it using PCCTS.  In
     19  * addition, we ask that this header remain intact in our source code.
     20  * As long as these guidelines are kept, we expect to continue enhancing
     21  * this system and expect to make other tools available as they are
     22  * completed.
     23  *
     24  * ANTLR 1.33
     25  * Terence Parr
     26  * Parr Research Corporation
     27  * with Purdue University and AHPCRC, University of Minnesota
     28  * 1989-2001
     29  */
     30 
     31 #include <stdio.h>
     32 #include <ctype.h>
     33 /* MR1						                                                */
     34 /* MR1  10-Apr-97  MR1	Replace use of __STDC__ with __USE_PROTOS	    */
     35 /* MR1				                                                        */
     36 #include "pcctscfg.h"
     37 #include "set.h"
     38 #include "syn.h"
     39 #include "hash.h"
     40 #include "generic.h"
     41 
     42 #define DLGErrorString "invalid token"
     43 
     44 /* Generate a complete lexical description of the lexemes found in the grammar */
     45 void
     46 #ifdef __USE_PROTOS
     47 genLexDescr( void )
     48 #else
     49 genLexDescr( )
     50 #endif
     51 {
     52 	ListNode *p;
     53 	FILE *dlgFile = fopen(OutMetaName(DlgFileName), "w");
     54 	require(dlgFile!=NULL, eMsg1("genLexFile: cannot open %s", OutMetaName(DlgFileName)) );
     55 #ifdef SPECIAL_FOPEN
     56 	special_fopen_actions(OutMetaName(DlgFileName));	             /* MR1 */
     57 #endif
     58 	fprintf(dlgFile, "<<\n");
     59 	fprintf(dlgFile, "/* %s -- DLG Description of scanner\n", DlgFileName);
     60 	fprintf(dlgFile, " *\n");
     61 	fprintf(dlgFile, " * Generated from:");
     62 	{int i; for (i=0; i<NumFiles; i++) fprintf(dlgFile, " %s", FileStr[i]);}
     63 	fprintf(dlgFile, "\n");
     64 	fprintf(dlgFile, " *\n");
     65 	fprintf(dlgFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");
     66 	fprintf(dlgFile, " * Purdue University Electrical Engineering\n");
     67 	fprintf(dlgFile, " * With AHPCRC, University of Minnesota\n");
     68 	fprintf(dlgFile, " * ANTLR Version %s\n", Version);
     69 	fprintf(dlgFile, " */\n\n");
     70     if (FirstAction != NULL ) dumpAction( FirstAction, dlgFile, 0, -1, 0, 1 );  /* MR11 MR15b */
     71     fprintf(dlgFile, "#define ANTLR_VERSION	%s\n", VersionDef);
     72 	if ( GenCC )
     73 	{
     74 		if ( !UserDefdTokens ) fprintf(dlgFile, "#include \"%s\"\n", DefFileName);
     75 		else fprintf(dlgFile, "#include %s\n", UserTokenDefsFile);
     76 		fprintf(dlgFile, "#include \"%s\"\n", ATOKEN_H);
     77 		if ( GenAST ) fprintf(dlgFile, "#include \"%s\"\n", ASTBASE_H);
     78 		if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );
     79 	}
     80 	else
     81 	{
     82 		fprintf(dlgFile, "#include \"pcctscfg.h\"\n");
     83 		fprintf(dlgFile, "#include \"pccts_stdio.h\"\n");
     84 		if ( strcmp(ParserName, DefaultParserName)!=0 )
     85 			fprintf(dlgFile, "#define %s %s\n", DefaultParserName, ParserName);
     86 		if ( strcmp(ParserName, DefaultParserName)!=0 )
     87 			fprintf(dlgFile, "#include \"%s\"\n", RemapFileName);
     88 		if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 );
     89 		if ( FoundGuessBlk )
     90 		{
     91 			fprintf(dlgFile, "#define ZZCAN_GUESS\n");
     92 			fprintf(dlgFile, "#include \"pccts_setjmp.h\"\n");
     93 		}
     94 		if ( OutputLL_k > 1 ) fprintf(dlgFile, "#define LL_K %d\n", OutputLL_k);
     95 		if ( DemandLookahead ) fprintf(dlgFile, "#define DEMAND_LOOK\n");
     96         if (TraceGen) {
     97           fprintf(dlgFile,"#ifndef zzTRACE_RULES\n");  /* MR20 */
     98           fprintf(dlgFile,"#define zzTRACE_RULES\n");  /* MR20 */
     99           fprintf(dlgFile,"#endif\n");  /* MR22 */
    100         };
    101 		fprintf(dlgFile, "#include \"antlr.h\"\n");
    102 		if ( GenAST ) {
    103 			fprintf(dlgFile, "#include \"ast.h\"\n");
    104 		}
    105 		if ( UserDefdTokens )
    106 			fprintf(dlgFile, "#include %s\n", UserTokenDefsFile);
    107 		/* still need this one as it has the func prototypes */
    108 		fprintf(dlgFile, "#include \"%s\"\n", DefFileName);
    109 		fprintf(dlgFile, "#include \"dlgdef.h\"\n");
    110 		fprintf(dlgFile, "LOOKAHEAD\n");
    111 		fprintf(dlgFile, "\n");
    112 		fprintf(dlgFile, "void\n");
    113 		fprintf(dlgFile, "#ifdef __USE_PROTOS\n");
    114 		fprintf(dlgFile, "zzerraction(void)\n");
    115 		fprintf(dlgFile, "#else\n");
    116 		fprintf(dlgFile, "zzerraction()\n");
    117 		fprintf(dlgFile, "#endif\n");
    118 		fprintf(dlgFile, "{\n");
    119 		fprintf(dlgFile, "\t(*zzerr)(\"%s\");\n", DLGErrorString);
    120 		fprintf(dlgFile, "\tzzadvance();\n");
    121 		fprintf(dlgFile, "\tzzskip();\n");
    122 		fprintf(dlgFile, "}\n");
    123 	}
    124 	fprintf(dlgFile, ">>\n\n");
    125 
    126 	/* dump all actions */
    127 
    128 /* MR1									                                    */
    129 /* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class     */
    130 /* MR1	 	   	  via <<%%lexmember ....>> & <<%%lexprefix ...>>            */
    131 /* MR1				                					    */
    132           if (LexActions != NULL) {
    133             for (p = LexActions->next; p!=NULL; p=p->next)
    134 		{
    135 /* MR1 */	fprintf(dlgFile, "<<%%%%lexaction\n");
    136 			dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );
    137 			fprintf(dlgFile, ">>\n\n");
    138 		}
    139 	  };
    140 
    141 /* MR1 */ if (GenCC) {
    142 /* MR1 */   fprintf(dlgFile,"<<%%%%parserclass %s>>\n\n",CurrentClassName);
    143 /* MR1 */ };
    144 
    145 /* MR1 */ if (LexPrefixActions != NULL) {
    146 /* MR1 */   for (p = LexPrefixActions->next; p!=NULL; p=p->next)
    147 /* MR1 */       {
    148 /* MR1 */               fprintf(dlgFile, "<<%%%%lexprefix\n");
    149 /* MR1 */               dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );
    150 /* MR1 */               fprintf(dlgFile, ">>\n\n");
    151 /* MR1 */       }
    152 /* MR1 */ };
    153 
    154 /* MR1 */ if (LexMemberActions != NULL) {
    155 /* MR1 */   for (p = LexMemberActions->next; p!=NULL; p=p->next)
    156 /* MR1 */       {
    157 /* MR1 */               fprintf(dlgFile, "<<%%%%lexmember\n");
    158 /* MR1 */               dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 );
    159 /* MR1 */               fprintf(dlgFile, ">>\n\n");
    160 /* MR1 */       }
    161 /* MR1 */ };
    162 
    163 	/* dump all regular expression rules/actions (skip sentinel node) */
    164 	if ( ExprOrder == NULL ) {
    165 		warnNoFL("no regular expressions found in grammar");
    166 	}
    167 	else dumpLexClasses(dlgFile);
    168 	fprintf(dlgFile, "%%%%\n");
    169 	fclose( dlgFile );
    170 }
    171 
    172 /* For each lexical class, scan ExprOrder looking for expressions
    173  * in that lexical class.  Print out only those that match.
    174  * Each element of the ExprOrder list has both an expr and an lclass
    175  * field.
    176  */
    177 void
    178 #ifdef __USE_PROTOS
    179 dumpLexClasses( FILE *dlgFile )
    180 #else
    181 dumpLexClasses( dlgFile )
    182 FILE *dlgFile;
    183 #endif
    184 {
    185 	int i;
    186 	TermEntry *t;
    187 	ListNode *p;
    188 	Expr *q;
    189 
    190 	for (i=0; i<NumLexClasses; i++)
    191 	{
    192 		fprintf(dlgFile, "\n%%%%%s\n\n", lclass[i].classnum);
    193 		for (p=ExprOrder->next; p!=NULL; p=p->next)
    194 		{
    195 			q = (Expr *) p->elem;
    196 			if ( q->lclass != i ) continue;
    197 			lexmode(i);
    198 			t = (TermEntry *) hash_get(Texpr, q->expr);
    199 			require(t!=NULL, eMsg1("genLexDescr: rexpr %s not in hash table",q->expr) );
    200 			if ( t->token == EpToken ) continue;
    201 			fprintf(dlgFile, "%s\n\t<<\n", StripQuotes(q->expr));
    202 			/* replace " killed by StripQuotes() */
    203 			q->expr[ strlen(q->expr) ] = '"';
    204 			if ( !GenCC ) {
    205 				if ( TokenString(t->token) != NULL )
    206 					fprintf(dlgFile, "\t\tNLA = %s;\n", TokenString(t->token));
    207 				else
    208 					fprintf(dlgFile, "\t\tNLA = %d;\n", t->token);
    209 			}
    210 			if ( t->action != NULL ) dumpAction( t->action, dlgFile, 2,-1,0,1 );
    211 			if ( GenCC ) {
    212 				if ( TokenString(t->token) != NULL )
    213 					fprintf(dlgFile, "\t\treturn %s;\n", TokenString(t->token));
    214 				else
    215 					fprintf(dlgFile, "\t\treturn (ANTLRTokenType)%d;\n", t->token);
    216 			}
    217 			fprintf(dlgFile, "\t>>\n\n");
    218 		}
    219 	}
    220 }
    221 
    222 /* Strip the leading path (if any) from a filename */
    223 char *
    224 #ifdef __USE_PROTOS
    225 StripPath( char *fileName )
    226 #else
    227 StripPath( fileName )
    228 char *fileName;
    229 #endif
    230 {
    231 	char *p;
    232 	static char dirSym[2] = DirectorySymbol;
    233 
    234 	if(NULL != (p = strrchr(fileName, dirSym[0])))
    235 		p++;
    236 	else
    237 		p = fileName;
    238 
    239 	return(p);
    240 }
    241 
    242 /* Generate a list of #defines && list of struct definitions for
    243  * aggregate retv's */
    244 void
    245 #ifdef __USE_PROTOS
    246 genDefFile( void )
    247 #else
    248 genDefFile( )
    249 #endif
    250 {
    251 	int i;
    252 
    253 	/* If C++ mode and #tokdef used, then don't need anything in here since
    254 	 * C++ puts all definitions in the class file name.
    255 	 */
    256 	if ( GenCC && UserTokenDefsFile ) return;
    257     if ( MR_Inhibit_Tokens_h_Gen) return;
    258 
    259 	DefFile = fopen(OutMetaName(DefFileName), "w");
    260 	require(DefFile!=NULL, eMsg1("genDefFile: cannot open %s", OutMetaName(DefFileName)) );
    261 #ifdef SPECIAL_FOPEN
    262 	special_fopen_actions(OutMetaName(DefFileName));	             /* MR1 */
    263 #endif
    264 	fprintf(DefFile, "#ifndef %s\n", StripPath(gate_symbol(DefFileName)));
    265 	fprintf(DefFile, "#define %s\n", StripPath(gate_symbol(DefFileName)));
    266 
    267 	fprintf(DefFile, "/* %s -- List of labelled tokens and stuff\n", DefFileName);
    268 	fprintf(DefFile, " *\n");
    269 	fprintf(DefFile, " * Generated from:");
    270 	for (i=0; i<NumFiles; i++) fprintf(DefFile, " %s", FileStr[i]);
    271 	fprintf(DefFile, "\n");
    272 	fprintf(DefFile, " *\n");
    273 	fprintf(DefFile, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");
    274 	fprintf(DefFile, " * Purdue University Electrical Engineering\n");
    275 	fprintf(DefFile, " * ANTLR Version %s\n", Version);
    276 	fprintf(DefFile, " */\n");
    277 
    278 	if ( !GenCC && LexGen ) {
    279 		fprintf(DefFile,"#define zzEOF_TOKEN %d\n",
    280 				TokenInd!=NULL?TokenInd[EofToken]:EofToken);
    281 	}
    282 
    283 	if ( !UserDefdTokens )
    284 	{
    285 		int first=1;
    286 
    287 		if ( GenCC ) fprintf(DefFile, "enum ANTLRTokenType {\n");
    288 		for (i=1; i<TokenNum; i++)
    289 		{
    290 			/* Don't do EpToken or expr w/o labels */
    291 			if ( TokenString(i)!=NULL && i != EpToken )
    292 			{
    293 				TermEntry *p;
    294 
    295 				if ( WarningLevel>1 )
    296 				{
    297 					int j;
    298 					/* look in all lexclasses for the reg expr */
    299 
    300 /* MR10  Derek Pappas                                                */
    301 /* MR10     A #tokclass doesn't have associated regular expressiones */
    302 /* MR10        so don't warn user about it's omission                */
    303 
    304                     p = (TermEntry *) hash_get(Tname, TokenString(i));
    305 
    306                     if (p != NULL && ! p->classname) {
    307     					for (j=0; j<NumLexClasses; j++)
    308     					{
    309     						lexmode(j);
    310     						if ( ExprString(i)!=NULL ) break;
    311     					}
    312     					if ( j>=NumLexClasses )
    313     					{
    314     						warnNoFL(eMsg1("token label has no associated rexpr: %s",TokenString(i)));
    315     					}
    316                     };
    317 				}
    318 				require((p=(TermEntry *)hash_get(Tname, TokenString(i))) != NULL,
    319 						"token not in sym tab when it should be");
    320 				if ( !p->classname )
    321 				{
    322 					if ( GenCC ) {
    323 						if ( !first ) fprintf(DefFile, ",\n");
    324 						first = 0;
    325 						fprintf(DefFile, "\t%s=%d", TokenString(i), i);
    326 					}
    327 					else
    328 						fprintf(DefFile, "#define %s %d\n", TokenString(i), i);
    329 				}
    330 			}
    331 		}
    332 /* MR1									                                    */
    333 /* MR1  10-Apr-97 133MR1	Prevent use of varying sizes of integer	    */
    334 /* MR1				for the enum ANTLRTokenType                             */
    335 /* MR1								           */
    336 		if ( GenCC ) {				                                 /* MR1 */
    337  		 	 if ( !first ) fprintf(DefFile, ",\n");                  /* MR14 */
    338 		     fprintf(DefFile, "\tDLGminToken=0");                 /* MR1 */
    339 		     fprintf(DefFile, ",\n\tDLGmaxToken=9999};\n");          /* MR1 */
    340                 };						                             /* MR1 */
    341 	}
    342 
    343 	if ( !GenCC ) GenRulePrototypes(DefFile, SynDiag);
    344 
    345 	fprintf(DefFile, "\n#endif\n");
    346 }
    347 
    348 void
    349 #ifdef __USE_PROTOS
    350 GenRemapFile( void )
    351 #else
    352 GenRemapFile( )
    353 #endif
    354 {
    355 	if ( strcmp(ParserName, DefaultParserName)!=0 )
    356 	{
    357 		FILE *f;
    358 		int i;
    359 
    360 		f = fopen(OutMetaName(RemapFileName), "w");
    361 		require(f!=NULL, eMsg1("GenRemapFile: cannot open %s", OutMetaName(RemapFileName)) );
    362 #ifdef SPECIAL_FOPEN
    363 		special_fopen_actions(OutMetaName(RemapFileName));           /* MR1 */
    364 #endif
    365 		fprintf(f, "/* %s -- List of symbols to remap\n", RemapFileName);
    366 		fprintf(f, " *\n");
    367 		fprintf(f, " * Generated from:");
    368 		for (i=0; i<NumFiles; i++) fprintf(f, " %s", FileStr[i]);
    369 		fprintf(f, "\n");
    370 		fprintf(f, " *\n");
    371 		fprintf(f, " * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n");
    372 		fprintf(f, " * Purdue University Electrical Engineering\n");
    373 		fprintf(f, " * ANTLR Version %s\n", Version);
    374 		fprintf(f, " */\n");
    375 
    376 		GenRuleFuncRedefs(f, SynDiag);
    377 		GenPredefinedSymbolRedefs(f);
    378 		if ( GenAST ) GenASTSymbolRedefs(f);
    379 		GenSetRedefs(f);
    380 
    381 		fclose(f);
    382 	}
    383 }
    384 
    385 /* Generate a bunch of #defines that rename all functions to be "ParserName_func" */
    386 void
    387 #ifdef __USE_PROTOS
    388 GenRuleFuncRedefs( FILE *f, Junction *p )
    389 #else
    390 GenRuleFuncRedefs( f, p )
    391 FILE *f;
    392 Junction *p;
    393 #endif
    394 {
    395 	fprintf(f, "\n/* rename rule functions to be 'ParserName_func' */\n");
    396 	while ( p!=NULL )
    397 	{
    398 		fprintf(f, "#define %s %s_%s\n", p->rname, ParserName, p->rname);
    399 		p = (Junction *)p->p2;
    400 	}
    401 }
    402 
    403 /* Generate a bunch of #defines that rename all standard symbols to be
    404  * "ParserName_symbol".  The list of standard symbols to change is in
    405  * globals.c.
    406  */
    407 void
    408 #ifdef __USE_PROTOS
    409 GenPredefinedSymbolRedefs( FILE *f )
    410 #else
    411 GenPredefinedSymbolRedefs( f )
    412 FILE *f;
    413 #endif
    414 {
    415 	char **p;
    416 
    417 	fprintf(f, "\n/* rename PCCTS-supplied symbols to be 'ParserName_symbol' */\n");
    418 	for (p = &StandardSymbols[0]; *p!=NULL; p++)
    419 	{
    420 		fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p);
    421 	}
    422 }
    423 
    424 /* Generate a bunch of #defines that rename all AST symbols to be
    425  * "ParserName_symbol".  The list of AST symbols to change is in
    426  * globals.c.
    427  */
    428 void
    429 #ifdef __USE_PROTOS
    430 GenASTSymbolRedefs( FILE *f )
    431 #else
    432 GenASTSymbolRedefs( f )
    433 FILE *f;
    434 #endif
    435 {
    436 	char **p;
    437 
    438 	fprintf(f, "\n/* rename PCCTS-supplied AST symbols to be 'ParserName_symbol' */\n");
    439 	for (p = &ASTSymbols[0]; *p!=NULL; p++)
    440 	{
    441 		fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p);
    442 	}
    443 }
    444 
    445 /* redefine all sets generated by ANTLR; WARNING:  'zzerr', 'setwd' must match
    446  * use in bits.c (DumpSetWd() etc...)
    447  */
    448 void
    449 #ifdef __USE_PROTOS
    450 GenSetRedefs( FILE *f )
    451 #else
    452 GenSetRedefs( f )
    453 FILE *f;
    454 #endif
    455 {
    456 	int i;
    457 
    458 	for (i=1; i<=wordnum; i++)
    459 	{
    460 		fprintf(f, "#define setwd%d %s_setwd%d\n", i, ParserName, i);
    461 	}
    462 	for (i=1; i<=esetnum; i++)
    463 	{
    464 		fprintf(f, "#define zzerr%d %s_err%d\n", i, ParserName, i);
    465 	}
    466 }
    467 
    468 /* Find all return types/parameters that require structs and def
    469  * all rules with ret types.
    470  *
    471  * This is for the declaration, not the definition.
    472  */
    473 void
    474 #ifdef __USE_PROTOS
    475 GenRulePrototypes( FILE *f, Junction *p )
    476 #else
    477 GenRulePrototypes( f, p )
    478 FILE *f;
    479 Junction *p;
    480 #endif
    481 {
    482 	int i;
    483 
    484 	i = 1;
    485 	while ( p!=NULL )
    486 	{
    487 		if ( p->ret != NULL )
    488 		{
    489 /* MR23 */	if ( hasMultipleOperands(p->ret) )
    490 			{
    491 				DumpRetValStruct(f, p->ret, i);
    492 			}
    493 			fprintf(f, "\n#ifdef __USE_PROTOS\n");
    494 /* MR23 */	if ( hasMultipleOperands(p->ret) )
    495 			{
    496 				fprintf(f, "extern struct _rv%d", i);
    497 			}
    498 			else
    499 			{
    500 				fprintf(f, "extern ");
    501 				DumpType(p->ret, f);
    502 			}
    503 			fprintf(f, " %s%s(", RulePrefix, p->rname);
    504 			DumpANSIFunctionArgDef(f,p,1 /* emit initializers ? */);
    505 			fprintf(f, ";\n");
    506 			fprintf(f, "#else\n");
    507 /* MR23 */	if ( hasMultipleOperands(p->ret) )
    508 			{
    509 				fprintf(f, "extern struct _rv%d", i);
    510 			}
    511 			else
    512 			{
    513 				fprintf(f, "extern ");
    514 				DumpType(p->ret, f);
    515 			}
    516 			fprintf(f, " %s%s();\n", RulePrefix, p->rname);
    517 			fprintf(f, "#endif\n");
    518 		}
    519 		else
    520 		{
    521 			fprintf(f, "\n#ifdef __USE_PROTOS\n");
    522 			fprintf(f, "void %s%s(", RulePrefix, p->rname);
    523 			DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */ );
    524 			fprintf(f, ";\n");
    525 #ifdef OLD
    526 			if ( p->pdecl != NULL || GenAST )
    527 			{
    528 				if ( GenAST ) {
    529 					fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":"");
    530 				}
    531 				if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
    532 			}
    533 			else fprintf(f, "void");
    534 			fprintf(f, ");\n");
    535 #endif
    536 			fprintf(f, "#else\n");
    537 			fprintf(f, "extern void %s%s();\n", RulePrefix, p->rname);
    538 			fprintf(f, "#endif\n");
    539 		}
    540 		i++;
    541 		p = (Junction *)p->p2;
    542 	}
    543 }
    544 
    545 /* Define all rules in the class.h file; generate any required
    546  * struct definitions first, however.
    547  */
    548 void
    549 #ifdef __USE_PROTOS
    550 GenRuleMemberDeclarationsForCC( FILE *f, Junction *q )
    551 #else
    552 GenRuleMemberDeclarationsForCC( f, q )
    553 FILE *f;
    554 Junction *q;
    555 #endif
    556 {
    557 	Junction *p = q;
    558 	int i;
    559 
    560 	fprintf(f, "private:\n");
    561 
    562 	/* Dump dflt handler declaration */
    563 	fprintf(f, "\tvoid zzdflthandlers( int _signal, int *_retsignal );\n\n");
    564 
    565 	fprintf(f, "public:\n");
    566 
    567 	/* Dump return value structs */
    568 	i = 1;
    569 	while ( p!=NULL )
    570 	{
    571 		if ( p->ret != NULL )
    572 		{
    573 /* MR23 */	if ( hasMultipleOperands(p->ret) )
    574 			{
    575 				DumpRetValStruct(f, p->ret, i);
    576 			}
    577 		}
    578 		i++;
    579 		p = (Junction *)p->p2;
    580 	}
    581 
    582 	/* Dump member func defs && CONSTRUCTOR */
    583 	fprintf(f, "\t%s(ANTLRTokenBuffer *input);\n", CurrentClassName);
    584 /*
    585 	fprintf(f, "\t%s(ANTLRTokenBuffer *input, ANTLRTokenType eof);\n",
    586 			   CurrentClassName);
    587 */
    588 
    589 	i = 1;
    590 	p = q;
    591 	while ( p!=NULL )
    592 	{
    593 		if ( p->ret != NULL )
    594 		{
    595 /* MR23 */	if ( hasMultipleOperands(p->ret) )
    596 			{
    597 				fprintf(f, "\tstruct _rv%d", i);
    598 			}
    599 			else
    600 			{
    601 				fprintf(f, "\t");
    602 				DumpType(p->ret, f);
    603 			}
    604 			fprintf(f, " %s%s(",RulePrefix,p->rname);
    605 			DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */ );
    606 			fprintf(f, ";\n");
    607 #ifdef OLD
    608 			if ( p->pdecl != NULL || GenAST )
    609 			{
    610 				if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":"");
    611 				if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
    612 			}
    613 			fprintf(f, ");\n");
    614 #endif
    615 		}
    616 		else
    617 		{
    618 			fprintf(f, "\tvoid %s%s(",RulePrefix,p->rname);
    619 			DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */);
    620 			fprintf(f, ";\n");
    621 #ifdef OLD
    622 			if ( p->pdecl != NULL || GenAST )
    623 			{
    624 				if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":"");
    625 				if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl);
    626 			}
    627 			fprintf(f, ");\n");
    628 #endif
    629 		}
    630 		i++;
    631 		p = (Junction *)p->p2;
    632 	}
    633 }
    634 
    635 /* Given a list of ANSI-style parameter declarations, print out a
    636  * comma-separated list of the symbols (w/o types).
    637  * Basically, we look for a comma, then work backwards until start of
    638  * the symbol name.  Then print it out until 1st non-alnum char.  Now,
    639  * move on to next parameter.
    640  *
    641  */
    642 
    643 /* MR5 	Jan Mikkelsen 26-May-97 - added initalComma parameter              */
    644 
    645 void
    646 #ifdef __USE_PROTOS
    647 DumpListOfParmNames(char *pdecl, FILE *output, int initialComma)    /* MR5 */
    648 #else
    649 DumpListOfParmNames(pdecl, output, initialComma)		            /* MR5 */
    650 char *pdecl;	             		 			  	                /* MR5 */
    651 FILE *output;							                            /* MR5 */
    652 int initialComma;			                                        /* MR5 */
    653 #endif
    654 {
    655 	int firstTime = 1, done = 0;
    656 	require(output!=NULL, "DumpListOfParmNames: NULL parm");
    657 
    658 	if ( pdecl == NULL ) return;
    659 	while ( !done )
    660 	{
    661 		if ( !firstTime || initialComma ) putc(',', output);        /* MR5 */
    662 		done = DumpNextNameInDef(&pdecl, output);
    663 		firstTime = 0;
    664 	}
    665 }
    666 
    667 /* given a list of parameters or return values, dump the next
    668  * name to output.  Return 1 if last one just printed, 0 if more to go.
    669  */
    670 
    671 /* MR23 Total rewrite */
    672 
    673 int
    674 #ifdef __USE_PROTOS
    675 DumpNextNameInDef( char **q, FILE *output )
    676 #else
    677 DumpNextNameInDef( q, output )
    678 char **q;
    679 FILE *output;
    680 #endif
    681 {
    682 	char *p;
    683 	char *t;
    684 	char *pDataType;
    685 	char *pSymbol;
    686 	char *pEqualSign;
    687 	char *pValue;
    688 	char *pSeparator;
    689 	int nest = 0;
    690 
    691 	p = endFormal(*q,
    692 			      &pDataType,
    693 				  &pSymbol,
    694 				  &pEqualSign,
    695 				  &pValue,
    696 				  &pSeparator,
    697 				  &nest);
    698 
    699     /* MR26 Handle rule arguments such as: IIR_Bool (IIR_Decl::*contstraint)()
    700        For this we need to strip off anything which follows the symbol.
    701      */
    702 
    703 /* MR26 */  t = pSymbol;
    704 /* MR26 */	if (t != NULL) {
    705 /* MR26 */		for (t = pSymbol; *t != 0; t++) {
    706 /* MR26 */			if (! (isalpha(*t) || isdigit(*t) || *t == '_' || *t == '$')) break;
    707 /* MR26 */		}
    708 /* MR26 */	}
    709 /* MR26 */	fprintf(output,strBetween(pSymbol, t, pSeparator));
    710 
    711     *q = p;
    712     return (*pSeparator  == 0);
    713 }
    714 
    715 /* Given a list of ANSI-style parameter declarations, dump K&R-style
    716  * declarations, one per line for each parameter.  Basically, convert
    717  * comma to semi-colon, newline.
    718  */
    719 void
    720 #ifdef __USE_PROTOS
    721 DumpOldStyleParms( char *pdecl, FILE *output )
    722 #else
    723 DumpOldStyleParms( pdecl, output )
    724 char *pdecl;
    725 FILE *output;
    726 #endif
    727 {
    728 	require(output!=NULL, "DumpOldStyleParms: NULL parm");
    729 
    730 	if ( pdecl == NULL ) return;
    731 	while ( *pdecl != '\0' )
    732 	{
    733 		if ( *pdecl == ',' )
    734 		{
    735 			pdecl++;
    736 			putc(';', output); putc('\n', output);
    737 			while ( *pdecl==' ' || *pdecl=='\t' || *pdecl=='\n' ) pdecl++;
    738 		}
    739 		else {putc(*pdecl, output); pdecl++;}
    740 	}
    741 	putc(';', output);
    742 	putc('\n', output);
    743 }
    744 
    745 /* Take in a type definition (type + symbol) and print out type only */
    746 /* MR23 Total rewrite */
    747 
    748 void
    749 #ifdef __USE_PROTOS
    750 DumpType( char *s, FILE *f )
    751 #else
    752 DumpType( s, f )
    753 char *s;
    754 FILE *f;
    755 #endif
    756 {
    757 	char *p;
    758 	char *pDataType;
    759 	char *pSymbol;
    760 	char *pEqualSign;
    761 	char *pValue;
    762 	char *pSeparator;
    763 	int nest = 0;
    764 
    765 	require(s!=NULL, "DumpType: invalid type string");
    766 
    767 	p = endFormal(s,
    768 			      &pDataType,
    769 				  &pSymbol,
    770 				  &pEqualSign,
    771 				  &pValue,
    772 				  &pSeparator,
    773 				  &nest);
    774 	fprintf(f,strBetween(pDataType, pSymbol, pSeparator));
    775 }
    776 
    777 /* check to see if string e is a word in string s */
    778 int
    779 #ifdef __USE_PROTOS
    780 strmember( char *s, char *e )
    781 #else
    782 strmember( s, e )
    783 char *s;
    784 char *e;
    785 #endif
    786 {
    787     register char *p;
    788     require(s!=NULL&&e!=NULL, "strmember: NULL string");
    789 
    790     if ( *e=='\0' ) return 1;   /* empty string is always member */
    791     do {
    792 	while ( *s!='\0' && !isalnum(*s) && *s!='_' )
    793 	++s;
    794 	p = e;
    795 	while ( *p!='\0' && *p==*s ) {p++; s++;}
    796 	if ( *p=='\0' ) {
    797 	    if ( *s=='\0' ) return 1;
    798 	    if ( !isalnum (*s) && *s != '_' ) return 1;
    799 	}
    800 	while ( isalnum(*s) || *s == '_' )
    801 	++s;
    802     } while ( *s!='\0' );
    803     return 0;
    804 }
    805 
    806 #if 0
    807 
    808 /* MR23 Replaced by hasMultipleOperands() */
    809 
    810 int
    811 #ifdef __USE_PROTOS
    812 HasComma( char *s )
    813 #else
    814 HasComma( s )
    815 char *s;
    816 #endif
    817 {
    818 	while (*s!='\0')
    819 		if ( *s++ == ',' ) return 1;
    820 	return 0;
    821 }
    822 #endif
    823 
    824 
    825 /* MR23 Total rewrite */
    826 
    827 void
    828 #ifdef __USE_PROTOS
    829 DumpRetValStruct( FILE *f, char *ret, int i )
    830 #else
    831 DumpRetValStruct( f, ret, i )
    832 FILE *f;
    833 char *ret;
    834 int i;
    835 #endif
    836 {
    837 	char *p = ret;
    838 	char *pDataType;
    839 	char *pSymbol;
    840 	char *pEqualSign;
    841 	char *pValue;
    842 	char *pSeparator;
    843     int nest = 0;
    844 
    845 	fprintf(f, "\nstruct _rv%d {\n", i);
    846 	while (*p != 0 && nest == 0) {
    847 		p = endFormal(p,
    848 			          &pDataType,
    849 					  &pSymbol,
    850 					  &pEqualSign,
    851 					  &pValue,
    852 					  &pSeparator,
    853 					  &nest);
    854 		fprintf(f,"\t");
    855 		fprintf(f,strBetween(pDataType, pSymbol, pSeparator));
    856 		fprintf(f," ");
    857 		fprintf(f,strBetween(pSymbol, pEqualSign, pSeparator));
    858 		fprintf(f,";\n");
    859     }
    860 	fprintf(f,"};\n");
    861 }
    862 
    863 /* given "s" yield s -- DESTRUCTIVE (we modify s if starts with " else return s) */
    864 char *
    865 #ifdef __USE_PROTOS
    866 StripQuotes( char *s )
    867 #else
    868 StripQuotes( s )
    869 char *s;
    870 #endif
    871 {
    872 	if ( *s == '"' )
    873 	{
    874 		s[ strlen(s)-1 ] = '\0';    /* remove last quote */
    875 		return( s+1 );				/* return address past initial quote */
    876 	}
    877 	return( s );
    878 }
    879