1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/cmdline.cpp 
   3 // Purpose:     wxCmdLineParser implementation 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  28     #include "wx/dynarray.h" 
  29     #include "wx/string.h" 
  35 #include "wx/cmdline.h" 
  37 #if wxUSE_CMDLINE_PARSER 
  41 #include "wx/datetime.h" 
  42 #include "wx/msgout.h" 
  43 #include "wx/filename.h" 
  45 // ---------------------------------------------------------------------------- 
  47 // ---------------------------------------------------------------------------- 
  49 static wxString 
GetTypeName(wxCmdLineParamType type
); 
  51 static wxString 
GetOptionName(const wxChar 
*p
, const wxChar 
*allowedChars
); 
  53 static wxString 
GetShortOptionName(const wxChar 
*p
); 
  55 static wxString 
GetLongOptionName(const wxChar 
*p
); 
  57 // ---------------------------------------------------------------------------- 
  59 // ---------------------------------------------------------------------------- 
  61 // an internal representation of an option 
  62 struct wxCmdLineOption
 
  64     wxCmdLineOption(wxCmdLineEntryType k
, 
  68                     wxCmdLineParamType typ
, 
  71         wxASSERT_MSG( !shrt
.empty() || !lng
.empty(), 
  72                       _T("option should have at least one name") ); 
  76                 GetShortOptionName(shrt
).Len() == shrt
.Len(), 
  77                 wxT("Short option contains invalid characters") 
  82                 GetLongOptionName(lng
).Len() == lng
.Len(), 
  83                 wxT("Long option contains invalid characters") 
  99     // can't use union easily here, so just store all possible data fields, we 
 100     // don't waste much (might still use union later if the number of supported 
 101     // types increases, so always use the accessor functions and don't access 
 102     // the fields directly!) 
 104     void Check(wxCmdLineParamType 
WXUNUSED_UNLESS_DEBUG(typ
)) const 
 106         wxASSERT_MSG( type 
== typ
, _T("type mismatch in wxCmdLineOption") ); 
 109     long GetLongVal() const 
 110         { Check(wxCMD_LINE_VAL_NUMBER
); return m_longVal
; } 
 111     const wxString
& GetStrVal() const 
 112         { Check(wxCMD_LINE_VAL_STRING
); return m_strVal
;  } 
 114     const wxDateTime
& GetDateVal() const 
 115         { Check(wxCMD_LINE_VAL_DATE
);   return m_dateVal
; } 
 116 #endif // wxUSE_DATETIME 
 118     void SetLongVal(long val
) 
 119         { Check(wxCMD_LINE_VAL_NUMBER
); m_longVal 
= val
; m_hasVal 
= true; } 
 120     void SetStrVal(const wxString
& val
) 
 121         { Check(wxCMD_LINE_VAL_STRING
); m_strVal 
= val
; m_hasVal 
= true; } 
 123     void SetDateVal(const wxDateTime
& val
) 
 124         { Check(wxCMD_LINE_VAL_DATE
); m_dateVal 
= val
; m_hasVal 
= true; } 
 125 #endif // wxUSE_DATETIME 
 127     void SetHasValue(bool hasValue 
= true) { m_hasVal 
= hasValue
; } 
 128     bool HasValue() const { return m_hasVal
; } 
 131     wxCmdLineEntryType kind
; 
 135     wxCmdLineParamType type
; 
 144     wxDateTime m_dateVal
; 
 145 #endif // wxUSE_DATETIME 
 148 struct wxCmdLineParam
 
 150     wxCmdLineParam(const wxString
& desc
, 
 151                    wxCmdLineParamType typ
, 
 159     wxString description
; 
 160     wxCmdLineParamType type
; 
 164 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
); 
 165 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
); 
 167 #include "wx/arrimpl.cpp" 
 169 WX_DEFINE_OBJARRAY(wxArrayOptions
) 
 170 WX_DEFINE_OBJARRAY(wxArrayParams
) 
 172 // the parser internal state 
 173 struct wxCmdLineParserData
 
 176     wxString m_switchChars
;     // characters which may start an option 
 177     bool m_enableLongOptions
;   // true if long options are enabled 
 178     wxString m_logo
;            // some extra text to show in Usage() 
 181     wxArrayString m_arguments
