produce ANSI C under -a option
This commit is contained in:
@@ -29,6 +29,7 @@ static string rcsid = "$Header$";
|
||||
p_mem alloc(), ralloc();
|
||||
string store();
|
||||
p_gram search();
|
||||
long ftell();
|
||||
|
||||
static int nparams; /* parameter count for nonterminals */
|
||||
static int acount; /* count #of global actions */
|
||||
@@ -211,6 +212,7 @@ rule { register p_nont p;
|
||||
p->n_count = acount;
|
||||
acount = 0;
|
||||
p->n_lineno = linecount;
|
||||
p->n_off = ftell(fact);
|
||||
}
|
||||
[ params { p->n_flags |= PARAMS;
|
||||
if (nparams > 15) {
|
||||
|
||||
@@ -131,19 +131,48 @@ do_compute() {
|
||||
STATIC
|
||||
createsets() {
|
||||
/*
|
||||
* Allocate space for the sets
|
||||
* Allocate space for the sets. Also determine which files use
|
||||
* which nonterminals, and determine which nonterminals can be
|
||||
* made static.
|
||||
*/
|
||||
register p_nont p;
|
||||
register p_file f;
|
||||
register p_start st;
|
||||
register int i;
|
||||
int n = NINTS(NBYTES(nnonterms));
|
||||
p_mem alloc();
|
||||
|
||||
for (p = nonterms; p < maxnt; p++) {
|
||||
p->n_first = get_set();
|
||||
p->n_follow = get_set();
|
||||
walk(p->n_rule);
|
||||
for (f = files; f < maxfiles; f++) {
|
||||
register p_set s;
|
||||
f->f_used = s = (p_set) alloc((unsigned)n*sizeof(*(f->f_used)));
|
||||
for (i = n; i; i--) *s++ = 0;
|
||||
for (i = f->f_nonterminals; i != -1; i = p->n_next) {
|
||||
p = &nonterms[i];
|
||||
p->n_flags |= GENSTATIC;
|
||||
p->n_first = get_set();
|
||||
p->n_follow = get_set();
|
||||
walk(f->f_used, p->n_rule);
|
||||
}
|
||||
}
|
||||
for (f = files; f < maxfiles; f++) {
|
||||
for (i = f->f_nonterminals; i != -1; i = p->n_next) {
|
||||
register p_file f2;
|
||||
|
||||
p = &nonterms[i];
|
||||
for (f2 = files; f2 < maxfiles; f2++) {
|
||||
if (f2 != f && IN(f2->f_used, i)) {
|
||||
p->n_flags &= ~GENSTATIC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (st = start; st; st = st->ff_next) {
|
||||
nonterms[st->ff_nont].n_flags &= ~GENSTATIC;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
walk(p) register p_gram p; {
|
||||
walk(u, p) p_set u; register p_gram p; {
|
||||
/*
|
||||
* Walk through the grammar rule p, allocating sets
|
||||
*/
|
||||
@@ -156,7 +185,7 @@ walk(p) register p_gram p; {
|
||||
q = g_getterm(p);
|
||||
q->t_first = get_set();
|
||||
q->t_follow = get_set();
|
||||
walk(q->t_rule);
|
||||
walk(u, q->t_rule);
|
||||
break; }
|
||||
case ALTERNATION : {
|
||||
register p_link l;
|
||||
@@ -164,7 +193,12 @@ walk(p) register p_gram p; {
|
||||
l = g_getlink(p);
|
||||
l->l_symbs = get_set();
|
||||
l->l_others = get_set();
|
||||
walk(l->l_rule);
|
||||
walk(u, l->l_rule);
|
||||
break; }
|
||||
case NONTERM : {
|
||||
register int i = g_getcont(p);
|
||||
|
||||
PUTIN(u, i);
|
||||
break; }
|
||||
case EORULE :
|
||||
return;
|
||||
|
||||
@@ -75,3 +75,4 @@ extern string rec_file, incl_file;
|
||||
extern int low_percentage, high_percentage;
|
||||
extern int min_cases_for_jmptable;
|
||||
extern int jmptable_option;
|
||||
extern int ansi_c;
|
||||
|
||||
@@ -56,6 +56,8 @@ STATIC prset();
|
||||
STATIC macro();
|
||||
STATIC controlline();
|
||||
STATIC getparams();
|
||||
STATIC getansiparams();
|
||||
STATIC genprototypes();
|
||||
STATIC gettok();
|
||||
STATIC rulecode();
|
||||
STATIC int * dopush();
|
||||
@@ -113,6 +115,8 @@ gencode(argc) {
|
||||
opentemp(f_input);
|
||||
correct_prefix();
|
||||
/* generate code ... */
|
||||
if (ansi_c) fputs("#define LL_ANSI_C 1\n", fpars);
|
||||
fprintf(fpars, "#define LL_LEXI %s\n", lexical);
|
||||
copyfile(incl_file);
|
||||
generate(p);
|
||||
getaction(2);
|
||||
@@ -123,6 +127,7 @@ gencode(argc) {
|
||||
}
|
||||
geninclude();
|
||||
genrecovery();
|
||||
fclose(fact);
|
||||
}
|
||||
|
||||
STATIC
|
||||
@@ -165,8 +170,10 @@ genrecovery() {
|
||||
opentemp((string) 0);
|
||||
f = fpars;
|
||||
correct_prefix();
|
||||
copyfile(incl_file);
|
||||
if (!firsts) fputs("#define LLNOFIRSTS\n", f);
|
||||
if (ansi_c) fputs("#define LL_ANSI_C 1\n", f);
|
||||
fprintf(f, "#define LL_LEXI %s\n", lexical);
|
||||
copyfile(incl_file);
|
||||
for (st = start; st; st = st->ff_next) {
|
||||
/* Make sure that every set the parser needs is in the list
|
||||
* before generating a define of the number of them!
|
||||
@@ -178,17 +185,23 @@ genrecovery() {
|
||||
}
|
||||
i = maxptr - setptr;
|
||||
fprintf(f,
|
||||
"#define LL_LEXI %s\n#define LL_SSIZE %d\n#define LL_NSETS %d\n#define LL_NTERMINALS %d\n",
|
||||
lexical,
|
||||
"#define LL_SSIZE %d\n#define LL_NSETS %d\n#define LL_NTERMINALS %d\n",
|
||||
nbytes,
|
||||
i > 0 ? i : 1,
|
||||
ntokens);
|
||||
if (onerror) fprintf(f,"#define LL_USERHOOK %s\n", onerror);
|
||||
/* Now generate the routines that call the startsymbols */
|
||||
for (st = start; st; st = st->ff_next) {
|
||||
fputs(st->ff_name, f);
|
||||
if (ansi_c) for (st = start; st; st = st->ff_next) {
|
||||
p = &nonterms[st->ff_nont];
|
||||
fputs("() {\n\tunsigned int s[LL_NTERMINALS+LL_NSETS+2];\n\tLLnewlevel(s);\n\tLLread();\n", f);
|
||||
fputs("void ", f);
|
||||
genextname(st->ff_nont, p->n_name, f);
|
||||
fputs("(void);\n", f);
|
||||
}
|
||||
for (st = start; st; st = st->ff_next) {
|
||||
if (ansi_c) fputs("void ", f);
|
||||
fprintf(f, "%s(%s)", st->ff_name, ansi_c ? "void" : "");
|
||||
p = &nonterms[st->ff_nont];
|
||||
fputs(" {\n\tunsigned int s[LL_NTERMINALS+LL_NSETS+2];\n\tLLnewlevel(s);\n\tLLread();\n", f);
|
||||
if (g_gettype(p->n_rule) == ALTERNATION) {
|
||||
genpush(findindex(p->n_contains));
|
||||
}
|
||||
@@ -238,6 +251,7 @@ generate(f) p_file f; {
|
||||
int i;
|
||||
register p_first ff;
|
||||
int mustpop;
|
||||
int is_first = 1;
|
||||
|
||||
fprintf(fpars, "#define LL_LEXI %s\n", lexical);
|
||||
listcount = 0;
|
||||
@@ -258,13 +272,18 @@ generate(f) p_file f; {
|
||||
getntparams(p) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (is_first) genprototypes(f);
|
||||
is_first = 0;
|
||||
if (p->n_flags & GENSTATIC) fputs("static ", fpars);
|
||||
if (ansi_c) fputs("void ", fpars);
|
||||
genextname(s, p->n_name, fpars);
|
||||
if (p->n_flags & PARAMS) {
|
||||
fputs("(\n", fpars);
|
||||
controlline();
|
||||
getparams();
|
||||
if (ansi_c) getansiparams(1);
|
||||
else getparams();
|
||||
}
|
||||
else fputs("() {\n", fpars);
|
||||
else fprintf(fpars, "(%s) {\n", ansi_c ? "void" : "");
|
||||
if (p->n_flags & LOCALS) getaction(1);
|
||||
i = getntsafe(p);
|
||||
mustpop = NOPOP;
|
||||
@@ -380,6 +399,71 @@ getparams() {
|
||||
fprintf(fpars, "%c {\n",add_semi);
|
||||
}
|
||||
|
||||
STATIC
|
||||
genprototypes(f)
|
||||
register p_file f;
|
||||
{
|
||||
/*
|
||||
* Generate prototypes for all nonterminals
|
||||
*/
|
||||
register int i;
|
||||
register p_nont p;
|
||||
long off = ftell(fact);
|
||||
|
||||
for (i = 0; i < nnonterms; i++) {
|
||||
if (! IN(f->f_used, i)) continue;
|
||||
p = &nonterms[i];
|
||||
if (g_gettype(p->n_rule) == EORULE &&
|
||||
getntparams(p) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (ansi_c || (p->n_flags & GENSTATIC)) {
|
||||
if (p->n_flags & GENSTATIC) fputs("static ", fpars);
|
||||
if (ansi_c) fputs("void ", fpars);
|
||||
genextname(i, p->n_name, fpars);
|
||||
if (! ansi_c) fputs("();\n", fpars);
|
||||
else if (p->n_flags & PARAMS) {
|
||||
fputs("(\n", fpars);
|
||||
fseek(fact, p->n_off, 0);
|
||||
controlline();
|
||||
getansiparams(0);
|
||||
fseek(fact, off, 0);
|
||||
}
|
||||
else fputs("(void);\n", fpars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
getansiparams(mkdef) {
|
||||
/* getansiparams is called if a nonterminal has parameters
|
||||
* and an ANSI C function definition/declaration has to be produced.
|
||||
* If a definition has to be produced, "mkdef" is set to 1.
|
||||
*/
|
||||
register int l;
|
||||
char add_semi = ' ';
|
||||
int delayed = 0;
|
||||
|
||||
ltext[0] = '\0';
|
||||
while ((l = gettok()) != ENDDECL) {
|
||||
if (delayed) {
|
||||
fputc(',', fpars);
|
||||
delayed = 0;
|
||||
}
|
||||
if ((l == ';' || l == ',') && ltext[0] != '\0') {
|
||||
/*
|
||||
* The last identifier found before a ';' or a ','
|
||||
* must be a parameter
|
||||
*/
|
||||
delayed = 1;
|
||||
ltext[0] = '\0';
|
||||
}
|
||||
else if (l == IDENT) fprintf(fpars, "%s", ltext);
|
||||
else fputc(l, fpars);
|
||||
}
|
||||
fprintf(fpars, ") %c\n", mkdef ? '{' : ';');
|
||||
}
|
||||
|
||||
STATIC
|
||||
gettok() {
|
||||
/* Read from the action file. */
|
||||
|
||||
@@ -66,3 +66,4 @@ string rec_file, incl_file;
|
||||
int low_percentage = 10, high_percentage = 30;
|
||||
int min_cases_for_jmptable = 8;
|
||||
int jmptable_option;
|
||||
int ansi_c = 0;
|
||||
|
||||
@@ -100,6 +100,10 @@ main(argc,argv) register string argv[]; {
|
||||
ntneeded = 1;
|
||||
ntprint = 1;
|
||||
continue;
|
||||
case 'a':
|
||||
case 'A':
|
||||
ansi_c = 1;
|
||||
continue;
|
||||
default:
|
||||
fprintf(stderr,"illegal option : %c\n",*arg);
|
||||
exit(1);
|
||||
|
||||
@@ -105,6 +105,7 @@ typedef struct {
|
||||
*/
|
||||
# define getntparams(p) ((p)->n_flags&017)
|
||||
# define setntparams(p,i) {assert(((unsigned)(i))<=017);(p)->n_flags&=~017;(p)->n_flags|=(i);}
|
||||
# define GENSTATIC 01000 /* set if routine can be made static */
|
||||
# define RECURSIVE 02000 /* Set if the default rule is recursive */
|
||||
# define PARAMS 04000 /* tells if a nonterminal has parameters */
|
||||
# define EMPTY 010000 /* tells if a nonterminal produces empty */
|
||||
@@ -133,6 +134,7 @@ typedef struct {
|
||||
p_set n_contains; /* pointer to symbols that can be produced */
|
||||
string n_name; /* name of nonterminal */
|
||||
int n_next; /* index of next nonterminal */
|
||||
long n_off; /* index of parameters in action file */
|
||||
} t_nont, *p_nont;
|
||||
|
||||
/*
|
||||
@@ -225,6 +227,7 @@ typedef struct f_file {
|
||||
*/
|
||||
int f_nonterminals; /* list of nonterminals in this file */
|
||||
int f_terminals; /* list of terminals in this file */
|
||||
p_set f_used; /* set of nonterminals used in this file */
|
||||
} t_file, *p_file;
|
||||
|
||||
typedef struct info_alloc {
|
||||
|
||||
Reference in New Issue
Block a user