1 /* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
2 * For full copyright and restrictions on use see the file COPYING in the top
3 * level of the LLgen tree.
9 * An Extended LL(1) Parser Generator
11 * Author : Ceriel J.H. Jacobs
16 * Contains main program, and some error message routines
26 static string rcsid6 = "$Id: main.c,v 2.26 2002/09/11 13:32:57 ceriel Exp $";
29 /* In this file the following routines are defined: */
38 extern char *mktemp();
41 main(argc,argv) register string argv[]; {
51 while (argc >= 2 && (arg = argv[1], *arg == '-')) {
58 min_cases_for_jmptable = atoi(arg);
70 low_percentage = atoi(++arg);
74 high_percentage = atoi(++arg);
84 fprintf(stderr,"duplicate -r flag\n");
92 fprintf(stderr,"duplicate -i flag\n");
97 #endif /* not NDEBUG */
107 #ifdef NON_CORRECTING
122 fprintf(stderr,"illegal option : %c\n",*arg);
131 if (verbose) beg_sbrk = sbrk(0);
133 #ifdef NON_CORRECTING
134 if ((subpars_sim) && (!non_corr)) {
135 fprintf(stderr,"option -s illegal without -n, turned off\n");
141 * Now check wether the sets should include nonterminals
143 if (verbose == 2) ntneeded = 1;
150 rec_file = libpath("rec");
155 incl_file = libpath("incl");
159 #ifdef NON_CORRECTING
161 nc_incl_file = libpath("nc_incl");
162 nc_rec_file = libpath ("nc_rec");
167 if ((fact = fopen(f_temp,"w")) == NULL) {
168 fputs("Cannot create temporary\n",stderr);
172 readgrammar(argc,argv);
173 sprintf(f_out, OUTFILE, prefix ? prefix : "LL");
175 /* for the following two filenames only one L is used; historical
178 sprintf(f_include, HFILE, prefix ? prefix : "L");
179 sprintf(f_rec, RFILE, prefix ? prefix : "L");
180 #ifdef NON_CORRECTING
182 sprintf(f_nc, NCFILE, prefix ? prefix : "L");
185 maxnt = &nonterms[nnonterms];
186 maxt = &tokens[ntokens];
188 * Now, the grammar is read. Do some computations
190 co_reach(); /* Check for undefined and unreachable */
191 if (nerrors) comfatal();
194 if (nerrors) comfatal();
197 fputs("No code generation for input from standard input\n",
204 fprintf(stderr, "number of nonterminals: %d\n", nnonterms);
205 fprintf(stderr, "number of tokens: %d\n", ntokens);
206 fprintf(stderr, "number of term structures: %d\n", nterms);
207 fprintf(stderr, "number of alternation structures: %d\n", nalts);
208 fprintf(stderr, "total memory used: %ld\n", (long)(sbrk(0) - beg_sbrk));
214 readgrammar(argc,argv) char *argv[]; {
216 * Do just what the name suggests : read the grammar
222 f_input = "no filename";
224 * Build the file structure
226 files = p = (p_file) alloc((unsigned) (argc+1) * sizeof(t_file));
229 f_input = "standard input";
233 if ((finput = fopen(f_input=argv[1],"r")) == NULL) {
234 fatal(0,e_noopen,f_input);
242 if (! lexical) lexical = "yylex";
244 * There must be a start symbol!
246 if (! nerrors && start == 0) {
247 fatal(linecount,"Missing %%start");
249 if (nerrors) comfatal();
253 doparse(p) register p_file p; {
262 p->f_nonterminals = norder;
263 p->f_terminals = torder;
267 error(lineno,s,t,u) string s,t,u; {
269 * Just an error message
273 if (!lineno) lineno = 1;
274 fprintf(stderr,"\"%s\", line %d: ",f_input, lineno);
275 fprintf(stderr,s,t,u);
280 warning(lineno,s,t,u) string s,t,u; {
286 if (!lineno) lineno = 1;
287 fprintf(stderr,"\"%s\", line %d: (Warning) ",f_input, lineno);
288 fprintf(stderr,s,t,u);
293 fatal(lineno,s,t,u) string s,t,u; {
303 * Some common code for exit on errors
309 if (fpars != NULL) fclose(fpars);
314 copyfile(file) string file; {
316 * Copies a file indicated by the parameter to filedescriptor fpars.
321 if ((f = fopen(file,"r")) == NULL) {
322 fatal(0,"Cannot open library file %s, call an expert",file);
324 while ((c = getc(f)) != EOF) putc(c,fpars);
328 install(target, source) string target, source; {
330 * Copy the temporary file generated from source to target
331 * if allowed (which means that the target must be generated
332 * by LLgen from the source, or that the target is not present
335 register FILE *f1, *f2;
339 * First open temporary, generated for source
341 if ((f1 = fopen(f_pars,"r")) == NULL) {
342 fatal(0,e_noopen,f_pars);
345 * Now open target for reading
347 if ((f2 = fopen(target,"r")) == NULL) {
349 RENAME(f_pars, target);
353 * Compute length of LLgen identification string. The target must
356 cnt = strlen(LLgenid) + strlen(source) - 2;
358 * Now compare the target with the temporary
364 } while (c1 == c2 && c1 != EOF);
368 * Here, if c1 != c2 the target must be recreated
372 fatal(0,"%s : not a file generated by LLgen",target);
374 RENAME(f_pars,target);