diff --git a/common/t-w32-cmdline.c b/common/t-w32-cmdline.c index 8686a376a..172489c70 100644 --- a/common/t-w32-cmdline.c +++ b/common/t-w32-cmdline.c @@ -59,8 +59,18 @@ test_all (void) { "a\\\\\\b d\"e f\"g h", 3, { "a\\\\\\b", "de fg", "h" }}, { "a\\\\\\\"b c d", 3, { "a\\\"b", "c", "d" }}, { "a\\\\\\\\\"b c\" d e", 3, { "a\\\\b c", "d", "e" }}, + /* Examples from "Parsing C Command-Line Arguments" dated 11/09/2020. + * https://docs.microsoft.com/en-us/cpp/c-language/\ + * parsing-c-command-line-arguments?view=msvc-160 + */ + { "\"a b c\" d e", 3, { "a b c", "d", "e" }}, + { "\"ab\\\"c\" \"\\\\\" d", 3, { "ab\"c", "\\", "d" }}, + { "a\\\\\\b d\"e f\"g h", 3, { "a\\\\\\b", "de fg", "h" }}, + { "a\\\\\\\"b c d", 3, { "a\\\"b", "c", "d" }}, + { "a\\\\\\\\\"b c\" d e", 3, { "a\\\\b c", "d", "e" }}, + { "a\"b\"\" c d", 1, { "ab\" c d" }}, /* Some arbitrary tests created using mingw. - * But I am nire sure whether their parser is fully correct. + * But I am not sure whether their parser is fully correct. */ { "e:a a b\"c\" ", 3, { "e:a", "a", "bc" }}, /* { "e:a a b\"c\"\" d\"\"e \" ", */ diff --git a/common/w32-misc.c b/common/w32-misc.c index 8aef12e4a..ae194facb 100644 --- a/common/w32-misc.c +++ b/common/w32-misc.c @@ -46,7 +46,7 @@ count_backslashes (const char *s) static void -strip_one_arg (char *string) +strip_one_arg (char *string, int endquote) { char *s, *d; unsigned int n, i; @@ -62,6 +62,12 @@ strip_one_arg (char *string) if ((n&1)) /* Odd number of backslashes. */ *d++ = '"'; /* Print the quote. */ } + else if (!s[n] && endquote) + { + for (i=0; i < n/2; i++) + *d++ = '\\'; + s--; + } else /* Print all backslashes. */ { for (i=0; i < n; i++) @@ -94,10 +100,21 @@ parse_cmdstring (char *string, char **argv) { if (*p == '\\' && p[1] == '"') p++; + else if (*p == '\\' && p[1] == '\\') + p++; else if (*p == '"') { - if (argv && (p[1] == ' ' || p[1] == '\t' || !p[1])) - *p = 0; + if (p[1] == ' ' || p[1] == '\t' || !p[1]) + { + if (argv) + { + *p = 0; + strip_one_arg (p0, 1); + argv[argc] = p0; + } + argc++; + p0 = NULL; + } inquote = 0; } } @@ -126,7 +143,7 @@ parse_cmdstring (char *string, char **argv) if (argv) { *p = 0; - strip_one_arg (p0); + strip_one_arg (p0, inquote); argv[argc] = p0; } argc++; @@ -144,7 +161,7 @@ parse_cmdstring (char *string, char **argv) if (argv) { *p = 0; - strip_one_arg (p0); + strip_one_arg (p0, inquote); argv[argc] = p0; } argc++;