From: Vadim Zeitlin Date: Wed, 16 Jul 2008 00:49:25 +0000 (+0000) Subject: implement flag for Unix-like behaviour in wxCmdLineParser::ConverStringToArgs() X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/a4761b4c08e6272c69bd242b3323ab47dbbc8902 implement flag for Unix-like behaviour in wxCmdLineParser::ConverStringToArgs() git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54648 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/cmdline.h b/include/wx/cmdline.h index 4539dd61ab..10bf956eb0 100644 --- a/include/wx/cmdline.h +++ b/include/wx/cmdline.h @@ -19,6 +19,13 @@ #include "wx/arrstr.h" #include "wx/cmdargs.h" +// determines ConvertStringToArgs() behaviour +enum wxCmdLineSplitType +{ + wxCMD_LINE_SPLIT_DOS, + wxCMD_LINE_SPLIT_UNIX +}; + #if wxUSE_CMDLINE_PARSER class WXDLLIMPEXP_FWD_BASE wxDateTime; @@ -233,7 +240,9 @@ public: void Reset(); // break down the command line in arguments - static wxArrayString ConvertStringToArgs(const wxString& cmdline); + static wxArrayString + ConvertStringToArgs(const wxString& cmdline, + wxCmdLineSplitType type = wxCMD_LINE_SPLIT_DOS); private: // common part of all ctors @@ -251,7 +260,9 @@ private: class WXDLLIMPEXP_BASE wxCmdLineParser { public: - static wxArrayString ConvertStringToArgs(const wxString& cmdline); + static wxArrayString + ConvertStringToArgs(const wxString& cmdline, + wxCmdLineSplitType type = wxCMD_LINE_SPLIT_DOS); }; #endif // wxUSE_CMDLINE_PARSER/!wxUSE_CMDLINE_PARSER diff --git a/interface/wx/cmdline.h b/interface/wx/cmdline.h index 5aae4a95b7..6dd779f8ce 100644 --- a/interface/wx/cmdline.h +++ b/interface/wx/cmdline.h @@ -59,6 +59,15 @@ enum wxCmdLineEntryType wxCMD_LINE_NONE ///< Use this to terminate the list. }; +/** + Flags determining ConvertStringToArgs() behaviour. + */ +enum wxCmdLineSplitType +{ + wxCMD_LINE_SPLIT_DOS, + wxCMD_LINE_SPLIT_UNIX +}; + /** The structure wxCmdLineEntryDesc is used to describe the one command line switch, option or parameter. An array of such structures should be passed @@ -301,12 +310,20 @@ public: bool AreLongOptionsEnabled() const; /** - Breaks down the string containing the full command line in words. The - words are separated by whitespace. The quotes can be used in the input - string to quote the white space and the back slashes can be used to - quote the quotes. + Breaks down the string containing the full command line in words. + + Words are separated by whitespace and double quotes can be used to + preserve the spaces inside the words. + + By default, this function uses Windows-like word splitting algorithm, + i.e. single quotes have no special meaning and backslash can't be used + to escape spaces neither. With @c wxCMD_LINE_SPLIT_UNIX flag Unix + semantics is used, i.e. both single and double quotes can be used and + backslash can be used to escape all the other special characters. */ - static wxArrayString ConvertStringToArgs(const wxChar cmdline); + static wxArrayString + ConvertStringToArgs(const wxChar cmdline, + wxCmdLineSplitType flags = wxCMD_LINE_SPLIT_DOS); /** Identical to EnableLongOptions(@false). diff --git a/src/common/cmdline.cpp b/src/common/cmdline.cpp index f055522190..95afbfe27f 100644 --- a/src/common/cmdline.cpp +++ b/src/common/cmdline.cpp @@ -1280,15 +1280,15 @@ static wxString GetLongOptionName(wxString::const_iterator p, */ /* static */ -wxArrayString wxCmdLineParser::ConvertStringToArgs(const wxString& cmdline) +wxArrayString +wxCmdLineParser::ConvertStringToArgs(const wxString& cmdline, + wxCmdLineSplitType type) { wxArrayString args; wxString arg; arg.reserve(1024); - bool isInsideQuotes = false; - const wxString::const_iterator end = cmdline.end(); wxString::const_iterator p = cmdline.begin(); @@ -1303,31 +1303,76 @@ wxArrayString wxCmdLineParser::ConvertStringToArgs(const wxString& cmdline) break; // parse this parameter - bool lastBS = false; + bool lastBS = false, + isInsideQuotes = false; + wxChar chDelim = '\0'; for ( arg.clear(); p != end; ++p ) { const wxChar ch = *p; - if ( ch == '"' ) + + if ( type == wxCMD_LINE_SPLIT_DOS ) { - if ( !lastBS ) + if ( ch == '"' ) { - isInsideQuotes = !isInsideQuotes; + if ( !lastBS ) + { + isInsideQuotes = !isInsideQuotes; - // don't put quote in arg - continue; + // don't put quote in arg + continue; + } + //else: quote has no special meaning but the backslash + // still remains -- makes no sense but this is what + // Windows does + } + // note that backslash does *not* quote the space, only quotes do + else if ( !isInsideQuotes && (ch == ' ' || ch == '\t') ) + { + ++p; // skip this space anyhow + break; } - //else: quote has no special meaning but the backslash - // still remains -- makes no sense but this is what - // Windows does + + lastBS = ch == '\\'; } - // note that backslash does *not* quote the space, only quotes do - else if ( !isInsideQuotes && (ch == ' ' || ch == '\t') ) + else // type == wxCMD_LINE_SPLIT_UNIX { - ++p; // skip this space anyhow - break; - } + if ( !lastBS ) + { + if ( isInsideQuotes ) + { + if ( ch == chDelim ) + { + isInsideQuotes = false; + + continue; // don't use the quote itself + } + } + else // not in quotes and not escaped + { + if ( ch == '\'' || ch == '"' ) + { + isInsideQuotes = true; + chDelim = ch; - lastBS = ch == '\\'; + continue; // don't use the quote itself + } + + if ( ch == ' ' || ch == '\t' ) + { + ++p; // skip this space anyhow + break; + } + } + + lastBS = ch == '\\'; + if ( lastBS ) + continue; + } + else // escaped by backslash, just use as is + { + lastBS = false; + } + } arg += ch; } diff --git a/tests/cmdline/cmdlinetest.cpp b/tests/cmdline/cmdlinetest.cpp index 388166ffaf..d1f8ec7c4e 100644 --- a/tests/cmdline/cmdlinetest.cpp +++ b/tests/cmdline/cmdlinetest.cpp @@ -55,12 +55,26 @@ CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( CmdLineTestCase, "CmdLineTestCase" ); void CmdLineTestCase::ConvertStringTestCase() { - #define WX_ASSERT_ARGS_EQUAL(s, args) \ + #define WX_ASSERT_DOS_ARGS_EQUAL(s, args) \ + { \ + const wxArrayString \ + argsDOS(wxCmdLineParser::ConvertStringToArgs(args, \ + wxCMD_LINE_SPLIT_DOS)); \ + WX_ASSERT_STRARRAY_EQUAL(s, argsDOS); \ + } + + #define WX_ASSERT_UNIX_ARGS_EQUAL(s, args) \ { \ - const wxArrayString a(wxCmdLineParser::ConvertStringToArgs(args));\ - WX_ASSERT_STRARRAY_EQUAL(s, a); \ + const wxArrayString \ + argsUnix(wxCmdLineParser::ConvertStringToArgs(args, \ + wxCMD_LINE_SPLIT_UNIX)); \ + WX_ASSERT_STRARRAY_EQUAL(s, argsUnix); \ } + #define WX_ASSERT_ARGS_EQUAL(s, args) \ + WX_ASSERT_DOS_ARGS_EQUAL(s, args) \ + WX_ASSERT_UNIX_ARGS_EQUAL(s, args) + // normal cases WX_ASSERT_ARGS_EQUAL( "foo", "foo" ) WX_ASSERT_ARGS_EQUAL( "foo bar", "\"foo bar\"" ) @@ -74,12 +88,31 @@ void CmdLineTestCase::ConvertStringTestCase() WX_ASSERT_ARGS_EQUAL( "foo", "foo \t " ) WX_ASSERT_ARGS_EQUAL( "foo|bar", "foo bar " ) WX_ASSERT_ARGS_EQUAL( "foo|bar|", "foo bar \"" ) - WX_ASSERT_ARGS_EQUAL( "foo|bar|\\", "foo bar \\" ) + WX_ASSERT_DOS_ARGS_EQUAL( "foo|bar|\\", "foo bar \\" ) + WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar|", "foo bar \\" ) - // check for (broken) Windows semantics: backslash doesn't escape spaces - WX_ASSERT_ARGS_EQUAL( "foo|bar\\|baz", "foo bar\\ baz" ); - WX_ASSERT_ARGS_EQUAL( "foo|bar\\\"baz", "foo \"bar\\\"baz\"" ); + WX_ASSERT_ARGS_EQUAL( "12 34", "1\"2 3\"4" ); + WX_ASSERT_ARGS_EQUAL( "1|2 34", "1 \"2 3\"4" ); + WX_ASSERT_ARGS_EQUAL( "1|2 3|4", "1 \"2 3\" 4" ); + // check for (broken) Windows semantics: backslash doesn't escape spaces + WX_ASSERT_DOS_ARGS_EQUAL( "foo|bar\\|baz", "foo bar\\ baz" ); + WX_ASSERT_DOS_ARGS_EQUAL( "foo|bar\\\"baz", "foo \"bar\\\"baz\"" ); + + // check for more sane Unix semantics: backslash does escape spaces and + // quotes + WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar baz", "foo bar\\ baz" ); + WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar\"baz", "foo \"bar\\\"baz\"" ); + + // check that single quotes work too with Unix semantics + WX_ASSERT_UNIX_ARGS_EQUAL( "foo bar", "'foo bar'" ) + WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar baz", "foo 'bar baz'" ) + WX_ASSERT_UNIX_ARGS_EQUAL( "foo|bar baz", "foo 'bar baz'" ) + WX_ASSERT_UNIX_ARGS_EQUAL( "O'Henry", "\"O'Henry\"" ) + WX_ASSERT_UNIX_ARGS_EQUAL( "O'Henry", "O\\'Henry" ) + + #undef WX_ASSERT_DOS_ARGS_EQUAL + #undef WX_ASSERT_UNIX_ARGS_EQUAL #undef WX_ASSERT_ARGS_EQUAL }