1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        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 license 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "cmdline.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  31 #include "wx/cmdline.h" 
  33 #if wxUSE_CMDLINE_PARSER 
  36     #include "wx/string.h" 
  40     #include "wx/dynarray.h" 
  41     #include "wx/filefn.h" 
  46 #include "wx/datetime.h" 
  47 #include "wx/msgout.h" 
  49 // ---------------------------------------------------------------------------- 
  51 // ---------------------------------------------------------------------------- 
  53 static wxString 
GetTypeName(wxCmdLineParamType type
); 
  55 static wxString 
GetOptionName(const wxChar 
*p
, const wxChar 
*allowedChars
); 
  57 static wxString 
GetShortOptionName(const wxChar 
*p
); 
  59 static wxString 
GetLongOptionName(const wxChar 
*p
); 
  61 // ---------------------------------------------------------------------------- 
  63 // ---------------------------------------------------------------------------- 
  65 // an internal representation of an option 
  66 struct wxCmdLineOption
 
  68     wxCmdLineOption(wxCmdLineEntryType k
, 
  72                     wxCmdLineParamType typ
, 
  75         wxASSERT_MSG( !shrt
.empty() || !lng
.empty(), 
  76                       _T("option should have at least one name") ); 
  80                 GetShortOptionName(shrt
).Len() == shrt
.Len(), 
  81                 wxT("Short option contains invalid characters") 
  86                 GetLongOptionName(lng
).Len() == lng
.Len(), 
  87                 wxT("Long option contains invalid characters") 
 102     // can't use union easily here, so just store all possible data fields, we 
 103     // don't waste much (might still use union later if the number of supported 
 104     // types increases, so always use the accessor functions and don't access 
 105     // the fields directly!) 
 107     void Check(wxCmdLineParamType 
WXUNUSED_UNLESS_DEBUG(typ
)) const 
 109         wxASSERT_MSG( type 
== typ
, _T("type mismatch in wxCmdLineOption") ); 
 112     long GetLongVal() const 
 113         { Check(wxCMD_LINE_VAL_NUMBER
); return m_longVal
; } 
 114     const wxString
& GetStrVal() const 
 115         { Check(wxCMD_LINE_VAL_STRING
); return m_strVal
;  } 
 116     const wxDateTime
& GetDateVal() const 
 117         { Check(wxCMD_LINE_VAL_DATE
);   return m_dateVal
; } 
 119     void SetLongVal(long val
) 
 120         { Check(wxCMD_LINE_VAL_NUMBER
); m_longVal 
= val
; m_hasVal 
= TRUE
; } 
 121     void SetStrVal(const wxString
& val
) 
 122         { 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
; } 
 126     void SetHasValue(bool hasValue 
= TRUE
) { m_hasVal 
= hasValue
; } 
 127     bool HasValue() const { return m_hasVal
; } 
 130     wxCmdLineEntryType kind
; 
 134     wxCmdLineParamType type
; 
 142     wxDateTime m_dateVal
; 
 145 struct wxCmdLineParam
 
 147     wxCmdLineParam(const wxString
& desc
, 
 148                    wxCmdLineParamType typ
, 
 156     wxString description
; 
 157     wxCmdLineParamType type
; 
 161 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
); 
 162 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
); 
 164 #include "wx/arrimpl.cpp" 
 166 WX_DEFINE_OBJARRAY(wxArrayOptions
); 
 167 WX_DEFINE_OBJARRAY(wxArrayParams
); 
 169 // the parser internal state 
 170 struct wxCmdLineParserData
 
 173     wxString m_switchChars
;     // characters which may start an option 
 174     bool m_enableLongOptions
;   // TRUE if long options are enabled 
 175     wxString m_logo
;            // some extra text to show in Usage() 
 178     wxArrayString m_arguments
;  // == argv, argc == m_arguments.GetCount() 
 179     wxArrayOptions m_options
;   // all possible options and switchrs 
 180     wxArrayParams m_paramDesc
;  // description of all possible params 
 181     wxArrayString m_parameters
