+
+/*
+Returns a string which is equal to the string pointed to by p, but up to the
+point where p contains an character that's not allowed.
+Allowable characters are letters and numbers, and characters pointed to by
+the parameter allowedChars.
+
+For example, if p points to "abcde-@-_", and allowedChars is "-_",
+this function returns "abcde-".
+*/
+static wxString GetOptionName(const wxChar *p,
+ const wxChar *allowedChars)
+{
+ wxString argName;
+
+ while ( *p && (wxIsalnum(*p) || wxStrchr(allowedChars, *p)) )
+ {
+ argName += *p++;
+ }
+
+ return argName;
+}
+
+// Besides alphanumeric characters, short and long options can
+// have other characters.
+
+// A short option additionally can have these
+#define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
+
+// A long option can have the same characters as a short option and a '-'.
+#define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
+ wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
+
+static wxString GetShortOptionName(const wxChar *p)
+{
+ return GetOptionName(p, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION);
+}
+
+static wxString GetLongOptionName(const wxChar *p)
+{
+ return GetOptionName(p, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION);
+}
+
+#endif // wxUSE_CMDLINE_PARSER
+
+// ----------------------------------------------------------------------------
+// global functions
+// ----------------------------------------------------------------------------
+
+/*
+ This function is mainly used under Windows (as under Unix we always get the
+ command line arguments as argc/argv anyhow) and so it tries to handle the
+ Windows path names (separated by backslashes) correctly. For this it only
+ considers that a backslash may be used to escape another backslash (but
+ normally this is _not_ needed) or a quote but nothing else.
+
+ In particular, to pass a single argument containing a space to the program
+ it should be quoted:
+
+ myprog.exe foo bar -> argc = 3, argv[1] = "foo", argv[2] = "bar"
+ myprog.exe "foo bar" -> argc = 2, argv[1] = "foo bar"
+
+ To pass an argument containing spaces and quotes, the latter should be
+ escaped with a backslash:
+
+ myprog.exe "foo \"bar\"" -> argc = 2, argv[1] = "foo "bar""
+
+ This hopefully matches the conventions used by Explorer/command line
+ interpreter under Windows. If not, this function should be fixed.
+ */
+
+/* static */
+wxArrayString wxCmdLineParser::ConvertStringToArgs(const wxChar *p)
+{
+ wxArrayString args;
+
+ wxString arg;
+ arg.reserve(1024);
+
+ bool isInsideQuotes = FALSE;
+ for ( ;; )
+ {
+ // skip white space
+ while ( *p == _T(' ') || *p == _T('\t') )
+ p++;
+
+ // anything left?
+ if ( *p == _T('\0') )
+ break;
+
+ // parse this parameter
+ arg.clear();
+ for ( ;; p++ )
+ {
+ // do we have a (lone) backslash?
+ bool isQuotedByBS = FALSE;
+ while ( *p == _T('\\') )
+ {
+ p++;
+
+ // if we have 2 backslashes in a row, output one
+ // unless it looks like a UNC path \\machine\dir\file.ext
+ if ( isQuotedByBS || arg.Len() == 0 )
+ {
+ arg += _T('\\');
+ isQuotedByBS = FALSE;
+ }
+ else // the next char is quoted
+ {
+ isQuotedByBS = TRUE;
+ }
+ }
+
+ bool skipChar = FALSE,
+ endParam = FALSE;
+ switch ( *p )
+ {
+ case _T('"'):
+ if ( !isQuotedByBS )
+ {
+ // don't put the quote itself in the arg
+ skipChar = TRUE;
+
+ isInsideQuotes = !isInsideQuotes;
+ }
+ //else: insert a literal quote
+
+ break;
+
+ case _T(' '):
+ case _T('\t'):
+ // we intentionally don't check for preceding backslash
+ // here as if we allowed it to be used to escape spaces the
+ // cmd line of the form "foo.exe a:\ c:\bar" wouldn't be
+ // parsed correctly
+ if ( isInsideQuotes )
+ {
+ // preserve it, skip endParam below
+ break;
+ }
+ //else: fall through
+
+ case _T('\0'):
+ endParam = TRUE;
+ break;
+
+ default:
+ if ( isQuotedByBS )
+ {
+ // ignore backslash before an ordinary character - this
+ // is needed to properly handle the file names under
+ // Windows appearing in the command line
+ arg += _T('\\');
+ }
+ }
+
+ // end of argument?
+ if ( endParam )
+ break;
+
+ // otherwise copy this char to arg
+ if ( !skipChar )
+ {
+ arg += *p;
+ }
+ }
+
+ args.Add(arg);
+ }
+
+ return args;
+}
+