aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lex.c61
-rw-r--r--test/pp.c4
-rw-r--r--test/pp.h8
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
@@ -889,6 +889,23 @@ ppif(struct lexer *lx, const struct span *span)
}
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)
{
vlong v;
@@ -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