; // all params found 
 184     wxCmdLineParserData(); 
 185     void SetArguments(int argc
, wxChar 
**argv
); 
 186     void SetArguments(const wxString
& cmdline
); 
 188     int FindOption(const wxString
& name
); 
 189     int FindOptionByLongName(const wxString
& name
); 
 192 // ============================================================================ 
 194 // ============================================================================ 
 196 // ---------------------------------------------------------------------------- 
 197 // wxCmdLineParserData 
 198 // ---------------------------------------------------------------------------- 
 200 wxCmdLineParserData::wxCmdLineParserData() 
 202     m_enableLongOptions 
= TRUE
; 
 204     m_switchChars 
= _T("-"); 
 206     m_switchChars 
= _T("/-"); 
 210 void wxCmdLineParserData::SetArguments(int argc
, wxChar 
**argv
) 
 214     for ( int n 
= 0; n 
< argc
; n
++ ) 
 216         m_arguments
.Add(argv
[n
]); 
 220 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
) 
 224     m_arguments
.Add(wxTheApp
->GetAppName()); 
 226     wxArrayString args 
= wxCmdLineParser::ConvertStringToArgs(cmdLine
); 
 228     WX_APPEND_ARRAY(m_arguments
, args
); 
 231 int wxCmdLineParserData::FindOption(const wxString
& name
) 
 235         size_t count 
= m_options
.GetCount(); 
 236         for ( size_t n 
= 0; n 
< count
; n
++ ) 
 238             if ( m_options
[n
].shortName 
== name 
) 
 249 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
) 
 251     size_t count 
= m_options
.GetCount(); 
 252     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 254         if ( m_options
[n
].longName 
== name 
) 
 264 // ---------------------------------------------------------------------------- 
 265 // construction and destruction 
 266 // ---------------------------------------------------------------------------- 
 268 void wxCmdLineParser::Init() 
 270     m_data 
= new wxCmdLineParserData
; 
 273 void wxCmdLineParser::SetCmdLine(int argc
, wxChar 
**argv
) 
 275     m_data
->SetArguments(argc
, argv
); 
 278 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
) 
 280     m_data
->SetArguments(cmdline
); 
 283 wxCmdLineParser::~wxCmdLineParser() 
 288 // ---------------------------------------------------------------------------- 
 290 // ---------------------------------------------------------------------------- 
 292 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
) 
 294     m_data
->m_switchChars 
= switchChars
; 
 297 void wxCmdLineParser::EnableLongOptions(bool enable
) 
 299     m_data
->m_enableLongOptions 
= enable
; 
 302 bool wxCmdLineParser::AreLongOptionsEnabled() 
 304     return m_data
->m_enableLongOptions
; 
 307 void wxCmdLineParser::SetLogo(const wxString
& logo
) 
 309     m_data
->m_logo 
= logo
; 
 312 // ---------------------------------------------------------------------------- 
 313 // command line construction 
 314 // ---------------------------------------------------------------------------- 
 316 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc 
*desc
) 
 320         switch ( desc
->kind 
) 
 322             case wxCMD_LINE_SWITCH