;  // == argv, argc == m_arguments.GetCount() 
 182     wxArrayOptions m_options
;   // all possible options and switchrs 
 183     wxArrayParams m_paramDesc
;  // description of all possible params 
 184     wxArrayString m_parameters
; // all params found 
 187     wxCmdLineParserData(); 
 188     void SetArguments(int argc
, char **argv
); 
 190     void SetArguments(int argc
, wxChar 
**argv
); 
 191 #endif // wxUSE_UNICODE 
 192     void SetArguments(const wxString
& cmdline
); 
 194     int FindOption(const wxString
& name
); 
 195     int FindOptionByLongName(const wxString
& name
); 
 198 // ============================================================================ 
 200 // ============================================================================ 
 202 // ---------------------------------------------------------------------------- 
 203 // wxCmdLineParserData 
 204 // ---------------------------------------------------------------------------- 
 206 wxCmdLineParserData::wxCmdLineParserData() 
 208     m_enableLongOptions 
= true; 
 210     m_switchChars 
= _T("-"); 
 212     m_switchChars 
= _T("/-"); 
 216 void wxCmdLineParserData::SetArguments(int argc
, char **argv
) 
 220     for ( int n 
= 0; n 
< argc
; n
++ ) 
 222         m_arguments
.push_back(wxString::FromAscii(argv
[n
])); 
 228 void wxCmdLineParserData::SetArguments(int argc
, wxChar 
**argv
) 
 232     for ( int n 
= 0; n 
< argc
; n
++ ) 
 234         m_arguments
.push_back(argv
[n
]); 
 238 #endif // wxUSE_UNICODE 
 240 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
) 
 244     if(wxTheApp 
&& wxTheApp
->argc 
> 0) 
 245         m_arguments
.push_back(wxTheApp
->argv
[0]); 
 247         m_arguments
.push_back(wxEmptyString
); 
 249     wxArrayString args 
= wxCmdLineParser::ConvertStringToArgs(cmdLine
); 
 251     WX_APPEND_ARRAY(m_arguments
, args
); 
 254 int wxCmdLineParserData::FindOption(const wxString
& name
) 
 258         size_t count 
= m_options
.GetCount(); 
 259         for ( size_t n 
= 0; n 
< count
; n
++ ) 
 261             if ( m_options
[n
].shortName 
== name 
) 
 272 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
) 
 274     size_t count 
= m_options
.GetCount(); 
 275     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 277         if ( m_options
[n
].longName 
== name 
) 
 287 // ---------------------------------------------------------------------------- 
 288 // construction and destruction 
 289 // ---------------------------------------------------------------------------- 
 291 void wxCmdLineParser::Init() 
 293     m_data 
= new wxCmdLineParserData
; 
 296 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
) 
 298     m_data
->SetArguments(argc
, argv
); 
 303 void wxCmdLineParser::SetCmdLine(int argc
, wxChar 
**argv
) 
 305     m_data
->SetArguments(argc
, argv
); 
 308 #endif // wxUSE_UNICODE 
 310 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
) 
 312     m_data
->SetArguments(cmdline
); 
 315 wxCmdLineParser::~wxCmdLineParser() 
 320 // ---------------------------------------------------------------------------- 
 322 // ---------------------------------------------------------------------------- 
 324 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
) 
 326     m_data
->m_switchChars 
= switchChars
; 
 329 void wxCmdLineParser::EnableLongOptions(bool enable
) 
 331     m_data
->m_enableLongOptions 
= enable
; 
 334 bool wxCmdLineParser::AreLongOptionsEnabled() 
 336     return m_data
->m_enableLongOptions
; 
 339 void wxCmdLineParser::SetLogo(const wxString
& logo
) 
 341     m_data
->m_logo 
= logo
; 
 344 // ---------------------------------------------------------------------------- 
 345 // command line construction 
 346 // ---------------------------------------------------------------------------- 
 348 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc 
*desc
) 
 352         switch ( desc
->kind 
) 
 354             case wxCMD_LINE_SWITCH
