produce ANSI C under -a option
authorceriel <none@none>
Tue, 26 Nov 1991 15:38:41 +0000 (15:38 +0000)
committerceriel <none@none>
Tue, 26 Nov 1991 15:38:41 +0000 (15:38 +0000)
util/LLgen/LLgen.1
util/LLgen/lib/incl
util/LLgen/lib/rec
util/LLgen/src/LLgen.g
util/LLgen/src/compute.c
util/LLgen/src/extern.h
util/LLgen/src/gencode.c
util/LLgen/src/global.c
util/LLgen/src/main.c
util/LLgen/src/types.h

index 3a44d30..8f9e94d 100644 (file)
@@ -4,7 +4,7 @@
 .SH NAME
 LLgen, an extended LL(1) parser generator
 .SH SYNOPSIS
-LLgen [ \-vxw ] [ \-j[\fInum\fP] ] [ \-l\fInum\fP ] [ \-h\fInum\fP ] file ...
+LLgen [ \-vxwa ] [ \-j[\fInum\fP] ] [ \-l\fInum\fP ] [ \-h\fInum\fP ] file ...
 .SH DESCRIPTION
 \fILLgen\fP
 converts a context-free grammar into a set of
@@ -76,6 +76,8 @@ symbols and these extended sets are also included in the
 file.
 .IP \fB\-w\fP
 no warnings are given.
+.IP \fB\-a\fP
+Produce ANSI C function headers and prototypes.
 .IP \fB\-j\fP[\fInum\fP]
 when this flag is given, \fILLgen\fP will generate dense switches,
 so that the compiler can generate a jump table for it. This will only be
index 793bc1d..6360260 100644 (file)
@@ -25,3 +25,32 @@ extern int LLcsymb;
 #define LLtdecr(d)     {LL_assert(LLtcnt[d] > 0); LLtcnt[d]--;}
 #define LLsincr(d)     LLscnt[d]++
 #define LLtincr(d)     LLtcnt[d]++
+
+#if LL_ANSI_C
+extern int LL_LEXI(void);
+extern void LLread(void);
+extern int LLskip(void);
+extern int LLnext(int);
+extern void LLerror(int);
+extern void LLnewlevel(unsigned int *);
+extern void LLoldlevel(unsigned int *);
+#ifndef LL_FASTER
+extern void LLscan(int);
+#endif
+#ifndef LLNOFIRSTS
+extern int LLfirst(int, int);
+#endif
+#else /* not LL_ANSI_C */
+extern LLread();
+extern int LLskip();
+extern int LLnext();
+extern LLerror();
+extern LLnewlevel();
+extern LLoldlevel();
+#ifndef LL_FASTER
+extern LLscan();
+#endif
+#ifndef LLNOFIRSTS
+extern int LLfirst();
+#endif
+#endif /* not LL_ANSI_C */
index 109c99f..5a23082 100644 (file)
@@ -3,37 +3,35 @@
  * This file is copied into Lpars.c.
  */
 
-# ifndef lint
+#ifndef lint
 static char *rcsid = "$Header$";
-# endif
+#endif
 
 unsigned int   LLtcnt[LL_NTERMINALS];
 unsigned int   LLscnt[LL_NSETS];
 int            LLcsymb, LLsymb;
 static int     LLlevel;
 
-/* In this file are defined: */
-extern         LLread();
-extern int     LLskip();
-extern int     LLnext();
-#ifndef LL_FASTER
-extern         LLscan();
+#if LL_ANSI_C
+void   LLmessage(int);
 #endif
-extern         LLerror();
-# ifndef LLNOFIRSTS
-extern int     LLfirst();
-# endif
-extern         LLnewlevel();
-extern         LLoldlevel();
-
 #ifdef LL_USERHOOK
+#if LL_ANSI_C
+static void    LLdoskip(int);
+static int     LLuserhook(int, int*);
+#else
 static         LLdoskip();
 static int     LLuserhook();
 #endif
+#endif
 
 #ifndef LL_FASTER
+#if LL_ANSI_C
+void LLscan(int t)
+#else
 LLscan(t)
        int     t;
+#endif
 {
        /*
         * Check if the next symbol is equal to the parameter
@@ -48,7 +46,11 @@ LLscan(t)
 }
 #endif
 
+#if LL_ANSI_C
+void LLread(void) {
+#else
 LLread() {
+#endif
        for (;;) {
                if ((LLcsymb = LLindex[(LLsymb = LL_LEXI())]) >= 0) return;
                LLmessage(0);
@@ -56,8 +58,12 @@ LLread() {
        /* NOTREACHED */
 }
 
+#if LL_ANSI_C
+void LLerror(int t)
+#else
 LLerror(t)
        int     t;
+#endif
 {
        register int i;
 
@@ -67,7 +73,7 @@ LLerror(t)
 #ifdef LL_USERHOOK
                static int lst[] = { EOFILE, 0 };
                if (LLuserhook(EOFILE, lst)) /* nothing */;
-#endif LL_USERHOOK
+#endif /* LL_USERHOOK */
                if (LLsymb != EOFILE && LLsymb > 0) {
                        LLmessage(-1);
                        while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE) 
@@ -91,17 +97,25 @@ LLerror(t)
        if (LLsymb != t) LLmessage(t);
 }
 
