diff --git a/Makefile b/Makefile index a87a1fcce05e8725978e2e158c53a028138edb77..9993e004153b0de2bb22f70465b3bf6e74d047d9 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ chibicc: $(OBJS) $(OBJS): chibicc.h test/%.exe: chibicc test/%.c - ./chibicc -c -o test/$*.o test/$*.c + ./chibicc -Itest -c -o test/$*.o test/$*.c $(CC) -o $@ test/$*.o -xc test/common test: $(TESTS) @@ -35,7 +35,7 @@ stage2/%.o: chibicc self.py %.c stage2/test/%.exe: stage2/chibicc test/%.c mkdir -p stage2/test - ./stage2/chibicc -c -o stage2/test/$*.o test/$*.c + ./stage2/chibicc -Itest -c -o stage2/test/$*.o test/$*.c $(CC) -o $@ stage2/test/$*.o -xc test/common test-stage2: $(TESTS:test/%=stage2/test/%) diff --git a/chibicc.h b/chibicc.h index 9cd1ed26b822372f6b2e45df182749d44fa94f9b..4a09b1954bc7811d39a6fca242dec85a878d6751 100644 --- a/chibicc.h +++ b/chibicc.h @@ -348,4 +348,5 @@ int align_to(int n, int align); bool file_exists(char *path); +extern StringArray include_paths; extern char *base_file; diff --git a/main.c b/main.c index 4c520c5d0d9a90f51f61b4150917babf3c7e94c7..4abfeca9a9a3cba0c97b56655f0240957fde9925 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,7 @@ #include "chibicc.h" +StringArray include_paths; + static bool opt_E; static bool opt_S; static bool opt_c; @@ -19,7 +21,12 @@ static void usage(int status) { } static bool take_arg(char *arg) { - return !strcmp(arg, "-o"); + char *x[] = {"-o", "-I"}; + + for (int i = 0; i < sizeof(x) / sizeof(*x); i++) + if (!strcmp(arg, x[i])) + return true; + return false; } static void parse_args(int argc, char **argv) { @@ -69,6 +76,11 @@ static void parse_args(int argc, char **argv) { continue; } + if (!strncmp(argv[i], "-I", 2)) { + strarray_push(&include_paths, argv[i] + 2); + continue; + } + if (!strcmp(argv[i], "-cc1-input")) { base_file = argv[++i]; continue; diff --git a/preprocess.c b/preprocess.c index ca06ed91e4af7cf52dc83af8c2cedf0e5f9259a2..487e5b495a1ad5cb8c317fc710288d4c37dedf89 100644 --- a/preprocess.c +++ b/preprocess.c @@ -596,6 +596,19 @@ static bool expand_macro(Token **rest, Token *tok) { return true; } +static char *search_include_paths(char *filename) { + if (filename[0] == '/') + return filename; + + // Search a file from the include paths. + for (int i = 0; i < include_paths.len; i++) { + char *path = format("%s/%s", include_paths.data[i], filename); + if (file_exists(path)) + return path; + } + return NULL; +} + // Read an #include argument. static char *read_include_filename(Token **rest, Token *tok, bool *is_dquote) { // Pattern 1: #include "foo.h" @@ -669,7 +682,7 @@ static Token *preprocess2(Token *tok) { bool is_dquote; char *filename = read_include_filename(&tok, tok->next, &is_dquote); - if (filename[0] != '/') { + if (filename[0] != '/' && is_dquote) { char *path = format("%s/%s", dirname(strdup(start->file->name)), filename); if (file_exists(path)) { tok = include_file(tok, path, start->next->next); @@ -677,8 +690,8 @@ static Token *preprocess2(Token *tok) { } } - // TODO: Search a file from the include paths. - tok = include_file(tok, filename, start->next->next); + char *path = search_include_paths(filename); + tok = include_file(tok, path ? path : filename, start->next->next); continue; } diff --git a/self.py b/self.py index 32e058071534e4611a44745bd566b956338de891..88af153fdeedee53873d5ec340c45f9035fc61ac 100755 --- a/self.py +++ b/self.py @@ -95,6 +95,8 @@ FILE *open_memstream(char **ptr, size_t *sizeloc); char *dirname(char *path); char *strncpy(char *dest, char *src, long n); int stat(char *pathname, struct stat *statbuf); +int stat(char *pathname, struct stat *statbuf); +char *dirname(char *path); """) for path in sys.argv[1:]: diff --git a/test/driver.sh b/test/driver.sh index 2358af8895dfa3ed689fb8a1368699178634751a..80bc0db790019fb7d230b6a53595e3fb21796d08 100755 --- a/test/driver.sh +++ b/test/driver.sh @@ -85,4 +85,10 @@ echo "#include \"$tmp/out1\"" | $chibicc -E -o $tmp/out2 - cat $tmp/out2 | grep -q foo check '-E and -o' +# -I +mkdir $tmp/dir +echo foo > $tmp/dir/i-option-test +echo "#include \"i-option-test\"" | $chibicc -I$tmp/dir -E - | grep -q foo +check -I + echo OK