scc

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

commit 432127aad4a212d5d02dd74d9c7340ef68a85804
parent 06411a4af49b020ced2d40e295afe72605caaec8
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat, 23 May 2015 20:03:06 +0200

Improve ifdef/ifndef

Diffstat:
Mcc1/cc1.h | 2+-
Mcc1/cpp.c | 87+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mcc1/lex.c | 4+---
3 files changed, 49 insertions(+), 44 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -290,7 +290,7 @@ extern void freetree(Node *np); extern Node *expr(void), *negate(Node *np); /* cpp.c */ -extern char *preprocessor(char *s); +extern bool preprocessor(char *s); extern bool expand(Symbol *sym); /* diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -13,8 +13,16 @@ static char *argp; static unsigned arglen; -static unsigned numif; +static unsigned numif, iffalse; static Symbol *lastmacro; +static void +cleanup(char *s) +{ + while (isspace(*s)) + ++s; + if (*s != '\0') + error("trailing characters after preprocessor directive"); +} static void nextcpp(void) @@ -264,7 +272,7 @@ mkdefine(char *s, Symbol *sym) return s; } -static char * +static bool define(char *s) { char *t; @@ -291,7 +299,9 @@ define(char *s) /* nothing */; for (t = s + strlen(s); isspace(*--t); *t = '\0') /* nothing */; - return mkdefine(s, sym); + s = mkdefine(s, sym); + cleanup(s); + return 1; too_long: error("macro identifier too long"); @@ -299,7 +309,7 @@ bad_define: error("macro names must be identifiers"); } -static char * +static bool include(char *s) { char fname[FILENAME_MAX], delim, c, *p; @@ -329,7 +339,8 @@ include(char *s) abort(); } - return p+1; + cleanup(p+1); + return 1; not_found: error("included file '%s' not found", fname); @@ -339,7 +350,7 @@ bad_include: error("#include expects \"FILENAME\" or <FILENAME>"); } -static char * +static bool line(char *s) { char *p, *q; @@ -364,8 +375,10 @@ line(char *s) p = q+1; /* passthrough */ case '\0': + /* TODO: check this atoi */ setfline(atoi(s)-1); - return p; + cleanup(p); + return 1; default: goto bad_file; } @@ -376,29 +389,26 @@ bad_line: error("first parameter of #line is not a positive integer"); } -static char * +static bool pragma(char *s) { - while (*s) - ++s; - return s; + cleanup(s); + return 1; } -static char * +static bool usererr(char *s) { - fprintf(stderr, "%s:%u:error: #error %s\n", getfname(), getfline(), s); - exit(-1); + error("#error %s", s); } -static char * +static bool ifclause(char *s, int isdef) { unsigned curif, len; char *endp; Symbol *sym; - while (isspace(*s)) ++s; for (endp = s; isalnum(*endp) || *endp == '_'; ++endp) @@ -407,51 +417,54 @@ ifclause(char *s, int isdef) error("..."); memcpy(yytext, s, len); yytext[len] = '\0'; - while (isspace(*endp)) - ++endp; - if (*endp != '\0') - error("trailing characters after preprocessor directive"); - + cleanup(endp); curif = numif++; - sym = lookup(NS_CPP); - if ((sym->flags & ISDEFINED) != 0 == isdef) - return endp; + + if (iffalse != 0) { + sym = lookup(NS_CPP); + if ((sym->flags & ISDEFINED) != 0 == isdef) + return 1; + } + + ++iffalse; while (curif != numif) { if (!moreinput()) error("found EOF while ..."); } - return ""; + --iffalse; + + return 1; } -static char * +static bool ifdef(char *s) { return ifclause(s, 1); } -static char * +static bool ifndef(char *s) { return ifclause(s, 0); } -static char * +static bool endif(char *s) { if (numif == 0) error("#endif without #if"); --numif; - return NULL; + return iffalse == 0; } -char * +bool preprocessor(char *p) { char *q; unsigned short n; static struct { char *name; - char *(*fun)(char *); + bool (*fun)(char *); } *bp, cmds[] = { "define", define, "include", include, @@ -467,11 +480,11 @@ preprocessor(char *p) while (isspace(*p)) ++p; if (*p != '#') - return p; + return 0; for (++p; isspace(*p); ++p) /* nothing */; if (*p == '\0') - return p; + return 1; for (q = p; isalpha(*q); ++q) /* nothing */; if ((n = q - p) == 0) @@ -481,13 +494,7 @@ preprocessor(char *p) for (bp = cmds; bp->name; ++bp) { if (strncmp(bp->name, p, n)) continue; - if ((q = (*bp->fun)(q)) == NULL) - return NULL; - while (isspace(*q)) - ++q; - if (*q != '\0') - error("trailing characters after preprocessor directive"); - return q; + return (*bp->fun)(q); } incorrect: error("incorrect preprocessor directive"); diff --git a/cc1/lex.c b/cc1/lex.c @@ -202,9 +202,7 @@ repeat: *(p = input->line) = '\0'; readline(); - if ((p = preprocessor(p)) == NULL) - return 1; - if (*p == '\0') + if (preprocessor(p)) goto repeat; input->p = input->begin = p; return 1;