aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--preprocess.c26
-rw-r--r--tests/084.sh28
2 files changed, 54 insertions, 0 deletions
diff --git a/preprocess.c b/preprocess.c
index 5b7c180..72e8ca3 100644
--- a/preprocess.c
+++ b/preprocess.c
@@ -362,6 +362,11 @@ int find_pp_macro(Preprocessor* pp, String* name) {
return -1;
}
+void undef_pp_macro(Preprocessor* pp, int idx) {
+ pp->pp_macros->data[idx].name.len = 0;
+ // TODO: Can predefined macro like __FILE__ be undefined?
+}
+
void add_include_path(Preprocessor* pp, char* include_path) {
pp->include_paths[pp->n_include_paths].data = include_path;
pp->include_paths[pp->n_include_paths].len = strlen(include_path);
@@ -867,6 +872,24 @@ Token* process_define_directive(Preprocessor* pp, Token* tok) {
return NULL;
}
+Token* process_undef_directive(Preprocessor* pp, Token* tok) {
+ Token* tok2 = skip_whitespace(tok + 1);
+ if (tok2->kind == TokenKind_ident && string_equals_cstr(&tok2->raw, "undef")) {
+ tok2 = skip_whitespace(tok2 + 1);
+ if (tok2->kind == TokenKind_ident) {
+ Token* macro_name = tok2;
+ ++tok2;
+ int pp_macro_idx = find_pp_macro(pp, &macro_name->raw);
+ if (pp_macro_idx != -1) {
+ undef_pp_macro(pp, pp_macro_idx);
+ }
+ }
+ remove_directive_tokens(tok, tok2);
+ return tok2;
+ }
+ return NULL;
+}
+
BOOL expand_macro(Preprocessor* pp, Token* tok) {
int pp_macro_idx = find_pp_macro(pp, &tok->raw);
if (pp_macro_idx == -1) {
@@ -945,6 +968,9 @@ void process_pp_directives(Preprocessor* pp) {
} else if ((next_tok = process_define_directive(pp, tok)) != NULL) {
tok = next_tok;
continue;
+ } else if ((next_tok = process_undef_directive(pp, tok)) != NULL) {
+ tok = next_tok;
+ continue;
} else {
fatal_error("%s:%d: unknown preprocessor directive (%s)", tok->loc.filename, tok->loc.line,
token_stringify(tok + 1));
diff --git a/tests/084.sh b/tests/084.sh
new file mode 100644
index 0000000..3b2fe15
--- /dev/null
+++ b/tests/084.sh
@@ -0,0 +1,28 @@
+set -e
+
+cat <<'EOF' > expected
+A is defined
+A is undefined
+EOF
+
+bash ../../test_diff.sh <<'EOF'
+int printf();
+
+int main() {
+#define A 1
+
+#ifdef A
+ printf("A is defined\n");
+#else
+ printf("A is undefined\n");
+#endif
+
+#undef A
+
+#ifdef A
+ printf("A is defined\n");
+#else
+ printf("A is undefined\n");
+#endif
+}
+EOF