From 63fa01fd4f7bc7a28a6e223d49f8eca34ac8bfde Mon Sep 17 00:00:00 2001 From: Doug Coleman Date: Tue, 11 Oct 2011 12:21:04 -0700 Subject: [PATCH] Proper double-quote and backslash escaping for windows command line arguments. Fixes #245. --- .../io/launcher/windows/windows-tests.factor | 21 +++++++++++++++++++ basis/io/launcher/windows/windows.factor | 19 ++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/basis/io/launcher/windows/windows-tests.factor b/basis/io/launcher/windows/windows-tests.factor index 3d3d29a937..c5050336ca 100644 --- a/basis/io/launcher/windows/windows-tests.factor +++ b/basis/io/launcher/windows/windows-tests.factor @@ -18,6 +18,27 @@ IN: io.launcher.windows.tests [ "\"\\\"hi you\\\"\"" ] [ { "\"hi you\"" } join-arguments ] unit-test +! Commented line -- what should appear on the command line +! \foo\\bar\\\bas\ -> \foo\\bar\\\bas\ +[ "\\foo\\\\bar\\\\\\bas\\" ] +[ { "\\foo\\\\bar\\\\\\bas\\" } join-arguments ] unit-test + +! \"foo"\\bar\\\bas\ -> \\\"foo\"\\bar\\\bas\ +[ "\\\\\\\"foo\\\"\\\\bar\\\\\\bas\\" ] +[ { "\\\"foo\"\\\\bar\\\\\\bas\\" } join-arguments ] unit-test + +! \foo\\"bar"\\\bas\ -> \foo\\\\\"bar\"\\\bas\ +[ "\\foo\\\\\\\\\\\"bar\\\"\\\\\\bas\\" ] +[ { "\\foo\\\\\"bar\"\\\\\\bas\\" } join-arguments ] unit-test + +! \foo\\bar\\\"bas"\ -> \foo\\bar\\\\\\\"bas\"\ +[ "\\foo\\\\bar\\\\\\\\\\\\\\\"bas\\\"\\" ] +[ { "\\foo\\\\bar\\\\\\\"bas\"\\" } join-arguments ] unit-test + +! \foo\\bar bar\\\bas\ -> "\foo\\bar bar\\\bas\\" +[ "\"\\foo\\\\bar bar\\\\\\bas\\\\\"" ] +[ { "\\foo\\\\bar bar\\\\\\bas\\" } join-arguments ] unit-test + [ ] [ diff --git a/basis/io/launcher/windows/windows.factor b/basis/io/launcher/windows/windows.factor index 100f2d36ff..1a9a5a7fbb 100755 --- a/basis/io/launcher/windows/windows.factor +++ b/basis/io/launcher/windows/windows.factor @@ -58,9 +58,26 @@ TUPLE: CreateProcess-args 0 count-trailing-backslashes 2 * CHAR: \\ append ; +! Find groups of \, groups of \ followed by ", or naked " : escape-double-quote ( str -- newstr ) - "\"" split "\\\"" join ; + [ + { [ drop CHAR: \ = ] [ nip "\\\"" member? ] } 2&& + ] monotonic-split [ + dup last CHAR: " = [ + dup length 1 > [ + ! String of backslashes + double-quote + length 1 - 2 * CHAR: \ "\\\"" append + ] [ + ! Single double-quote + drop "\\\"" + ] if + ] when + ] map "" concat-as ; +! Naked double-quotes get a backslash before them +! Backslashes before a double-quote get doubled in the output +! If there's a space, double trailing backslashes and surround by quotes +! See http://msdn.microsoft.com/en-us/library/ms647232.aspx : escape-argument ( str -- newstr ) escape-double-quote CHAR: \s over member? [