: 
 323                 AddSwitch(desc
->shortName
, desc
->longName
, desc
->description
, 
 327             case wxCMD_LINE_OPTION
: 
 328                 AddOption(desc
->shortName
, desc
->longName
, desc
->description
, 
 329                           desc
->type
, desc
->flags
); 
 332             case wxCMD_LINE_PARAM
: 
 333                 AddParam(desc
->description
, desc
->type
, desc
->flags
); 
 337                 wxFAIL_MSG( _T("unknown command line entry type") ); 
 338                 // still fall through 
 340             case wxCMD_LINE_NONE
: 
 346 void wxCmdLineParser::AddSwitch(const wxString
& shortName
, 
 347                                 const wxString
& longName
, 
 348                                 const wxString
& desc
, 
 351     wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
, 
 352                   _T("duplicate switch") ); 
 354     wxCmdLineOption 
*option 
= new wxCmdLineOption(wxCMD_LINE_SWITCH
, 
 355                                                   shortName
, longName
, desc
, 
 356                                                   wxCMD_LINE_VAL_NONE
, flags
); 
 358     m_data
->m_options
.Add(option
); 
 361 void wxCmdLineParser::AddOption(const wxString
& shortName
, 
 362                                 const wxString
& longName
, 
 363                                 const wxString
& desc
, 
 364                                 wxCmdLineParamType type
, 
 367     wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
, 
 368                   _T("duplicate option") ); 
 370     wxCmdLineOption 
*option 
= new wxCmdLineOption(wxCMD_LINE_OPTION
, 
 371                                                   shortName
, longName
, desc
, 
 374     m_data
->m_options
.Add(option
); 
 377 void wxCmdLineParser::AddParam(const wxString
& desc
, 
 378                                wxCmdLineParamType type
, 
 381     // do some consistency checks: a required parameter can't follow an 
 382     // optional one and nothing should follow a parameter with MULTIPLE flag 
 384     if ( !m_data
->m_paramDesc
.IsEmpty() ) 
 386         wxCmdLineParam
& param 
= m_data
->m_paramDesc
.Last(); 
 388         wxASSERT_MSG( !(param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE
), 
 389                       _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") ); 
 391         if ( !(flags 
& wxCMD_LINE_PARAM_OPTIONAL
) ) 
 393             wxASSERT_MSG( !(param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL
), 
 394                           _T("a required parameter can't follow an optional one") ); 
 399     wxCmdLineParam 
*param 
= new wxCmdLineParam(desc
, type
, flags
); 
 401     m_data
->m_paramDesc
.Add(param
); 
 404 // ---------------------------------------------------------------------------- 
 405 // access to parse command line 
 406 // ---------------------------------------------------------------------------- 
 408 bool wxCmdLineParser::Found(const wxString
& name
) const 
 410     int i 
= m_data
->FindOption(name
); 
 411     if ( i 
== wxNOT_FOUND 
) 
 412         i 
= m_data
->FindOptionByLongName(name
); 
 414     wxCHECK_MSG( i 
!= wxNOT_FOUND
, FALSE
, _T("unknown switch") ); 
 416     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 417     if ( !opt
.HasValue() ) 
 423 bool wxCmdLineParser::Found(const wxString
& name
, wxString 
*value
) const 
 425     int i 
= m_data
->FindOption(name
); 
 426     if ( i 
== wxNOT_FOUND 
) 
 427         i 
= m_data
->FindOptionByLongName(name
); 
 429     wxCHECK_MSG( i 
!= wxNOT_FOUND
, FALSE
, _T("unknown option") ); 
 431     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 432     if ( !opt
.HasValue() ) 
 435     wxCHECK_MSG( value
, FALSE
, _T("NULL pointer in wxCmdLineOption::Found") ); 
 437     *value 
= opt
.GetStrVal(); 
 442 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const 
 444     int i 
= m_data
->FindOption(name
); 
 445     if ( i 
== wxNOT_FOUND 
) 
 446         i 
= m_data
->FindOptionByLongName(name
); 
 448     wxCHECK_MSG( i 
!= wxNOT_FOUND
, FALSE
, _T("unknown option") ); 
 450     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 451     if ( !opt
.HasValue() ) 
 454     wxCHECK_MSG( value
, FALSE
, _T("NULL pointer in wxCmdLineOption::Found") ); 
 456     *value 
= opt
.GetLongVal(); 
 461 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime 
*value
) const 
 463     int i 
= m_data
->FindOption(name
); 
 464     if ( i 
== wxNOT_FOUND 
) 
 465         i 
= m_data
->FindOptionByLongName(name
); 
 467     wxCHECK_MSG( i 
!= wxNOT_FOUND
, FALSE
, _T("unknown option") ); 
 469     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 470     if ( !opt
.HasValue() ) 
 473     wxCHECK_MSG( value
, FALSE
, _T("NULL pointer in wxCmdLineOption::Found") ); 
 475     *value 
= opt
.GetDateVal(); 
 480 size_t wxCmdLineParser::GetParamCount() const 
 482     return m_data
->m_parameters
.GetCount(); 
 485 wxString 
wxCmdLineParser::GetParam(size_t n
) const 
 487     wxCHECK_MSG( n 
< GetParamCount(), wxEmptyString
, _T("invalid param index") ); 
 489     return m_data
->m_parameters
[n
]; 
 492 // Resets switches and options 
 493 void wxCmdLineParser::Reset() 
 495     for ( size_t i 
= 0; i 
< m_data
->m_options
.Count(); i
++ ) 
 497         wxCmdLineOption
& opt 
= m_data
->m_options
[i
]; 
 498         opt
.SetHasValue(FALSE
); 
 503 // ---------------------------------------------------------------------------- 
 504 // the real work is done here 
 505 // ---------------------------------------------------------------------------- 
 507 int wxCmdLineParser::Parse(bool showUsage
) 
 509     bool maybeOption 
= TRUE
;    // can the following arg be an option? 
 510     bool ok 
= TRUE
;             // TRUE until an error is detected 
 511     bool helpRequested 
= FALSE
; // TRUE if "-h" was given 
 512     bool hadRepeatableParam 
= FALSE
; // TRUE if found param with MULTIPLE flag 
 514     size_t currentParam 
= 0;    // the index in m_paramDesc 
 516     size_t countParam 
= m_data
->m_paramDesc
.GetCount(); 
 523     size_t count 
= m_data
->m_arguments
.GetCount(); 
 524     for ( size_t n 
= 1; ok 
&& (n 
< count
); n
++ )    // 0 is program name 
 526         arg 
= m_data
->m_arguments
[n
]; 
 528         // special case: "--" should be discarded and all following arguments 
 529         // should be considered as parameters, even if they start with '-' and 
 530         // not like options (this is POSIX-like) 
 531         if ( arg 
== _T("--") ) 
 538         // empty argument or just '-' is not an option but a parameter 
 539         if ( maybeOption 
&& arg
.length() > 1 && 
 540                 wxStrchr(m_data
->m_switchChars
, arg
[0u]) ) 
 544             int optInd 
= wxNOT_FOUND
;   // init to suppress warnings 
 546             // an option or a switch: find whether it's a long or a short one 
 547             if ( arg
[0u] == _T('-') && arg
[1u] == _T('-') ) 
 553                 const wxChar 
*p 
= arg
.c_str() + 2; 
 555                 bool longOptionsEnabled 
= AreLongOptionsEnabled(); 
 557                 name 
= GetLongOptionName(p
); 
 559                 if (longOptionsEnabled
) 
 561                     optInd 
= m_data
->FindOptionByLongName(name
); 
 562                     if ( optInd 
== wxNOT_FOUND 
) 
 564                         errorMsg 
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str()) << "\n"; 
 569                     optInd 
= wxNOT_FOUND
; // Sanity check 
 571                     // Print the argument including leading "--" 
 572                     name
.Prepend( wxT("--") ); 
 573                     errorMsg 
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << "\n"; 
 581                 // a short one: as they can be cumulated, we try to find the 
 582                 // longest substring which is a valid option 
 583                 const wxChar 
*p 
= arg
.c_str() + 1; 
 585                 name 
= GetShortOptionName(p
); 
 587                 size_t len 
= name
.length(); 
 592                         // we couldn't find a valid option name in the 
 593                         // beginning of this string 
 594                         errorMsg 
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << "\n"; 
 600                         optInd 
= m_data
->FindOption(name
.Left(len
)); 
 602                         // will try with one character less the next time 
 606                 while ( optInd 
== wxNOT_FOUND 
); 
 608                 len
++;  // compensates extra len-- above 
 609                 if ( (optInd 
!= wxNOT_FOUND
) && (len 
!= name
.length()) ) 
 611                     // first of all, the option name is only part of this 
 613                     name 
= name
.Left(len
); 
 615                     // our option is only part of this argument, there is 
 616                     // something else in it - it is either the value of this 
 617                     // option or other switches if it is a switch 
 618                     if ( m_data
->m_options
[(size_t)optInd
].kind
 
 619                             == wxCMD_LINE_SWITCH 
) 
 621                         // pretend that all the rest of the argument is the 
 622                         // next argument, in fact 
 623                         wxString arg2 
= arg
[0u]; 
 624                         arg2 
+= arg
.Mid(len 
+ 1); // +1 for leading '-' 
 626                         m_data
->m_arguments
.Insert(arg2
, n 
+ 1); 
 629                     //else: it's our value, we'll deal with it below 
 633             if ( optInd 
== wxNOT_FOUND 
) 
 637                 continue;   // will break, in fact 
 640             wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)optInd
]; 
 641             if ( opt
.kind 
== wxCMD_LINE_SWITCH 
) 
 643                 // nothing more to do 
 646                 if ( opt
.flags 
& wxCMD_LINE_OPTION_HELP 
) 
 648                     helpRequested 