-# ifndef LLNOFIRSTS
-LLfirst(x, d) {
+#ifndef LLNOFIRSTS
+#if LL_ANSI_C
+int LLfirst(int x, int d) {
+#else
+int LLfirst(x, d) {
+#endif
        register int i;
 
        return (i = LLindex[x]) >= 0 &&
                (LLsets[d + (i >> 3)] & (1 << (i & 07)));
 }
-# endif
+#endif
 
-LLnext(n)
+#if LL_ANSI_C
+int LLnext(int n)
+#else
+int LLnext(n)
        int     n;
+#endif
 {
        /*      returns: 0 if the current symbol is'nt skipped, and it
                         is'nt a member of "n",
@@ -122,7 +136,11 @@ LLnext(n)
        return retval;
 }
 
-LLskip() {
+#if LL_ANSI_C
+int LLskip(void) {
+#else
+int LLskip() {
+#endif
        /*      returns 0 if the current symbol is'nt skipped, and
                1 if it is, t.i., we have a new symbol
        */
@@ -130,20 +148,27 @@ LLskip() {
        return LLdoskip(0);
 }
 
-static int
-LLuserhook(exp, list)
-       int exp;
+#if LL_ANSI_C
+extern void LL_USERHOOK(int, int *);
+static int LLuserhook(int e, int *list)
+#else
+static int LLuserhook(e, list)
+       int e;
        int *list;
+#endif
 {
        int old = LLsymb;
-       LL_USERHOOK(exp, list);
+       LL_USERHOOK(e, list);
        LLread();
        return LLsymb != old;
 }
 
-static
-LLmklist(list)
+#if LL_ANSI_C
+static void LLmklist(register int *list)
+#else
+static LLmklist(list)
        register int *list;
+#endif
 {
        char Xset[LL_SSIZE];
        register char *p;
@@ -167,13 +192,16 @@ LLmklist(list)
        *list = 0;
 }
 
-static
-LLdoskip(exp)
-       int     exp;
+#if LL_ANSI_C
+static int LLdoskip(int e)
+#else
+static int LLdoskip(e)
+       int     e;
+#endif
 {
        int LLx;
        int list[LL_NTERMINALS+1];
-#endif LL_USERHOOK
+#endif /* LL_USERHOOK */
        register int i;
        int retval;
        int LLi, LLb;
@@ -181,13 +209,13 @@ LLdoskip(exp)
        retval = 0;
 #ifdef LL_USERHOOK
        LLmklist(list);
-       LLx = LLuserhook(exp, list);
+       LLx = LLuserhook(e, list);
        if (LLx) retval = 1;
-#endif LL_USERHOOK
+#endif /* LL_USERHOOK */
        for (;;) {
                if (LLtcnt[LLcsymb] != 0) {
 #ifdef LL_USERHOOK
-                       if (!exp || !LLx || LLcsymb == LLindex[exp])
+                       if (!e || !LLx || LLcsymb == LLindex[e])
 #endif
                        return retval;
                }
@@ -197,7 +225,7 @@ LLdoskip(exp)
                        if (LLscnt[i] != 0) {
                                if (LLsets[LL_SSIZE*i+LLi] & LLb) {
 #ifdef LL_USERHOOK
-                                       if (!exp || !LLx || LLcsymb == LLindex[exp])
+                                       if (!e || !LLx || LLcsymb == LLindex[e])
 #endif
                                        return retval;
                                }
@@ -205,10 +233,10 @@ LLdoskip(exp)
                }
 #ifdef LL_USERHOOK
                if (LLx) {
-                       LLx = LLuserhook(exp, list);
+                       LLx = LLuserhook(e, list);
                        continue;
                }
-#endif LL_USERHOOK
+#endif /* LL_USERHOOK */
                LLmessage(0);
                retval = 1;
                LLread();
@@ -216,7 +244,11 @@ LLdoskip(exp)
        /* NOTREACHED */
 }
 
+#if LL_ANSI_C
+void LLnewlevel(unsigned int *LLsinfo) {
+#else
 LLnewlevel(LLsinfo) unsigned int *LLsinfo; {
+#endif
        register int i;
 
        if (LLlevel++) {
@@ -234,16 +266,18 @@ LLnewlevel(LLsinfo) unsigned int *LLsinfo; {
        LLtincr(0);
 }
 
-LLoldlevel(LLsinfo)
-       unsigned int *LLsinfo;
-{
+#if LL_ANSI_C
+void LLoldlevel(unsigned int *LLsinfo) {
+#else
+LLoldlevel(LLsinfo) unsigned int *LLsinfo; {
+#endif
        register int i;
 
        LLtdecr(0);
-# ifdef LL_DEBUG
+#ifdef LL_DEBUG
        for (i = 0; i < LL_NTERMINALS; i++) LL_assert(LLtcnt[i] == 0);
        for (i = 0; i < LL_NSETS; i++) LL_assert(LLscnt[i] == 0);
-# endif
+#endif
        if (--LLlevel) {
                for (i = LL_NSETS - 1; i >= 0; i--) {
                        LLscnt[i] = LLsinfo[LL_NTERMINALS+i];
index 07c392a..3ab9807 100644 (file)
@@ -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) {
index 272dfcb..cde5d77 100644 (file)
@@ -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;
index 8bcf9c6..13aed5b 100644 (file)
@@ -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;
index 9ed83cc..c3e6248 100644 (file)
@@ -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 */
+       if (ansi_c) for (st = start; st; st = st->ff_next) {
+               p = &nonterms[st->ff_nont];
+               fputs("void ", f);
+               genextname(st->ff_nont, p->n_name, f);
+               fputs("(void);\n", f);
+       }
        for (st = start; st; st = st->ff_next) {
-               fputs(st->ff_name, f);
+               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);
+               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. */
index ac05236..66f2932 100644 (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;
index 584842c..eb49ccb 100644 (file)
@@ -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);
index 931765f..69d286b 100644 (file)
@@ -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 {