aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2025-08-24 23:18:32 +0900
committernsfisis <nsfisis@gmail.com>2025-08-24 23:55:28 +0900
commit78f961696c3bd761c9f43e368765055e33834b90 (patch)
treeb6eb4514d1c4cf997f4cc92cfc7de594566d701e
parentc8851cbda7da8ff579efb6603d2dff2576768863 (diff)
downloadducc-78f961696c3bd761c9f43e368765055e33834b90.tar.gz
ducc-78f961696c3bd761c9f43e368765055e33834b90.tar.zst
ducc-78f961696c3bd761c9f43e368765055e33834b90.zip
feat: resolve include name relative to the current file name
-rw-r--r--src/preprocess.c16
-rw-r--r--tests/055.sh39
-rw-r--r--tests/057.sh2
3 files changed, 46 insertions, 11 deletions
diff --git a/src/preprocess.c b/src/preprocess.c
index e44bbf4..3ed9740 100644
--- a/src/preprocess.c
+++ b/src/preprocess.c
@@ -1220,18 +1220,22 @@ void process_ifndef_directive(Preprocessor* pp, int directive_token_pos) {
remove_directive_tokens(pp, directive_token_pos, pp->pos);
}
-const char* read_include_header_name(Preprocessor* pp) {
+Token* read_include_header_name(Preprocessor* pp) {
Token* tok = next_pp_token(pp);
if (tok->kind != TokenKind_header_name) {
fatal_error("%s:%d: invalid #include", tok->loc.filename, tok->loc.line);
}
-
- return tok->value.string;
+ return tok;
}
-const char* resolve_include_name(Preprocessor* pp, const char* include_name) {
+const char* resolve_include_name(Preprocessor* pp, const Token* include_name_token) {
+ const char* include_name = include_name_token->value.string;
if (include_name[0] == '"') {
- return strndup(include_name + 1, strlen(include_name) - 2);
+ char* current_filename = strdup(include_name_token->loc.filename);
+ const char* current_dir = dirname(current_filename);
+ char* buf = calloc(strlen(include_name) - 2 + 1 + strlen(current_dir) + 1, sizeof(char));
+ sprintf(buf, "%s/%.*s", current_dir, strlen(include_name) - 2, include_name + 1);
+ return buf;
} else {
for (int i = 0; i < pp->n_include_paths; ++i) {
char* buf = calloc(strlen(include_name) - 2 + 1 + strlen(pp->include_paths[i]) + 1, sizeof(char));
@@ -1291,7 +1295,7 @@ void expand_include_directive(Preprocessor* pp, int directive_token_pos, const c
void process_include_directive(Preprocessor* pp, int directive_token_pos) {
next_pp_token(pp);
skip_whitespaces(pp);
- const char* include_name = read_include_header_name(pp);
+ Token* include_name = read_include_header_name(pp);
const char* include_name_resolved = resolve_include_name(pp, include_name);
if (include_name_resolved == NULL) {
fatal_error("cannot resolve include file name: %s", include_name);
diff --git a/tests/055.sh b/tests/055.sh
index 6fc3608..997f12b 100644
--- a/tests/055.sh
+++ b/tests/055.sh
@@ -1,7 +1,3 @@
-cat <<'EOF' > expected
-8
-EOF
-
cat <<'EOF' > header.h
int add(int a, int b) {
return a + b;
@@ -10,6 +6,9 @@ int add(int a, int b) {
int printf(const char*, ...);
EOF
+cat <<'EOF' > expected
+8
+EOF
test_diff <<'EOF'
#include "header.h"
@@ -18,3 +17,35 @@ int main() {
return 0;
}
EOF
+
+mkdir -p foo
+cat <<'EOF' > bar.h
+#include "baz.h"
+EOF
+cat <<'EOF' > baz.h
+#define A 123
+EOF
+cat <<'EOF' > foo/bar.h
+#include "baz.h"
+EOF
+cat <<'EOF' > foo/baz.h
+#define A 456
+EOF
+
+cat <<'EOF' > expected
+123
+456
+EOF
+test_diff <<'EOF'
+int printf(const char*, ...);
+
+int main() {
+#include "bar.h"
+ printf("%d\n", A);
+
+#undef A
+
+#include "foo/bar.h"
+ printf("%d\n", A);
+}
+EOF
diff --git a/tests/057.sh b/tests/057.sh
index 8850e55..291030c 100644
--- a/tests/057.sh
+++ b/tests/057.sh
@@ -1,5 +1,5 @@
cat <<'EOF' > expected
-cannot open include file: nonexistent.h
+cannot open include file: ./nonexistent.h
EOF
test_compile_error <<'EOF'