From: Vadim Zeitlin Date: Sun, 25 Nov 2001 21:36:28 +0000 (+0000) Subject: added wxCmdLineParser::ConvertStringToArgs(), wxApp::ConertToStandardCommandArgs... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/31f6de22b0575e7feac83e7f99b5774a3490fc1a added wxCmdLineParser::ConvertStringToArgs(), wxApp::ConertToStandardCommandArgs() now uses it git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@12698 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/cmdline.h b/include/wx/cmdline.h index a3a685ce3f..dccfc40687 100644 --- a/include/wx/cmdline.h +++ b/include/wx/cmdline.h @@ -191,8 +191,11 @@ public: // gets the value of Nth parameter (as string only for now) wxString GetParam(size_t n = 0u) const; - // Resets switches and options - void Reset(); + // Resets switches and options + void Reset(); + + // break down the command line in arguments + static wxArrayString ConvertStringToArgs(const wxChar *cmdline); private: // common part of all ctors @@ -201,6 +204,17 @@ private: struct wxCmdLineParserData *m_data; }; -#endif // wxUSE_CMDLINE_PARSER +#else // !wxUSE_CMDLINE_PARSER + +// this function is always available (even if !wxUSE_CMDLINE_PARSER) because it +// is used by wxWin itself under Windows +class WXDLLEXPORT wxCmdLineParser +{ +public: + static wxArrayString ConvertStringToArgs(const wxChar *cmdline); +}; + +#endif // wxUSE_CMDLINE_PARSER/!wxUSE_CMDLINE_PARSER #endif // _WX_CMDLINE_H_ + diff --git a/include/wx/msw/app.h b/include/wx/msw/app.h index e361fa3ca8..c6e1348015 100644 --- a/include/wx/msw/app.h +++ b/include/wx/msw/app.h @@ -81,7 +81,7 @@ public: static bool UnregisterWindowClasses(); // Convert Windows to argc, argv style - void ConvertToStandardCommandArgs(char* p); + void ConvertToStandardCommandArgs(const char* p); // message processing // ------------------ diff --git a/samples/console/console.cpp b/samples/console/console.cpp index 662ca1c85a..51b30e3160 100644 --- a/samples/console/console.cpp +++ b/samples/console/console.cpp @@ -39,42 +39,46 @@ // conditional compilation // ---------------------------------------------------------------------------- -// what to test (in alphabetic order)? - -//#define TEST_ARRAYS -//#define TEST_CHARSET -//#define TEST_CMDLINE -//#define TEST_DATETIME -//#define TEST_DIR -//#define TEST_DLLLOADER -//#define TEST_ENVIRON -//#define TEST_EXECUTE -//#define TEST_FILE -#define TEST_FILECONF -//#define TEST_FILENAME -//#define TEST_FILETIME -//#define TEST_FTP -//#define TEST_HASH -//#define TEST_INFO_FUNCTIONS -//#define TEST_LIST -//#define TEST_LOCALE -//#define TEST_LOG -//#define TEST_LONGLONG -//#define TEST_MIME -//#define TEST_PATHLIST -//#define TEST_REGCONF -//#define TEST_REGEX -//#define TEST_REGISTRY -//#define TEST_SNGLINST -//#define TEST_SOCKETS -//#define TEST_STREAMS -//#define TEST_STRINGS -//#define TEST_THREADS -//#define TEST_TIMER -//#define TEST_VCARD -- don't enable this (VZ) -//#define TEST_WCHAR -//#define TEST_ZIP -//#define TEST_ZLIB +// what to test (in alphabetic order)? uncomment the line below to do all tests +//#define TEST_ALL +#ifdef TEST_ALL + #define TEST_ARRAYS + #define TEST_CHARSET + #define TEST_CMDLINE + #define TEST_DATETIME + #define TEST_DIR + #define TEST_DLLLOADER + #define TEST_ENVIRON + #define TEST_EXECUTE + #define TEST_FILE + #define TEST_FILECONF + #define TEST_FILENAME + #define TEST_FILETIME + #define TEST_FTP + #define TEST_HASH + #define TEST_INFO_FUNCTIONS + #define TEST_LIST + #define TEST_LOCALE + #define TEST_LOG + #define TEST_LONGLONG + #define TEST_MIME + #define TEST_PATHLIST + #define TEST_REGCONF + #define TEST_REGEX + #define TEST_REGISTRY + #define TEST_SNGLINST + #define TEST_SOCKETS + #define TEST_STREAMS + #define TEST_STRINGS + #define TEST_THREADS + #define TEST_TIMER + // #define TEST_VCARD -- don't enable this (VZ) + #define TEST_WCHAR + #define TEST_ZIP + #define TEST_ZLIB +#else + #define TEST_CMDLINE +#endif #ifdef TEST_SNGLINST #include "wx/snglinst.h" @@ -178,6 +182,8 @@ static void TestCharset() #include "wx/cmdline.h" #include "wx/datetime.h" +#if wxUSE_CMDLINE_PARSER + static void ShowCmdLine(const wxCmdLineParser& parser) { wxString s = "Input files: "; @@ -209,6 +215,32 @@ static void ShowCmdLine(const wxCmdLineParser& parser) wxLogMessage(s); } +#endif // wxUSE_CMDLINE_PARSER + +static void TestCmdLineConvert() +{ + static const char *cmdlines[] = + { + "arg1 arg2", + "-a \"-bstring 1\" -c\"string 2\" \"string 3\"", + "literal \\\" and \"\"", + }; + + for ( size_t n = 0; n < WXSIZEOF(cmdlines); n++ ) + { + const char *cmdline = cmdlines[n]; + printf("Parsing: %s\n", cmdline); + wxArrayString args = wxCmdLineParser::ConvertStringToArgs(cmdline); + + size_t count = args.GetCount(); + printf("\targc = %u\n", count); + for ( size_t arg = 0; arg < count; arg++ ) + { + printf("\targv[%u] = %s\n", arg, args[arg]); + } + } +} + #endif // TEST_CMDLINE // ---------------------------------------------------------------------------- @@ -4944,6 +4976,9 @@ int main(int argc, char **argv) #endif // TEST_CHARSET #ifdef TEST_CMDLINE + TestCmdLineConvert(); + +#if wxUSE_CMDLINE_PARSER static const wxCmdLineEntryDesc cmdLineDesc[] = { { wxCMD_LINE_SWITCH, _T("h"), _T("help"), "show this help message", @@ -4984,6 +5019,8 @@ int main(int argc, char **argv) wxLogMessage("Syntax error detected, aborting."); break; } +#endif // wxUSE_CMDLINE_PARSER + #endif // TEST_CMDLINE #ifdef TEST_STRINGS diff --git a/src/common/cmdline.cpp b/src/common/cmdline.cpp index 46517df3a2..142cf53dad 100644 --- a/src/common/cmdline.cpp +++ b/src/common/cmdline.cpp @@ -28,6 +28,8 @@ #pragma hdrstop #endif +#include "wx/cmdline.h" + #if wxUSE_CMDLINE_PARSER #ifndef WX_PRECOMP @@ -42,7 +44,6 @@ #include #include "wx/datetime.h" -#include "wx/cmdline.h" // ---------------------------------------------------------------------------- // private functions @@ -201,44 +202,9 @@ void wxCmdLineParserData::SetArguments(const wxString& cmdLine) m_arguments.Add(wxTheApp->GetAppName()); - // Break up string - // Treat strings enclosed in double-quotes as single arguments - int i = 0; - int len = cmdLine.Length(); - while (i < len) - { - // Skip whitespace - while ((i < len) && wxIsspace(cmdLine.GetChar(i))) - i ++; - - if (i < len) - { - if (cmdLine.GetChar(i) == wxT('"')) // We found the start of a string - { - i ++; - int first = i; - while ((i < len) && (cmdLine.GetChar(i) != wxT('"'))) - i ++; - - wxString arg(cmdLine.Mid(first, (i - first))); + wxArrayString args = wxCmdLineParser::ConvertStringToArgs(cmdLine); - m_arguments.Add(arg); - - if (i < len) - i ++; // Skip past 2nd quote - } - else // Unquoted argument - { - int first = i; - while ((i < len) && !wxIsspace(cmdLine.GetChar(i))) - i ++; - - wxString arg(cmdLine.Mid(first, (i - first))); - - m_arguments.Add(arg); - } - } - } + WX_APPEND_ARRAY(m_arguments, args); } int wxCmdLineParserData::FindOption(const wxString& name) @@ -964,7 +930,7 @@ void wxCmdLineParser::Usage() } // ---------------------------------------------------------------------------- -// global functions +// private functions // ---------------------------------------------------------------------------- static wxString GetTypeName(wxCmdLineParamType type) @@ -985,3 +951,96 @@ static wxString GetTypeName(wxCmdLineParamType type) } #endif // wxUSE_CMDLINE_PARSER + +// ---------------------------------------------------------------------------- +// global functions +// ---------------------------------------------------------------------------- + +/* 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 + if ( isQuotedByBS ) + { + 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'): + if ( isInsideQuotes ) + { + // preserve it, skip endParam below + break; + } + //else: fall through + + case _T('\0'): + endParam = TRUE; + break; + } + + // end of argument? + if ( endParam ) + break; + + // otherwise copy this char to arg + if ( !skipChar ) + { + arg += *p; + } + } + + args.Add(arg); + } + + return args; +} + diff --git a/src/msw/app.cpp b/src/msw/app.cpp index 91a7290854..67e6a44eae 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -45,9 +45,10 @@ #include "wx/dynarray.h" #include "wx/wxchar.h" #include "wx/icon.h" + #include "wx/log.h" #endif -#include "wx/log.h" +#include "wx/cmdline.h" #include "wx/module.h" #include "wx/msw/private.h" @@ -548,73 +549,28 @@ bool wxApp::UnregisterWindowClasses() // Convert Windows to argc, argv style // --------------------------------------------------------------------------- -void wxApp::ConvertToStandardCommandArgs(char* lpCmdLine) +void wxApp::ConvertToStandardCommandArgs(const char* lpCmdLine) { - wxStringList args; + // break the command line in words + wxArrayString args = + wxCmdLineParser::ConvertStringToArgs(wxConvertMB2WX(lpCmdLine)); - wxString cmdLine(lpCmdLine); - int count = 0; + // +1 here for the program name + argc = args.GetCount() + 1; - // Get application name - wxChar name[260]; // 260 is MAX_PATH value from windef.h - ::GetModuleFileName(wxhInstance, name, WXSIZEOF(name)); + // and +1 here for the terminating NULL + argv = new wxChar *[argc + 1]; - args.Add(name); - count++; + argv[0] = new wxChar[260]; // 260 is MAX_PATH value from windef.h + ::GetModuleFileName(wxhInstance, argv[0], 260); - wxStrcpy(name, wxFileNameFromPath(name)); - wxStripExtension(name); - wxTheApp->SetAppName(name); - - // Break up string - // Treat strings enclosed in double-quotes as single arguments - int i = 0; - int len = cmdLine.Length(); - while (i < len) + for ( int i = 1; i < argc; i++ ) { - // Skip whitespace - while ((i < len) && wxIsspace(cmdLine.GetChar(i))) - i ++; - - if (i < len) - { - if (cmdLine.GetChar(i) == wxT('"')) // We found the start of a string - { - i ++; - int first = i; - while ((i < len) && (cmdLine.GetChar(i) != wxT('"'))) - i ++; - - wxString arg(cmdLine.Mid(first, (i - first))); - - args.Add(arg); - count ++; - - if (i < len) - i ++; // Skip past 2nd quote - } - else // Unquoted argument - { - int first = i; - while ((i < len) && !wxIsspace(cmdLine.GetChar(i))) - i ++; - - wxString arg(cmdLine.Mid(first, (i - first))); - - args.Add(arg); - count ++; - } - } + argv[i] = copystring(args[i - 1]); } - wxTheApp->argv = new wxChar*[count + 1]; - for (i = 0; i < count; i++) - { - wxString arg(args[i]); - wxTheApp->argv[i] = copystring((const wxChar*)arg); - } - wxTheApp->argv[count] = NULL; // argv[] is a NULL-terminated list - wxTheApp->argc = count; + // argv[] must be NULL-terminated + argv[argc] = NULL; } //// Cleans up any wxWindows internal structures left lying around