2 * genmk -- a program to make makefiles for PCCTS
5 * Terence John Parr 1989 - 1994
10 #include "config.h" /* be sensitive to what ANTLR/DLG call the files */
14 #define DONE return 1;
17 #define DONE return 0;
21 #define require(expr, err) {if ( !(expr) ) fatal(err);}
25 #define MAX_CLASSES 50
27 char *RENAME_OBJ_FLAG="-o",
28 *RENAME_EXE_FLAG="-o";
30 char *dlg = "parser.dlg";
32 char *hdr = "stdpccts.h";
33 char *tok = "tokens.h";
34 char *mode = "mode.h";
37 char ATOKENBUFFER_O[100];
42 char DLEXERBASE_O[100];
45 static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES];
46 static int num_files = 0;
47 static int num_classes = 0;
48 static int user_lexer = 0;
49 static char *user_token_types = NULL;
50 static int gen_CPP = 0;
51 static char *outdir=".";
52 static char *dlg_class = "DLGLexer";
53 static int gen_trees = 0;
67 static void ProcessArgs(int, char **, Opt *);
69 static void ProcessArgs();
119 fprintf(stderr, "invalid option: '%s'; ignored...",s);
123 require(num_files<MAX_FILES, "exceeded max # of input files");
124 files[num_files++] = s;
129 pClass( char *s, char *t )
136 require(num_classes<MAX_CLASSES, "exceeded max # of grammar classes");
137 classes[num_classes++] = t;
142 pDLGClass( char *s, char *t )
150 fprintf(stderr, "-dlg-class makes no sense without C++ mode; ignored...");
157 pOdir( char *s, char *t )
169 pHdr( char *s, char *t )
180 { "-CC", 0, pCPP, "Generate C++ output"},
181 { "-class", 1, pClass, "Name of a grammar class defined in grammar (if C++)"},
182 { "-dlg-class", 1,pDLGClass,"Name of DLG lexer class (default=DLGLexer) (if C++)"},
183 { "-header", 1,pHdr, "Name of ANTLR standard header info (default=no file)"},
184 { "-o", 1, pOdir, "Directory where output files should go (default=\".\")"},
185 { "-project", 1, pProj, "Name of executable to create (default=t)"},
186 { "-token-types", 1, pUT, "Token types are in this file (don't use tokens.h)"},
187 { "-trees", 0, pTrees, "Generate ASTs"},
188 { "-user-lexer", 0, pUL, "Do not create a DLG-based scanner"},
189 { "*", 0, pFile, "" }, /* anything else is a file */
190 { NULL, 0, NULL, NULL }
199 if ( argc == 1 ) { help(); DIE; }
200 ProcessArgs(argc-1, &(argv[1]), options);
202 strcpy(ATOKENBUFFER_O, ATOKENBUFFER_C);
203 ATOKENBUFFER_O[strlen(ATOKENBUFFER_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
204 strcat(ATOKENBUFFER_O, OBJ_FILE_SUFFIX);
205 strcpy(APARSER_O, APARSER_C);
206 APARSER_O[strlen(APARSER_O)-strlen(CPP_FILE_SUFFIX)] = '\0';
207 strcat(APARSER_O, OBJ_FILE_SUFFIX);
209 strcpy(ASTBASE_O, ASTBASE_C);
210 ASTBASE_O[strlen(ASTBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
211 strcat(ASTBASE_O, OBJ_FILE_SUFFIX);
213 strcpy(PCCTSAST_O, PCCTSAST_C);
214 PCCTSAST_O[strlen(PCCTSAST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
215 strcat(PCCTSAST_O, OBJ_FILE_SUFFIX);
217 strcpy(LIST_O, LIST_C);
218 LIST_O[strlen(LIST_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
219 strcat(LIST_O, OBJ_FILE_SUFFIX);
221 strcpy(DLEXERBASE_O, DLEXERBASE_C);
222 DLEXERBASE_O[strlen(DLEXERBASE_C)-strlen(CPP_FILE_SUFFIX)] = '\0';
223 strcat(DLEXERBASE_O, OBJ_FILE_SUFFIX);
225 if ( num_files == 0 ) fatal("no grammar files specified; exiting...");
226 if ( !gen_CPP && num_classes>0 ) {
227 warn("can't define classes w/o C++ mode; turning on C++ mode...\n");
230 if ( gen_CPP && num_classes==0 ) {
231 fatal("must define classes >0 grammar classes in C++ mode\n");
234 mk(project, files, num_files, argc, argv);
241 static char buf[1000+1];
243 fprintf(stderr, "genmk [options] f1.g ... fn.g\n");
244 while ( p->option!=NULL && *(p->option) != '*' )
247 if ( p->arg ) sprintf(buf, "%s ___", p->option);
248 else strcpy(buf, p->option);
249 fprintf(stderr, "\t%-16s %s\n", buf, p->descr);
254 mk(project, files, n, argc, argv)
264 printf("# PCCTS makefile for: ");
265 pfiles(files, n, NULL);
268 printf("# Created from:");
269 for (i=0; i<argc; i++) printf(" %s", argv[i]);
272 printf("# PCCTS release 1.32\n");
273 printf("# Project: %s\n", project);
274 if ( gen_CPP ) printf("# C++ output\n");
275 else printf("# C output\n");
276 if ( user_lexer ) printf("# User-defined scanner\n");
277 else printf("# DLG scanner\n");
278 if ( user_token_types!=NULL ) printf("# User-defined token types in '%s'\n", user_token_types);
279 else printf("# ANTLR-defined token types\n");
281 if ( user_token_types!=NULL ) {
282 printf("# Make sure #tokdefs directive in ANTLR grammar lists this file:\n");
283 printf("TOKENS = %s", user_token_types);
285 else printf("TOKENS = %stokens.h", DIR());
288 printf("# The following filenames must be consistent with ANTLR/DLG flags\n");
289 printf("DLG_FILE = %s%s\n", DIR(), dlg);
290 printf("ERR = %serr\n", DIR());
291 if ( strcmp(hdr,"stdpccts.h")!=0 ) printf("HDR_FILE = %s%s\n", DIR(), hdr);
292 else printf("HDR_FILE =\n");
293 if ( !gen_CPP ) printf("MOD_FILE = %s%s\n", DIR(), mode);
294 if ( !gen_CPP ) printf("SCAN = %s\n", scan);
295 else printf("SCAN = %s%s\n", DIR(), dlg_class);
297 printf("PCCTS = .\n");
298 printf("ANTLR_H = $(PCCTS)%sh\n", DirectorySymbol);
299 printf("BIN = $(PCCTS)%sbin\n", DirectorySymbol);
300 printf("ANTLR = $(BIN)%santlr\n", DirectorySymbol);
301 printf("DLG = $(BIN)%sdlg\n", DirectorySymbol);
302 printf("CFLAGS = -I. -I$(ANTLR_H)");
303 if ( strcmp(outdir, ".")!=0 ) printf(" -I%s", outdir);
306 if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);
307 if ( user_lexer ) printf(" -gx");
308 if ( gen_CPP ) printf(" -CC");
309 if ( strcmp(hdr,"stdpccts.h")!=0 ) printf(" -gh %s", hdr);
310 if ( gen_trees ) printf(" -gt");
312 printf("DFLAGS = -C2 -i");
313 if ( gen_CPP ) printf(" -CC");
314 if ( strcmp(dlg_class,"DLGLexer")!=0 ) printf(" -cl %s", dlg_class);
315 if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir);
318 pfiles(files, n, NULL);
321 if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);
322 else pfiles(files, n, "c");
326 pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);
328 printf("$(ANTLR_H)%s%s", DirectorySymbol, APARSER_C);
329 if ( !user_lexer ) printf(" $(ANTLR_H)%s%s", DirectorySymbol, DLEXERBASE_C);
332 printf("$(ANTLR_H)%s%s", DirectorySymbol, ASTBASE_C);
333 printf(" $(ANTLR_H)%s%s", DirectorySymbol, PCCTSAST_C);
334 /* printf(" $(ANTLR_H)%s%s", DirectorySymbol, LIST_C); */
337 printf(" $(ANTLR_H)%s%s", DirectorySymbol, ATOKENBUFFER_C);
340 if ( gen_CPP ) printf(" $(SCAN)%s", CPP_FILE_SUFFIX);
341 else printf(" %s$(SCAN).c", DIR());
343 if ( !gen_CPP ) printf(" $(ERR).c");
346 pfiles(files, n, "o");
350 pclasses(classes, num_classes, "o");
352 printf(" %s%s", DIR(), APARSER_O);
354 printf(" %s%s", DIR(), DLEXERBASE_O);
358 printf("%s%s", DIR(), ASTBASE_O);
359 printf(" %s%s", DIR(), PCCTSAST_O);
360 /* printf(" %s%s", DIR(), LIST_O); */
363 printf(" %s%s", DIR(), ATOKENBUFFER_O);
366 if ( gen_CPP ) printf(" $(SCAN)%s", OBJ_FILE_SUFFIX);
367 else printf(" %s$(SCAN)%s", DIR(), OBJ_FILE_SUFFIX);
369 if ( !gen_CPP ) printf(" $(ERR)%s", OBJ_FILE_SUFFIX);
372 printf("ANTLR_SPAWN = ");
373 if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT);
374 else pfiles(files, n, "c");
377 pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT);
379 pclasses(classes, num_classes, "h");
380 if ( strcmp(hdr,"stdpccts.h")!=0 ) {
382 printf("$(HDR_FILE) stdpccts.h");
386 if ( !user_token_types ) printf(" $(TOKENS)");
389 printf(" $(DLG_FILE)");
390 if ( !user_token_types ) printf(" $(TOKENS)");
392 if ( !gen_CPP ) printf(" $(ERR).c");
396 if ( gen_CPP ) printf("DLG_SPAWN = $(SCAN)%s", CPP_FILE_SUFFIX);
397 else printf("DLG_SPAWN = %s$(SCAN).c", DIR());
398 if ( gen_CPP ) printf(" $(SCAN).h");
399 if ( !gen_CPP ) printf(" $(MOD_FILE)");
404 printf("#CCC=g++\n");
405 printf("CC=$(CCC)\n");
407 else printf("#CC=cc\n");
409 /* set up dependencies */
410 printf("\n%s : $(OBJ) $(SRC)\n", project);
411 printf(" %s %s %s $(CFLAGS) $(OBJ)\n",
412 gen_CPP?"$(CCC)":"$(CC)",
417 /* how to compile parser files */
419 for (i=0; i<num_files; i++)
421 pfiles(&files[i], 1, "o");
423 printf(" : $(TOKENS)");
426 if ( gen_CPP ) printf(" : $(TOKENS) $(SCAN).h");
427 else printf(" : $(MOD_FILE) $(TOKENS)");
430 if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);
431 else pfiles(&files[i], 1, "c");
432 if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
434 printf(" %s -c $(CFLAGS) %s ",gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
435 pfiles(&files[i], 1, "o");
437 if ( gen_CPP ) pfiles(&files[i], 1, CPP_FILE_SUFFIX_NO_DOT);
438 else pfiles(&files[i], 1, "c");
442 /* how to compile err.c */
444 printf("$(ERR)%s : $(ERR).c", OBJ_FILE_SUFFIX);
445 if ( !user_lexer ) printf(" $(TOKENS)");
447 printf(" %s -c $(CFLAGS) %s $(ERR)%s $(ERR).c",
448 gen_CPP?"$(CCC)":"$(CC)",
454 /* how to compile Class.c */
455 for (i=0; i<num_classes; i++)
457 pclasses(&classes[i], 1, "o");
459 printf(" : $(TOKENS)");
462 printf(" : $(TOKENS) $(SCAN).h");
465 pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);
467 pclasses(&classes[i], 1, "h");
468 if ( gen_CPP && strcmp(hdr,"stdpccts.h")!=0 ) printf(" $(HDR_FILE)");
470 printf(" %s -c $(CFLAGS) %s ",
471 gen_CPP?"$(CCC)":"$(CC)",
473 pclasses(&classes[i], 1, "o");
475 pclasses(&classes[i], 1, CPP_FILE_SUFFIX_NO_DOT);
479 /* how to compile scan.c */
481 if ( gen_CPP ) printf("$(SCAN)%s : $(SCAN)%s", OBJ_FILE_SUFFIX, CPP_FILE_SUFFIX);
482 else printf("%s$(SCAN)%s : %s$(SCAN).c", DIR(), OBJ_FILE_SUFFIX, DIR());
483 if ( !user_lexer ) printf(" $(TOKENS)");
485 if ( gen_CPP ) printf(" $(CCC) -c $(CFLAGS) %s $(SCAN)%s $(SCAN)%s",
489 else printf(" $(CC) -c $(CFLAGS) %s %s$(SCAN)%s %s$(SCAN).c",
497 printf("$(ANTLR_SPAWN) : $(GRM)\n");
498 printf(" $(ANTLR) $(AFLAGS) $(GRM)\n");
503 printf("$(DLG_SPAWN) : $(DLG_FILE)\n");
504 if ( gen_CPP ) printf(" $(DLG) $(DFLAGS) $(DLG_FILE)\n");
505 else printf(" $(DLG) $(DFLAGS) $(DLG_FILE) $(SCAN).c\n");
508 /* do the makes for ANTLR/DLG support */
511 printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);
512 printf(" %s -c $(CFLAGS) %s ",
513 gen_CPP?"$(CCC)":"$(CC)",
515 printf("%s%s $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C);
517 printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);
518 printf(" %s -c $(CFLAGS) %s ",
519 gen_CPP?"$(CCC)":"$(CC)",
521 printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C);
524 printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);
525 printf(" %s -c $(CFLAGS) %s ",
526 gen_CPP?"$(CCC)":"$(CC)",
528 printf("%s%s $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C);
532 printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);
533 printf(" %s -c $(CFLAGS) %s ",
534 gen_CPP?"$(CCC)":"$(CC)",
536 printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C);
538 printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);
539 printf(" %s -c $(CFLAGS) %s ",
540 gen_CPP?"$(CCC)":"$(CC)",
542 printf("%s%s $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C);
545 printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);
546 printf(" %s -c $(CFLAGS) %s ",
547 gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG);
548 printf("%s%s $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C);
553 /* clean and scrub targets */
555 printf("\nclean:\n");
556 printf(" rm -f *%s core %s", OBJ_FILE_SUFFIX, project);
557 if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);
560 printf("\nscrub:\n");
561 printf(" rm -f *%s core %s", OBJ_FILE_SUFFIX, project);
562 if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX);
563 printf(" $(ANTLR_SPAWN)");
564 if ( !user_lexer ) printf(" $(DLG_SPAWN)");
568 pfiles(files, n, suffix)
577 char *p = &(*files)[strlen(*files)-1];
578 if ( !first ) putchar(' ');
580 while ( p > *files && *p != '.' ) --p;
584 "genmk: filenames must be file.suffix format: %s\n",
588 if ( suffix == NULL ) printf("%s", *files);
593 if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX);
594 else printf("%s.%s", *files, suffix);
602 pclasses(classes, n, suffix)
611 if ( !first ) putchar(' ');
613 if ( suffix == NULL ) printf("%s", *classes);
616 if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX);
617 else printf("%s.%s", *classes, suffix);
626 ProcessArgs( int argc, char **argv, Opt *options )
628 ProcessArgs( argc, argv, options )
635 require(argv!=NULL, "ProcessArgs: command line NULL");
640 while ( p->option != NULL )
642 if ( strcmp(p->option, "*") == 0 ||
643 strcmp(p->option, *argv) == 0 )
647 (*p->process)( *argv, *(argv+1) );
652 (*p->process)( *argv );
664 fprintf(stderr, "genmk: %s\n", err_);
671 fprintf(stderr, "genmk: %s\n", err_);
676 static char buf[200+1];
678 if ( strcmp(outdir,TopDirectory)==0 ) return "";
679 sprintf(buf, "%s%s", outdir, DirectorySymbol);