ack/util/LLgen/src/main.c
George Koehler 33c0573598 Remove code to calculate memory usage with sbrk().
In many systems, malloc() can allocate outside the brk area.  The
calculation with sbrk() misses those allocations.  When LLgen or ncgg
reported the memory usage, the value was probably too low.
2018-11-14 16:13:54 -05:00

374 lines
7 KiB
C

/* 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 <stdlib.h>
#include <string.h>
# include "types.h"
# include "io.h"
# include "extern.h"
# include "sets.h"
# include "assert.h"
# ifndef NORCSID
static string rcsid6 = "$Id$";
# endif
/* In this file the following routines are defined: */
extern int main();
STATIC readgrammar();
STATIC doparse();
extern error();
extern fatal();
extern comfatal();
extern copyfile();
extern void install();
main(argc,argv) register string argv[]; {
register string arg;
string libpath();
/* 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--;
}
#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
close(mkstemp(f_temp));
close(mkstemp(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);
}
exit(0);
}
STATIC
readgrammar(argc,argv) 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);
}
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");
}
if (nerrors) comfatal();
}
STATIC
doparse(p) register 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 */
error(lineno,s,t,u) string s,t,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(lineno,s,t,u) string s,t,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 */
fatal(lineno,s,t,u) string s,t,u; {
/*
* Fatal error
*/
error(lineno,s,t,u);
comfatal();
}
comfatal() {
/*
* 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);
}
copyfile(file) string 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);
}
while ((c = getc(f)) != EOF) putc(c,fpars);
fclose(f);
}
void
install(target, source) string target, 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);
}
/*
* 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);
}
RENAME(f_pars,target);
}
}