: 
 355                 AddSwitch(desc
->shortName
, desc
->longName
, desc
->description
, 
 359             case wxCMD_LINE_OPTION
: 
 360                 AddOption(desc
->shortName
, desc
->longName
, desc
->description
, 
 361                           desc
->type
, desc
->flags
); 
 364             case wxCMD_LINE_PARAM
: 
 365                 AddParam(desc
->description
, desc
->type
, desc
->flags
); 
 369                 wxFAIL_MSG( _T("unknown command line entry type") ); 
 370                 // still fall through 
 372             case wxCMD_LINE_NONE
: 
 378 void wxCmdLineParser::AddSwitch(const wxString
& shortName
, 
 379                                 const wxString
& longName
, 
 380                                 const wxString
& desc
, 
 383     wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
, 
 384                   _T("duplicate switch") ); 
 386     wxCmdLineOption 
*option 
= new wxCmdLineOption(wxCMD_LINE_SWITCH
, 
 387                                                   shortName
, longName
, desc
, 
 388                                                   wxCMD_LINE_VAL_NONE
, flags
); 
 390     m_data
->m_options
.Add(option
); 
 393 void wxCmdLineParser::AddOption(const wxString
& shortName
, 
 394                                 const wxString
& longName
, 
 395                                 const wxString
& desc
, 
 396                                 wxCmdLineParamType type
, 
 399     wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
, 
 400                   _T("duplicate option") ); 
 402     wxCmdLineOption 
*option 
= new wxCmdLineOption(wxCMD_LINE_OPTION
, 
 403                                                   shortName
, longName
, desc
, 
 406     m_data
->m_options
.Add(option
); 
 409 void wxCmdLineParser::AddParam(const wxString
& desc
, 
 410                                wxCmdLineParamType type
, 
 413     // do some consistency checks: a required parameter can't follow an 
 414     // optional one and nothing should follow a parameter with MULTIPLE flag 
 416     if ( !m_data
->m_paramDesc
.IsEmpty() ) 
 418         wxCmdLineParam
& param 
= m_data
->m_paramDesc
.Last(); 
 420         wxASSERT_MSG( !(param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE
), 
 421                       _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") ); 
 423         if ( !(flags 
& wxCMD_LINE_PARAM_OPTIONAL
) ) 
 425             wxASSERT_MSG( !(param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL
), 
 426                           _T("a required parameter can't follow an optional one") ); 
 431     wxCmdLineParam 
*param 
= new wxCmdLineParam(desc
, type
, flags
); 
 433     m_data
->m_paramDesc
.Add(param
); 
 436 // ---------------------------------------------------------------------------- 
 437 // access to parse command line 
 438 // ---------------------------------------------------------------------------- 
 440 bool wxCmdLineParser::Found(const wxString
& name
) const 
 442     int i 
= m_data
->FindOption(name
); 
 443     if ( i 
== wxNOT_FOUND 
) 
 444         i 
= m_data
->FindOptionByLongName(name
); 
 446     wxCHECK_MSG( i 
!= wxNOT_FOUND
, false, _T("unknown switch") ); 
 448     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 449     if ( !opt
.HasValue() ) 
 455 bool wxCmdLineParser::Found(const wxString
& name
, wxString 
*value
) const 
 457     int i 
= m_data
->FindOption(name
); 
 458     if ( i 
== wxNOT_FOUND 
) 
 459         i 
= m_data
->FindOptionByLongName(name
); 
 461     wxCHECK_MSG( i 
!= wxNOT_FOUND
, false, _T("unknown option") ); 
 463     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 464     if ( !opt
.HasValue() ) 
 467     wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") ); 
 469     *value 
= opt
.GetStrVal(); 
 474 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const 
 476     int i 
= m_data
->FindOption(name
); 
 477     if ( i 
== wxNOT_FOUND 
) 
 478         i 
= m_data
->FindOptionByLongName(name
); 
 480     wxCHECK_MSG( i 
!= wxNOT_FOUND
, false, _T("unknown option") ); 
 482     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 483     if ( !opt
.HasValue() ) 
 486     wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") ); 
 488     *value 
= opt
.GetLongVal(); 
 494 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime 
*value
) const 
 496     int i 
= m_data
->FindOption(name
); 
 497     if ( i 
== wxNOT_FOUND 
) 
 498         i 
= m_data
->FindOptionByLongName(name
); 
 500     wxCHECK_MSG( i 
!= wxNOT_FOUND
, false, _T("unknown option") ); 
 502     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 503     if ( !opt
.HasValue() ) 
 506     wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") ); 
 508     *value 
= opt
.GetDateVal(); 
 512 #endif // wxUSE_DATETIME 
 514 size_t wxCmdLineParser::GetParamCount() const 
 516     return m_data
->m_parameters
.size(); 
 519 wxString 
wxCmdLineParser::GetParam(size_t n
) const 
 521     wxCHECK_MSG( n 
< GetParamCount(), wxEmptyString
, _T("invalid param index") ); 
 523     return m_data
->m_parameters
[n
]; 
 526 // Resets switches and options 
 527 void wxCmdLineParser::Reset() 
 529     for ( size_t i 
= 0; i 
< m_data
->m_options
.Count(); i
++ ) 
 531         wxCmdLineOption
& opt 
= m_data
->m_options
[i
]; 
 532         opt
.SetHasValue(false); 
 537 // ---------------------------------------------------------------------------- 
 538 // the real work is done here 
 539 // ---------------------------------------------------------------------------- 
 541 int wxCmdLineParser::Parse(bool showUsage
) 
 543     bool maybeOption 
= true;    // can the following arg be an option? 
 544     bool ok 
= true;             // true until an error is detected 
 545     bool helpRequested 
= false; // true if "-h" was given 
 546     bool hadRepeatableParam 
= false; // true if found param with MULTIPLE flag 
 548     size_t currentParam 
= 0;    // the index in m_paramDesc 
 550     size_t countParam 
= m_data
->m_paramDesc
.GetCount(); 
 557     size_t count 
= m_data
->m_arguments
.size(); 
 558     for ( size_t n 
= 1; ok 
&& (n 
< count
); n
++ )    // 0 is program name 
 560         arg 
= m_data
->m_arguments
[n
]; 
 562         // special case: "--" should be discarded and all following arguments 
 563         // should be considered as parameters, even if they start with '-' and 
 564         // not like options (this is POSIX-like) 
 565         if ( arg 
== _T("--") ) 
 572         // empty argument or just '-' is not an option but a parameter 
 573         if ( maybeOption 
&& arg
.length() > 1 && 
 574                 wxStrchr(m_data
->m_switchChars
, arg
[0u]) ) 
 578             int optInd 
= wxNOT_FOUND
;   // init to suppress warnings 
 580             // an option or a switch: find whether it's a long or a short one 
 581             if ( arg
[0u] == _T('-') && arg
[1u] == _T('-') ) 
 587                 const wxChar 
*p 
= arg
.c_str() + 2; 
 589                 bool longOptionsEnabled 
= AreLongOptionsEnabled(); 
 591                 name 
= GetLongOptionName(p
); 
 593                 if (longOptionsEnabled
) 
 595                     optInd 
= m_data
->FindOptionByLongName(name
); 
 596                     if ( optInd 
== wxNOT_FOUND 
) 
 598                         errorMsg 
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str()) << wxT("\n"); 
 603                     optInd 
= wxNOT_FOUND
; // Sanity check 
 605                     // Print the argument including leading "--" 
 606                     name
.Prepend( wxT("--") ); 
 607                     errorMsg 
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n"); 
 615                 // a short one: as they can be cumulated, we try to find the 
 616                 // longest substring which is a valid option 
 617                 const wxChar 
*p 
= arg
.c_str() + 1; 
 619                 name 
= GetShortOptionName(p
); 
 621                 size_t len 
= name
.length(); 
 626                         // we couldn't find a valid option name in the 
 627                         // beginning of this string 
 628                         errorMsg 
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n"); 
 634                         optInd 
= m_data
->FindOption(name
.Left(len
)); 
 636                         // will try with one character less the next time 
 640                 while ( optInd 
== wxNOT_FOUND 
); 
 642                 len
++;  // compensates extra len-- above 
 643                 if ( (optInd 
!= wxNOT_FOUND
) && (len 
!= name
.length()) ) 
 645                     // first of all, the option name is only part of this 
 647                     name 
= name
.Left(len
); 
 649                     // our option is only part of this argument, there is 
 650                     // something else in it - it is either the value of this 
 651                     // option or other switches if it is a switch 
 652                     if ( m_data
->m_options
[(size_t)optInd
].kind
 
 653                             == wxCMD_LINE_SWITCH 
) 
 655                         // pretend that all the rest of the argument is the 
 656                         // next argument, in fact 
 657                         wxString arg2 
= arg
[0u]; 
 658                         arg2 
+= arg
.Mid(len 
+ 1); // +1 for leading '-' 
 660                         m_data
->m_arguments
.insert
 
 661                             (m_data
->m_arguments
.begin() + n 
+ 1, arg2
); 
 664                     //else: it's our value, we'll deal with it below 
 668             if ( optInd 
== wxNOT_FOUND 
) 
 672                 continue;   // will break, in fact 
 675             wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)optInd
]; 
 676             if ( opt
.kind 
== wxCMD_LINE_SWITCH 
) 
 678                 // nothing more to do 
 681                 if ( opt
.flags 
& wxCMD_LINE_OPTION_HELP 
) 
 683                     helpRequested 