= TRUE
; 
 650                     // it's not an error, but we still stop here 
 658                 // +1 for leading '-' 
 659                 const wxChar 
*p 
= arg
.c_str() + 1 + name
.length(); 
 662                     p
++;    // for another leading '-' 
 664                     if ( *p
++ != _T('=') ) 
 666                         errorMsg 
<< wxString::Format(_("Option '%s' requires a value, '=' expected."), name
.c_str()) << "\n"; 
 682                             // the value is in the next argument 
 685                                 // ... but there is none 
 686                                 errorMsg 
<< wxString::Format(_("Option '%s' requires a value."), 
 687                                                              name
.c_str()) << "\n"; 
 693                                 // ... take it from there 
 694                                 p 
= m_data
->m_arguments
[n
].c_str(); 
 699                             // the value is right here: this may be legal or 
 700                             // not depending on the option style 
 701                             if ( opt
.flags 
& wxCMD_LINE_NEEDS_SEPARATOR 
) 
 703                                 errorMsg 
<< wxString::Format(_("Separator expected after the option '%s'."), 
 704                                                              name
.c_str()) << "\n"; 
 717                             wxFAIL_MSG( _T("unknown option type") ); 
 718                             // still fall through 
 720                         case wxCMD_LINE_VAL_STRING
: 
 721                             opt
