From ee02d04a9b21fb9889b022be9d3ee285139c25c2 Mon Sep 17 00:00:00 2001 From: flysand7 Date: Thu, 19 Sep 2024 22:18:46 +1100 Subject: [PATCH 1/2] [os2/process]: Don't quote arguments unless needed --- core/os/os2/process_windows.odin | 56 ++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/core/os/os2/process_windows.odin b/core/os/os2/process_windows.odin index edb321509..f2b889c72 100644 --- a/core/os/os2/process_windows.odin +++ b/core/os/os2/process_windows.odin @@ -638,6 +638,19 @@ _parse_command_line :: proc(cmd_line_w: [^]u16, allocator: runtime.Allocator) -> return } +@(private) +QUOTED_CHARS :: "()[]{}^=;!'+,`~\" " + +@(private) +_char_needs_escape :: proc(ch: u8) -> bool { + for r in transmute([]byte) string(QUOTED_CHARS) { + if ch == r { + return true + } + } + return false +} + _build_command_line :: proc(command: []string, allocator: runtime.Allocator) -> string { _write_byte_n_times :: #force_inline proc(builder: ^strings.Builder, b: byte, n: int) { for _ in 0 ..< n { @@ -650,26 +663,35 @@ _build_command_line :: proc(command: []string, allocator: runtime.Allocator) -> strings.write_byte(&builder, ' ') } j := 0 - strings.write_byte(&builder, '"') - for j < len(arg) { - backslashes := 0 - for j < len(arg) && arg[j] == '\\' { - backslashes += 1 + arg_needs_quoting := false + // Note(flysand): From documentation of `cmd.exe`, run "cmd /?" + if strings.contains_any(arg, QUOTED_CHARS) { + arg_needs_quoting = true + } + if !arg_needs_quoting { + strings.write_string(&builder, arg) + } else { + strings.write_byte(&builder, '"') + for j < len(arg) { + backslashes := 0 + for j < len(arg) && arg[j] == '\\' { + backslashes += 1 + j += 1 + } + if j == len(arg) { + _write_byte_n_times(&builder, '\\', 2*backslashes) + break + } else if arg[j] == '"' { + _write_byte_n_times(&builder, '\\', 2*backslashes+1) + strings.write_byte(&builder, arg[j]) + } else { + _write_byte_n_times(&builder, '\\', backslashes) + strings.write_byte(&builder, arg[j]) + } j += 1 } - if j == len(arg) { - _write_byte_n_times(&builder, '\\', 2*backslashes) - break - } else if arg[j] == '"' { - _write_byte_n_times(&builder, '\\', 2*backslashes+1) - strings.write_byte(&builder, '"') - } else { - _write_byte_n_times(&builder, '\\', backslashes) - strings.write_byte(&builder, arg[j]) - } - j += 1 + strings.write_byte(&builder, '"') } - strings.write_byte(&builder, '"') } return strings.to_string(builder) } From dad418cf910682c17de076591cab843e8241e602 Mon Sep 17 00:00:00 2001 From: flysand7 Date: Sat, 5 Oct 2024 07:23:15 +1100 Subject: [PATCH 2/2] Remove unused things --- core/os/os2/process_windows.odin | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/core/os/os2/process_windows.odin b/core/os/os2/process_windows.odin index f2b889c72..ec4884ea2 100644 --- a/core/os/os2/process_windows.odin +++ b/core/os/os2/process_windows.odin @@ -638,19 +638,6 @@ _parse_command_line :: proc(cmd_line_w: [^]u16, allocator: runtime.Allocator) -> return } -@(private) -QUOTED_CHARS :: "()[]{}^=;!'+,`~\" " - -@(private) -_char_needs_escape :: proc(ch: u8) -> bool { - for r in transmute([]byte) string(QUOTED_CHARS) { - if ch == r { - return true - } - } - return false -} - _build_command_line :: proc(command: []string, allocator: runtime.Allocator) -> string { _write_byte_n_times :: #force_inline proc(builder: ^strings.Builder, b: byte, n: int) { for _ in 0 ..< n { @@ -663,14 +650,7 @@ _build_command_line :: proc(command: []string, allocator: runtime.Allocator) -> strings.write_byte(&builder, ' ') } j := 0 - arg_needs_quoting := false - // Note(flysand): From documentation of `cmd.exe`, run "cmd /?" - if strings.contains_any(arg, QUOTED_CHARS) { - arg_needs_quoting = true - } - if !arg_needs_quoting { - strings.write_string(&builder, arg) - } else { + if strings.contains_any(arg, "()[]{}^=;!'+,`~\" ") { strings.write_byte(&builder, '"') for j < len(arg) { backslashes := 0 @@ -691,6 +671,8 @@ _build_command_line :: proc(command: []string, allocator: runtime.Allocator) -> j += 1 } strings.write_byte(&builder, '"') + } else { + strings.write_string(&builder, arg) } } return strings.to_string(builder)