scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 0292d84f3feaf3337dba488fe975708adb50a64f
parent 563c6e05e6b37e0d42a609cc1c38c818fc09a773
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 25 May 2015 12:43:42 +0200

Fix conditional inclusion

The previous implementation was obscure and it has failures.
It was due to the fact that the disabled lines were skipped in
the own preprocessor code, and it made hard to handle #else.
The solution, of course, is to handle them in morelines.

Diffstat:
Mcc1/cc1.h | 1+
Mcc1/cpp.c | 66++++++++++++++++++++++++++++++++----------------------------------
Mcc1/lex.c | 3++-
3 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -300,6 +300,7 @@ extern struct yystype yylval; extern char yytext[]; extern unsigned yytoken; extern unsigned short yylen; +extern int cppoff; extern Type *voidtype, *pvoidtype, *booltype, *uchartype, *chartype, diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -14,9 +14,11 @@ static char *argp; static unsigned arglen; -static unsigned numif, iffalse; +static unsigned numif; static Symbol *lastmacro; +unsigned char ifstatus[NR_COND]; + static bool iden(char **str) { @@ -245,7 +247,7 @@ set_nargs: return s; } /* - * Copy a define string, and substitute formal arguments of the + * Copy a string define, and substitute formal arguments of the * macro into strings in the form @XX@, where XX is the position * of the argument in the argument list. */ @@ -313,8 +315,10 @@ define(char *s) char *t; Symbol *sym; + if (cppoff) + return 1; if (!iden(&s)) - error("macro names must be identifiers"); + error("#define must have an identifier as parameter"); sym = lookup(NS_CPP); if ((sym->flags & ISDEFINED) && sym->ns == NS_CPP) { @@ -335,6 +339,8 @@ include(char *s) { char delim, c, *p, *file; + if (cppoff) + return 1; if ((c = *s++) == '>') delim = '>'; else if (c == '"') @@ -361,6 +367,8 @@ line(char *s) char *file; long n; + if (cppoff) + return 1; if ((n = strtol(s, &s, 10)) <= 0 || n > USHRT_MAX) error("first parameter of #line is not a positive integer"); @@ -388,38 +396,35 @@ line(char *s) static bool pragma(char *s) { + if (cppoff) + return 1; return 1; } static bool usererr(char *s) { + if (cppoff) + return 1; error("#error %s", s); } static bool ifclause(char *s, int isdef) { - unsigned curif; - char *endp; Symbol *sym; + unsigned n = numif++; - if (iden(&s)) - error("..."); - cleanup(s); + if (numif == NR_COND-1) + error("too much nesting levels of conditional inclusion"); - ++numif; - if (iffalse == 0) { - sym = lookup(NS_CPP); - if ((sym->flags & ISDEFINED) != 0 == isdef) - return 1; - } + if (!iden(&s)) + error("#ifdef clause must have an identifier as parameter"); + cleanup(s); - curif = iffalse++; - while (curif != iffalse) { - if (!moreinput()) - error("found EOF while ..."); - } + sym = lookup(NS_CPP); + if (!(ifstatus[n] = (sym->flags & ISDEFINED) != 0 == isdef)) + ++cppoff; return 1; } @@ -439,32 +444,25 @@ ifndef(char *s) static bool endif(char *s) { - cleanup(s); if (numif == 0) error("#endif without #if"); - --numif; - return iffalse == 0; + cleanup(s); + if (!ifstatus[--numif]) + --cppoff; + return 1; } static bool elseclause(char *s) { - unsigned curif; + struct ifstatus *ip; - cleanup(s); if (numif == 0) error("#else without #if"); + cleanup(s); + cppoff += (ifstatus[numif-1] ^= 1) ? -1 : 1; - if (iffalse == 0) { - curif = iffalse++; - while (curif != iffalse) { - if (!moreinput()) - error("found EOF while ..."); - } - } - --iffalse; - - return iffalse != 0; + return 1; } bool diff --git a/cc1/lex.c b/cc1/lex.c @@ -26,6 +26,7 @@ unsigned yytoken; struct yystype yylval; char yytext[IDENTSIZ + 1]; unsigned short yylen; +int cppoff; static unsigned lex_ns = NS_IDEN; static int safe, eof, incomment; @@ -204,7 +205,7 @@ repeat: readline(); while (isspace(*p)) ++p; - if (*p == '\0' || preprocessor(p)) + if (*p == '\0' || preprocessor(p) || cppoff) goto repeat; input->p = input->begin = p; return 1;