Commit e3ad13e054

Andrew Kelley <superjoe30@gmail.com>
2017-10-16 02:15:01
fix windows argument parsing
1 parent f87f980
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);
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;
         }
     }
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
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) {
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 {