= true; 
 685                     // it's not an error, but we still stop here 
 693                 // +1 for leading '-' 
 694                 const wxChar 
*p 
= arg
.c_str() + 1 + name
.length(); 
 697                     p
++;    // for another leading '-' 
 699                     if ( *p
++ != _T('=') ) 
 701                         errorMsg 
<< wxString::Format(_("Option '%s' requires a value, '=' expected."), name
.c_str()) << wxT("\n"); 
 717                             // the value is in the next argument 
 720                                 // ... but there is none 
 721                                 errorMsg 
<< wxString::Format(_("Option '%s' requires a value."), 
 722                                                              name
.c_str()) << wxT("\n"); 
 728                                 // ... take it from there 
 729                                 p 
= m_data
->m_arguments
[n
].c_str(); 
 734                             // the value is right here: this may be legal or 
 735                             // not depending on the option style 
 736                             if ( opt
.flags 
& wxCMD_LINE_NEEDS_SEPARATOR 
) 
 738                                 errorMsg 
<< wxString::Format(_("Separator expected after the option '%s'."), 
 739                                                              name
.c_str()) << wxT("\n"); 
 752                             wxFAIL_MSG( _T("unknown option type") ); 
 753                             // still fall through 
 755                         case wxCMD_LINE_VAL_STRING
