diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 24052d3c6..38d40c7cf 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -54,7 +54,7 @@ jobs: run: | make ack-setup.exe - name: upload setup - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: ${{ github.event.repository.name }}.${{ github.sha }} path: ack-setup.exe diff --git a/lang/cem/cpp.ansi/LLlex.c b/lang/cem/cpp.ansi/LLlex.c index 583db777b..400024992 100644 --- a/lang/cem/cpp.ansi/LLlex.c +++ b/lang/cem/cpp.ansi/LLlex.c @@ -7,6 +7,8 @@ #include "parameters.h" +#include +#include #include #include #include "input.h" @@ -19,8 +21,9 @@ #include "class.h" #include "error.h" #include "bits.h" +#include "domacro.h" -#define BUFSIZ 1024 +#define BUFFERSIZE 1024 struct token dot; @@ -32,20 +35,17 @@ int AccFileSpecifier = 0; /* return filespecifier <...> */ int LexSave = 0; /* last character read by GetChar */ extern int InputLevel; /* # of current macro expansions */ - #define FLG_ESEEN 0x01 /* possibly a floating point number */ #define FLG_DOTSEEN 0x02 /* certainly a floating point number */ - /* Private forward definitions */ static arith char_constant(char*); -static char* string_token(char *, int); +static char* string_token(char*, int); static int quoted(register int); static int val_in_base(register int, int); static int trigraph(void); - int LLlex(void) { return (DOT != EOF) ? GetToken(&dot) : EOF; @@ -58,7 +58,7 @@ int GetToken(register struct token* ptok) combination. Macro replacement is also performed if it is needed. */ - char buf[BUFSIZ]; + char buf[BUFFERSIZE]; register int ch, nch; again: /* rescan the input after an error or replacement */ @@ -433,9 +433,10 @@ void skiplinecomment(void) { /* The last character read has been the '/' of '//'. We read and discard all characters up to but not including the next - NL. */ - - for (;;) { + NL. */ + + for (;;) + { int c = GetChar(); if ((class(c) == STNL) || (c == EOI)) { @@ -479,7 +480,7 @@ static arith char_constant(char* nm) return val; } -static char* string_token(char *nm, int stop_char) +static char* string_token(char* nm, int stop_char) { register int ch; register int str_size; @@ -597,9 +598,32 @@ int GetChar(void) sequences and removes occurences of \\\n. */ register int ch; + static bool atnewline = true; again: LoadChar(ch); + if (ch == EOI) + { + if (!atnewline) + { + PushBack(); + ch = '\n'; + } + else + { + if (nestcount > 0) + { + nestlevel = svnestlevel[nestcount--]; + goto again; + } + + if (nestlevel > svnestlevel[nestcount]) + warning("missing #endif"); + else if (NoUnstack) + warning("unexpected EOF"); + } + } + atnewline = (ch == '\n'); /* possible trigraph sequence */ if (ch == '?') diff --git a/lang/cem/cpp.ansi/domacro.c b/lang/cem/cpp.ansi/domacro.c index b382a0c60..ddca0d58d 100644 --- a/lang/cem/cpp.ansi/domacro.c +++ b/lang/cem/cpp.ansi/domacro.c @@ -39,7 +39,6 @@ extern int do_preprocess; /* Internal declarations */ - static void do_define(void); static void do_elif(void); static void do_else(void); @@ -49,21 +48,20 @@ static void do_if(void); static void do_ifdef(int); static void do_include(void); static void do_line(unsigned int); -static int find_name(char* , char* []); -static char* get_text(char* [], int* ); -static int getparams(char* [], char []); +static int find_name(char*, char*[]); +static char* get_text(char*[], int*); +static int getparams(char*[], char[]); static int ifexpr(void); -static int macroeq(register char*, register char *); +static int macroeq(register char*, register char*); static void skip_block(int); static void do_error(void); /* External dependencies to C files with no include files */ extern void If_expr(void); -extern void add_dependency(char *); - +extern void add_dependency(char*); char* GetIdentifier(int skiponerr /* skip the rest of the line on error */ - ) +) { /* Returns a pointer to the identifier that is read from the input stream. When the input does not contain an @@ -89,7 +87,6 @@ char* GetIdentifier(int skiponerr /* skip the rest of the line on error */ return tk.tk_str; } - void domacro(void) { struct token tk; /* the token itself */ @@ -346,7 +343,7 @@ static int ifexpr(void) static void do_include(void) { /* do_include() performs the inclusion of a file. - */ + */ char* filenm; char* result; int tok; @@ -390,7 +387,7 @@ static void do_include(void) static void do_define(void) { /* do_define() interprets a #define control line. - */ + */ register char* str; /* the #defined identifier's descriptor */ int nformals = -1; /* keep track of the number of formals */ char* formals[NPARAMS]; /* pointers to the names of the formals */ @@ -505,7 +502,7 @@ static void do_ifdef(int how) register char* str; /* how == 1 : ifdef; how == 0 : ifndef - */ + */ push_if(); if (!(str = GetIdentifier(1))) { @@ -697,7 +694,7 @@ void macro_def(register struct idf* id, char* text, int nformals, int length, in newdef->mc_flag = flags; /* special flags */ } -static int find_name(char* nm, char *index[]) +static int find_name(char* nm, char* index[]) { /* find_name() returns the index of "nm" in the namelist "index" if it can be found there. 0 is returned if it is @@ -888,7 +885,7 @@ static char* get_text(char* formals[], int* length) as strings, without taking care of the leading and trailing blanks (spaces and tabs). */ -static int macroeq(register char* s, register char *t) +static int macroeq(register char* s, register char* t) { /* skip leading spaces */ diff --git a/lang/cem/cpp.ansi/domacro.h b/lang/cem/cpp.ansi/domacro.h index 7bdc7a465..f488f9b00 100644 --- a/lang/cem/cpp.ansi/domacro.h +++ b/lang/cem/cpp.ansi/domacro.h @@ -1,17 +1,17 @@ /* Copyright (c) 2019 ACK Project. - * See the copyright notice in the ACK home directory, + * See the copyright notice in the ACK home directory, * in the file "Copyright". * * Created on: 2019-02-09 - * + * */ #ifndef DOMACRO_H_ #define DOMACRO_H_ struct idf; -void macro_def(register struct idf* id, char* text, int nformals, int length, int flags); -void do_undef(char* argstr); +extern void macro_def(register struct idf* id, char* text, int nformals, int length, int flags); +extern void do_undef(char* argstr); /* Control line interpreter. The '#' has already been read by the lexical analyzer by which this function is called. The token appearing directly after the '#' is obtained by calling @@ -21,7 +21,11 @@ void do_undef(char* argstr); Pragma's are handled by do_pragma(). They are passed on to the compiler. */ -void domacro(void); -char* GetIdentifier(int skiponerr); +extern void domacro(void); +extern char* GetIdentifier(int skiponerr); + +extern int nestlevel; +extern int nestcount; +extern int svnestlevel[]; #endif /* DOMACRO_H_ */ diff --git a/lang/cem/cpp.ansi/input.c b/lang/cem/cpp.ansi/input.c index 161f065eb..36a0afba9 100644 --- a/lang/cem/cpp.ansi/input.c +++ b/lang/cem/cpp.ansi/input.c @@ -11,28 +11,30 @@ #include "input.h" #include "error.h" #include "replace.h" +#include "domacro.h" -#define INP_PUSHBACK 3 -#define INP_TYPE struct file_info -#define INP_VAR finfo -struct file_info finfo; +#define INP_NPUSHBACK 3 +#define INP_TYPE struct file_info +#define INP_VAR finfo +struct file_info finfo; #include #include -char *getwdir(register char *fn) +char* getwdir(register char* fn) { - register char *p; - char *strrchr(); + register char* p; p = strrchr(fn, '/'); - while (p && *(p + 1) == '\0') { /* remove trailing /'s */ + while (p && *(p + 1) == '\0') + { /* remove trailing /'s */ *p = '\0'; p = strrchr(fn, '/'); } if (fn[0] == '\0' || (fn[0] == '/' && p == &fn[0])) /* absolute path */ return ""; - if (p) { + if (p) + { *p = '\0'; fn = Salloc(fn, (unsigned)(p - &fn[0] + 1)); *p = '/'; @@ -41,8 +43,8 @@ char *getwdir(register char *fn) return "."; } -int NoUnstack; -int InputLevel; +int NoUnstack; +int InputLevel; int AtEoIT(void) { @@ -54,12 +56,6 @@ int AtEoIT(void) int AtEoIF(void) { - extern int nestlevel; - extern int nestcount; - extern int svnestlevel[]; - - if (nestlevel > svnestlevel[nestcount]) warning("missing #endif"); - else if (NoUnstack) warning("unexpected EOF"); - nestlevel = svnestlevel[nestcount--]; - return 0; + /* Configure inp_pkg to always return EOIs at the end of source files. */ + return 1; } diff --git a/lang/m2/comp/input.c b/lang/m2/comp/input.c index 6402380d0..92c3da00e 100644 --- a/lang/m2/comp/input.c +++ b/lang/m2/comp/input.c @@ -16,6 +16,7 @@ #include "f_info.h" struct f_info file_info; #include "input.h" +#include "error.h" #include diff --git a/lang/pc/comp/input.c b/lang/pc/comp/input.c index 6f8a00d32..a36cdf45a 100644 --- a/lang/pc/comp/input.c +++ b/lang/pc/comp/input.c @@ -9,6 +9,7 @@ struct f_info file_info; #include "input.h" #include #include "idf.h" +#include "error.h" #include diff --git a/modules/src/input/inp_pkg.body b/modules/src/input/inp_pkg.body index 2a025cd52..73575f9db 100644 --- a/modules/src/input/inp_pkg.body +++ b/modules/src/input/inp_pkg.body @@ -89,6 +89,10 @@ struct INP_i_buf { #endif /* not INP_READ_IN_ONE */ +/* Used for the pushback buffer when between input files, where INP_head isn't + * valid. */ +static char INP_pushbackbuf[INP_NPUSHBACK + 1]; + char *_ipp; INP_PRIVATE struct INP_buffer_header *INP_head, *INP_free; @@ -331,6 +335,13 @@ int InsertText(char *text, int length) return 1; } +void INP_pushback(void) +{ + if ((_ipp == INP_head->bh_text) || (_ipp == &INP_pushbackbuf[0])) + fatal("inp underflow\n"); + _ipp--; +} + #define RAWLOAD(dest) \ ((void)((dest = *_ipp++) || (dest = loadbuf()))) @@ -361,7 +372,6 @@ int loadchar(void) int loadbuf(void) { register struct INP_buffer_header *bh = INP_head; - static char buf[INP_NPUSHBACK + 1]; int FromFile; if (!bh) { /* stack exhausted, EOF on sourcefile */ @@ -404,7 +414,7 @@ int loadbuf(void) #if INP_NPUSHBACK > 1 { register char *so = &(bh->bh_text[bh->bh_size]); - register char *de = &buf[INP_NPUSHBACK - 1]; + register char *de = &INP_pushbackbuf[INP_NPUSHBACK - 1]; register int i = INP_NPUSHBACK - 1; if (i >= bh->bh_size) i = bh->bh_size - 1; @@ -414,8 +424,8 @@ int loadbuf(void) } } #endif - buf[INP_NPUSHBACK-1] = 0; /* make PushBack work on EOI */ - _ipp = &buf[INP_NPUSHBACK]; + INP_pushbackbuf[INP_NPUSHBACK-1] = 0; /* make PushBack work on EOI */ + _ipp = &INP_pushbackbuf[INP_NPUSHBACK]; if (bh->bh_fd) { /* unstack a file */ #ifndef INP_READ_IN_ONE @@ -428,7 +438,7 @@ int loadbuf(void) free(bh->bh_text); #endif /* INP_READ_IN_ONE */ } - bh->bh_text = buf; + bh->bh_text = INP_pushbackbuf; bh->bh_size = INP_NPUSHBACK - 1; if (FromFile) { if (AtEoIF()) { @@ -444,7 +454,7 @@ int loadbuf(void) } } - if (bh->bh_eofreturned && _ipp == &buf[INP_NPUSHBACK]) { + if (bh->bh_eofreturned && _ipp == &INP_pushbackbuf[INP_NPUSHBACK]) { return EOI; } @@ -453,6 +463,6 @@ int loadbuf(void) LoadChar(c); return c; } - _ipp = &buf[INP_NPUSHBACK]; + _ipp = &INP_pushbackbuf[INP_NPUSHBACK]; return EOI; } diff --git a/modules/src/input/inp_pkg.spec b/modules/src/input/inp_pkg.spec index 1b12a3f49..e33264e80 100644 --- a/modules/src/input/inp_pkg.spec +++ b/modules/src/input/inp_pkg.spec @@ -21,8 +21,11 @@ /* INPUT PRIMITIVES */ #define LoadChar(dest) (dest = loadchar()) -#define PushBack() (--_ipp) -#define ChPushBack(ch) (*--_ipp = (ch)) + +extern void INP_pushback(void); +#define PushBack INP_pushback + +#define ChPushBack(ch) (INP_pushback(), *_ipp = (ch)) /* EOI may be defined as -1 in most programs but the character -1 may be expanded to the int -1 which causes troubles with indexing. diff --git a/tests/plat/bugs/bug-310-cpp-no-trailing-newline_c.c b/tests/plat/bugs/bug-310-cpp-no-trailing-newline_c.c new file mode 100644 index 000000000..1a771d522 --- /dev/null +++ b/tests/plat/bugs/bug-310-cpp-no-trailing-newline_c.c @@ -0,0 +1,8 @@ +#include "test.h" + +int main(void) { + finished(); +} + +#if 0 +#endif // no trailing newline \ No newline at end of file diff --git a/tests/plat/bugs/build.lua b/tests/plat/bugs/build.lua index 833d0f120..bb0dbdfd0 100644 --- a/tests/plat/bugs/build.lua +++ b/tests/plat/bugs/build.lua @@ -6,6 +6,7 @@ bundle { "./bug-203-ego-sr_c-O3.c", "./bug-22-inn_mod.mod", "./bug-62-notvar_var_e.c", + "./bug-310-cpp-no-trailing-newline_c.c", } } diff --git a/util/LLgen/build.lua b/util/LLgen/build.lua index 8e5bd4ca7..533d10b8e 100644 --- a/util/LLgen/build.lua +++ b/util/LLgen/build.lua @@ -3,7 +3,7 @@ clibrary { hdrs = { "./src/cclass.h", "./src/extern.h", - "./src/io.h", + "./src/fileio.h", "./src/Lpars.h", "./src/sets.h", "./src/types.h", diff --git a/util/LLgen/src/LLgen.c b/util/LLgen/src/LLgen.c index bce39148b..65e98c35a 100644 --- a/util/LLgen/src/LLgen.c +++ b/util/LLgen/src/LLgen.c @@ -56,7 +56,7 @@ extern void LLnc_recover(void); #include #include #include "types.h" -#include "io.h" +#include "fileio.h" #include "extern.h" #include "assert.h" #include "cclass.h" diff --git a/util/LLgen/src/LLgen.g b/util/LLgen/src/LLgen.g index 896e458bd..bd346004d 100644 --- a/util/LLgen/src/LLgen.g +++ b/util/LLgen/src/LLgen.g @@ -21,7 +21,7 @@ #include #include #include "types.h" -#include "io.h" +#include "fileio.h" #include "extern.h" #include "assert.h" #include "cclass.h" diff --git a/util/LLgen/src/check.c b/util/LLgen/src/check.c index 488021c72..ee98f74d9 100644 --- a/util/LLgen/src/check.c +++ b/util/LLgen/src/check.c @@ -19,15 +19,15 @@ #include #include #include -# include "types.h" -# include "extern.h" -# include "io.h" -# include "sets.h" -# include "assert.h" +#include "types.h" +#include "extern.h" +#include "fileio.h" +#include "sets.h" +#include "assert.h" -# ifndef NORCSID +#ifndef NORCSID static string rcsid1 = "$Id$"; -# endif +#endif static string c_first = "> firstset "; static string c_contains = "> containset "; @@ -37,7 +37,7 @@ static int level; /* In this file are defined : */ void conflchecks(void); -STATIC void prline(char *); +STATIC void prline(char*); STATIC void printset(register p_set, string); STATIC int check(register p_gram); STATIC void moreverbose(register p_set); @@ -93,8 +93,7 @@ void conflchecks(void) p = &nonterms[s]; if (p->n_flags & RECURSIVE) { - error(p->n_lineno, "Recursion in default for nonterminal %s", - p->n_name); + error(p->n_lineno, "Recursion in default for nonterminal %s", p->n_name); } /* * If a printout is needed for this rule in @@ -106,8 +105,7 @@ void conflchecks(void) printset(p->n_first, c_first); printset(p->n_contains, c_contains); printset(p->n_follow, c_follow); - fprintf(fout, "> rule%s\n\t", - p->n_flags & EMPTY ? "\t(EMPTY producing)" : ""); + fprintf(fout, "> rule%s\n\t", p->n_flags & EMPTY ? "\t(EMPTY producing)" : ""); level = 8; prrule(p->n_rule); level = 0; @@ -123,7 +121,7 @@ void conflchecks(void) fclose(fout); } -STATIC void prline(char *s) +STATIC void prline(char* s) { fputs(s, fout); spaces(); @@ -204,105 +202,101 @@ STATIC int check(register p_gram p) { switch (g_gettype(p)) { - case EORULE: - return retval; - case NONTERM: - { - register p_nont n; - - n = &nonterms[g_getcont(p)]; - if (g_getnpar(p) != getntparams(n)) + case EORULE: + return retval; + case NONTERM: { - error(p->g_lineno, "Call of %s: parameter count mismatch", - n->n_name); - } - break; - } - case TERM: - { - register p_term q; + register p_nont n; - q = g_getterm(p); - retval |= check(q->t_rule); - if (r_getkind(q) == FIXED) + n = &nonterms[g_getcont(p)]; + if (g_getnpar(p) != getntparams(n)) + { + error(p->g_lineno, "Call of %s: parameter count mismatch", n->n_name); + } break; - if (setempty(q->t_first)) - { - q->t_flags |= EMPTYFIRST; - retval = 1; - error(p->g_lineno, "No symbols in term", NULL); - } - if (empty(q->t_rule)) - { - q->t_flags |= EMPTYTERM; - retval = 1; - error(p->g_lineno, - "Term with variable repetition count produces empty", - NULL); } - temp = setalloc(); - setunion(temp, q->t_first); - if (!setintersect(temp, q->t_follow)) + case TERM: { - /* - * q->t_first * q->t_follow != EMPTY - */ - if (!(q->t_flags & RESOLVER)) + register p_term q; + + q = g_getterm(p); + retval |= check(q->t_rule); + if (r_getkind(q) == FIXED) + break; + if (setempty(q->t_first)) + { + q->t_flags |= EMPTYFIRST; + retval = 1; + error(p->g_lineno, "No symbols in term", NULL); + } + if (empty(q->t_rule)) + { + q->t_flags |= EMPTYTERM; + retval = 1; + error(p->g_lineno, "Term with variable repetition count produces empty", NULL); + } + temp = setalloc(); + setunion(temp, q->t_first); + if (!setintersect(temp, q->t_follow)) { /* - * No conflict resolver + * q->t_first * q->t_follow != EMPTY */ - error(p->g_lineno, "Repetition conflict", NULL); - retval = 1; - moreverbose(temp); + if (!(q->t_flags & RESOLVER)) + { + /* + * No conflict resolver + */ + error(p->g_lineno, "Repetition conflict", NULL); + retval = 1; + moreverbose(temp); + } } - } - else - { - if (q->t_flags & RESOLVER) + else { - q->t_flags |= NOCONF; - warning(p->g_lineno, "%%while without conflict", NULL); + if (q->t_flags & RESOLVER) + { + q->t_flags |= NOCONF; + warning(p->g_lineno, "%%while without conflict", NULL); + } } + free((p_mem)temp); + break; } - free((p_mem) temp); - break; - } - case ALTERNATION: - { - register p_link l; - - l = g_getlink(p); - temp = setalloc(); - setunion(temp, l->l_symbs); - if (!setintersect(temp, l->l_others)) + case ALTERNATION: { - /* - * temp now contains the conflicting - * symbols - */ - if (!(l->l_flag & (COND | PREFERING | AVOIDING))) + register p_link l; + + l = g_getlink(p); + temp = setalloc(); + setunion(temp, l->l_symbs); + if (!setintersect(temp, l->l_others)) { - error(p->g_lineno, "Alternation conflict", NULL); - retval = 1; - moreverbose(temp); + /* + * temp now contains the conflicting + * symbols + */ + if (!(l->l_flag & (COND | PREFERING | AVOIDING))) + { + error(p->g_lineno, "Alternation conflict", NULL); + retval = 1; + moreverbose(temp); + } } - } - else - { - if (l->l_flag & (COND | PREFERING | AVOIDING)) + else { - l->l_flag |= NOCONF; - warning(p->g_lineno, "Conflict resolver without conflict", - NULL); + if (l->l_flag & (COND | PREFERING | AVOIDING)) + { + l->l_flag |= NOCONF; + warning(p->g_lineno, "Conflict resolver without conflict", NULL); + } } + free((p_mem)temp); + if (l->l_flag & PREFERING) + propagate(l->l_symbs, p + 1); + retval |= check(l->l_rule); + break; } - free((p_mem) temp); - if (l->l_flag & PREFERING) - propagate(l->l_symbs, p + 1); - retval |= check(l->l_rule); - break; - } } p++; } @@ -331,7 +325,7 @@ STATIC void prrule(p_gram p) /* * Create a verbose printout of grammar rule p */ - register FILE *f; + register FILE* f; int present = 0; int firstalt = 1; @@ -340,120 +334,118 @@ STATIC void prrule(p_gram p) { switch (g_gettype(p)) { - case EORULE: - fputs("\n", f); - return; - case TERM: - { - register p_term q; - register int c; - - q = g_getterm(p); - if (present) - prline("\n"); - fputs("[ ", f); - level += 4; - if (q->t_flags & RESOLVER) - { - prline("%while (..)\n"); - } - if (q->t_flags & PERSISTENT) - { - prline("%persistent\n"); - } - if (r_getkind(q) != FIXED) + case EORULE: + fputs("\n", f); + return; + case TERM: { - if (!(q->t_flags & PERSISTENT)) + register p_term q; + register int c; + + q = g_getterm(p); + if (present) + prline("\n"); + fputs("[ ", f); + level += 4; + if (q->t_flags & RESOLVER) { - prline("> continue repetition on the\n"); + prline("%while (..)\n"); } - printset(q->t_first, c_first); if (q->t_flags & PERSISTENT) { - prline("> continue repetition on the\n"); + prline("%persistent\n"); } - printset(q->t_contains, c_contains); - prline("> terminate repetition on the\n"); - printset(q->t_follow, c_follow); - if (q->t_flags & EMPTYFIRST) + if (r_getkind(q) != FIXED) { - prline(">>> empty first\n"); + if (!(q->t_flags & PERSISTENT)) + { + prline("> continue repetition on the\n"); + } + printset(q->t_first, c_first); + if (q->t_flags & PERSISTENT) + { + prline("> continue repetition on the\n"); + } + printset(q->t_contains, c_contains); + prline("> terminate repetition on the\n"); + printset(q->t_follow, c_follow); + if (q->t_flags & EMPTYFIRST) + { + prline(">>> empty first\n"); + } + if (q->t_flags & EMPTYTERM) + { + prline(">>> term produces empty\n"); + } + cfcheck(q->t_first, q->t_follow, q->t_flags & RESOLVER); } - if (q->t_flags & EMPTYTERM) + prrule(q->t_rule); + level -= 4; + spaces(); + c = r_getkind(q); + fputs(c == STAR ? "]*" : c == PLUS ? "]+" : c == OPT ? "]?" : "]", f); + if ((c = r_getnum(q))) { - prline(">>> term produces empty\n"); + fprintf(f, "%d", c); } - cfcheck(q->t_first, q->t_follow, q->t_flags & RESOLVER); + prline("\n"); + break; } - prrule(q->t_rule); - level -= 4; - spaces(); - c = r_getkind(q); - fputs(c == STAR ? "]*" : c == PLUS ? "]+" : c == OPT ? "]?" : "]", - f); - if ((c = r_getnum(q))) + case ACTION: + fputs("{..} ", f); + break; + case ALTERNATION: { - fprintf(f, "%d", c); - } - prline("\n"); - break; - } - case ACTION: - fputs("{..} ", f); - break; - case ALTERNATION: - { - register p_link l; + register p_link l; - l = g_getlink(p); - if (firstalt) - { - firstalt = 0; - } - else - prline("|\n"); - printset(l->l_symbs, "> alternative on "); - cfcheck(l->l_symbs, l->l_others, - (int) (l->l_flag & (COND | PREFERING | AVOIDING))); - fputs(" ", f); - level += 4; - if (l->l_flag & DEF) - { - prline("%default\n"); - } - if (l->l_flag & AVOIDING) - { - prline("%avoid\n"); - } - if (l->l_flag & PREFERING) - { - prline("%prefer\n"); - } - if (l->l_flag & COND) - { - prline("%if ( ... )\n"); + l = g_getlink(p); + if (firstalt) + { + firstalt = 0; + } + else + prline("|\n"); + printset(l->l_symbs, "> alternative on "); + cfcheck(l->l_symbs, l->l_others, (int)(l->l_flag & (COND | PREFERING | AVOIDING))); + fputs(" ", f); + level += 4; + if (l->l_flag & DEF) + { + prline("%default\n"); + } + if (l->l_flag & AVOIDING) + { + prline("%avoid\n"); + } + if (l->l_flag & PREFERING) + { + prline("%prefer\n"); + } + if (l->l_flag & COND) + { + prline("%if ( ... )\n"); + } + prrule(l->l_rule); + level -= 4; + if (g_gettype(p + 1) == EORULE) + { + return; + } + spaces(); + p++; + continue; } - prrule(l->l_rule); - level -= 4; - if (g_gettype(p+1) == EORULE) + case LITERAL: + case TERMINAL: { - return; - } - spaces(); - p++; - continue; - } - case LITERAL: - case TERMINAL: - { - register p_token pt = &tokens[g_getcont(p)]; + register p_token pt = &tokens[g_getcont(p)]; - fprintf(f, pt->t_tokno < 0400 ? "'%s' " : "%s ", pt->t_string); - break; - } - case NONTERM: - fprintf(f, "%s ", nonterms[g_getcont(p)].n_name); - break; + fprintf(f, pt->t_tokno < 0400 ? "'%s' " : "%s ", pt->t_string); + break; + } + case NONTERM: + fprintf(f, "%s ", nonterms[g_getcont(p)].n_name); + break; } p++; present = 1; @@ -487,7 +479,7 @@ STATIC void cfcheck(p_set s1, p_set s2, int flag) prline(">>> %if/%while, no conflict\n"); } } - free((p_mem) temp); + free((p_mem)temp); } STATIC void resolve(p_gram p) @@ -499,34 +491,34 @@ STATIC void resolve(p_gram p) { switch (g_gettype(p)) { - case EORULE: - return; - case TERM: - resolve(g_getterm(p)->t_rule); - break; - case ALTERNATION: - { - register p_link l; - - l = g_getlink(p); - if (l->l_flag & AVOIDING) - { - /* - * On conflicting symbols, this rule - * is never chosen - */ - setminus(l->l_symbs, l->l_others); - } - if (setempty(l->l_symbs)) + case EORULE: + return; + case TERM: + resolve(g_getterm(p)->t_rule); + break; + case ALTERNATION: { - /* - * This may be caused by the statement above - */ - error(p->g_lineno, "Alternative never chosen", NULL); + register p_link l; + + l = g_getlink(p); + if (l->l_flag & AVOIDING) + { + /* + * On conflicting symbols, this rule + * is never chosen + */ + setminus(l->l_symbs, l->l_others); + } + if (setempty(l->l_symbs)) + { + /* + * This may be caused by the statement above + */ + error(p->g_lineno, "Alternative never chosen", NULL); + } + resolve(l->l_rule); + break; } - resolve(l->l_rule); - break; - } } p++; } diff --git a/util/LLgen/src/compute.c b/util/LLgen/src/compute.c index 43c7dbc52..cf1cf326b 100644 --- a/util/LLgen/src/compute.c +++ b/util/LLgen/src/compute.c @@ -23,7 +23,7 @@ # include "extern.h" # include "sets.h" # include "assert.h" -# include "io.h" +# include "fileio.h" # ifndef NORCSID static string rcsid = "$Id$"; diff --git a/util/LLgen/src/io.h b/util/LLgen/src/fileio.h similarity index 67% rename from util/LLgen/src/io.h rename to util/LLgen/src/fileio.h index 552f28867..c4d21e596 100644 --- a/util/LLgen/src/io.h +++ b/util/LLgen/src/fileio.h @@ -21,16 +21,16 @@ /* FILES */ -# define OUTFILE "%s/%s.output" /* -v option */ -# define HFILE "%s/%spars.h" /* file for "#define's " */ -# define RFILE "%s/%spars.c" /* Error recovery */ +#define OUTFILE "%s/%s.output" /* -v option */ +#define HFILE "%s/%spars.h" /* file for "#define's " */ +#define RFILE "%s/%spars.c" /* Error recovery */ #ifdef NON_CORRECTING -# define NCFILE "%s/%sncor.c" /* Non-corrcting error recovery */ +#define NCFILE "%s/%sncor.c" /* Non-corrcting error recovery */ #endif -extern FILE *finput; -extern FILE *fpars; -extern FILE *fact; -extern FILE *fout; +extern FILE* finput; +extern FILE* fpars; +extern FILE* fact; +extern FILE* fout; extern string f_dir; extern string f_pars; extern string f_temp; diff --git a/util/LLgen/src/gencode.c b/util/LLgen/src/gencode.c index 0c24f74f2..400115b62 100644 --- a/util/LLgen/src/gencode.c +++ b/util/LLgen/src/gencode.c @@ -22,7 +22,7 @@ #include #include # include "types.h" -# include "io.h" +# include "fileio.h" # include "extern.h" # include "sets.h" # include "assert.h" diff --git a/util/LLgen/src/global.c b/util/LLgen/src/global.c index 8333f3684..048de669b 100644 --- a/util/LLgen/src/global.c +++ b/util/LLgen/src/global.c @@ -19,7 +19,7 @@ #include # include "types.h" # include "extern.h" -# include "io.h" +# include "fileio.h" # ifndef NORCSID static string rcsid4 = "$Id$"; diff --git a/util/LLgen/src/machdep.c b/util/LLgen/src/machdep.c index 602edcb61..921602a9f 100644 --- a/util/LLgen/src/machdep.c +++ b/util/LLgen/src/machdep.c @@ -15,25 +15,24 @@ * machdep.c * Machine dependant things */ +#if defined _WIN32 +#include +#endif #include #include #include #include -#if defined WIN32 -#include -#endif -# include "extern.h" -# include "types.h" +#include "extern.h" +#include "types.h" -# ifndef NORCSID +#ifndef NORCSID static string rcsid5 = "$Id$"; -# endif +#endif #ifndef LIBDIR #define LIBDIR "lib" #endif - string libpath(string s) { /* Must deliver a full pathname to the library file "s" */ @@ -55,7 +54,7 @@ string maketempfile() string filename = aprintf("%s/llgen-XXXXXX", tmp); int fd = mkstemp(filename); if (fd == -1) - fatal(1, "Cannot create temporary file.", NULL); + fatal(1, "Cannot create temporary file.", NULL); close(fd); return filename; diff --git a/util/LLgen/src/main.c b/util/LLgen/src/main.c index 4cc711323..da440baff 100644 --- a/util/LLgen/src/main.c +++ b/util/LLgen/src/main.c @@ -19,7 +19,7 @@ #include #include # include "types.h" -# include "io.h" +# include "fileio.h" # include "extern.h" # include "sets.h" # include "assert.h" diff --git a/util/LLgen/src/name.c b/util/LLgen/src/name.c index 871a1567e..da7eaab06 100644 --- a/util/LLgen/src/name.c +++ b/util/LLgen/src/name.c @@ -22,7 +22,7 @@ # include "types.h" # include "extern.h" # include "assert.h" -# include "io.h" +# include "fileio.h" # ifndef NORCSID static string rcsid7 = "$Id$"; diff --git a/util/LLgen/src/reach.c b/util/LLgen/src/reach.c index eebdecdcb..9b458165d 100644 --- a/util/LLgen/src/reach.c +++ b/util/LLgen/src/reach.c @@ -20,7 +20,7 @@ #include # include "types.h" # include "extern.h" -# include "io.h" +# include "fileio.h" # include "assert.h" # ifndef NORCSID diff --git a/util/LLgen/src/savegram.c b/util/LLgen/src/savegram.c index 32539cfca..f7851ac68 100644 --- a/util/LLgen/src/savegram.c +++ b/util/LLgen/src/savegram.c @@ -24,14 +24,13 @@ * [B | C]* becomes X; X: B X | C X | {empty} etc. */ - #include -#include -# include "types.h" -# include "extern.h" -# include "io.h" -# include "assert.h" -# include "sets.h" +#include +#include "types.h" +#include "extern.h" +#include "fileio.h" +#include "assert.h" +#include "sets.h" #define LLALT 9999 @@ -46,16 +45,18 @@ STATIC void save_rule(); STATIC void save_set(); /* t_list will contain terms to be `flattened' */ -static struct t_list { +static struct t_list +{ p_term term; int t_nt_num; -} *t_list; +}* t_list; /* Subparse list will contain symbols in %substart */ -static struct subparse_list { +static struct subparse_list +{ p_gram sub_action; int sub_nt_num; -} *sub_list; +}* sub_list; /* Index in t_list */ static int t_list_index; @@ -64,41 +65,41 @@ static int t_list_index; static int sub_list_index; /* File to save grammar to */ -static FILE *fgram; +static FILE* fgram; /* Nonterminal number to simulate parsers that get called in actions used when LLgen called with -n -s options */ int act_nt; -void save_grammar(FILE *f) +void save_grammar(FILE* f) { /* * Save the grammar */ - register p_nont p; - register p_start st; - register int nt_nr; + register p_nont p; + register p_start st; + register int nt_nr; fgram = f; /* Compute highest nonterminal nr. */ nt_highest = nnonterms + assval - 1; - /* Generate some constants in the grammar file */ /* Allocate terms list */ - t_list = (struct t_list *) alloc(nterms * sizeof(struct t_list)); + t_list = (struct t_list*)alloc(nterms * sizeof(struct t_list)); t_list_index = 0; - sub_list = (struct subparse_list *) alloc(nsubstarts * sizeof(struct subparse_list)); + sub_list = (struct subparse_list*)alloc(nsubstarts * sizeof(struct subparse_list)); fputs("static ", fgram); fputs((prefix ? prefix : "LL"), fgram); fputs("grammar[] = {\n", fgram); /* Check if -n -s option is on */ - if (subpars_sim) { + if (subpars_sim) + { /* Allocate action simulation nt */ @@ -119,21 +120,20 @@ void save_grammar(FILE *f) fprintf(fgram, "%d,\n", 1); for (st = start; st; st = st->ff_next) { - fprintf(fgram, "%d, %d, %d, \n", st->ff_nont + assval, - act_nt, LLALT); + fprintf(fgram, "%d, %d, %d, \n", st->ff_nont + assval, act_nt, LLALT); } fprintf(fgram, "%d, \n", 0); - } /* Now process all rules */ - for (p = nonterms, nt_nr = assval; p < maxnt; p++, nt_nr++) { + for (p = nonterms, nt_nr = assval; p < maxnt; p++, nt_nr++) + { fprintf(fgram, "/* nr. %d %s */\n", nt_nr, p->n_name); - fprintf(fgram, "%d, ",nt_nr); - if (! p->n_rule) { /* undefined */ + fprintf(fgram, "%d, ", nt_nr); + if (!p->n_rule) + { /* undefined */ f_input = p->n_string; - error(p->n_lineno,"Nonterminal %s not defined", - p->n_name); + error(p->n_lineno, "Nonterminal %s not defined", p->n_name); } /* Save the first_set and follow set */ @@ -154,114 +154,117 @@ void save_grammar(FILE *f) fprintf(fgram, "/* Fresh nonterminals */\n"); - { int i; - for (i = 0; i < t_list_index; i++) { + int i; + for (i = 0; i < t_list_index; i++) + { - /* Terms of the form [] without + ? * or number produce - a NIL pointer in the term-list */ - if ((t_list + i)->term == (struct term *) 0) { - continue; - } - - fprintf(fgram, "%d, ", (t_list + i)->t_nt_num); - - /* Save the first and follow sets */ - - save_set((t_list + i)->term->t_nc_first); - save_set((t_list + i)->term->t_nc_follow); - - /* NOTE: A VARIABLE REPETITION COUNT TERMS RULE IS NOT - ALLOWED TO PRODUCE EMPTY IN LLGEN - */ - - switch(r_getkind((t_list + i)->term)) { - case FIXED: - /* Already done by repeating new nonterminal */ - - /* FIXED term-rule may produce empty */ - if (empty((t_list +i)->term->t_rule)) - fprintf(fgram, "%d,\n", 1); - else - fprintf(fgram, "%d,\n", 0); - - save_rule((t_list + i)->term->t_rule, 0); - fprintf(fgram, "%d,\n", 0); - break; - case STAR: - /* Save the rule, appending the new lhs for this rule */ - - /* Star rules always produce empty */ - fprintf(fgram, "1,\n"); + /* Terms of the form [] without + ? * or number produce + a NIL pointer in the term-list */ + if ((t_list + i)->term == (struct term*)0) + { + continue; + } - save_rule((t_list + i)->term->t_rule, - (t_list + i)->t_nt_num); - fprintf(fgram, "%d,\n%d,\n", LLALT, 0); - /* ALT EMPTY*/ - break; - case PLUS: - /* Save the rule appending a fresh nonterminal */ + fprintf(fgram, "%d, ", (t_list + i)->t_nt_num); - fprintf(fgram, "%d,\n", 0); + /* Save the first and follow sets */ - save_rule((t_list + i)->term->t_rule, ++nt_highest); - fprintf(fgram, "%d,\n", 0); /* EOR */ - fprintf(fgram, "%d, ", nt_highest); - /* First set of the extra nonterm is same as - for the term */ - /* Except that the new nonterm also produces empty ! */ save_set((t_list + i)->term->t_nc_first); save_set((t_list + i)->term->t_nc_follow); - fprintf(fgram, "1,\n"); - fprintf(fgram, "%d, ", (t_list+i)->t_nt_num); - fprintf(fgram, "%d,\n%d,\n", LLALT, 0); /* ALT EMPTY */ - break; - case OPT: - fprintf(fgram, "1,\n"); - save_rule((t_list + i)->term->t_rule, 0); - fprintf(fgram, "%d,\n%d,\n", LLALT, 0); /* ALT EMPTY */ - break; + + /* NOTE: A VARIABLE REPETITION COUNT TERMS RULE IS NOT + ALLOWED TO PRODUCE EMPTY IN LLGEN + */ + + switch (r_getkind((t_list + i)->term)) + { + case FIXED: + /* Already done by repeating new nonterminal */ + + /* FIXED term-rule may produce empty */ + if (empty((t_list + i)->term->t_rule)) + fprintf(fgram, "%d,\n", 1); + else + fprintf(fgram, "%d,\n", 0); + + save_rule((t_list + i)->term->t_rule, 0); + fprintf(fgram, "%d,\n", 0); + break; + case STAR: + /* Save the rule, appending the new lhs for this rule */ + + /* Star rules always produce empty */ + fprintf(fgram, "1,\n"); + + save_rule((t_list + i)->term->t_rule, (t_list + i)->t_nt_num); + fprintf(fgram, "%d,\n%d,\n", LLALT, 0); + /* ALT EMPTY*/ + break; + case PLUS: + /* Save the rule appending a fresh nonterminal */ + + fprintf(fgram, "%d,\n", 0); + + save_rule((t_list + i)->term->t_rule, ++nt_highest); + fprintf(fgram, "%d,\n", 0); /* EOR */ + fprintf(fgram, "%d, ", nt_highest); + /* First set of the extra nonterm is same as + for the term */ + /* Except that the new nonterm also produces empty ! */ + save_set((t_list + i)->term->t_nc_first); + save_set((t_list + i)->term->t_nc_follow); + fprintf(fgram, "1,\n"); + fprintf(fgram, "%d, ", (t_list + i)->t_nt_num); + fprintf(fgram, "%d,\n%d,\n", LLALT, 0); /* ALT EMPTY */ + break; + case OPT: + fprintf(fgram, "1,\n"); + save_rule((t_list + i)->term->t_rule, 0); + fprintf(fgram, "%d,\n%d,\n", LLALT, 0); /* ALT EMPTY */ + break; + } } } - } /* Resolve %substarts */ - if (!subpars_sim) { - int i,s,check; + if (!subpars_sim) + { + int i, s, check; p_start ff, gg; p_set temp_set; - for (i = 0; i < sub_list_index; i++) { + for (i = 0; i < sub_list_index; i++) + { fprintf(fgram, "%d, ", (sub_list + i)->sub_nt_num); /* Compute the first set */ temp_set = setalloc(); - for (ff = g_getsubparse((sub_list + i)->sub_action); - ff; ff = ff->ff_next){ - s = setunion(temp_set, - (&nonterms[ff->ff_nont])->n_first); - check = 0; - for (gg =start; gg; gg = gg->ff_next) - if (ff->ff_nont == gg->ff_nont) - check = 1; - if (check == 0) - warning((sub_list + i)->sub_action->g_lineno, - "\"%s\" is not a startsymbol", - (&nonterms[ff->ff_nont])->n_name); - } - save_set(temp_set); - save_set(temp_set); - free(temp_set); + for (ff = g_getsubparse((sub_list + i)->sub_action); ff; ff = ff->ff_next) + { + s = setunion(temp_set, (&nonterms[ff->ff_nont])->n_first); + check = 0; + for (gg = start; gg; gg = gg->ff_next) + if (ff->ff_nont == gg->ff_nont) + check = 1; + if (check == 0) + warning( + (sub_list + i)->sub_action->g_lineno, "\"%s\" is not a startsymbol", + (&nonterms[ff->ff_nont])->n_name); + } + save_set(temp_set); + save_set(temp_set); + free(temp_set); - /* Produces empty */ - fprintf(fgram, "1,\n"); + /* Produces empty */ + fprintf(fgram, "1,\n"); - ff = g_getsubparse((sub_list + i)->sub_action); + ff = g_getsubparse((sub_list + i)->sub_action); - for (; ff; ff = ff->ff_next) - fprintf(fgram, "%d, %d, %d, \n", ff->ff_nont + assval, - (sub_list + i)->sub_nt_num, - LLALT); - fprintf(fgram, "%d, \n", 0); + for (; ff; ff = ff->ff_next) + fprintf( + fgram, "%d, %d, %d, \n", ff->ff_nont + assval, (sub_list + i)->sub_nt_num, + LLALT); + fprintf(fgram, "%d, \n", 0); } } @@ -271,11 +274,11 @@ void save_grammar(FILE *f) STATIC void save_rule(register p_gram p, int tail) { -/* - Walk through rule p, saving it. The non-terminal tail is - appended to the rule. It needs to be appended in this function - to process alt-rules correctly. Tail == 0 means don't append. - */ + /* + Walk through rule p, saving it. The non-terminal tail is + appended to the rule. It needs to be appended in this function + to process alt-rules correctly. Tail == 0 means don't append. + */ int in_alt; int illegal_num; @@ -289,77 +292,80 @@ STATIC void save_rule(register p_gram p, int tail) illegal_num = tokens[g_getcont(illegal_gram)].t_tokno; in_alt = 0; - for (;;) { - switch(g_gettype(p)) { - case ALTERNATION : - if (in_alt) - fprintf(fgram, "%d,\n", LLALT); - else - in_alt = 1; - save_rule(g_getlink(p)->l_rule, tail); - break; - case TERM : - /* Make entry in term list */ - (t_list + t_list_index)->term = g_getterm(p); - /* Test for [] without specifier */ - if (g_getterm(p) == (struct term *) 0) { - t_list_index++; + for (;;) + { + switch (g_gettype(p)) + { + case ALTERNATION: + if (in_alt) + fprintf(fgram, "%d,\n", LLALT); + else + in_alt = 1; + save_rule(g_getlink(p)->l_rule, tail); break; - } - (t_list + t_list_index++)->t_nt_num = ++nt_highest; - fprintf(fgram, "%d, ", nt_highest); - /* Check if repetition, if so handle here */ - if (r_getkind(g_getterm(p)) == FIXED) - { - int k; - for (k = 1; k < r_getnum(g_getterm(p)); k++) - fprintf(fgram, "%d, ", nt_highest); - } - break; - case NONTERM : - fprintf(fgram, "%d, ", g_getcont(p) + assval); - break; - case TERMINAL: - if (g_getcont(p) == g_getcont(illegal_gram)) { - /* %illegal. Ignore. */ + case TERM: + /* Make entry in term list */ + (t_list + t_list_index)->term = g_getterm(p); + /* Test for [] without specifier */ + if (g_getterm(p) == (struct term*)0) + { + t_list_index++; + break; + } + (t_list + t_list_index++)->t_nt_num = ++nt_highest; + fprintf(fgram, "%d, ", nt_highest); + /* Check if repetition, if so handle here */ + if (r_getkind(g_getterm(p)) == FIXED) + { + int k; + for (k = 1; k < r_getnum(g_getterm(p)); k++) + fprintf(fgram, "%d, ", nt_highest); + } break; - } - if (p->g_erroneous) - fprintf(fgram, "%d, ", illegal_num); - else - fprintf(fgram, "%d, ", - tokens[g_getcont(p)].t_tokno); - break; - case LITERAL: - if (p->g_erroneous) - fprintf(fgram, "%d, ", illegal_num); - else - fprintf(fgram, "%d, ", - tokens[g_getcont(p)].t_tokno); - break; - case ACTION: - if (subpars_sim) { - fprintf(fgram, "%d, ", act_nt); - } - else if (g_getsubparse(p)) { - /* Allocate nonterminal that will simulate - subparser - */ - (sub_list + sub_list_index)->sub_nt_num = - ++nt_highest; - (sub_list + sub_list_index++)->sub_action = p; + case NONTERM: + fprintf(fgram, "%d, ", g_getcont(p) + assval); + break; + case TERMINAL: + if (g_getcont(p) == g_getcont(illegal_gram)) + { + /* %illegal. Ignore. */ + break; + } + if (p->g_erroneous) + fprintf(fgram, "%d, ", illegal_num); + else + fprintf(fgram, "%d, ", tokens[g_getcont(p)].t_tokno); + break; + case LITERAL: + if (p->g_erroneous) + fprintf(fgram, "%d, ", illegal_num); + else + fprintf(fgram, "%d, ", tokens[g_getcont(p)].t_tokno); + break; + case ACTION: + if (subpars_sim) + { + fprintf(fgram, "%d, ", act_nt); + } + else if (g_getsubparse(p)) + { + /* Allocate nonterminal that will simulate + subparser + */ + (sub_list + sub_list_index)->sub_nt_num = ++nt_highest; + (sub_list + sub_list_index++)->sub_action = p; - fprintf(fgram, "%d, ", nt_highest); - } - break; - case EORULE : - if ((! in_alt) && tail ) - /* If this rule is not an alt, append tail now. - If it is an alt, the recursive call of this function - has appended tail to each alternative - */ - fprintf(fgram, "%d, ", tail); - return; + fprintf(fgram, "%d, ", nt_highest); + } + break; + case EORULE: + if ((!in_alt) && tail) + /* If this rule is not an alt, append tail now. + If it is an alt, the recursive call of this function + has appended tail to each alternative + */ + fprintf(fgram, "%d, ", tail); + return; } p++; } @@ -372,13 +378,16 @@ STATIC void save_set(p_set p) int j; j = nbytes; - for (;;) { - i = (unsigned) *p++; - for (k = 0; k < sizeof(int); k++) { - fprintf(fgram,"0%o,",(int)(i & 0377)); + for (;;) + { + i = (unsigned)*p++; + for (k = 0; k < sizeof(int); k++) + { + fprintf(fgram, "0%o,", (int)(i & 0377)); i >>= 8; - if (--j == 0) { - fputs("\n",fgram); + if (--j == 0) + { + fputs("\n", fgram); return; } } diff --git a/util/LLgen/src/tokens.c b/util/LLgen/src/tokens.c index 936795710..18117f4c7 100644 --- a/util/LLgen/src/tokens.c +++ b/util/LLgen/src/tokens.c @@ -56,7 +56,7 @@ extern void LLnc_recover(void); #include #include "types.h" -# include "io.h" +# include "fileio.h" # include "extern.h" # include "assert.h" # include "cclass.h" diff --git a/util/LLgen/src/tokens.g b/util/LLgen/src/tokens.g index 7f1b603fb..5b4cc3cd7 100644 --- a/util/LLgen/src/tokens.g +++ b/util/LLgen/src/tokens.g @@ -20,7 +20,7 @@ { #include #include "types.h" -# include "io.h" +# include "fileio.h" # include "extern.h" # include "assert.h" # include "cclass.h"