From e1c03d9e8eb52b489d9b47bbe2f12cacac8a999f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 4 Jan 2018 13:48:45 -0500 Subject: [PATCH] self-hosted compiler works on windows * better error message for realpath failing * fix bug in std.io.readFileAllocExtra incorrectly returning error.EndOfStream * implement std.os.selfExePath and std.os.selfExeDirPath for windows --- src-self-hosted/module.zig | 2 +- std/io.zig | 2 +- std/os/index.zig | 51 ++++++++++++++++++++++++++++---------- std/os/windows/index.zig | 2 ++ 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/src-self-hosted/module.zig b/src-self-hosted/module.zig index a8098217ec..2e1ebf0e3a 100644 --- a/src-self-hosted/module.zig +++ b/src-self-hosted/module.zig @@ -208,7 +208,7 @@ pub const Module = struct { const root_src_path = self.root_src_path ?? @panic("TODO handle null root src path"); const root_src_real_path = os.path.real(self.allocator, root_src_path) %% |err| { - %return printError("unable to open '{}': {}", root_src_path, err); + %return printError("unable to get real path '{}': {}", root_src_path, err); return err; }; %defer self.allocator.free(root_src_real_path); diff --git a/std/io.zig b/std/io.zig index 44e5634ae0..9c39a02a8c 100644 --- a/std/io.zig +++ b/std/io.zig @@ -513,7 +513,7 @@ pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len %defer allocator.free(buf); var adapter = FileInStream.init(&file); - %return adapter.stream.readNoEof(buf); + %return adapter.stream.readNoEof(buf[0..size]); return buf; } diff --git a/std/os/index.zig b/std/os/index.zig index f668546a37..96d374503f 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -1544,6 +1544,40 @@ pub fn openSelfExe() -> %io.File { } } +/// Get the path to the current executable. +/// If you only need the directory, use selfExeDirPath. +/// If you only want an open file handle, use openSelfExe. +/// This function may return an error if the current executable +/// was deleted after spawning. +/// Caller owns returned memory. +pub fn selfExePath(allocator: &mem.Allocator) -> %[]u8 { + switch (builtin.os) { + Os.linux => { + @compileError("TODO: selfExePath for linux"); + }, + Os.windows => { + var out_path = %return Buffer.initSize(allocator, 256); + %defer out_path.deinit(); + while (true) { + const dword_len = %return math.cast(windows.DWORD, out_path.len()); + const copied_amt = windows.GetModuleFileNameA(null, out_path.ptr(), dword_len); + if (copied_amt <= 0) { + const err = windows.GetLastError(); + return switch (err) { + else => unexpectedErrorWindows(err), + }; + } + if (copied_amt < out_path.len()) { + out_path.shrink(copied_amt); + return out_path.toOwnedSlice(); + } + %return out_path.resize(out_path.len() * 2); + } + }, + else => @compileError("Unsupported OS"), + } +} + /// Get the directory path that contains the current executable. /// Caller owns returned memory. pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 { @@ -1559,19 +1593,10 @@ pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 { return allocator.shrink(u8, full_exe_path, dir.len); }, Os.windows => { - @panic("TODO windows std.os.selfExeDirPath"); - //buf_resize(out_path, 256); - //for (;;) { - // DWORD copied_amt = GetModuleFileName(nullptr, buf_ptr(out_path), buf_len(out_path)); - // if (copied_amt <= 0) { - // return ErrorFileNotFound; - // } - // if (copied_amt < buf_len(out_path)) { - // buf_resize(out_path, copied_amt); - // return 0; - // } - // buf_resize(out_path, buf_len(out_path) * 2); - //} + const self_exe_path = %return selfExePath(allocator); + %defer allocator.free(self_exe_path); + const dirname = os.path.dirname(self_exe_path); + return allocator.shrink(u8, self_exe_path, dirname.len); }, else => @compileError("unimplemented: std.os.selfExeDirPath for " ++ @tagName(builtin.os)), } diff --git a/std/os/windows/index.zig b/std/os/windows/index.zig index 0ce3794cdc..d460e94f64 100644 --- a/std/os/windows/index.zig +++ b/std/os/windows/index.zig @@ -48,6 +48,8 @@ pub extern "kernel32" stdcallcc fn GetExitCodeProcess(hProcess: HANDLE, lpExitCo pub extern "kernel32" stdcallcc fn GetFileSizeEx(hFile: HANDLE, lpFileSize: &LARGE_INTEGER) -> BOOL; +pub extern "kernel32" stdcallcc fn GetModuleFileNameA(hModule: ?HMODULE, lpFilename: LPSTR, nSize: DWORD) -> DWORD; + pub extern "kernel32" stdcallcc fn GetLastError() -> DWORD; pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(in_hFile: HANDLE,