: 
 756                             opt
.SetStrVal(value
); 
 759                         case wxCMD_LINE_VAL_NUMBER
: 
 762                                 if ( value
.ToLong(&val
) ) 
 768                                     errorMsg 
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."), 
 769                                                                  value
.c_str(), name
.c_str()) << wxT("\n"); 
 777                         case wxCMD_LINE_VAL_DATE
: 
 780                                 const wxChar 
*res 
= dt
.ParseDate(value
); 
 783                                     errorMsg 
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."), 
 784                                                                  name
.c_str(), value
.c_str()) << wxT("\n"); 
 794 #endif // wxUSE_DATETIME 
 802             if ( currentParam 
< countParam 
) 
 804                 wxCmdLineParam
& param 
= m_data
->m_paramDesc
[currentParam
]; 
 806                 // TODO check the param type 
 808                 m_data
->m_parameters
.push_back(arg
); 
 810                 if ( !(param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE
) ) 
 816                     wxASSERT_MSG( currentParam 
== countParam 
- 1, 
 817                                   _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") ); 
 819                     // remember that we did have this last repeatable parameter 
 820                     hadRepeatableParam 
= true; 
 825                 errorMsg 
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str()) << wxT("\n"); 
 832     // verify that all mandatory options were given 
 835         size_t countOpt 
= m_data
->m_options
.GetCount(); 
 836         for ( size_t n 
= 0; ok 
&& (n 
< countOpt
); n
++ ) 
 838             wxCmdLineOption
