Home | History | Annotate | Download | only in genmk
      1 /*
      2  * genmk -- a program to make makefiles for PCCTS
      3  *
      4  * ANTLR 1.33MR23
      5  * Terence John Parr 1989 - 2000
      6  * Purdue University
      7  * U of MN
      8  */
      9 
     10 #include <stdio.h>
     11 #include <string.h>
     12 #include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */
     13 
     14 #ifdef VAXC
     15 #define DIE		return 0;
     16 #define DONE	return 1;
     17 #else
     18 #define DIE		return 1;
     19 #define DONE	return 0;
     20 #endif
     21 
     22 #ifndef require
     23 #define require(expr, err) {if ( !(expr) ) fatal(err);}
     24 #endif
     25 
     26 #define MAX_FILES	50
     27 #define MAX_CFILES	1600
     28 #define MAX_SFILES	50
     29 #define MAX_SORS	50
     30 #define MAX_CLASSES	50
     31 
     32 char *RENAME_OBJ_FLAG="-o",
     33      *RENAME_EXE_FLAG="-o";
     34 
     35 char *dlg = "parser.dlg";
     36 char *err = "err.c";
     37 char *hdr = "stdpccts.h";
     38 char *tok = "tokens.h";
     39 char *mode = "mode.h";
     40 char *scan = "scan";
     41 
     42 char ATOKENBUFFER_O[100];
     43 char APARSER_O[100];
     44 char ASTBASE_O[100];
     45 char PCCTSAST_O[100];
     46 char LIST_O[100];
     47 char DLEXERBASE_O[100];
     48 
     49 /* Option flags */
     50 static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES];
     51 static char *cfiles[MAX_CFILES];
     52 static char *sfiles[MAX_SORS][MAX_SFILES],*sclasses[MAX_SORS];
     53 static int  num_sfiles[MAX_SORS]; /*sorcerer files in group */
     54 static int  num_sors = 0; /*sorcerer groups */
     55 static int  num_files = 0; /* grammar files */
     56 static int  num_cfiles = 0; /* additional C/C++ files */
     57 static int  num_classes = 0; /* ANTLR classes */
     58 static int  user_lexer = 0;
     59 static char *user_token_types = NULL;
     60 static int  gen_CPP = 0;
     61 static char *outdir=".";
     62 static char *dlg_class = "DLGLexer";
     63 static int  gen_trees = 0;
     64 static int  gen_hoist = 0;
     65 static int  nondef_comp = 0; /* 1=compiler is non default */
     66 static char *compilerCCC="CC";
     67 static char *compilerCC="cc";
     68 static char *pccts_path="/usr/local/pccts";
     69 
     70 #ifdef __STDC__
     71 void help(void);
     72 void mk(char *project, char **files, int n, int argc, char **argv);
     73 void pfiles(char **files, int n, char *suffix);
     74 void fatal(char *msg);
     75 void warn(char *msg);
     76 #else
     77 void help();
     78 void mk();
     79 void pfiles();
     80 void fatal();
     81 void warn();
     82 #endif
     83 
     84 typedef struct _Opt {
     85 			char *option;
     86 			int arg;
     87 #ifdef __cplusplus
     88 			void (*process)(...);
     89 #else
     90 			void (*process)();
     91 #endif
     92 			char *descr;
     93 		} Opt;
     94 
     95 #ifdef __STDC__
     96 static void ProcessArgs(int, char **, Opt *);
     97 #else
     98 static void ProcessArgs();
     99 #endif
    100 
    101 static void
    102 #ifdef __STDC__
    103 pProj(char *s, char *t )
    104 #else
    105 pProj( s, t )
    106 char *s;
    107 char *t;
    108 #endif
    109 {
    110 	project = t;
    111 }
    112 
    113 static void
    114 #ifdef __STDC__
    115 pUL( char *s )
    116 #else
    117 pUL( s )
    118 char *s;
    119 #endif
    120 {
    121 	user_lexer = 1;
    122 }
    123 
    124 static void
    125 #ifdef __STDC__
    126 pCPP( char *s )
    127 #else
    128 pCPP( s )
    129 char *s;
    130 #endif
    131 {
    132 	gen_CPP = 1;
    133 }
    134 
    135 static void
    136 #ifdef __STDC__
    137 pUT( char *s, char *t )
    138 #else
    139 pUT( s, t )
    140 char *s;
    141 char *t;
    142 #endif
    143 {
    144 	user_token_types = t;
    145 }
    146 
    147 static void
    148 #ifdef __STDC__
    149 pTrees( char *s )
    150 #else
    151 pTrees( s )
    152 char *s;
    153 #endif
    154 {
    155 	gen_trees = 1;
    156 }
    157 
    158 static void
    159 #ifdef __STDC__
    160 pHoist( char *s )
    161 #else
    162 pHoist( s )
    163 char *s;
    164 #endif
    165 {
    166 	gen_hoist = 1;
    167 }
    168 
    169 static void
    170 #ifdef __STDC__
    171 pSor( char *s )
    172 #else
    173 pSor( s )
    174 char *s;
    175 #endif
    176 {
    177 	require(num_sors<MAX_SORS, "exceeded max # of sorcerer groups");
    178 	num_sors++;
    179 	pTrees(NULL); /* silently turn on tree generation */
    180 }
    181 
    182 static void
    183 #ifdef __STDC__
    184 pSFiles( char *s, char *t )
    185 #else
    186 pSFiles( s, t )
    187 char *s;
    188 char *t;
    189 #endif
    190 {
    191 	if (num_sors==0)
    192 	{
    193 		pSor(NULL);
    194 		warn("sorcerer input file before any '-sor' option");
    195 	}
    196 
    197 	require(num_sfiles[num_sors-1]<MAX_SFILES,
    198 		 "exceeded max # of sorcerer input files");
    199 	sfiles[num_sors-1][num_sfiles[num_sors-1]++] = t;
    200 }
    201 
    202 static void
    203 #ifdef __STDC__
    204 pCFiles( char *s, char *t )
    205 #else
    206 pCFiles( s, t )
    207 char *s;
    208 char *t;
    209 #endif
    210 {
    211 	require(num_cfiles<MAX_CFILES, "exceeded max # of C/C++ input files");
    212 	cfiles[num_cfiles++] = t;
    213 }
    214 
    215 int
    216 #ifdef __STDC__
    217 isKnownSuffix( char *s )
    218 #else
    219 isKnownSuffix( s )
    220 	char *s;
    221 #endif
    222 {
    223 	if(s==NULL) return 0;
    224 	if (strcasecmp(s,".c")==0) return 1;
    225 	if (strcasecmp(s,".cc")==0) return 1;
    226 	if (strcasecmp(s,".cpp")==0) return 1;
    227 	if (strcasecmp(s,".cxx")==0) return 1;
    228 	if (strcasecmp(s,CPP_FILE_SUFFIX)==0) return 1;
    229 	if (strcasecmp(s,".sor")==0) return 2;
    230 	return 0;
    231 }
    232 
    233 static void
    234 #ifdef __STDC__
    235 pFile( char *s )
    236 #else
    237 pFile( s )
    238 char *s;
    239 #endif
    240 {
    241 	if ( *s=='-' )
    242 	{
    243 		fprintf(stderr, "invalid option: '%s'; ignored...",s);
    244 		return;
    245 	}
    246 	switch(isKnownSuffix(strrchr(s,'.')))
    247 	{
    248 	 case 1: /* c/c++ */
    249 		pCFiles("-cfiles",s);
    250 		return;
    251 	 case 2: /* sorcerer */
    252 		pSFiles("",s);
    253 		return;
    254 	 default: /* grammar (ANTLR) */
    255 		break;
    256 	}
    257 	require(num_files<MAX_FILES, "exceeded max # of input files");
    258 	files[num_files++] = s;
    259 }
    260 
    261 static void
    262 #ifdef __STDC__
    263 pClass( char *s, char *t )
    264 #else
    265 pClass( s, t )
    266 char *s;
    267 char *t;
    268 #endif
    269 {
    270 	if (num_sors==0)
    271 	{
    272 		require(num_classes<MAX_CLASSES, "exceeded max # of grammar classes");
    273 		classes[num_classes++] = t;
    274 	} else
    275 	{
    276 		sclasses[num_sors-1] = t; /* one class per sorcerer group (last valid) */
    277 	}
    278 }
    279 
    280 static void
    281 #ifdef __STDC__
    282 pDLGClass( char *s, char *t )
    283 #else
    284 pDLGClass( s, t )
    285 char *s;
    286 char *t;
    287 #endif
    288 {
    289 	if ( !gen_CPP ) {
    290 		fprintf(stderr, "-dlg-class makes no sense without C++ mode; ignored...");
    291 	}
    292 	else dlg_class = t;
    293 }
    294 
    295 static void
    296 #ifdef __STDC__
    297 pOdir( char *s, char *t )
    298 #else
    299 pOdir( s, t )
    300 char *s;
    301 char *t;
    302 #endif
    303 {
    304 	outdir = t;
    305 }
    306 
    307 static void
    308 #ifdef __STDC__
    309 pHdr( char *s, char *t )
    310 #else
    311 pHdr( s, t )
    312 char *s;
    313 char *t;
    314 #endif
    315 {
    316 	hdr = t;
    317 }
    318 
    319 static void
    320 #ifdef __STDC__
    321 pCompiler( char *s, char *t )
    322 #else
    323 pCompiler( s, t )
    324 char *s;
    325 char *t;
    326 #endif
    327 {
    328 	compilerCCC = t;
    329 	compilerCC = t;
    330 	nondef_comp = 1;
    331 }
    332 
    333 static void
    334 #ifdef __STDC__
    335 ppccts_path( char *s, char *t )
    336 #else
    337 ppccts_path( s, t )
    338 char *s;
    339 char *t;
    340 #endif
    341 {
    342 	pccts_path = t;
    343 }
    344 
    345 Opt options[] = {
    346 	{ "-CC", 0,	pCPP,			"Generate C++ output"},
    347 	{ "-class", 1,	pClass,		"Name of a grammar class defined in grammar (if C++)"},
    348 	{ "-dlg-class", 1,pDLGClass,"Name of DLG lexer class (default=DLGLexer) (if C++)"},
    349 	{ "-header", 1,pHdr,		"Name of ANTLR standard header info (default=no file)"},
    350 	{ "-o", 1,	pOdir,			"Directory where output files should go (default=\".\")"},
    351 	{ "-project", 1,	pProj,	"Name of executable to create (default=t)"},
    352 	{ "-token-types", 1, pUT,	"Token types are in this file (don't use tokens.h)"},
    353 	{ "-trees", 0, pTrees,		"Generate ASTs"},
    354 	{ "-user-lexer", 0,	pUL,	"Do not create a DLG-based scanner"},
    355 	{ "-mrhoist",0,pHoist,      "Maintenance release style hoisting"},
    356 	{ "-cfiles",1,pCFiles,      "Additional files in C or C++ to compile"},
    357 	{ "-sor",0,pSor,           "Start of sorcerer group"},
    358 	{ "-pccts_path",1,ppccts_path,
    359 			"Path for $PCCTS directory (default is /usr/local/pccts)"},
    360 	{ "-compiler",1,pCompiler,
    361 			"Default compiler (default is CC/cc)"},
    362 	{ "*", 0,pFile, 	        "" },	/* anything else is a file */
    363 	{ NULL, 0, NULL, NULL }
    364 };
    365 
    366 #ifdef __STDC__
    367 extern char *DIR(void);
    368 #else
    369 extern char *DIR();
    370 #endif
    371 
    372 #ifdef __STDC__
    373 int main(int argc, char **argv)
    374 #else
    375 int main(argc, argv)
    376 int argc;
    377 char **argv;
    378 #endif
    379 {
    380 	int i;
    381 
    382 	if ( argc == 1 ) { help(); DIE; }
    383 	for(i=0;i<MAX_SORS;i++) num_sfiles[i]=0;
    384 
    385 	ProcessArgs(argc-1, &(argv[1]), options);
    386 
    387 	strcpy(ATOKENBUFFER_O, ATOKENBUFFER_C);
    388 	ATOKENBUFFER_O[strlen(ATOKENBUFFER_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
    389 	strcat(ATOKENBUFFER_O, OBJ_FILE_SUFFIX);
    390 	strcpy(APARSER_O, APARSER_C);
    391 	APARSER_O[strlen(APARSER_O)-strlen(CPP_FILE_SUFFIX)] = '\0';
    392 	strcat(APARSER_O, OBJ_FILE_SUFFIX);
    393 
    394 	strcpy(ASTBASE_O, ASTBASE_C);
    395 	ASTBASE_O[strlen(ASTBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
    396 	strcat(ASTBASE_O, OBJ_FILE_SUFFIX);
    397 
    398 	strcpy(PCCTSAST_O, PCCTSAST_C);
    399 	PCCTSAST_O[strlen(PCCTSAST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
    400 	strcat(PCCTSAST_O, OBJ_FILE_SUFFIX);
    401 
    402 	strcpy(LIST_O, LIST_C);
    403 	LIST_O[strlen(LIST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
    404 	strcat(LIST_O, OBJ_FILE_SUFFIX);
    405 
    406 	strcpy(DLEXERBASE_O, DLEXERBASE_C);
    407 	DLEXERBASE_O[strlen(DLEXERBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
    408 	strcat(DLEXERBASE_O, OBJ_FILE_SUFFIX);
    409 
    410 	if ( num_files == 0 ) fatal("no grammar files specified; exiting...");
    411 	if ( !gen_CPP && num_classes>0 ) {
    412 		warn("can't define classes w/o C++ mode; turning on C++ mode...\n");
    413 		gen_CPP=1;
    414 	}
    415 	if (!gen_CPP && num_sors) {
    416 		warn("can't define sorcerer group in C mode (yet); turning on C++ mode...\n");
    417 		gen_CPP=1;
    418 	}
    419 	if ( gen_CPP && num_classes==0 ) {
    420 		fatal("must define classes >0 grammar classes in C++ mode\n");
    421 	}
    422 
    423 	mk(project, files, num_files, argc, argv);
    424 	DONE;
    425 }
    426 
    427 #ifdef __STDC__
    428 void help(void)
    429 #else
    430 void help()
    431 #endif
    432 {
    433 	Opt *p = options;
    434 	static char buf[1000+1];
    435 
    436 	fprintf(stderr, "genmk [options] f1.g ... fn.g\n");
    437 	while ( p->option!=NULL && *(p->option) != '*' )
    438 	{
    439 		buf[0]='\0';
    440 		if ( p->arg ) sprintf(buf, "%s ___", p->option);
    441 		else strcpy(buf, p->option);
    442 		fprintf(stderr, "\t%-16s   %s\n", buf, p->descr);
    443 		p++;
    444 	}
    445 }
    446 
    447 #ifdef __STDC__
    448 void mk(char *project, char **files, int n, int argc, char **argv)
    449 #else
    450 void mk(project, files, n, argc, argv)
    451 char *project;
    452 char **files;
    453 int n;
    454 int argc;
    455 char **argv;
    456 #endif
    457 {
    458 	int i,j;
    459 
    460 	printf("#\n");
    461 	printf("# PCCTS makefile for: ");
    462 	pfiles(files, n, NULL);
    463 	printf("\n");
    464 	printf("#\n");
    465 	printf("# Created from:");
    466 	for (i=0; i<argc; i++) printf(" %s", argv[i]);
    467 	printf("\n");
    468 	printf("#\n");
    469 	printf("# PCCTS release 1.33MR23\n");
    470 	printf("# Project: %s\n", project);
    471 	if ( gen_CPP ) printf("# C++ output\n");
    472 	else printf("# C output\n");
    473 	if ( user_lexer ) printf("# User-defined scanner\n");
    474 	else printf("# DLG scanner\n");
    475 	if ( user_token_types!=NULL ) printf("# User-defined token types in '%s'\n", user_token_types);
    476 	else printf("# ANTLR-defined token types\n");
    477 	printf("#\n");
    478 /***********
    479 	printf(".SUFFIXES:\n.SUFFIXES:\t.o .cpp .c .h .g .i .dlg .sor\n");
    480  ***********/
    481 	if ( user_token_types!=NULL ) {
    482 		printf("# Make sure #tokdefs directive in ANTLR grammar lists this file:\n");
    483 		printf("TOKENS = %s", user_token_types);
    484 	}
    485 	else printf("TOKENS = %stokens.h", DIR());
    486 	printf("\n");
    487 	printf("#\n");
    488 	printf("# The following filenames must be consistent with ANTLR/DLG flags\n");
    489 	printf("DLG_FILE = %s%s\n", DIR(), dlg);
    490 	printf("ERR = %serr\n", DIR());
    491 	if ( strcmp(hdr,"stdpccts.h")!=0 ) printf("HDR_FILE = %s%s\n", DIR(), hdr);
    492 	else printf("HDR_FILE =\n");
    493 	if ( !gen_CPP ) printf("MOD_FILE = %s%s\n", DIR(), mode);
    494 	if ( !gen_CPP ) printf("SCAN = %s\n", scan);
    495 	else printf("SCAN = %s%s\n", DIR(), dlg_class);
    496 
    497 	printf("PCCTS = %s\n",pccts_path);
    498 	printf("ANTLR_H = $(PCCTS)%sh\n", DirectorySymbol);
    499 	if (num_sors>0) {
    500 		printf("SOR_H = $(PCCTS)%ssorcerer%sh\n", DirectorySymbol, DirectorySymbol);
    501 		printf("SOR_LIB = $(PCCTS)%ssorcerer%slib\n",
    502 			 	DirectorySymbol, DirectorySymbol);
    503 	}
    504 	printf("BIN = $(PCCTS)%sbin\n", DirectorySymbol);
    505 	printf("ANTLR = $(BIN)%santlr\n", DirectorySymbol);
    506 	printf("DLG = $(BIN)%sdlg\n", DirectorySymbol);
    507 	if (num_sors>0) printf("SOR = $(BIN)%ssor\n", DirectorySymbol);
    508 	printf("CFLAGS = -I. -I$(ANTLR_H)");
    509 	if (num_sors>0) printf(" -I$(SOR_H)");
    510 	if ( strcmp(outdir, ".")!=0 ) printf(" -I%s", outdir);
    511 	printf(" $(COTHER)");
    512 	printf("\n");
    513 	printf("AFLAGS =");
    514 	if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);
    515 	if ( user_lexer ) printf(" -gx");
    516 	if ( gen_CPP ) printf(" -CC");
    517 	if ( strcmp(hdr,"stdpccts.h")!=0 ) printf(" -gh %s", hdr);
    518 	if ( gen_trees ) printf(" -gt");
    519 	if ( gen_hoist ) {
    520 		printf(" -mrhoist on") ;
    521 	} else {
    522 		printf(" -mrhoist off");
    523 	};
    524 	printf(" $(AOTHER)");
    525 	printf("\n");
    526 	printf("DFLAGS = -C2 -i");
    527 	if ( gen_CPP ) printf(" -CC");
    528 	if ( strcmp(dlg_class,"DLGLexer")!=0 ) printf(" -cl %s", dlg_class);
    529 	if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);
    530 	printf(" $(DOTHER)");
    531 	printf("\n");
    532 	if (num_sors>0)
    533 	{
    534 		printf("SFLAGS = -CPP");
    535 		if ( strcmp(outdir,".")!=0 ) printf(" -out-dir %s", outdir);
    536 		printf(" $(SOTHER)\n");
    537 	}
    538 	printf("GRM = ");
    539 	pfiles(files, n, NULL);
    540 	printf("\n");
    541 	printf("SRC = ");
    542 	if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);
    543 	else pfiles(files, n, "c");
    544 	if ( gen_CPP ) {
    545 		printf(" \\\n\t");
    546 		pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);
    547 		printf(" \\\n\t");
    548 		printf("$(ANTLR_H)%s%s", DirectorySymbol, APARSER_C);
    549 		if ( !user_lexer ) printf(" $(ANTLR_H)%s%s", DirectorySymbol, DLEXERBASE_C);
    550 		if ( gen_trees ) {
    551 			printf(" \\\n\t");
    552 			printf("$(ANTLR_H)%s%s", DirectorySymbol, ASTBASE_C);
    553 			printf(" $(ANTLR_H)%s%s", DirectorySymbol, PCCTSAST_C);
    554 /*			printf(" $(ANTLR_H)%s%s", DirectorySymbol, LIST_C); */
    555 			printf(" \\\n\t");
    556 		}
    557 		printf(" $(ANTLR_H)%s%s", DirectorySymbol, ATOKENBUFFER_C);
    558 	}
    559 	if ( !user_lexer ) {
    560 		if ( gen_CPP ) printf(" $(SCAN)%s", CPP_FILE_SUFFIX);
    561 		else printf(" %s$(SCAN).c", DIR());
    562 	}
    563 	if ( !gen_CPP ) printf(" $(ERR).c");
    564 	for (i=0;i<num_sors;i++)
    565 	{
    566 		printf(" \\\n\t");
    567 		pclasses(&sclasses[i],1,CPP_FILE_SUFFIX_NO_DOT);
    568 		printf(" ");
    569 		pfiles(&sfiles[i][0],num_sfiles[i],CPP_FILE_SUFFIX_NO_DOT);
    570 	}
    571 	if(num_sors>0)
    572 		printf(" \\\n\t$(SOR_LIB)%sSTreeParser.cpp", DirectorySymbol);
    573 	if (num_cfiles>0)
    574 	{
    575 		printf(" \\\n\t");
    576 		pfiles(cfiles,num_cfiles,NULL);
    577 	}
    578 	printf("\n\n");
    579 	printf("OBJ = ");
    580 	pfiles(files, n, "o");
    581 	if ( gen_CPP ) {
    582 		printf(" \\\n\t");
    583 		pclasses(classes, num_classes, "o");
    584 		printf(" \\\n\t");
    585 		printf("%s%s", DIR(), APARSER_O);
    586 		if ( !user_lexer ) {
    587 			printf(" %s%s", DIR(), DLEXERBASE_O);
    588 		}
    589 		if ( gen_trees ) {
    590 			printf(" \\\n\t");
    591 			printf("%s%s", DIR(), ASTBASE_O);
    592 			printf(" %s%s", DIR(), PCCTSAST_O);
    593 /*			printf(" %s%s", DIR(), LIST_O); */
    594 			printf(" \\\n\t");
    595 		}
    596 		printf(" %s%s", DIR(), ATOKENBUFFER_O);
    597 	}
    598 	if ( !user_lexer ) {
    599 		if ( gen_CPP ) printf(" $(SCAN)%s", OBJ_FILE_SUFFIX);
    600 		else printf(" %s$(SCAN)%s", DIR(), OBJ_FILE_SUFFIX);
    601 	}
    602 	if ( !gen_CPP ) printf(" $(ERR)%s", OBJ_FILE_SUFFIX);
    603 	for (i=0;i<num_sors;i++)
    604 	{
    605 		printf(" \\\n\t");
    606 		pclasses(&sclasses[i],1,"o");
    607 		printf(" ");
    608 		pfiles(&sfiles[i][0],num_sfiles[i],"o");
    609 	}
    610 	if(num_sors>0) printf(" \\\n\tSTreeParser.o");
    611 	if (num_cfiles>0)
    612 	{
    613 		printf(" \\\n\t");
    614 		pfiles(cfiles,num_cfiles,"o");
    615 	}
    616 	printf("\n\n");
    617 
    618 	printf("ANTLR_SPAWN = ");
    619 	if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);
    620 	else pfiles(files, n, "c");
    621 	if ( gen_CPP ) {
    622 		printf(" ");
    623 		pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);
    624 		printf(" \\\n\t\t");
    625 		pclasses(classes, num_classes, "h");
    626 		if ( strcmp(hdr,"stdpccts.h")!=0 ) {
    627 			printf(" \\\n\t\t");
    628 			printf("$(HDR_FILE) stdpccts.h");
    629 		}
    630 	}
    631 	if ( user_lexer ) {
    632 		if ( !user_token_types ) printf(" $(TOKENS)");
    633 	}
    634 	else {
    635 		printf(" $(DLG_FILE)");
    636 		if ( !user_token_types ) printf(" $(TOKENS)");
    637 	}
    638 	if ( !gen_CPP ) printf(" $(ERR).c");
    639 	printf("\n");
    640 
    641 	if ( !user_lexer ) {
    642 		if ( gen_CPP ) printf("DLG_SPAWN = $(SCAN)%s", CPP_FILE_SUFFIX);
    643 		else printf("DLG_SPAWN = %s$(SCAN).c", DIR());
    644 		if ( gen_CPP ) printf(" $(SCAN).h");
    645 		if ( !gen_CPP ) printf(" $(MOD_FILE)");
    646 		printf("\n");
    647 	}
    648 
    649 	if ( gen_CPP ) {
    650 		if ( !nondef_comp )
    651 			printf("ifdef CXX\nCCC = $(CXX)\nendif\n\nifndef CCC\n");
    652 		printf("CCC = %s\n",compilerCCC);
    653 		if ( !nondef_comp ) printf("endif\n\n");
    654 	}
    655 	else
    656 	{
    657 		if ( !nondef_comp ) printf("ifndef CC\n");
    658 		printf("CC = %s\n",compilerCC);
    659 		if ( !nondef_comp ) printf("endif\n\n");
    660 	}
    661 
    662 	/* set up dependencies */
    663 	printf("\n%s : $(SRC) $(OBJ)\n", project);
    664 	printf("\t%s %s %s $(CFLAGS) $(OBJ)\n",
    665 		gen_CPP?"$(CCC)":"$(CC)",
    666 		RENAME_EXE_FLAG,
    667 		project);
    668 	printf("\n");
    669 
    670 	/* implicit rules */
    671 
    672 /*	if(gen_CPP)
    673 		printf("%%.o : %%.cpp\n\t$(CCC) -c $(CFLAGS) $<\n\n");
    674 
    675 	printf("%%.o : %%.c\n\t%s -c $(CFLAGS) $<\n\n",
    676 			gen_CPP?"$(CCC)":"$(CC)");
    677 */
    678 	/* how to compile parser files */
    679 
    680 	for (i=0; i<num_files; i++)
    681 	{
    682 		pfiles(&files[i], 1, "o");
    683 		if ( user_lexer ) {
    684 			printf(" : $(TOKENS)");
    685 		}
    686 		else {
    687 			if ( gen_CPP ) printf(" : $(TOKENS) $(SCAN).h");
    688 			else printf(" : $(MOD_FILE) $(TOKENS)");
    689 		}
    690 		printf(" ");
    691 		if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);
    692 		else pfiles(&files[i], 1, "c");
    693 		if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
    694 		printf("\n");
    695 		printf("\t%s -c $(CFLAGS) %s ",
    696 			gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
    697 		pfiles(&files[i], 1, "o");
    698 		printf(" ");
    699 		if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);
    700 		else pfiles(&files[i], 1, "c");
    701 		printf("\n\n");
    702 	}
    703 
    704 	for (i=0; i<num_cfiles; i++)
    705 	{
    706 		pfiles(&cfiles[i], 1, "o");
    707 		printf(" : ");
    708 		pfiles(&cfiles[i], 1, NULL);
    709 		if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
    710 /***	printf(" "); ***/
    711 /***	pfiles(&cfiles[i], 1, "h"); ***/
    712 		printf("\n");
    713 		printf("\t%s -c $(CFLAGS) %s ",
    714 			gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
    715 		pfiles(&cfiles[i], 1, "o");
    716 		printf(" ");
    717 		pfiles(&cfiles[i], 1, NULL);
    718 		printf("\n\n");
    719 
    720 /*
    721  *		pfiles(&cfiles[i], 1, "h");
    722  *		printf(" :\ntouch ");
    723  *		pfiles(&cfiles[i], 1, "h");
    724  *		printf("\n\n");
    725  */
    726 	}
    727 
    728 	/* how to compile err.c */
    729 	if ( !gen_CPP ) {
    730 		printf("$(ERR)%s : $(ERR).c", OBJ_FILE_SUFFIX);
    731 		if ( !user_lexer ) printf(" $(TOKENS)");
    732 		printf("\n");
    733 		printf("\t%s -c $(CFLAGS) %s $(ERR)%s $(ERR).c",
    734 			gen_CPP?"$(CCC)":"$(CC)",
    735 			RENAME_OBJ_FLAG,
    736 			OBJ_FILE_SUFFIX);
    737 		printf("\n\n");
    738 	}
    739 
    740 	/* how to compile Class.c */
    741 	for (i=0; i<num_classes; i++)
    742 	{
    743 		pclasses(&classes[i], 1, "o");
    744 		if ( user_lexer ) {
    745 			printf(" : $(TOKENS)");
    746 		}
    747 		else {
    748 			printf(" : $(TOKENS) $(SCAN).h");
    749 		}
    750 		printf(" ");
    751 		pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);
    752 		printf(" ");
    753 		pclasses(&classes[i], 1, "h");
    754 		if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
    755 		printf("\n");
    756 		printf("\t%s -c $(CFLAGS) %s ",
    757 			gen_CPP?"$(CCC)":"$(CC)",
    758 			RENAME_OBJ_FLAG);
    759 		pclasses(&classes[i], 1, "o");
    760 		printf(" ");
    761 		pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);
    762 		printf("\n\n");
    763 	}
    764 
    765 	/* how to compile scan.c */
    766 	if ( !user_lexer ) {
    767 		if ( gen_CPP ) printf("$(SCAN)%s : $(SCAN)%s", OBJ_FILE_SUFFIX, CPP_FILE_SUFFIX);
    768 		else printf("%s$(SCAN)%s : %s$(SCAN).c", DIR(), OBJ_FILE_SUFFIX, DIR());
    769 		if ( !user_lexer ) printf(" $(TOKENS)");
    770 		printf("\n");
    771 		if ( gen_CPP ) printf("\t$(CCC) -c $(CFLAGS) %s $(SCAN)%s $(SCAN)%s",
    772 							RENAME_OBJ_FLAG,
    773 							OBJ_FILE_SUFFIX,
    774 							CPP_FILE_SUFFIX);
    775 		else printf("\t$(CC) -c $(CFLAGS) %s %s$(SCAN)%s %s$(SCAN).c",
    776 					RENAME_OBJ_FLAG,
    777 					DIR(),
    778 					OBJ_FILE_SUFFIX,
    779 					DIR());
    780 		printf("\n\n");
    781 	}
    782 /* how to compile sorcerer classes */
    783 	for (i=0;i<num_sors;i++)
    784 	{
    785 		pclasses(&sclasses[i], 1, "o");
    786 		printf(" : ");
    787 		pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);
    788 		printf(" ");
    789 		pclasses(&sclasses[i], 1, "h");
    790 		if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
    791 		printf("\n");
    792 		printf("\t%s -c $(CFLAGS) %s ",
    793 				gen_CPP?"$(CCC)":"$(CC)",
    794 				RENAME_OBJ_FLAG);
    795 		pclasses(&sclasses[i], 1, "o");
    796 		printf(" ");
    797 		pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);
    798 		printf("\n\n");
    799 /* how to compile i-th sorcerer's files*/
    800 		for (j=0; j<num_sfiles[i]; j++)
    801 		{
    802 			pfiles(&sfiles[i][j], 1, "o");
    803 			printf(" : ");
    804 			if ( gen_CPP ) pfiles(&sfiles[i][j], 1, CPP_FILE_SUFFIX_NO_DOT);
    805 			else pfiles(&sfiles[i][j], 1, "c");
    806 			if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
    807 			printf("\n");
    808 			printf("\t%s -c $(CFLAGS) %s ",
    809 					gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
    810 			pfiles(&sfiles[i][j], 1, "o");
    811 			printf(" ");
    812 			if ( gen_CPP ) pfiles(&sfiles[i][j], 1, CPP_FILE_SUFFIX_NO_DOT);
    813 			else pfiles(&sfiles[i][j], 1, "c");
    814 			printf("\n\n");
    815 		}
    816 		if ( gen_CPP ) pfiles(&sfiles[i][0], num_sfiles[i], CPP_FILE_SUFFIX_NO_DOT);
    817 		else pfiles(&sfiles[i][0], num_sfiles[i], "c");
    818 		if ( gen_CPP )
    819 		{
    820 			printf(" ");
    821 			pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);
    822 			printf(" ");
    823 			pclasses(&sclasses[i], 1, "h");
    824 			if ( strcmp(hdr,"stdpccts.h")!=0 )
    825 			{
    826 				printf(" ");
    827 				printf("$(HDR_FILE) stdpccts.h");
    828 			}
    829 		}
    830 		printf(" : ");
    831 		pfiles(&sfiles[i][0],num_sfiles[i],NULL);
    832 		printf("\n\t$(SOR) $(SFLAGS) ");
    833 		pfiles(&sfiles[i][0],num_sfiles[i],NULL);
    834 		printf("\n\n");
    835 	}
    836 	if(num_sors>0)
    837 	{
    838 		printf("STreeParser%s : $(SOR_LIB)%sSTreeParser.cpp\n",
    839 				OBJ_FILE_SUFFIX,DirectorySymbol);
    840 		printf("\t%s -c $(CFLAGS) %s ",
    841 				gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
    842 		printf("STreeParser%s ",OBJ_FILE_SUFFIX);
    843 		printf("$(SOR_LIB)%sSTreeParser.cpp\n\n",DirectorySymbol);
    844 	}
    845 
    846 	printf("$(ANTLR_SPAWN) : $(GRM)\n");
    847 	printf("\t$(ANTLR) $(AFLAGS) $(GRM)\n");
    848 
    849 	if ( !user_lexer )
    850 	{
    851 		printf("\n");
    852 		printf("$(DLG_SPAWN) : $(DLG_FILE)\n");
    853 		if ( gen_CPP ) printf("\t$(DLG) $(DFLAGS) $(DLG_FILE)\n");
    854 		else printf("\t$(DLG) $(DFLAGS) $(DLG_FILE) $(SCAN).c\n");
    855 	}
    856 
    857 	/* do the makes for ANTLR/DLG support */
    858 	if ( gen_CPP ) {
    859 		printf("\n");
    860 		printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);
    861 		printf("\t%s -c $(CFLAGS) %s ",
    862 				gen_CPP?"$(CCC)":"$(CC)",
    863 				RENAME_OBJ_FLAG);
    864 		printf("%s%s $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);
    865 		printf("\n");
    866 		printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);
    867 		printf("\t%s -c $(CFLAGS) %s ",
    868 				gen_CPP?"$(CCC)":"$(CC)",
    869 				RENAME_OBJ_FLAG);
    870 		printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);
    871 		if ( !user_lexer ) {
    872 			printf("\n");
    873 			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);
    874 			printf("\t%s -c $(CFLAGS) %s ",
    875 					gen_CPP?"$(CCC)":"$(CC)",
    876 					RENAME_OBJ_FLAG);
    877 			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);
    878 		}
    879 		if ( gen_trees ) {
    880 			printf("\n");
    881 			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);
    882 			printf("\t%s -c $(CFLAGS) %s ",
    883 					gen_CPP?"$(CCC)":"$(CC)",
    884 					RENAME_OBJ_FLAG);
    885 			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);
    886 			printf("\n");
    887 			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);
    888 			printf("\t%s -c $(CFLAGS) %s ",
    889 					gen_CPP?"$(CCC)":"$(CC)",
    890 					RENAME_OBJ_FLAG);
    891 			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);
    892 			printf("\n");
    893 /*
    894 			printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);
    895 			printf("\t%s -c $(CFLAGS) %s ",
    896 					gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
    897 			printf("%s%s $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);
    898 */
    899 		}
    900 	}
    901 
    902 	/* clean and scrub targets */
    903 
    904 	printf("\nclean:\n");
    905 	printf("\trm -f *%s core %s", OBJ_FILE_SUFFIX, project);
    906 	if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);
    907 	printf("\n");
    908 
    909 	printf("\nscrub: clean\n");
    910 /*	printf("\trm -f *%s core %s", OBJ_FILE_SUFFIX, project); */
    911 /*	if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX); */
    912 	printf("\trm -f $(ANTLR_SPAWN)");
    913 	if ( !user_lexer ) printf(" $(DLG_SPAWN)");
    914 	for (i=0;i<num_sors;i++)
    915 	{
    916 		printf(" ");
    917 		if ( gen_CPP ) pfiles(&sfiles[i][0], num_sfiles[i], CPP_FILE_SUFFIX_NO_DOT);
    918 		else pfiles(&sfiles[i][0], num_sfiles[i], "c");
    919 		if ( gen_CPP )
    920 		{
    921 			printf(" ");
    922 			pclasses(&sclasses[i], 1, CPP_FILE_SUFFIX_NO_DOT);
    923 			printf(" ");
    924 			pclasses(&sclasses[i], 1, "h");
    925 		}
    926 	}
    927 	printf("\n\n");
    928 }
    929 
    930 #ifdef __STDC__
    931 void pfiles(char **files, int n, char *suffix)
    932 #else
    933 void pfiles(files, n, suffix)
    934 char **files;
    935 int n;
    936 char *suffix;
    937 #endif
    938 {
    939 	int first=1;
    940 
    941 	while ( n>0 )
    942 	{
    943 		char *p = &(*files)[strlen(*files)-1];
    944 		if ( !first ) putchar(' ');
    945 		first=0;
    946 		while ( p > *files && *p != '.' ) --p;
    947 		if ( p == *files )
    948 		{
    949 			fprintf(stderr,
    950 					"genmk: filenames must be file.suffix format: %s\n",
    951 					*files);
    952 			exit(-1);
    953 		}
    954 		if ( suffix == NULL ) printf("%s", *files);
    955 		else
    956 		{
    957 			*p = '\0';
    958 			printf("%s", DIR());
    959 			if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX);
    960 			else printf("%s.%s", *files, suffix);
    961 			*p = '.';
    962 		}
    963 		files++;
    964 		--n;
    965 	}
    966 }
    967 
    968 #ifdef __STDC__
    969 pclasses(char **classes, int n, char *suffix)
    970 #else
    971 pclasses(classes, n, suffix)
    972 char **classes;
    973 int n;
    974 char *suffix;
    975 #endif
    976 {
    977 	int first=1;
    978 
    979 	while ( n>0 )
    980 	{
    981 		if ( !first ) putchar(' ');
    982 		first=0;
    983 		if ( suffix == NULL ) printf("%s", *classes);
    984 		else {
    985 			printf("%s", DIR());
    986 			if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX);
    987 			else printf("%s.%s", *classes, suffix);
    988 		}
    989 		classes++;
    990 		--n;
    991 	}
    992 }
    993 
    994 static void
    995 #ifdef __STDC__
    996 ProcessArgs( int argc, char **argv, Opt *options )
    997 #else
    998 ProcessArgs( argc, argv, options )
    999 int argc;
   1000 char **argv;
   1001 Opt *options;
   1002 #endif
   1003 {
   1004 	Opt *p;
   1005 	require(argv!=NULL, "ProcessArgs: command line NULL");
   1006 
   1007 	while ( argc-- > 0 )
   1008 	{
   1009 		p = options;
   1010 		while ( p->option != NULL )
   1011 		{
   1012 			if ( strcmp(p->option, "*") == 0 ||
   1013 				 strcmp(p->option, *argv) == 0 )
   1014 			{
   1015 				if ( p->arg )
   1016 				{
   1017 					(*p->process)( *argv, *(argv+1) );
   1018 					argv++;
   1019 					argc--;
   1020 				}
   1021 				else
   1022 					(*p->process)( *argv );
   1023 				break;
   1024 			}
   1025 			p++;
   1026 		}
   1027 		argv++;
   1028 	}
   1029 }
   1030 
   1031 #ifdef __STDC__
   1032 void fatal( char *err_)
   1033 #else
   1034 void fatal( err_)
   1035 char *err_;
   1036 #endif
   1037 {
   1038 	fprintf(stderr, "genmk: %s\n", err_);
   1039 	exit(1);
   1040 }
   1041 
   1042 #ifdef __STDC__
   1043 void warn( char *err_)
   1044 #else
   1045 void warn( err_)
   1046 char *err_;
   1047 #endif
   1048 {
   1049 	fprintf(stderr, "genmk: %s\n", err_);
   1050 }
   1051 
   1052 #ifdef __STDC__
   1053 char *DIR(void)
   1054 #else
   1055 char *DIR()
   1056 #endif
   1057 {
   1058 	static char buf[200+1];
   1059 
   1060 	if ( strcmp(outdir,TopDirectory)==0 ) return "";
   1061 	sprintf(buf, "%s%s", outdir, DirectorySymbol);
   1062 	return buf;
   1063 }
   1064