.SetStrVal(value
); 
 724                         case wxCMD_LINE_VAL_NUMBER
: 
 727                                 if ( value
.ToLong(&val
) ) 
 733                                     errorMsg 
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."), 
 734                                                                  value
.c_str(), name
.c_str()) << "\n"; 
 741                         case wxCMD_LINE_VAL_DATE
: 
 744                                 const wxChar 
*res 
= dt
.ParseDate(value
); 
 747                                     errorMsg 
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."), 
 748                                                                  name
.c_str(), value
.c_str()) << "\n"; 
 765             if ( currentParam 
< countParam 
) 
 767                 wxCmdLineParam
& param 
= m_data
->m_paramDesc
[currentParam
]; 
 769                 // TODO check the param type 
 771                 m_data
->m_parameters
.Add(arg
); 
 773                 if ( !(param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE
) ) 
 779                     wxASSERT_MSG( currentParam 
== countParam 
- 1, 
 780                                   _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") ); 
 782                     // remember that we did have this last repeatable parameter 
 783                     hadRepeatableParam 
= TRUE
; 
 788                 errorMsg 
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str()) << "\n"; 
 795     // verify that all mandatory options were given 
 798         size_t countOpt 
= m_data
->m_options
.GetCount(); 
 799         for ( size_t n 
= 0; ok 
&& (n 
< countOpt
); n
++ ) 
 801             wxCmdLineOption
