From f02fb99340edd86848794dd9b85088998458a70d Mon Sep 17 00:00:00 2001 From: lemon Date: Fri, 12 Apr 2024 09:13:42 +0200 Subject: [PATCH] frontend: #ifdef --- lex.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++----- test/pp.c | 4 +++- test/pp.h | 8 ++++++++ 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/lex.c b/lex.c index a74fe60..547e018 100644 --- a/lex.c +++ b/lex.c @@ -888,6 +888,23 @@ ppif(struct lexer *lx, const struct span *span) ppcndstk[nppcnd++].elsep = 0; } +static void +ppifxdef(struct lexer *lx, bool defp, const struct span *span) +{ + struct token tk; + + lex0(lx, &tk); + if (!isppident(tk)) { + error(&tk.span, "macro name missing"); + ppskipline(lx); + return; + } + assert(nppcnd < arraylength(ppcndstk) && "too many nested #if"); + ppcndstk[nppcnd].ifspan = span->sl; + ppcndstk[nppcnd].cnd = (findmac(tk.s) == NULL) ^ defp ? PPCNDTRUE : PPCNDFALSE; + ppcndstk[nppcnd++].elsep = 0; +} + static void ppelif(struct lexer *lx, const struct span *span) { @@ -911,6 +928,36 @@ ppelif(struct lexer *lx, const struct span *span) case PPCNDTAKEN: assert(0); } } +static void +ppelifxdef(struct lexer *lx, bool defp, const struct span *span) +{ + struct token tk; + struct ppcnd *cnd; + + if (!nppcnd) { + error(span, "#elif%sdef without matching #if", &"n"[defp]); + ppif(lx, span); + return; + } + cnd = &ppcndstk[nppcnd-1]; + if (cnd->elsep) { + error(span, "#elif%sdef after #else", &"n"[defp]); + return; + } + lex0(lx, &tk); + if (!isppident(tk)) { + error(&tk.span, "macro name missing"); + ppskipline(lx); + return; + } + switch (cnd->cnd) { + case PPCNDTRUE: cnd->cnd = PPCNDTAKEN; break; + case PPCNDFALSE: cnd->cnd = (findmac(tk.s) == NULL) ^ defp ? PPCNDTRUE : PPCNDFALSE; break; + case PPCNDTAKEN: assert(0); + } +} + + static void ppendif(struct lexer *lx, const struct span *span) @@ -1137,11 +1184,15 @@ lex(struct lexer *lx, struct token *tk_) if (!skip) { switch (findppcmd(tk)) { case PPXXX: goto BadPP; - case PPDEFINE: ppdefine(lx); break; - case PPIF: ppif(lx, &tk->span); break; - case PPELIF: ppelif(lx, &tk->span); break; - case PPENDIF: ppendif(lx, &tk->span); break; - case PPELSE: ppelse(lx, &tk->span); break; + case PPDEFINE: ppdefine(lx); break; + case PPIF: ppif(lx, &tk->span); break; + case PPIFDEF: ppifxdef(lx, 1, &tk->span); break; + case PPIFNDEF: ppifxdef(lx, 0, &tk->span); break; + case PPELIF: ppelif(lx, &tk->span); break; + case PPELIFDEF: ppelifxdef(lx, 1, &tk->span); break; + case PPELIFNDEF: ppelifxdef(lx, 0, &tk->span); break; + case PPENDIF: ppendif(lx, &tk->span); break; + case PPELSE: ppelse(lx, &tk->span); break; case PPINCLUDE: ppinclude(lx, &tk->span); break; default: assert(0&&"nyi"); } diff --git a/test/pp.c b/test/pp.c index 0c199dc..ee4b98a 100644 --- a/test/pp.c +++ b/test/pp.c @@ -1,8 +1,10 @@ #include "pp.h" +#include "pp.h" + int main(void) { hi(); - return Foo; + return Foo + Bar; } diff --git a/test/pp.h b/test/pp.h index 69da492..80042fd 100644 --- a/test/pp.h +++ b/test/pp.h @@ -1,6 +1,14 @@ +#ifndef GUARD +#define GUARD + extern warnhere(); #define Foo 9 void hi() { extern int printf(); printf("hi from header\n"); } + +#elifndef Ww +#define Bar 7 + +#endif -- 2.45.2