aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-07-21 18:39:48 +0900
committernsfisis <nsfisis@gmail.com>2025-08-15 10:04:31 +0900
commit1c48d0fe728c263bbe946a5d3adebaa29323ddff (patch)
treec3d3da95701e088028f204b668f48672e3faf4ea
parentadfe15f9fa0f4e69b343679dca6cf12fc96e3819 (diff)
downloadducc-1c48d0fe728c263bbe946a5d3adebaa29323ddff.tar.gz
ducc-1c48d0fe728c263bbe946a5d3adebaa29323ddff.tar.zst
ducc-1c48d0fe728c263bbe946a5d3adebaa29323ddff.zip
feat: partially implement #ifdef, #else and #endif directives
-rw-r--r--preprocess.c48
-rw-r--r--tests/062.sh38
2 files changed, 86 insertions, 0 deletions
diff --git a/preprocess.c b/preprocess.c
index a8b3b91..205e2bd 100644
--- a/preprocess.c
+++ b/preprocess.c
@@ -37,6 +37,7 @@ struct Preprocessor {
int n_pp_tokens;
PpDefines* pp_defines;
int include_depth;
+ int skip_pp_tokens;
};
typedef struct Preprocessor Preprocessor;
@@ -83,6 +84,11 @@ int find_pp_define(Preprocessor* pp, String* name) {
return -1;
}
+int skip_pp_tokens(Preprocessor* pp) {
+ // TODO: support nested #if
+ return pp->skip_pp_tokens;
+}
+
void pp_tokenize_all(Preprocessor* pp) {
char* buf;
int ch;
@@ -416,7 +422,49 @@ void process_pp_directives(Preprocessor* pp) {
pp->n_pp_tokens += n_include_pp_tokens;
}
+ } else if (tok2->kind == PpTokenKind_identifier && string_equals_cstr(&tok2->raw, "ifdef")) {
+ ++tok2;
+ while (tok2->kind != PpTokenKind_eof && tok2->kind == PpTokenKind_whitespace)
+ ++tok2;
+ if (tok2->kind == PpTokenKind_identifier) {
+ // Process #ifdef directive.
+ PpToken* name = tok2;
+ ++tok2;
+
+ pp->skip_pp_tokens = find_pp_define(pp, &name->raw) == -1;
+ }
+ // Remove #ifdef directive.
+ while (tok != tok2 + 1) {
+ tok->kind = PpTokenKind_whitespace;
+ tok->raw.len = 0;
+ tok->raw.data = NULL;
+ ++tok;
+ }
+ } else if (tok2->kind == PpTokenKind_identifier && string_equals_cstr(&tok2->raw, "endif")) {
+ ++tok2;
+ pp->skip_pp_tokens = 0;
+ // Remove #endif directive.
+ while (tok != tok2 + 1) {
+ tok->kind = PpTokenKind_whitespace;
+ tok->raw.len = 0;
+ tok->raw.data = NULL;
+ ++tok;
+ }
+ } else if (tok2->kind == PpTokenKind_identifier && string_equals_cstr(&tok2->raw, "else")) {
+ ++tok2;
+ pp->skip_pp_tokens = 1 - pp->skip_pp_tokens;
+ // Remove #else directive.
+ while (tok != tok2 + 1) {
+ tok->kind = PpTokenKind_whitespace;
+ tok->raw.len = 0;
+ tok->raw.data = NULL;
+ ++tok;
+ }
}
+ } else if (skip_pp_tokens(pp)) {
+ tok->kind = PpTokenKind_whitespace;
+ tok->raw.len = 0;
+ tok->raw.data = NULL;
} else if (tok->kind == PpTokenKind_identifier) {
int pp_define_idx = find_pp_define(pp, &tok->raw);
if (pp_define_idx != -1) {
diff --git a/tests/062.sh b/tests/062.sh
new file mode 100644
index 0000000..d50ecc6
--- /dev/null
+++ b/tests/062.sh
@@ -0,0 +1,38 @@
+set -e
+
+cat <<'EOF' > expected
+__ducc__ is defined.
+A is defined.
+B is undefined.
+EOF
+
+bash ../../test_diff.sh <<'EOF'
+int printf();
+
+#define A 123
+
+int main() {
+
+#ifdef __ducc__
+ printf("__ducc__ is defined.\n");
+#else
+ printf("__ducc__ is undefined.\n");
+#endif
+
+#ifdef A
+ printf("A is defined.\n");
+#else
+ printf("A is undefined.\n");
+#endif
+
+#ifdef B
+ printf("B is defined.\n");
+#else
+ printf("B is undefined.\n");
+#endif
+
+#define B 456
+
+ return 0;
+}
+EOF