Commit d519ce87dd

Andrew Kelley <superjoe30@gmail.com>
2015-08-06 06:47:08
preprocessor runs once
1 parent e715213
src/buffer.cpp
@@ -0,0 +1,25 @@
+#include "buffer.hpp"
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+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;
+}
src/buffer.hpp
@@ -11,11 +11,15 @@
 #include "list.hpp"
 
 #include <assert.h>
+#include <stdint.h>
 
 struct Buf {
     ZigList<char> 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
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<char *> *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<Token> *tokens) {
+static Buf *preprocess(Buf *in_buf, ZigList<Token> *tokens,
+        ZigList<char *> *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<Token> *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<char *> 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));
 
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<char>(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;
-}
-
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 <typename T, long n>
 constexpr long array_length(const T (&)[n]) {
     return n;
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")