scc

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

commit 06411a4af49b020ced2d40e295afe72605caaec8
parent 5d75fa9ad62267658ce6ee314cd185fb02510960
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat, 23 May 2015 19:06:18 +0200

Add ifdef and ifndef clauses

This is a first versin, but it is functional. There is some points that are
not very elegant, but they can be solved later.

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

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -266,6 +266,7 @@ extern void extdecl(void), decl(void); /* lex.c */ extern char ahead(void); extern unsigned next(void); +extern bool moreinput(void); extern void expect(unsigned tok); extern void discard(void); extern char *getfname(void); diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -13,6 +13,7 @@ static char *argp; static unsigned arglen; +static unsigned numif; static Symbol *lastmacro; static void @@ -266,7 +267,6 @@ mkdefine(char *s, Symbol *sym) static char * define(char *s) { - extern char yytext[]; char *t; size_t len; Symbol *sym; @@ -391,6 +391,59 @@ usererr(char *s) exit(-1); } +static char * +ifclause(char *s, int isdef) +{ + unsigned curif, len; + char *endp; + Symbol *sym; + + + while (isspace(*s)) + ++s; + for (endp = s; isalnum(*endp) || *endp == '_'; ++endp) + /* nothing */; + if ((len = endp - s) > IDENTSIZ) + error("..."); + memcpy(yytext, s, len); + yytext[len] = '\0'; + while (isspace(*endp)) + ++endp; + if (*endp != '\0') + error("trailing characters after preprocessor directive"); + + curif = numif++; + sym = lookup(NS_CPP); + if ((sym->flags & ISDEFINED) != 0 == isdef) + return endp; + while (curif != numif) { + if (!moreinput()) + error("found EOF while ..."); + } + return ""; +} + +static char * +ifdef(char *s) +{ + return ifclause(s, 1); +} + +static char * +ifndef(char *s) +{ + return ifclause(s, 0); +} + +static char * +endif(char *s) +{ + if (numif == 0) + error("#endif without #if"); + --numif; + return NULL; +} + char * preprocessor(char *p) { @@ -402,6 +455,9 @@ preprocessor(char *p) } *bp, cmds[] = { "define", define, "include", include, + "ifdef", ifdef, + "ifndef", ifndef, + "endif", endif, "line", line, "pragma", pragma, "error", usererr, @@ -425,9 +481,10 @@ preprocessor(char *p) for (bp = cmds; bp->name; ++bp) { if (strncmp(bp->name, p, n)) continue; - q = (*bp->fun)(q); - while (isspace(*q++)) - /* nothing */; + if ((q = (*bp->fun)(q)) == NULL) + return NULL; + while (isspace(*q)) + ++q; if (*q != '\0') error("trailing characters after preprocessor directive"); return q; diff --git a/cc1/lex.c b/cc1/lex.c @@ -186,7 +186,7 @@ readline(void) *bp = '\0'; } -static bool +bool moreinput(void) { char *p; @@ -202,7 +202,9 @@ repeat: *(p = input->line) = '\0'; readline(); - if (*(p = preprocessor(p)) == '\0') + if ((p = preprocessor(p)) == NULL) + return 1; + if (*p == '\0') goto repeat; input->p = input->begin = p; return 1;