diff --git a/example/multiple_files/main.zig b/example/multiple_files/main.zig index c7cb2412e24c12a4b7fc1b1662442a4e97ce44f9..f5332316ad52c9f355f36e722217c4d6976d2920 100644 --- a/example/multiple_files/main.zig +++ b/example/multiple_files/main.zig @@ -1,4 +1,4 @@ -export executable "test"; +export executable "test-multiple-files"; use "libc.zig"; use "foo.zig"; diff --git a/src/analyze.cpp b/src/analyze.cpp index d7d5aeb5b0b44029b81d4e71de89f5689b22fe35..5239835f0fd8ca9e08500fc5ebd7df24740692a4 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -11,7 +11,7 @@ #include "zig_llvm.hpp" #include "os.hpp" -static void add_node_error(CodeGen *g, AstNode *node, Buf *msg) { +void add_node_error(CodeGen *g, AstNode *node, Buf *msg) { ErrorMsg *err = allocate(1); err->line_start = node->line; err->column_start = node->column; diff --git a/src/analyze.hpp b/src/analyze.hpp index 0dca23194d95d80d3c7a8731d0ff945493d6e5b6..110a3614e0071d7c7e3154b3643058266df08dfc 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -9,7 +9,10 @@ #define ZIG_ANALYZE_HPP struct CodeGen; +struct AstNode; +struct Buf; void semantic_analyze(CodeGen *g); +void add_node_error(CodeGen *g, AstNode *node, Buf *msg); #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index 5ce95023e1fd581d14835ff43a6a0de3c5336439..baae91a20627d35da1813b85c271d3a59fd5dca0 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -669,6 +669,7 @@ static void init(CodeGen *g, Buf *source_path) { } static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *source_path, Buf *source_code) { + int err; Buf full_path = BUF_INIT; os_path_join(g->root_source_dir, source_path, &full_path); @@ -736,7 +737,11 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *source_path, Buf *sou Buf full_path = BUF_INIT; os_path_join(g->root_source_dir, &top_level_decl->data.use.path, &full_path); Buf *import_code = buf_alloc(); - os_fetch_file_path(&full_path, import_code); + if ((err = os_fetch_file_path(&full_path, import_code))) { + add_node_error(g, top_level_decl, + buf_sprintf("unable to open \"%s\": %s", buf_ptr(&full_path), err_str(err))); + break; + } codegen_add_code(g, &top_level_decl->data.use.path, import_code); } } diff --git a/src/error.cpp b/src/error.cpp index 7c3064c1436d587bd830efdad2e0f331e9a769ca..7690dd07761370334f5f33b691c0b7fa44de6ae6 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -6,6 +6,12 @@ const char *err_str(int err) { case ErrorNoMem: return "out of memory"; case ErrorInvalidFormat: return "invalid format"; case ErrorSemanticAnalyzeFail: return "semantic analyze failed"; + case ErrorAccess: return "access denied"; + case ErrorInterrupted: return "interrupted"; + case ErrorSystemResources: return "lack of system resources"; + case ErrorFileNotFound: return "file not found"; + case ErrorFileSystem: return "file system error"; + case ErrorFileTooBig: return "file too big"; } return "(invalid error)"; } diff --git a/src/error.hpp b/src/error.hpp index 7da2cf832211c5d7b7152a61e9c0f3840727951b..742f30700e6d237548c7b4e4bd570a180ce27cd5 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -13,6 +13,12 @@ enum Error { ErrorNoMem, ErrorInvalidFormat, ErrorSemanticAnalyzeFail, + ErrorAccess, + ErrorInterrupted, + ErrorSystemResources, + ErrorFileNotFound, + ErrorFileSystem, + ErrorFileTooBig, }; const char *err_str(int err); diff --git a/src/os.cpp b/src/os.cpp index bfc8eaa776a7e1490f589e2bd78aa452cc807955..be0b01f8a7ecfd31cfbc09119070e5cfe3099e83 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -7,6 +7,7 @@ #include "os.hpp" #include "util.hpp" +#include "error.hpp" #include #include @@ -143,26 +144,65 @@ void os_write_file(Buf *full_path, Buf *contents) { int os_fetch_file(FILE *f, Buf *out_contents) { int fd = fileno(f); struct stat st; - if (fstat(fd, &st)) - zig_panic("unable to stat file: %s", strerror(errno)); + if (fstat(fd, &st)) { + switch (errno) { + case EACCES: + return ErrorAccess; + case ENOENT: + return ErrorFileNotFound; + case ENOMEM: + return ErrorSystemResources; + case EINTR: + return ErrorInterrupted; + case EINVAL: + zig_unreachable(); + default: + return ErrorFileSystem; + } + } off_t big_size = st.st_size; - if (big_size > INT_MAX) - zig_panic("file too big"); + if (big_size > INT_MAX) { + return ErrorFileTooBig; + } int size = (int)big_size; buf_resize(out_contents, size); ssize_t ret = read(fd, buf_ptr(out_contents), size); - if (ret != size) - zig_panic("unable to read file: %s", strerror(errno)); + if (ret != size) { + switch (errno) { + case EINTR: + return ErrorInterrupted; + case EINVAL: + case EISDIR: + zig_unreachable(); + default: + return ErrorFileSystem; + } + } return 0; } int os_fetch_file_path(Buf *full_path, Buf *out_contents) { FILE *f = fopen(buf_ptr(full_path), "rb"); - if (!f) - zig_panic("unable to open %s: %s\n", buf_ptr(full_path), strerror(errno)); + if (!f) { + switch (errno) { + case EACCES: + return ErrorAccess; + case EINTR: + return ErrorInterrupted; + case EINVAL: + zig_unreachable(); + case ENFILE: + case ENOMEM: + return ErrorSystemResources; + case ENOENT: + return ErrorFileNotFound; + default: + return ErrorFileSystem; + } + } int result = os_fetch_file(f, out_contents); fclose(f); return result; diff --git a/src/util.hpp b/src/util.hpp index b3180528dd40bda33872590813520ffdb07f7d94..74fcf8502051333fb724ab6c4e2f2a251cbb77ba 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -16,8 +16,6 @@ #define BREAKPOINT __asm("int $0x03") -static const int COMPILE_FAILED_ERR_CODE = 10; // chosen with a random number generator - void zig_panic(const char *format, ...) __attribute__((cold)) __attribute__ ((noreturn)) diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 7597ba761ad4ab98f5fd22c8f9432e65efde9510..979ad389971dad8779e289f9d9015693405845cf 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -249,6 +249,10 @@ fn b() {} #version("aoeu") export executable "test"; )SOURCE", 1, ".tmp_source.zig:2:1: error: invalid version string"); + + add_compile_fail_case("bad import", R"SOURCE( +use "bogus-does-not-exist.zig"; + )SOURCE", 1, ".tmp_source.zig:2:1: error: unable to open \"./bogus-does-not-exist.zig\": file not found"); } static void print_compiler_invokation(TestCase *test_case, Buf *zig_stderr) {