From d519ce87dd3c112dbaa087e2ef08514d5253f02a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 5 Aug 2015 21:47:08 -0700 Subject: [PATCH] preprocessor runs once --- CMakeLists.txt | 1 + src/buffer.cpp | 25 +++++++++++++++++++++++++ src/buffer.hpp | 26 +++++++++++++++++++++++++ src/main.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++---- src/util.cpp | 25 ------------------------- src/util.hpp | 3 --- 6 files changed, 99 insertions(+), 32 deletions(-) create mode 100644 src/buffer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 35e50bf2eb..356ff6d3cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ include_directories( set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/main.cpp" "${CMAKE_SOURCE_DIR}/src/util.cpp" + "${CMAKE_SOURCE_DIR}/src/buffer.cpp" ) set(CONFIGURE_OUT_FILE "${CMAKE_BINARY_DIR}/config.h") diff --git a/src/buffer.cpp b/src/buffer.cpp new file mode 100644 index 0000000000..7bcd1b3783 --- /dev/null +++ b/src/buffer.cpp @@ -0,0 +1,25 @@ +#include "buffer.hpp" +#include +#include +#include + +Buf *buf_sprintf(const char *format, ...) { + va_list ap, ap2; + va_start(ap, format); + va_copy(ap2, ap); + + int len1 = vsnprintf(nullptr, 0, format, ap); + assert(len1 >= 0); + + size_t required_size = len1 + 1; + + Buf *buf = buf_alloc_fixed(len1); + + int len2 = vsnprintf(buf_ptr(buf), required_size, format, ap2); + assert(len2 == len1); + + va_end(ap2); + va_end(ap); + + return buf; +} diff --git a/src/buffer.hpp b/src/buffer.hpp index f463ab776d..76115706c0 100644 --- a/src/buffer.hpp +++ b/src/buffer.hpp @@ -11,11 +11,15 @@ #include "list.hpp" #include +#include struct Buf { ZigList list; }; +Buf *buf_sprintf(const char *format, ...) + __attribute__ ((format (printf, 1, 2))); + static inline int buf_len(Buf *buf) { return buf->list.length - 1; } @@ -53,6 +57,10 @@ static inline Buf *buf_from_mem(char *ptr, int len) { return buf; } +static inline Buf *buf_from_str(char *str) { + return buf_from_mem(str, strlen(str)); +} + static inline Buf *buf_slice(Buf *in_buf, int start, int end) { assert(start >= 0); assert(end >= 0); @@ -79,4 +87,22 @@ static inline void buf_append_buf(Buf *buf, Buf *append_buf) { buf_append_str(buf, buf_ptr(append_buf), buf_len(append_buf)); } +// TODO this method needs work +static inline Buf *buf_dirname(Buf *buf) { + if (buf_len(buf) <= 2) + zig_panic("TODO buf_dirname small"); + int last_index = buf_len(buf) - 1; + if (buf_ptr(buf)[buf_len(buf) - 1] == '/') { + last_index = buf_len(buf) - 2; + } + for (int i = last_index; i >= 0; i -= 1) { + uint8_t c = buf_ptr(buf)[i]; + if (c == '/') { + return buf_slice(buf, 0, i); + } + } + zig_panic("TODO buf_dirname no slash"); +} + + #endif diff --git a/src/main.cpp b/src/main.cpp index 50d0eff383..5d1d088321 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,6 +25,7 @@ static int usage(char *arg0) { fprintf(stderr, "Usage: %s --output outfile code.zig\n" "Other options:\n" "--version print version number and exit\n" + "-Ipath add path to header include path\n" , arg0); return EXIT_FAILURE; } @@ -377,6 +378,8 @@ struct Preprocess { Buf *out_buf; Buf *in_buf; Token *token; + ZigList *include_paths; + Buf *cur_dir_path; }; __attribute__ ((format (printf, 2, 3))) @@ -395,8 +398,33 @@ enum IncludeState { IncludeStateQuote, }; -static void render_include(Preprocess *p, Buf *include_path, char unquote_char) { - fprintf(stderr, "render_include \"%s\" '%c'\n", buf_ptr(include_path), unquote_char); +static Buf *find_include_file(Preprocess *p, char *dir_path, char *file_path) { + Buf *full_path = buf_sprintf("%s/%s", dir_path, file_path); + + FILE *f = fopen(buf_ptr(full_path), "rb"); + if (!f) + return nullptr; + + return fetch_file(f); +} + +static void render_include(Preprocess *p, Buf *target_path, char unquote_char) { + if (unquote_char == '"') { + Buf *file_contents = find_include_file(p, buf_ptr(p->cur_dir_path), buf_ptr(target_path)); + if (file_contents) { + buf_append_buf(p->out_buf, file_contents); + return; + } + } + for (int i = 0; i < p->include_paths->length; i += 1) { + char *include_path = p->include_paths->at(i); + Buf *file_contents = find_include_file(p, include_path, buf_ptr(target_path)); + if (file_contents) { + buf_append_buf(p->out_buf, file_contents); + return; + } + } + preprocess_error(p, "include path \"%s\" not found", buf_ptr(target_path)); } static void parse_and_render_include(Preprocess *p, Buf *directive_buf, int pos) { @@ -469,10 +497,14 @@ static void render_token(Preprocess *p) { } } -static Buf *preprocess(Buf *in_buf, ZigList *tokens) { +static Buf *preprocess(Buf *in_buf, ZigList *tokens, + ZigList *include_paths, Buf *cur_dir_path) +{ Preprocess p = {0}; p.out_buf = buf_alloc(); p.in_buf = in_buf; + p.include_paths = include_paths; + p.cur_dir_path = cur_dir_path; for (int i = 0; i < tokens->length; i += 1) { p.token = &tokens->at(i); render_token(&p); @@ -480,10 +512,13 @@ static Buf *preprocess(Buf *in_buf, ZigList *tokens) { return p.out_buf; } +char cur_dir[1024]; + int main(int argc, char **argv) { char *arg0 = argv[0]; char *in_file = NULL; char *out_file = NULL; + ZigList include_paths = {0}; for (int i = 1; i < argc; i += 1) { char *arg = argv[i]; if (arg[0] == '-' && arg[1] == '-') { @@ -500,6 +535,8 @@ int main(int argc, char **argv) { return usage(arg0); } } + } else if (arg[0] == '-' && arg[1] == 'I') { + include_paths.append(arg + 2); } else if (!in_file) { in_file = arg; } else { @@ -511,12 +548,18 @@ int main(int argc, char **argv) { return usage(arg0); FILE *in_f; + Buf *cur_dir_path; if (strcmp(in_file, "-") == 0) { in_f = stdin; + char *result = getcwd(cur_dir, sizeof(cur_dir)); + if (!result) + zig_panic("unable to get current working directory: %s", strerror(errno)); + cur_dir_path = buf_from_str(result); } else { in_f = fopen(in_file, "rb"); if (!in_f) zig_panic("unable to open %s for reading: %s\n", in_file, strerror(errno)); + cur_dir_path = buf_dirname(buf_from_str(in_file)); } Buf *in_data = fetch_file(in_f); @@ -528,7 +571,7 @@ int main(int argc, char **argv) { fprintf(stderr, "\nTokens:\n"); print_tokens(in_data, tokens); - Buf *preprocessed_source = preprocess(in_data, tokens); + Buf *preprocessed_source = preprocess(in_data, tokens, &include_paths, cur_dir_path); fprintf(stderr, "\nPreprocessed source:\n%s\n", buf_ptr(preprocessed_source)); diff --git a/src/util.cpp b/src/util.cpp index 15cc6caab4..341b1c354b 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -19,28 +19,3 @@ void zig_panic(const char *format, ...) { va_end(ap); abort(); } - -char *zig_alloc_sprintf(int *len, const char *format, ...) { - va_list ap, ap2; - va_start(ap, format); - va_copy(ap2, ap); - - int len1 = vsnprintf(nullptr, 0, format, ap); - assert(len1 >= 0); - - size_t required_size = len1 + 1; - char *mem = allocate(required_size); - if (!mem) - return nullptr; - - int len2 = vsnprintf(mem, required_size, format, ap2); - assert(len2 == len1); - - va_end(ap2); - va_end(ap); - - if (len) - *len = len1; - return mem; -} - diff --git a/src/util.hpp b/src/util.hpp index 5571bc3306..0cb731b95d 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -41,9 +41,6 @@ static inline T *reallocate_nonzero(T * old, size_t new_count) { return ptr; } -char *zig_alloc_sprintf(int *len, const char *format, ...) - __attribute__ ((format (printf, 2, 3))); - template constexpr long array_length(const T (&)[n]) { return n;