Browse Source

[os2/process]: Don't quote arguments unless needed

flysand7 11 months ago
parent
commit
ee02d04a9b
1 changed files with 39 additions and 17 deletions
  1. 39 17
      core/os/os2/process_windows.odin

+ 39 - 17
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)
 }