diff options
| author | nsfisis <nsfisis@gmail.com> | 2025-08-24 23:18:32 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2025-08-24 23:55:28 +0900 |
| commit | 78f961696c3bd761c9f43e368765055e33834b90 (patch) | |
| tree | b6eb4514d1c4cf997f4cc92cfc7de594566d701e | |
| parent | c8851cbda7da8ff579efb6603d2dff2576768863 (diff) | |
| download | ducc-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.c | 16 | ||||
| -rw-r--r-- | tests/055.sh | 39 | ||||
| -rw-r--r-- | tests/057.sh | 2 |
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' |