& opt 
= m_data
->m_options
[n
]; 
 839             if ( (opt
.flags 
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() ) 
 844                     optName 
= opt
.shortName
; 
 848                     if ( AreLongOptionsEnabled() ) 
 850                         optName
.Printf( _("%s (or %s)"), 
 851                                         opt
.shortName
.c_str(), 
 852                                         opt
.longName
.c_str() ); 
 856                         optName
.Printf( wxT("%s"), 
 857                                         opt
.shortName
.c_str() ); 
 861                 errorMsg 
<< wxString::Format(_("The value for the option '%s' must be specified."), 
 862                                              optName
.c_str()) << wxT("\n"); 
 868         for ( ; ok 
&& (currentParam 
< countParam
); currentParam
++ ) 
 870             wxCmdLineParam
& param 
= m_data
->m_paramDesc
[currentParam
]; 
 871             if ( (currentParam 
== countParam 
- 1) && 
 872                  (param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE
) && 
 875                 // special case: currentParam wasn't incremented, but we did 
 876                 // have it, so don't give error 
 880             if ( !(param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL
) ) 
 882                 errorMsg 
<< wxString::Format(_("The required parameter '%s' was not specified."), 
 883                                              param
.description
.c_str()) << wxT("\n"); 
 890     // if there was an error during parsing the command line, show this error 
 891     // and also the usage message if it had been requested 
 892     if ( !ok 
&& (!errorMsg
.empty() || (helpRequested 
&& showUsage
)) ) 
 894         wxMessageOutput
* msgOut 
= wxMessageOutput::Get(); 
 899                 usage 
= GetUsageString(); 
 901             msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() ); 
 905             wxFAIL_MSG( _T("no wxMessageOutput object?") ); 
 909     return ok 
? 0 : helpRequested 
? -1 : 1; 
 912 // ---------------------------------------------------------------------------- 
 913 // give the usage message 
 914 // ---------------------------------------------------------------------------- 
 916 void wxCmdLineParser::Usage() 
 918     wxMessageOutput
* msgOut 
= wxMessageOutput::Get(); 
 921         msgOut
->Printf( wxT("%s"), GetUsageString().c_str() ); 
 925         wxFAIL_MSG( _T("no wxMessageOutput object?") ); 
 929 wxString 
wxCmdLineParser::GetUsageString() 
 932     if ( m_data
->m_arguments
.empty() ) 
 935             appname 
= wxTheApp
->GetAppName(); 
 939         appname 
= wxFileName(m_data
->m_arguments
[0]).GetName(); 
 942     // we construct the brief cmd line desc on the fly, but not the detailed 
 943     // help message below because we want to align the options descriptions 
 944     // and for this we must first know the longest one of them 
 946     wxArrayString namesOptions
, descOptions
; 
 948     if ( !m_data
->m_logo
.empty() ) 
 950         usage 
<< m_data
->m_logo 
<< _T('\n'); 
 953     usage 
<< wxString::Format(_("Usage: %s"), appname
.c_str()); 
 955     // the switch char is usually '-' but this can be changed with 
 956     // SetSwitchChars() and then the first one of possible chars is used 
 957     wxChar chSwitch 
= !m_data
->m_switchChars 
? _T('-') 
 958                                              : m_data
->m_switchChars
[0u]; 
 960     bool areLongOptionsEnabled 
= AreLongOptionsEnabled(); 
 961     size_t n
, count 
= m_data
->m_options
.GetCount(); 
 962     for ( n 
= 0; n 
< count
; n
++ ) 
 964         wxCmdLineOption
& opt 
= m_data
->m_options
[n
]; 
 967         if ( !(opt
.flags 
& wxCMD_LINE_OPTION_MANDATORY
) ) 
 972         if ( !opt
.shortName
.empty() ) 
 974             usage 
<< chSwitch 
<< opt
.shortName
; 
 976         else if ( areLongOptionsEnabled 
&& !opt
.longName
.empty() ) 
 978             usage 
<< _T("--") << opt
.longName
; 
 982             if (!opt
.longName
.empty()) 
 984                 wxFAIL_MSG( wxT("option with only a long name while long ") 
 985                     wxT("options are disabled") ); 
 989                 wxFAIL_MSG( _T("option without neither short nor long name") ); 
 995         if ( !opt
.shortName
.empty() ) 
 997             option 
<< _T("  ") << chSwitch 
<< opt
.shortName
; 
1000         if ( areLongOptionsEnabled 
&& !opt
.longName
.empty() ) 
1002             option 
<< (option
.empty() ? _T("  ") : _T(", ")) 
1003                    << _T("--") << opt
.longName
; 
1006         if ( opt
.kind 
!= wxCMD_LINE_SWITCH 
) 
1009             val 
<< _T('<') << GetTypeName(opt
.type
) << _T('>'); 
1010             usage 
<< _T(' ') << val
; 
1011             option 
<< (!opt
.longName 
? _T(':') : _T('=')) << val
; 
1014         if ( !(opt
.flags 
& wxCMD_LINE_OPTION_MANDATORY
) ) 
1019         namesOptions
.push_back(option
); 
1020         descOptions
.push_back(opt
.description
); 
1023     count 
= m_data
->m_paramDesc
.GetCount(); 
1024     for ( n 
= 0; n 
< count
; n
++ ) 
1026         wxCmdLineParam
& param 
= m_data
->m_paramDesc
[n
]; 
1029         if ( param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL 
) 
1034         usage 
<< param
.description
; 
1036         if ( param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE 
) 
1041         if ( param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL 
) 
1049     // now construct the detailed help message 
1050     size_t len
, lenMax 
= 0; 
1051     count 
= namesOptions
.size(); 
1052     for ( n 
= 0; n 
< count
; n
++ ) 
1054         len 
= namesOptions
[n
].length(); 
1059     for ( n 
= 0; n 
< count
; n
++ ) 
1061         len 
= namesOptions
[n
].length(); 
1062         usage 
<< namesOptions
[n
] 
1063               << wxString(_T(' '), lenMax 
- len
) << _T('\t') 
1071 // ---------------------------------------------------------------------------- 
1072 // private functions 
1073 // ---------------------------------------------------------------------------- 
1075 static wxString 
GetTypeName(wxCmdLineParamType type
) 
1081             wxFAIL_MSG( _T("unknown option type") ); 
1082             // still fall through 
1084         case wxCMD_LINE_VAL_STRING
: 
1088         case wxCMD_LINE_VAL_NUMBER
: 
1092         case wxCMD_LINE_VAL_DATE
: 
1101 Returns a string which is equal to the string pointed to by p, but up to the 
1102 point where p contains an character that's not allowed. 
1103 Allowable characters are letters and numbers, and characters pointed to by 
1104 the parameter allowedChars. 
1106 For example, if p points to "abcde-@-_", and allowedChars is "-_", 
1107 this function returns "abcde-". 
1109 static wxString 
GetOptionName(const wxChar 
*p
, 
1110     const wxChar 
*allowedChars
) 
1114     while ( *p 
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) ) 
1122 // Besides alphanumeric characters, short and long options can 
1123 // have other characters. 
1125 // A short option additionally can have these 
1126 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?") 
1128 // A long option can have the same characters as a short option and a '-'. 
1129 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \ 
1130     wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-") 
1132 static wxString 
GetShortOptionName(const wxChar 
*p
) 
1134     return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
); 
1137 static wxString 
GetLongOptionName(const wxChar 
*p
) 
1139     return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
); 
1142 #endif // wxUSE_CMDLINE_PARSER 
1144 // ---------------------------------------------------------------------------- 
1146 // ---------------------------------------------------------------------------- 
1149    This function is mainly used under Windows (as under Unix we always get the 
1150    command line arguments as argc/argv anyhow) and so it tries to follow 
1151    Windows conventions for the command line handling, not Unix ones. For 
1152    instance, backslash is not special except when it precedes double quote when 
1157 wxArrayString 
wxCmdLineParser::ConvertStringToArgs(const wxChar 
*p
) 
1164     bool isInsideQuotes 
= false; 
1168         while ( *p 
== _T(' ') || *p 
== _T('\t') ) 
1172         if ( *p 
== _T('\0') ) 
1175         // parse this parameter 
1176         bool endParam 
= false; 
1177         bool lastBS 
= false; 
1178         for ( arg
.clear(); !endParam
; p
++ ) 
1185                         isInsideQuotes 
= !isInsideQuotes
; 
1187                         // don't put quote in arg 
1190                     //else: quote has no special meaning but the backslash 
1191                     //      still remains -- makes no sense but this is what 
1197                     // backslash does *not* quote the space, only quotes do 
1198                     if ( isInsideQuotes 
) 
1200                         // skip assignment below 
1216             lastBS 
= *p 
== _T('\\'); 
1221         args
.push_back(arg
);