123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- /* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
- * For full copyright and restrictions on use see the file COPYING in the top
- * level of the LLgen tree.
- */
- /*
- * L L G E N
- *
- * An Extended LL(1) Parser Generator
- *
- * Author : Ceriel J.H. Jacobs
- */
- /*
- * main.c
- * Contains main program, and some error message routines
- */
- #include "types.h"
- #include "io.h"
- #include "extern.h"
- #include "sets.h"
- #include "assert.h"
- #include "LLgen.h"
- #include <missing_proto.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- int main(int argc, char *argv[])
- {
- string arg;
- string libpath();
- char *beg_sbrk = 0;
- /* Initialize */
- assval = 0400;
- /* read options */
- while (argc >= 2 && (arg = argv[1], *arg == '-')) {
- while (*++arg) {
- switch(*arg) {
- case 'j':
- case 'J':
- jmptable_option = 1;
- if (*++arg)
- min_cases_for_jmptable = atoi(arg);
- break;
- case 'w':
- case 'W':
- wflag = 1;
- continue;
- case 'v':
- case 'V':
- verbose++;
- continue;
- case 'l':
- case 'L':
- low_percentage = atoi(++arg);
- break;
- case 'h':
- case 'H':
- high_percentage = atoi(++arg);
- break;
- # ifndef NDEBUG
- case 'd':
- case 'D':
- debug++;
- continue;
- case 'r':
- case 'R':
- if (rec_file) {
- fprintf(stderr,"duplicate -r flag\n");
- exit(1);
- }
- rec_file = ++arg;
- break;
- case 'i':
- case 'I':
- if (incl_file) {
- fprintf(stderr,"duplicate -i flag\n");
- exit(1);
- }
- incl_file = ++arg;
- break;
- #endif /* not NDEBUG */
- case 'x':
- case 'X':
- ntneeded = 1;
- ntprint = 1;
- continue;
- case 'a':
- case 'A':
- ansi_c = 1;
- continue;
- #ifdef NON_CORRECTING
- case 'n':
- case 'N':
- non_corr = 1;
- continue;
- case 's':
- case 'S':
- subpars_sim = 1;
- continue;
- #endif
- case 'g':
- case 'G':
- strip_grammar = 1;
- continue;
- default:
- fprintf(stderr,"illegal option : %c\n",*arg);
- exit(1);
- }
- break;
- }
- argv++;
- argc--;
- }
- if (verbose) beg_sbrk = (char *)sbrk(0);
- #ifdef NON_CORRECTING
- if ((subpars_sim) && (!non_corr)) {
- fprintf(stderr,"option -s illegal without -n, turned off\n");
- subpars_sim = 0;
- }
- #endif
- /*
- * Now check wether the sets should include nonterminals
- */
- if (verbose == 2) ntneeded = 1;
- /*
- * Initialise
- */
- # ifndef NDEBUG
- if (!rec_file) {
- # endif
- rec_file = libpath("rec");
- # ifndef NDEBUG
- }
- if (!incl_file) {
- # endif
- incl_file = libpath("incl");
- # ifndef NDEBUG
- }
- # endif
- #ifdef NON_CORRECTING
- if (non_corr) {
- nc_incl_file = libpath("nc_incl");
- nc_rec_file = libpath ("nc_rec");
- }
- #endif
- mktemp(f_temp);
- mktemp(f_pars);
- if ((fact = fopen(f_temp,"w")) == NULL) {
- fputs("Cannot create temporary\n",stderr);
- exit(1);
- }
- name_init();
- readgrammar(argc,argv);
- sprintf(f_out, OUTFILE, prefix ? prefix : "LL");
- /* for the following two filenames only one L is used; historical
- reasons ...
- */
- sprintf(f_include, HFILE, prefix ? prefix : "L");
- sprintf(f_rec, RFILE, prefix ? prefix : "L");
- #ifdef NON_CORRECTING
- if (non_corr)
- sprintf(f_nc, NCFILE, prefix ? prefix : "L");
- #endif
- setinit(ntneeded);
- maxnt = &nonterms[nnonterms];
- maxt = &tokens[ntokens];
- /*
- * Now, the grammar is read. Do some computations
- */
- co_reach(); /* Check for undefined and unreachable */
- if (nerrors) comfatal();
- do_compute();
- conflchecks();
- if (nerrors) comfatal();
- fclose(fact);
- if (argc-- == 1) {
- fputs("No code generation for input from standard input\n",
- stderr);
- }
- else gencode(argc);
- UNLINK(f_temp);
- UNLINK(f_pars);
- if (verbose) {
- fprintf(stderr, "number of nonterminals: %d\n", nnonterms);
- fprintf(stderr, "number of tokens: %d\n", ntokens);
- fprintf(stderr, "number of term structures: %d\n", nterms);
- fprintf(stderr, "number of alternation structures: %d\n", nalts);
- fprintf(stderr, "total memory used: %ld\n", (long)((long)sbrk(0) - (long)beg_sbrk));
- }
- exit(0);
- }
- STATIC void readgrammar(int argc, char *argv[]) {
- /*
- * Do just what the name suggests : read the grammar
- */
- register p_file p;
- p_mem alloc();
- linecount = 0;
- f_input = "no filename";
- /*
- * Build the file structure
- */
- files = p = (p_file) alloc((unsigned) (argc+1) * sizeof(t_file));
- if (argc-- == 1) {
- finput = stdin;
- f_input = "standard input";
- doparse(p++);
- } else {
- while (argc--) {
- if ((finput = fopen(f_input=argv[1],"r")) == NULL) {
- fatal(0, e_noopen, f_input, NULL);
- }
- doparse(p++);
- argv++;
- fclose(finput);
- }
- }
- maxfiles = p;
- if (! lexical) lexical = "yylex";
- /*
- * There must be a start symbol!
- */
- if (! nerrors && start == 0) {
- fatal(linecount, "Missing %%start", NULL, NULL);
- }
- if (nerrors) comfatal();
- }
- STATIC void doparse(p_file p) {
- linecount = 0;
- p->f_name = f_input;
- p->f_firsts = 0;
- pfile = p;
- torder = -1;
- norder = -1;
- LLparse();
- p->f_nonterminals = norder;
- p->f_terminals = torder;
- }
- /* VARARGS1 */
- void error(int lineno, char *s, char *t, char *u) {
- /*
- * Just an error message
- */
- ++nerrors;
- if (!lineno) lineno = 1;
- fprintf(stderr,"\"%s\", line %d: ",f_input, lineno);
- fprintf(stderr,s,t,u);
- fputs("\n",stderr);
- }
- /* VARARGS1 */
- void warning(int lineno, char *s, char *t, char *u) {
- /*
- * Just a warning
- */
- if (wflag) return;
- if (!lineno) lineno = 1;
- fprintf(stderr,"\"%s\", line %d: (Warning) ",f_input, lineno);
- fprintf(stderr,s,t,u);
- fputs("\n",stderr);
- }
- /* VARARGS1 */
- void fatal(int lineno, char *s, char *t, char *u) {
- /*
- * Fatal error
- */
- error(lineno,s,t,u);
- comfatal();
- }
- void comfatal(void) {
- /*
- * Some common code for exit on errors
- */
- if (fact != NULL) {
- fclose(fact);
- UNLINK(f_temp);
- }
- if (fpars != NULL) fclose(fpars);
- UNLINK(f_pars);
- exit(1);
- }
- void copyfile(char *file) {
- /*
- * Copies a file indicated by the parameter to filedescriptor fpars.
- */
- register int c;
- register FILE *f;
- if ((f = fopen(file,"r")) == NULL) {
- fatal(0,"Cannot open library file %s, call an expert",file, NULL);
- }
- while ((c = getc(f)) != EOF) putc(c,fpars);
- fclose(f);
- }
- void install(char *target, char *source) {
- /*
- * Copy the temporary file generated from source to target
- * if allowed (which means that the target must be generated
- * by LLgen from the source, or that the target is not present
- */
- register int c1, c2;
- register FILE *f1, *f2;
- int cnt;
- /*
- * First open temporary, generated for source
- */
- if ((f1 = fopen(f_pars,"r")) == NULL) {
- fatal(0,e_noopen,f_pars, NULL);
- }
- /*
- * Now open target for reading
- */
- if ((f2 = fopen(target,"r")) == NULL) {
- fclose(f1);
- RENAME(f_pars, target);
- return;
- }
- /*
- * Compute length of LLgen identification string. The target must
- * start with that!
- */
- cnt = strlen(LLgenid) + strlen(source) - 2;
- /*
- * Now compare the target with the temporary
- */
- do {
- c1 = getc(f1);
- c2 = getc(f2);
- if (cnt >= 0) cnt--;
- } while (c1 == c2 && c1 != EOF);
- fclose(f1);
- fclose(f2);
- /*
- * Here, if c1 != c2 the target must be recreated
- */
- if (c1 != c2) {
- if (cnt >= 0) {
- fatal(0,"%s : not a file generated by LLgen",target, NULL);
- }
- RENAME(f_pars,target);
- }
- }
|