& opt 
= m_data
->m_options
[n
]; 
 802             if ( (opt
.flags 
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() ) 
 807                     optName 
= opt
.shortName
; 
 811                     if ( AreLongOptionsEnabled() ) 
 813                         optName
.Printf( _("%s (or %s)"), 
 814                                         opt
.shortName
.c_str(), 
 815                                         opt
.longName
.c_str() ); 
 819                         optName
.Printf( wxT("%s"), 
 820                                         opt
.shortName
.c_str() ); 
 824                 errorMsg 
<< wxString::Format(_("The value for the option '%s' must be specified."), 
 825                                              optName
.c_str()) << "\n"; 
 831         for ( ; ok 
&& (currentParam 
< countParam
); currentParam
++ ) 
 833             wxCmdLineParam
& param 
= m_data
->m_paramDesc
[currentParam
]; 
 834             if ( (currentParam 
== countParam 
- 1) && 
 835                  (param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE
) && 
 838                 // special case: currentParam wasn't incremented, but we did 
 839                 // have it, so don't give error 
 843             if ( !(param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL
) ) 
 845                 errorMsg 
<< wxString::Format(_("The required parameter '%s' was not specified."), 
 846                                              param
.description
.c_str()) << "\n"; 
 853     // if there was an error during parsing the command line, show this error 
 854     // and also the usage message if it had been requested 
 855     if ( !ok 
&& (!errorMsg
.empty() || (helpRequested 
&& showUsage
)) ) 
 857         wxMessageOutput
* msgOut 
= wxMessageOutput::Get(); 
 862                 usage 
= GetUsageString(); 
 864             msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() ); 
 868             wxFAIL_MSG( _T("no wxMessageOutput object?") ); 
 872     return ok 
? 0 : helpRequested 
? -1 : 1; 
 875 // ---------------------------------------------------------------------------- 
 876 // give the usage message 
 877 // ---------------------------------------------------------------------------- 
 879 void wxCmdLineParser::Usage() 
 881     wxMessageOutput
* msgOut 
= wxMessageOutput::Get(); 
 884         msgOut
->Printf( wxT("%s"), GetUsageString().c_str() ); 
 888         wxFAIL_MSG( _T("no wxMessageOutput object?") ); 
 892 wxString 
wxCmdLineParser::GetUsageString() 
 894     wxString appname 
= wxTheApp
->GetAppName(); 
 897         wxCHECK_MSG( !m_data
->m_arguments
.IsEmpty(), wxEmptyString
, 
 898                      _T("no program name") ); 
 900         appname 
= wxFileNameFromPath(m_data
->m_arguments
[0]); 
 901         wxStripExtension(appname
); 
 904     // we construct the brief cmd line desc on the fly, but not the detailed 
 905     // help message below because we want to align the options descriptions 
 906     // and for this we must first know the longest one of them 
 908     wxArrayString namesOptions
, descOptions
; 
 910     if ( !m_data
->m_logo
.empty() ) 
 912         usage 
<< m_data
->m_logo 
<< _T('\n'); 
 915     usage 
<< wxString::Format(_("Usage: %s"), appname
.c_str()); 
 917     // the switch char is usually '-' but this can be changed with 
 918     // SetSwitchChars() and then the first one of possible chars is used 
 919     wxChar chSwitch 
= !m_data
->m_switchChars 
? _T('-') 
 920                                              : m_data
->m_switchChars
[0u]; 
 922     bool areLongOptionsEnabled 
= AreLongOptionsEnabled(); 
 923     size_t n
, count 
= m_data
->m_options
.GetCount(); 
 924     for ( n 
= 0; n 
< count
; n
++ ) 
 926         wxCmdLineOption
& opt 
= m_data
->m_options
[n
]; 
 929         if ( !(opt
.flags 
& wxCMD_LINE_OPTION_MANDATORY
) ) 
 934         if ( !opt
.shortName
.empty() ) 
 936             usage 
<< chSwitch 
<< opt
.shortName
; 
 938         else if ( areLongOptionsEnabled 
&& !opt
.longName
.empty() ) 
 940             usage 
<< _T("--") << opt
.longName
; 
 944             if (!opt
.longName
.empty()) 
 946                 wxFAIL_MSG( wxT("option with only a long name while long ") 
 947                     wxT("options are disabled") ); 
 951                 wxFAIL_MSG( _T("option without neither short nor long name") ); 
 957         if ( !opt
.shortName
.empty() ) 
 959             option 
<< _T("  ") << chSwitch 
<< opt
.shortName
; 
 962         if ( areLongOptionsEnabled 
&& !opt
.longName
.empty() ) 
 964             option 
<< (option
.empty() ? _T("  ") : _T(", ")) 
 965                    << _T("--") << opt
.longName
; 
 968         if ( opt
.kind 
!= wxCMD_LINE_SWITCH 
) 
 971             val 
<< _T('<') << GetTypeName(opt
.type
) << _T('>'); 
 972             usage 
<< _T(' ') << val
; 
 973             option 
<< (!opt
.longName 
? _T(':') : _T('=')) << val
; 
 976         if ( !(opt
.flags 
& wxCMD_LINE_OPTION_MANDATORY
) ) 
 981         namesOptions
.Add(option
); 
 982         descOptions
.Add(opt
.description
); 
 985     count 
= m_data
->m_paramDesc
.GetCount(); 
 986     for ( n 
= 0; n 
< count
; n
++ ) 
 988         wxCmdLineParam
& param 
= m_data
->m_paramDesc
[n
]; 
 991         if ( param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL 
) 
 996         usage 
<< param
.description
; 
 998         if ( param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE 
) 
1003         if ( param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL 
) 
1011     // now construct the detailed help message 
1012     size_t len
, lenMax 
= 0; 
1013     count 
= namesOptions
.GetCount(); 
1014     for ( n 
= 0; n 
< count
; n
++ ) 
1016         len 
= namesOptions
[n
].length(); 
1021     for ( n 
= 0; n 
< count
; n
++ ) 
1023         len 
= namesOptions
[n
].length(); 
1024         usage 
<< namesOptions
[n
] 
1025               << wxString(_T(' '), lenMax 
- len
) << _T('\t') 
1033 // ---------------------------------------------------------------------------- 
1034 // private functions 
1035 // ---------------------------------------------------------------------------- 
1037 static wxString 
GetTypeName(wxCmdLineParamType type
) 
1043             wxFAIL_MSG( _T("unknown option type") ); 
1044             // still fall through 
1046         case wxCMD_LINE_VAL_STRING
: 
1050         case wxCMD_LINE_VAL_NUMBER
: 
1054         case wxCMD_LINE_VAL_DATE
: 
1063 Returns a string which is equal to the string pointed to by p, but up to the 
1064 point where p contains an character that's not allowed. 
1065 Allowable characters are letters and numbers, and characters pointed to by 
1066 the parameter allowedChars. 
1068 For example, if p points to "abcde-@-_", and allowedChars is "-_", 
1069 this function returns "abcde-". 
1071 static wxString 
GetOptionName(const wxChar 
*p
, 
1072     const wxChar 
*allowedChars
) 
1076     while ( *p 
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) ) 
1084 // Besides alphanumeric characters, short and long options can 
1085 // have other characters. 
1087 // A short option additionally can have these 
1088 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?") 
1090 // A long option can have the same characters as a short option and a '-'. 
1091 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \ 
1092     wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-") 
1094 static wxString 
GetShortOptionName(const wxChar 
*p
) 
1096     return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
); 
1099 static wxString 
GetLongOptionName(const wxChar 
*p
) 
1101     return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
); 
1104 #endif // wxUSE_CMDLINE_PARSER 
1106 // ---------------------------------------------------------------------------- 
1108 // ---------------------------------------------------------------------------- 
1111    This function is mainly used under Windows (as under Unix we always get the 
1112    command line arguments as argc/argv anyhow) and so it tries to handle the 
1113    Windows path names (separated by backslashes) correctly. For this it only 
1114    considers that a backslash may be used to escape another backslash (but 
1115    normally this is _not_ needed) or a quote but nothing else. 
1117    In particular, to pass a single argument containing a space to the program 
1118    it should be quoted: 
1120    myprog.exe foo bar       -> argc = 3, argv[1] = "foo", argv[2] = "bar" 
1121    myprog.exe "foo bar"     -> argc = 2, argv[1] = "foo bar" 
1123    To pass an argument containing spaces and quotes, the latter should be 
1124    escaped with a backslash: 
1126    myprog.exe "foo \"bar\"" -> argc = 2, argv[1] = "foo "bar"" 
1128    This hopefully matches the conventions used by Explorer/command line 
1129    interpreter under Windows. If not, this function should be fixed. 
1133 wxArrayString 
wxCmdLineParser::ConvertStringToArgs(const wxChar 
*p
) 
1140     bool isInsideQuotes 
= FALSE
; 
1144         while ( *p 
== _T(' ') || *p 
== _T('\t') ) 
1148         if ( *p 
== _T('\0') ) 
1151         // parse this parameter 
1155             // do we have a (lone) backslash? 
1156             bool isQuotedByBS 
= FALSE
; 
1157             while ( *p 
== _T('\\') ) 
1161                 // if we have 2 backslashes in a row, output one 
1162                 // unless it looks like a UNC path \\machine\dir\file.ext 
1163                 if ( isQuotedByBS 
|| arg
.Len() == 0 ) 
1166                     isQuotedByBS 
= FALSE
; 
1168                 else // the next char is quoted 
1170                     isQuotedByBS 
= TRUE
; 
1174             bool skipChar 
= FALSE
, 
1179                     if ( !isQuotedByBS 
) 
1181                         // don't put the quote itself in the arg 
1184                         isInsideQuotes 
= !isInsideQuotes
; 
1186                     //else: insert a literal quote 
1192                     // we intentionally don't check for preceding backslash 
1193                     // here as if we allowed it to be used to escape spaces the 
1194                     // cmd line of the form "foo.exe a:\ c:\bar" wouldn't be 
1196                     if ( isInsideQuotes 
) 
1198                         // preserve it, skip endParam below 
1201                     //else: fall through 
1210                         // ignore backslash before an ordinary character - this 
1211                         // is needed to properly handle the file names under 
1212                         // Windows appearing in the command line 
1221             // otherwise copy this char to arg