From e3ad13e05425b3afc9dbac19438ee8a978dcd1e8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 15 Oct 2017 20:15:01 -0400 Subject: [PATCH] fix windows argument parsing --- src/codegen.cpp | 2 +- src/os.cpp | 6 +++--- src/os.hpp | 2 ++ std/os/index.zig | 31 ++++++++++++++++++++----------- test/compile_errors.zig | 2 +- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 1b80ed6b3..5168a55fa 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4436,7 +4436,7 @@ static void do_code_gen(CodeGen *g) { if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), LLVMObjectFile, &err_msg, g->build_mode == BuildModeDebug)) { - zig_panic("unable to write object file: %s", err_msg); + zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg); } validate_inline_fns(g); diff --git a/src/os.cpp b/src/os.cpp index 03eed084b..2fcafead6 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -230,7 +230,7 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) { buf_init_from_buf(out_full_path, dirname); uint8_t c = *(buf_ptr(out_full_path) + buf_len(out_full_path) - 1); if (!os_is_sep(c)) - buf_append_char(out_full_path, '/'); + buf_append_char(out_full_path, ZIG_OS_SEP_CHAR); buf_append_buf(out_full_path, basename); } @@ -838,7 +838,7 @@ int os_make_path(Buf *path) { // march end_index backward until next path component while (true) { end_index -= 1; - if (buf_ptr(resolved_path)[end_index] == '/') + if (os_is_sep(buf_ptr(resolved_path)[end_index])) break; } continue; @@ -851,7 +851,7 @@ int os_make_path(Buf *path) { // march end_index forward until next path component while (true) { end_index += 1; - if (end_index == buf_len(resolved_path) || buf_ptr(resolved_path)[end_index] == '/') + if (end_index == buf_len(resolved_path) || os_is_sep(buf_ptr(resolved_path)[end_index])) break; } } diff --git a/src/os.hpp b/src/os.hpp index 293f6dcdf..1aac88536 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -97,12 +97,14 @@ int os_self_exe_path(Buf *out_path); #define ZIG_PRI_llu "I64u" #define ZIG_PRI_x64 "I64x" #define OS_SEP "\\" +#define ZIG_OS_SEP_CHAR '\\' #else #define ZIG_PRI_usize "zu" #define ZIG_PRI_u64 PRIu64 #define ZIG_PRI_llu "llu" #define ZIG_PRI_x64 PRIx64 #define OS_SEP "/" +#define ZIG_OS_SEP_CHAR '/' #endif #endif diff --git a/std/os/index.zig b/std/os/index.zig index 0e1342ab3..532633dfe 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -1220,7 +1220,6 @@ pub const ArgIteratorPosix = struct { pub const ArgIteratorWindows = struct { index: usize, cmd_line: &const u8, - backslash_count: usize, in_quote: bool, quote_count: usize, seen_quote_count: usize, @@ -1233,7 +1232,6 @@ pub const ArgIteratorWindows = struct { return ArgIteratorWindows { .index = 0, .cmd_line = cmd_line, - .backslash_count = 0, .in_quote = false, .quote_count = countQuotes(cmd_line), .seen_quote_count = 0, @@ -1266,25 +1264,30 @@ pub const ArgIteratorWindows = struct { } } + var backslash_count: usize = 0; while (true) : (self.index += 1) { const byte = self.cmd_line[self.index]; switch (byte) { 0 => return true, '"' => { - const quote_is_real = self.backslash_count % 2 == 0; + const quote_is_real = backslash_count % 2 == 0; if (quote_is_real) { self.seen_quote_count += 1; } }, '\\' => { - self.backslash_count += 1; + backslash_count += 1; }, ' ', '\t' => { if (self.seen_quote_count % 2 == 0 or self.seen_quote_count == self.quote_count) { return true; } + backslash_count = 0; + }, + else => { + backslash_count = 0; + continue; }, - else => continue, } } } @@ -1293,13 +1296,15 @@ pub const ArgIteratorWindows = struct { var buf = %return Buffer.initSize(allocator, 0); defer buf.deinit(); + var backslash_count: usize = 0; while (true) : (self.index += 1) { const byte = self.cmd_line[self.index]; switch (byte) { 0 => return buf.toOwnedSlice(), '"' => { - const quote_is_real = self.backslash_count % 2 == 0; - %return self.emitBackslashes(&buf, self.backslash_count / 2); + const quote_is_real = backslash_count % 2 == 0; + %return self.emitBackslashes(&buf, backslash_count / 2); + backslash_count = 0; if (quote_is_real) { self.seen_quote_count += 1; @@ -1311,10 +1316,11 @@ pub const ArgIteratorWindows = struct { } }, '\\' => { - self.backslash_count += 1; + backslash_count += 1; }, ' ', '\t' => { - %return self.emitBackslashes(&buf, self.backslash_count); + %return self.emitBackslashes(&buf, backslash_count); + backslash_count = 0; if (self.seen_quote_count % 2 == 1 and self.seen_quote_count != self.quote_count) { %return buf.appendByte(byte); } else { @@ -1322,7 +1328,8 @@ pub const ArgIteratorWindows = struct { } }, else => { - %return self.emitBackslashes(&buf, self.backslash_count); + %return self.emitBackslashes(&buf, backslash_count); + backslash_count = 0; %return buf.appendByte(byte); }, } @@ -1330,7 +1337,6 @@ pub const ArgIteratorWindows = struct { } fn emitBackslashes(self: &ArgIteratorWindows, buf: &Buffer, emit_count: usize) -> %void { - self.backslash_count = 0; var i: usize = 0; while (i < emit_count) : (i += 1) { %return buf.appendByte('\\'); @@ -1400,6 +1406,9 @@ test "windows arg parsing" { testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8{"a\\\"b", "c", "d"}); testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8{"a\\\\b c", "d", "e"}); testWindowsCmdLine(c"a b\tc \"d f", [][]const u8{"a", "b", "c", "\"d", "f"}); + + testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", + [][]const u8{".\\..\\zig-cache\\build", "bin\\zig.exe", ".\\..", ".\\..\\zig-cache", "--help"}); } fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const u8) { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 0ed02b70c..dd25886d2 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -889,7 +889,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { \\const resource = @embedFile("bogus.txt"); \\ \\export fn entry() -> usize { @sizeOf(@typeOf(resource)) } - , ".tmp_source.zig:1:29: error: unable to find '", "/bogus.txt'"); + , ".tmp_source.zig:1:29: error: unable to find '", "bogus.txt'"); cases.add("non-const expression in struct literal outside function", \\const Foo = struct {