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 
  40 #include <locale.h>             // for LC_ALL 
  42 #include "wx/datetime.h" 
  43 #include "wx/msgout.h" 
  44 #include "wx/filename.h" 
  45 #include "wx/apptrait.h" 
  46 #include "wx/scopeguard.h" 
  48 // ---------------------------------------------------------------------------- 
  50 // ---------------------------------------------------------------------------- 
  52 static wxString 
GetTypeName(wxCmdLineParamType type
); 
  54 static wxString 
GetOptionName(wxString::const_iterator p
, 
  55                               wxString::const_iterator end
, 
  56                               const wxChar 
*allowedChars
); 
  58 static wxString 
GetShortOptionName(wxString::const_iterator p
, 
  59                                    wxString::const_iterator end
); 
  61 static wxString 
GetLongOptionName(wxString::const_iterator p
, 
  62                                   wxString::const_iterator end
); 
  64 // ---------------------------------------------------------------------------- 
  66 // ---------------------------------------------------------------------------- 
  68 // an internal representation of an option 
  69 struct wxCmdLineOption
 
  71     wxCmdLineOption(wxCmdLineEntryType k
, 
  75                     wxCmdLineParamType typ
, 
  78         // wxCMD_LINE_USAGE_TEXT uses only description, shortName and longName is empty 
  79         if ( k 
!= wxCMD_LINE_USAGE_TEXT 
) 
  83                 !shrt
.empty() || !lng
.empty(), 
  84                  wxT("option should have at least one name") 
  89                 GetShortOptionName(shrt
.begin(), shrt
.end()).Len() == shrt
.Len(), 
  90                 wxT("Short option contains invalid characters") 
  95                 GetLongOptionName(lng
.begin(), lng
.end()).Len() == lng
.Len(), 
  96                 wxT("Long option contains invalid characters") 
 112     // can't use union easily here, so just store all possible data fields, we 
 113     // don't waste much (might still use union later if the number of supported 
 114     // types increases, so always use the accessor functions and don't access 
 115     // the fields directly!) 
 117     void Check(wxCmdLineParamType 
WXUNUSED_UNLESS_DEBUG(typ
)) const 
 119         wxASSERT_MSG( type 
== typ
, wxT("type mismatch in wxCmdLineOption") ); 
 122     double GetDoubleVal() const 
 123         { Check(wxCMD_LINE_VAL_DOUBLE
); return m_doubleVal
; } 
 124     long GetLongVal() const 
 125         { Check(wxCMD_LINE_VAL_NUMBER
); return m_longVal
; } 
 126     const wxString
& GetStrVal() const 
 127         { Check(wxCMD_LINE_VAL_STRING
); return m_strVal
;  } 
 129     const wxDateTime
& GetDateVal() const 
 130         { Check(wxCMD_LINE_VAL_DATE
);   return m_dateVal
; } 
 131 #endif // wxUSE_DATETIME 
 133     void SetDoubleVal(double val
) 
 134         { Check(wxCMD_LINE_VAL_DOUBLE
); m_doubleVal 
= val
; m_hasVal 
= true; } 
 135     void SetLongVal(long val
) 
 136         { Check(wxCMD_LINE_VAL_NUMBER
); m_longVal 
= val
; m_hasVal 
= true; } 
 137     void SetStrVal(const wxString
& val
) 
 138         { Check(wxCMD_LINE_VAL_STRING
); m_strVal 
= val
; m_hasVal 
= true; } 
 140     void SetDateVal(const wxDateTime
& val
) 
 141         { Check(wxCMD_LINE_VAL_DATE
); m_dateVal 
= val
; m_hasVal 
= true; } 
 142 #endif // wxUSE_DATETIME 
 144     void SetHasValue() { m_hasVal 
= true; } 
 145     bool HasValue() const { return m_hasVal
; } 
 147     void SetNegated() { m_isNegated 
= true; } 
 148     bool IsNegated() const { return m_isNegated
; } 
 150     // Reset to the initial state, called before parsing another command line. 
 158     wxCmdLineEntryType kind
; 
 162     wxCmdLineParamType type
; 
 173     wxDateTime m_dateVal
; 
 174 #endif // wxUSE_DATETIME 
 177 struct wxCmdLineParam
 
 179     wxCmdLineParam(const wxString
& desc
, 
 180                    wxCmdLineParamType typ
, 
 188     wxString description
; 
 189     wxCmdLineParamType type
; 
 193 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
); 
 194 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
); 
 196 #include "wx/arrimpl.cpp" 
 198 WX_DEFINE_OBJARRAY(wxArrayOptions
) 
 199 WX_DEFINE_OBJARRAY(wxArrayParams
) 
 201 // the parser internal state 
 202 struct wxCmdLineParserData
 
 205     wxString m_switchChars
;     // characters which may start an option 
 206     bool m_enableLongOptions
;   // true if long options are enabled 
 207     wxString m_logo
;            // some extra text to show in Usage() 
 210     wxArrayString m_arguments
;  // == argv, argc == m_arguments.GetCount() 
 211     wxArrayOptions m_options
;   // all possible options and switches 
 212     wxArrayParams m_paramDesc
;  // description of all possible params 
 213     wxArrayString m_parameters
; // all params found 
 216     wxCmdLineParserData(); 
 217     void SetArguments(int argc
, char **argv
); 
 219     void SetArguments(int argc
, wxChar 
**argv
); 
 220     void SetArguments(int argc
, const wxCmdLineArgsArray
& argv
); 
 221 #endif // wxUSE_UNICODE 
 222     void SetArguments(const wxString
& cmdline
); 
 224     int FindOption(const wxString
& name
); 
 225     int FindOptionByLongName(const wxString
& name
); 
 228 // ============================================================================ 
 230 // ============================================================================ 
 232 // ---------------------------------------------------------------------------- 
 233 // wxCmdLineParserData 
 234 // ---------------------------------------------------------------------------- 
 236 wxCmdLineParserData::wxCmdLineParserData() 
 238     m_enableLongOptions 
= true; 
 240     m_switchChars 
= wxT("-"); 
 242     m_switchChars 
= wxT("/-"); 
 249 // Small helper function setting locale for all categories. 
 251 // We define it because wxSetlocale() can't be easily used with wxScopeGuard as 
 252 // it has several overloads -- while this one can. 
 253 inline char *SetAllLocaleFacets(const char *loc
) 
 255     return wxSetlocale(LC_ALL
, loc
); 
 258 } // private namespace 
 260 void wxCmdLineParserData::SetArguments(int argc
, char **argv
) 
 264     // Command-line arguments are supposed to be in the user locale encoding 
 265     // (what else?) but wxLocale probably wasn't initialized yet as we're 
 266     // called early during the program startup and so our locale might not have 
 267     // been set from the environment yet. To work around this problem we 
 268     // temporarily change the locale here. The only drawback is that changing 
 269     // the locale is thread-unsafe but precisely because we're called so early 
 270     // it's hopefully safe to assume that no other threads had been created yet. 
 271     char * const locOld 
= SetAllLocaleFacets(""); 
 272     wxON_BLOCK_EXIT1( SetAllLocaleFacets
, locOld 
); 
 274     for ( int n 
= 0; n 
< argc
; n
++ ) 
 276         // try to interpret the string as being in the current locale 
 277         wxString 
arg(argv
[n
]); 
 279         // but just in case we guessed wrongly and the conversion failed, do 
 280         // try to salvage at least something 
 281         if ( arg
.empty() && argv
[n
][0] != '\0' ) 
 282             arg 
= wxString(argv
[n
], wxConvISO8859_1
); 
 284         m_arguments
.push_back(arg
); 
 290 void wxCmdLineParserData::SetArguments(int argc
, wxChar 
**argv
) 
 294     for ( int n 
= 0; n 
< argc
; n
++ ) 
 296         m_arguments
.push_back(argv
[n
]); 
 300 void wxCmdLineParserData::SetArguments(int WXUNUSED(argc
), 
 301                                        const wxCmdLineArgsArray
& argv
) 
 303     m_arguments 
= argv
.GetArguments(); 
 306 #endif // wxUSE_UNICODE 
 308 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
) 
 312     if(wxTheApp 
&& wxTheApp
->argc 
> 0) 
 313         m_arguments
.push_back(wxTheApp
->argv
[0]); 
 315         m_arguments
.push_back(wxEmptyString
); 
 317     wxArrayString args 
= wxCmdLineParser::ConvertStringToArgs(cmdLine
); 
 319     WX_APPEND_ARRAY(m_arguments
, args
); 
 322 int wxCmdLineParserData::FindOption(const wxString
& name
) 
 326         size_t count 
= m_options
.GetCount(); 
 327         for ( size_t n 
= 0; n 
< count
; n
++ ) 
 329             if ( m_options
[n
].shortName 
== name 
) 
 340 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
) 
 342     size_t count 
= m_options
.GetCount(); 
 343     for ( size_t n 
= 0; n 
< count
; n
++ ) 
 345         if ( m_options
[n
].longName 
== name 
) 
 355 // ---------------------------------------------------------------------------- 
 356 // construction and destruction 
 357 // ---------------------------------------------------------------------------- 
 359 void wxCmdLineParser::Init() 
 361     m_data 
= new wxCmdLineParserData
; 
 364 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
) 
 366     m_data
->SetArguments(argc
, argv
); 
 371 void wxCmdLineParser::SetCmdLine(int argc
, wxChar 
**argv
) 
 373     m_data
->SetArguments(argc
, argv
); 
 376 void wxCmdLineParser::SetCmdLine(int argc
, const wxCmdLineArgsArray
& argv
) 
 378     m_data
->SetArguments(argc
, argv
); 
 381 #endif // wxUSE_UNICODE 
 383 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
) 
 385     m_data
->SetArguments(cmdline
); 
 388 wxCmdLineParser::~wxCmdLineParser() 
 393 // ---------------------------------------------------------------------------- 
 395 // ---------------------------------------------------------------------------- 
 397 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
) 
 399     m_data
->m_switchChars 
= switchChars
; 
 402 void wxCmdLineParser::EnableLongOptions(bool enable
) 
 404     m_data
->m_enableLongOptions 
= enable
; 
 407 bool wxCmdLineParser::AreLongOptionsEnabled() const 
 409     return m_data
->m_enableLongOptions
; 
 412 void wxCmdLineParser::SetLogo(const wxString
& logo
) 
 414     m_data
->m_logo 
= logo
; 
 417 // ---------------------------------------------------------------------------- 
 418 // command line construction 
 419 // ---------------------------------------------------------------------------- 
 421 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc 
*desc
) 
 425         switch ( desc
->kind 
) 
 427             case wxCMD_LINE_SWITCH
: 
 428                 AddSwitch(desc
->shortName
, desc
->longName
, 
 429                           wxGetTranslation(desc
->description
), 
 433             case wxCMD_LINE_OPTION
: 
 434                 AddOption(desc
->shortName
, desc
->longName
, 
 435                           wxGetTranslation(desc
->description
), 
 436                           desc
->type
, desc
->flags
); 
 439             case wxCMD_LINE_PARAM
: 
 440                 AddParam(wxGetTranslation(desc
->description
), 
 441                          desc
->type
, desc
->flags
); 
 444             case wxCMD_LINE_USAGE_TEXT
: 
 445                 AddUsageText(wxGetTranslation(desc
->description
)); 
 449                 wxFAIL_MSG( wxT("unknown command line entry type") ); 
 450                 // still fall through 
 452             case wxCMD_LINE_NONE
: 
 458 void wxCmdLineParser::AddSwitch(const wxString
& shortName
, 
 459                                 const wxString
& longName
, 
 460                                 const wxString
& desc
, 
 463     wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
, 
 464                   wxT("duplicate switch") ); 
 466     wxCmdLineOption 
*option 
= new wxCmdLineOption(wxCMD_LINE_SWITCH
, 
 467                                                   shortName
, longName
, desc
, 
 468                                                   wxCMD_LINE_VAL_NONE
, flags
); 
 470     m_data
->m_options
.Add(option
); 
 473 void wxCmdLineParser::AddOption(const wxString
& shortName
, 
 474                                 const wxString
& longName
, 
 475                                 const wxString
& desc
, 
 476                                 wxCmdLineParamType type
, 
 479     wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
, 
 480                   wxT("duplicate option") ); 
 482     wxCmdLineOption 
*option 
= new wxCmdLineOption(wxCMD_LINE_OPTION
, 
 483                                                   shortName
, longName
, desc
, 
 486     m_data
->m_options
.Add(option
); 
 489 void wxCmdLineParser::AddParam(const wxString
& desc
, 
 490                                wxCmdLineParamType type
, 
 493     // do some consistency checks: a required parameter can't follow an 
 494     // optional one and nothing should follow a parameter with MULTIPLE flag 
 496     if ( !m_data
->m_paramDesc
.IsEmpty() ) 
 498         wxCmdLineParam
& param 
= m_data
->m_paramDesc
.Last(); 
 500         wxASSERT_MSG( !(param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE
), 
 501                       wxT("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") ); 
 503         if ( !(flags 
& wxCMD_LINE_PARAM_OPTIONAL
) ) 
 505             wxASSERT_MSG( !(param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL
), 
 506                           wxT("a required parameter can't follow an optional one") ); 
 509 #endif // wxDEBUG_LEVEL 
 511     wxCmdLineParam 
*param 
= new wxCmdLineParam(desc
, type
, flags
); 
 513     m_data
->m_paramDesc
.Add(param
); 
 516 void wxCmdLineParser::AddUsageText(const wxString
& text
) 
 518     wxASSERT_MSG( !text
.empty(), wxT("text can't be empty") ); 
 520     wxCmdLineOption 
*option 
= new wxCmdLineOption(wxCMD_LINE_USAGE_TEXT
, 
 521                                                   wxEmptyString
, wxEmptyString
, 
 522                                                   text
, wxCMD_LINE_VAL_NONE
, 0); 
 524     m_data
->m_options
.Add(option
); 
 527 // ---------------------------------------------------------------------------- 
 528 // access to parse command line 
 529 // ---------------------------------------------------------------------------- 
 531 bool wxCmdLineParser::Found(const wxString
& name
) const 
 533     return FoundSwitch(name
) != wxCMD_SWITCH_NOT_FOUND
; 
 536 wxCmdLineSwitchState 
wxCmdLineParser::FoundSwitch(const wxString
& name
) const 
 538     int i 
= m_data
->FindOption(name
); 
 539     if ( i 
== wxNOT_FOUND 
) 
 540         i 
= m_data
->FindOptionByLongName(name
); 
 542     wxCHECK_MSG( i 
!= wxNOT_FOUND
, wxCMD_SWITCH_NOT_FOUND
, wxT("unknown switch") ); 
 544     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 545     if ( !opt
.HasValue() ) 
 546         return wxCMD_SWITCH_NOT_FOUND
; 
 548     return opt
.IsNegated() ? wxCMD_SWITCH_OFF 
: wxCMD_SWITCH_ON
; 
 551 bool wxCmdLineParser::Found(const wxString
& name
, wxString 
*value
) const 
 553     int i 
= m_data
->FindOption(name
); 
 554     if ( i 
== wxNOT_FOUND 
) 
 555         i 
= m_data
->FindOptionByLongName(name
); 
 557     wxCHECK_MSG( i 
!= wxNOT_FOUND
, false, wxT("unknown option") ); 
 559     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 560     if ( !opt
.HasValue() ) 
 563     wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") ); 
 565     *value 
= opt
.GetStrVal(); 
 570 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const 
 572     int i 
= m_data
->FindOption(name
); 
 573     if ( i 
== wxNOT_FOUND 
) 
 574         i 
= m_data
->FindOptionByLongName(name
); 
 576     wxCHECK_MSG( i 
!= wxNOT_FOUND
, false, wxT("unknown option") ); 
 578     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 579     if ( !opt
.HasValue() ) 
 582     wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") ); 
 584     *value 
= opt
.GetLongVal(); 
 589 bool wxCmdLineParser::Found(const wxString
& name
, double *value
) const 
 591     int i 
= m_data
->FindOption(name
); 
 592     if ( i 
== wxNOT_FOUND 
) 
 593         i 
= m_data
->FindOptionByLongName(name
); 
 595     wxCHECK_MSG( i 
!= wxNOT_FOUND
, false, wxT("unknown option") ); 
 597     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 598     if ( !opt
.HasValue() ) 
 601     wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") ); 
 603     *value 
= opt
.GetDoubleVal(); 
 609 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime 
*value
) const 
 611     int i 
= m_data
->FindOption(name
); 
 612     if ( i 
== wxNOT_FOUND 
) 
 613         i 
= m_data
->FindOptionByLongName(name
); 
 615     wxCHECK_MSG( i 
!= wxNOT_FOUND
, false, wxT("unknown option") ); 
 617     wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)i
]; 
 618     if ( !opt
.HasValue() ) 
 621     wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") ); 
 623     *value 
= opt
.GetDateVal(); 
 627 #endif // wxUSE_DATETIME 
 629 size_t wxCmdLineParser::GetParamCount() const 
 631     return m_data
->m_parameters
.size(); 
 634 wxString 
wxCmdLineParser::GetParam(size_t n
) const 
 636     wxCHECK_MSG( n 
< GetParamCount(), wxEmptyString
, wxT("invalid param index") ); 
 638     return m_data
->m_parameters
[n
]; 
 641 // Resets switches and options 
 642 void wxCmdLineParser::Reset() 
 644     for ( size_t i 
= 0; i 
< m_data
->m_options
.GetCount(); i
++ ) 
 646         m_data
->m_options
[i
].Reset(); 
 651 // ---------------------------------------------------------------------------- 
 652 // the real work is done here 
 653 // ---------------------------------------------------------------------------- 
 655 int wxCmdLineParser::Parse(bool showUsage
) 
 657     bool maybeOption 
= true;    // can the following arg be an option? 
 658     bool ok 
= true;             // true until an error is detected 
 659     bool helpRequested 
= false; // true if "-h" was given 
 660     bool hadRepeatableParam 
= false; // true if found param with MULTIPLE flag 
 662     size_t currentParam 
= 0;    // the index in m_paramDesc 
 664     size_t countParam 
= m_data
->m_paramDesc
.GetCount(); 
 671     size_t count 
= m_data
->m_arguments
.size(); 
 672     for ( size_t n 
= 1; ok 
&& (n 
< count
); n
++ )    // 0 is program name 
 674         arg 
= m_data
->m_arguments
[n
]; 
 676         // special case: "--" should be discarded and all following arguments 
 677         // should be considered as parameters, even if they start with '-' and 
 678         // not like options (this is POSIX-like) 
 679         if ( arg 
== wxT("--") ) 
 686         // empty argument or just '-' is not an option but a parameter 
 687         if ( maybeOption 
&& arg
.length() > 1 && 
 688                 // FIXME-UTF8: use wc_str() after removing ANSI build 
 689                 wxStrchr(m_data
->m_switchChars
.c_str(), arg
[0u]) ) 
 693             int optInd 
= wxNOT_FOUND
;   // init to suppress warnings 
 695             // an option or a switch: find whether it's a long or a short one 
 696             if ( arg
.length() >= 3 && arg
[0u] == wxT('-') && arg
[1u] == wxT('-') ) 
 702                 wxString::const_iterator p 
= arg
.begin() + 2; 
 704                 bool longOptionsEnabled 
= AreLongOptionsEnabled(); 
 706                 name 
= GetLongOptionName(p
, arg
.end()); 
 708                 if (longOptionsEnabled
) 
 710                     optInd 
= m_data
->FindOptionByLongName(name
); 
 711                     if ( optInd 
== wxNOT_FOUND 
) 
 713                         errorMsg 
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str()) 
 719                     optInd 
= wxNOT_FOUND
; // Sanity check 
 721                     // Print the argument including leading "--" 
 722                     name
.Prepend( wxT("--") ); 
 723                     errorMsg 
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) 
 728             else // not a long option 
 732                 // a short one: as they can be cumulated, we try to find the 
 733                 // longest substring which is a valid option 
 734                 wxString::const_iterator p 
= arg
.begin() + 1; 
 736                 name 
= GetShortOptionName(p
, arg
.end()); 
 738                 size_t len 
= name
.length(); 
 743                         // we couldn't find a valid option name in the 
 744                         // beginning of this string 
 745                         errorMsg 
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) 
 752                         optInd 
= m_data
->FindOption(name
.Left(len
)); 
 754                         // will try with one character less the next time 
 758                 while ( optInd 
== wxNOT_FOUND 
); 
 760                 len
++;  // compensates extra len-- above 
 761                 if ( (optInd 
!= wxNOT_FOUND
) && (len 
!= name
.length()) ) 
 763                     // first of all, the option name is only part of this 
 765                     name 
= name
.Left(len
); 
 767                     // our option is only part of this argument, there is 
 768                     // something else in it - it is either the value of this 
 769                     // option or other switches if it is a switch 
 770                     if ( m_data
->m_options
[(size_t)optInd
].kind
 
 771                             == wxCMD_LINE_SWITCH 
) 
 773                         // if the switch is negatable and it is just followed 
 774                         // by '-' the '-' is considered to be part of this 
 776                         if ( (m_data
->m_options
[(size_t)optInd
].flags 
& 
 777                                     wxCMD_LINE_SWITCH_NEGATABLE
) && 
 781                         // pretend that all the rest of the argument is the 
 782                         // next argument, in fact 
 783                         wxString arg2 
= arg
[0u]; 
 784                         arg2 
+= arg
.Mid(len 
+ 1); // +1 for leading '-' 
 786                         m_data
->m_arguments
.insert
 
 787                             (m_data
->m_arguments
.begin() + n 
+ 1, arg2
); 
 790                         // only leave the part which wasn't extracted into the 
 791                         // next argument in this one 
 792                         arg 
= arg
.Left(len 
+ 1); 
 794                     //else: it's our value, we'll deal with it below 
 798             if ( optInd 
== wxNOT_FOUND 
) 
 802                 continue;   // will break, in fact 
 805             // look at what follows: 
 807             // +1 for leading '-' 
 808             wxString::const_iterator p 
= arg
.begin() + 1 + name
.length(); 
 809             wxString::const_iterator end 
= arg
.end(); 
 812                 ++p
;    // for another leading '-' 
 814             wxCmdLineOption
& opt 
= m_data
->m_options
[(size_t)optInd
]; 
 815             if ( opt
.kind 
== wxCMD_LINE_SWITCH 
) 
 817                 // we must check that there is no value following the switch 
 818                 bool negated 
= (opt
.flags 
& wxCMD_LINE_SWITCH_NEGATABLE
) && 
 819                                     p 
!= arg
.end() && *p 
== '-'; 
 821                 if ( !negated 
&& p 
!= arg
.end() ) 
 823                     errorMsg 
<< wxString::Format(_("Unexpected characters following option '%s'."), name
.c_str()) 
 827                 else // no value, as expected 
 829                     // nothing more to do 
 834                     if ( opt
.flags 
& wxCMD_LINE_OPTION_HELP 
) 
 836                         helpRequested 
= true; 
 838                         // it's not an error, but we still stop here 
 843             else // it's an option. not a switch 
 845                 switch ( p 
== end 
? '\0' : (*p
).GetValue() ) 
 854                         // the value is in the next argument 
 857                             // ... but there is none 
 858                             errorMsg 
<< wxString::Format(_("Option '%s' requires a value."), 
 866                             // ... take it from there 
 867                             p 
= m_data
->m_arguments
[n
].begin(); 
 868                             end 
= m_data
->m_arguments
[n
].end(); 
 873                         // the value is right here: this may be legal or 
 874                         // not depending on the option style 
 875                         if ( opt
.flags 
& wxCMD_LINE_NEEDS_SEPARATOR 
) 
 877                             errorMsg 
<< wxString::Format(_("Separator expected after the option '%s'."), 
 887                     wxString 
value(p
, end
); 
 891                             wxFAIL_MSG( wxT("unknown option type") ); 
 892                             // still fall through 
 894                         case wxCMD_LINE_VAL_STRING
: 
 895                             opt
.SetStrVal(value
); 
 898                         case wxCMD_LINE_VAL_NUMBER
: 
 901                                 if ( value
.ToLong(&val
) ) 
 907                                     errorMsg 
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."), 
 908                                                                  value
.c_str(), name
.c_str()) 
 916                         case wxCMD_LINE_VAL_DOUBLE
: 
 919                                 if ( value
.ToDouble(&val
) ) 
 921                                     opt
.SetDoubleVal(val
); 
 925                                     errorMsg 
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."), 
 926                                                                  value
.c_str(), name
.c_str()) 
 935                         case wxCMD_LINE_VAL_DATE
: 
 938                                 wxString::const_iterator end
; 
 939                                 if ( !dt
.ParseDate(value
, &end
) || end 
!= value
.end() ) 
 941                                     errorMsg 
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."), 
 942                                                                  name
.c_str(), value
.c_str()) 
 953 #endif // wxUSE_DATETIME 
 958         else // not an option, must be a parameter 
 960             if ( currentParam 
< countParam 
) 
 962                 wxCmdLineParam
& param 
= m_data
->m_paramDesc
[currentParam
]; 
 964                 // TODO check the param type 
 966                 m_data
->m_parameters
.push_back(arg
); 
 968                 if ( !(param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE
) ) 
 974                     wxASSERT_MSG( currentParam 
== countParam 
- 1, 
 975                                   wxT("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") ); 
 977                     // remember that we did have this last repeatable parameter 
 978                     hadRepeatableParam 
= true; 
 983                 errorMsg 
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str()) 
 991     // verify that all mandatory options were given 
 994         size_t countOpt 
= m_data
->m_options
.GetCount(); 
 995         for ( size_t n 
= 0; ok 
&& (n 
< countOpt
); n
++ ) 
 997             wxCmdLineOption
& opt 
= m_data
->m_options
[n
]; 
 998             if ( (opt
.flags 
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() ) 
1001                 if ( !opt
.longName 
) 
1003                     optName 
= opt
.shortName
; 
1007                     if ( AreLongOptionsEnabled() ) 
1009                         optName
.Printf( _("%s (or %s)"), 
1010                                         opt
.shortName
.c_str(), 
1011                                         opt
.longName
.c_str() ); 
1015                         optName
.Printf( wxT("%s"), 
1016                                         opt
.shortName
.c_str() ); 
1020                 errorMsg 
<< wxString::Format(_("The value for the option '%s' must be specified."), 
1028         for ( ; ok 
&& (currentParam 
< countParam
); currentParam
++ ) 
1030             wxCmdLineParam
& param 
= m_data
->m_paramDesc
[currentParam
]; 
1031             if ( (currentParam 
== countParam 
- 1) && 
1032                  (param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE
) && 
1033                  hadRepeatableParam 
) 
1035                 // special case: currentParam wasn't incremented, but we did 
1036                 // have it, so don't give error 
1040             if ( !(param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL
) ) 
1042                 errorMsg 
<< wxString::Format(_("The required parameter '%s' was not specified."), 
1043                                              param
.description
.c_str()) 
1051     // if there was an error during parsing the command line, show this error 
1052     // and also the usage message if it had been requested 
1053     if ( !ok 
&& (!errorMsg
.empty() || (helpRequested 
&& showUsage
)) ) 
1055         wxMessageOutput
* msgOut 
= wxMessageOutput::Get(); 
1060                 usage 
= GetUsageString(); 
1062             msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() ); 
1066             wxFAIL_MSG( wxT("no wxMessageOutput object?") ); 
1070     return ok 
? 0 : helpRequested 
? -1 : 1; 
1073 // ---------------------------------------------------------------------------- 
1074 // give the usage message 
1075 // ---------------------------------------------------------------------------- 
1077 void wxCmdLineParser::Usage() const 
1079     wxMessageOutput
* msgOut 
= wxMessageOutput::Get(); 
1082         msgOut
->Printf( wxT("%s"), GetUsageString().c_str() ); 
1086         wxFAIL_MSG( wxT("no wxMessageOutput object?") ); 
1090 wxString 
wxCmdLineParser::GetUsageString() const 
1093     if ( m_data
->m_arguments
.empty() ) 
1096             appname 
= wxTheApp
->GetAppName(); 
1100         appname 
= wxFileName(m_data
->m_arguments
[0]).GetName(); 
1103     // we construct the brief cmd line desc on the fly, but not the detailed 
1104     // help message below because we want to align the options descriptions 
1105     // and for this we must first know the longest one of them 
1107     wxArrayString namesOptions
, descOptions
; 
1109     if ( !m_data
->m_logo
.empty() ) 
1111         usage 
<< m_data
->m_logo 
<< wxT('\n'); 
1114     usage 
<< wxString::Format(_("Usage: %s"), appname
.c_str()); 
1116     // the switch char is usually '-' but this can be changed with 
1117     // SetSwitchChars() and then the first one of possible chars is used 
1118     wxChar chSwitch 
= !m_data
->m_switchChars 
? wxT('-') 
1119                                              : m_data
->m_switchChars
[0u]; 
1121     bool areLongOptionsEnabled 
= AreLongOptionsEnabled(); 
1122     size_t n
, count 
= m_data
->m_options
.GetCount(); 
1123     for ( n 
= 0; n 
< count
; n
++ ) 
1125         wxCmdLineOption
& opt 
= m_data
->m_options
[n
]; 
1126         wxString option
, negator
; 
1128         if ( opt
.kind 
!= wxCMD_LINE_USAGE_TEXT 
) 
1131             if ( !(opt
.flags 
& wxCMD_LINE_OPTION_MANDATORY
) ) 
1136             if ( opt
.flags 
& wxCMD_LINE_SWITCH_NEGATABLE 
) 
1137                 negator 
= wxT("[-]"); 
1139             if ( !opt
.shortName
.empty() ) 
1141                 usage 
<< chSwitch 
<< opt
.shortName 
<< negator
; 
1143             else if ( areLongOptionsEnabled 
&& !opt
.longName
.empty() ) 
1145                 usage 
<< wxT("--") << opt
.longName 
<< negator
; 
1149                 if (!opt
.longName
.empty()) 
1151                     wxFAIL_MSG( wxT("option with only a long name while long ") 
1152                                 wxT("options are disabled") ); 
1156                     wxFAIL_MSG( wxT("option without neither short nor long name") ); 
1160             if ( !opt
.shortName
.empty() ) 
1162                 option 
<< wxT("  ") << chSwitch 
<< opt
.shortName
; 
1165             if ( areLongOptionsEnabled 
&& !opt
.longName
.empty() ) 
1167                 option 
<< (option
.empty() ? wxT("  ") : wxT(", ")) 
1168                        << wxT("--") << opt
.longName
; 
1171             if ( opt
.kind 
!= wxCMD_LINE_SWITCH 
) 
1174                 val 
<< wxT('<') << GetTypeName(opt
.type
) << wxT('>'); 
1175                 usage 
<< wxT(' ') << val
; 
1176                 option 
<< (!opt
.longName 
? wxT(':') : wxT('=')) << val
; 
1179             if ( !(opt
.flags 
& wxCMD_LINE_OPTION_MANDATORY
) ) 
1185         namesOptions
.push_back(option
); 
1186         descOptions
.push_back(opt
.description
); 
1189     count 
= m_data
->m_paramDesc
.GetCount(); 
1190     for ( n 
= 0; n 
< count
; n
++ ) 
1192         wxCmdLineParam
& param 
= m_data
->m_paramDesc
[n
]; 
1195         if ( param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL 
) 
1200         usage 
<< param
.description
; 
1202         if ( param
.flags 
& wxCMD_LINE_PARAM_MULTIPLE 
) 
1204             usage 
<< wxT("..."); 
1207         if ( param
.flags 
& wxCMD_LINE_PARAM_OPTIONAL 
) 
1215     // set to number of our own options, not counting the standard ones 
1216     count 
= namesOptions
.size(); 
1218     // get option names & descriptions for standard options, if any: 
1219     wxAppTraits 
*traits 
= wxTheApp 
? wxTheApp
->GetTraits() : NULL
; 
1222         stdDesc 
= traits
->GetStandardCmdLineOptions(namesOptions
, descOptions
); 
1224     // now construct the detailed help message 
1225     size_t len
, lenMax 
= 0; 
1226     for ( n 
= 0; n 
< namesOptions
.size(); n
++ ) 
1228         len 
= namesOptions
[n
].length(); 
1233     for ( n 
= 0; n 
< namesOptions
.size(); n
++ ) 
1236             usage 
<< wxT('\n') << stdDesc
; 
1238         len 
= namesOptions
[n
].length(); 
1239         // desc contains text if name is empty 
1242             usage 
<< descOptions
[n
] << wxT('\n'); 
1246             usage 
<< namesOptions
[n
] 
1247                   << wxString(wxT(' '), lenMax 
- len
) << wxT('\t') 
1256 // ---------------------------------------------------------------------------- 
1257 // private functions 
1258 // ---------------------------------------------------------------------------- 
1260 static wxString 
GetTypeName(wxCmdLineParamType type
) 
1266             wxFAIL_MSG( wxT("unknown option type") ); 
1267             // still fall through 
1269         case wxCMD_LINE_VAL_STRING
: 
1273         case wxCMD_LINE_VAL_NUMBER
: 
1277         case wxCMD_LINE_VAL_DOUBLE
: 
1281         case wxCMD_LINE_VAL_DATE
: 
1290 Returns a string which is equal to the string pointed to by p, but up to the 
1291 point where p contains an character that's not allowed. 
1292 Allowable characters are letters and numbers, and characters pointed to by 
1293 the parameter allowedChars. 
1295 For example, if p points to "abcde-@-_", and allowedChars is "-_", 
1296 this function returns "abcde-". 
1298 static wxString 
GetOptionName(wxString::const_iterator p
, 
1299                               wxString::const_iterator end
, 
1300                               const wxChar 
*allowedChars
) 
1304     while ( p 
!= end 
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) ) 
1312 // Besides alphanumeric characters, short and long options can 
1313 // have other characters. 
1315 // A short option additionally can have these 
1316 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?") 
1318 // A long option can have the same characters as a short option and a '-'. 
1319 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \ 
1320     wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-") 
1322 static wxString 
GetShortOptionName(wxString::const_iterator p
, 
1323                                   wxString::const_iterator end
) 
1325     return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
); 
1328 static wxString 
GetLongOptionName(wxString::const_iterator p
, 
1329                                   wxString::const_iterator end
) 
1331     return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
); 
1334 #endif // wxUSE_CMDLINE_PARSER 
1336 // ---------------------------------------------------------------------------- 
1338 // ---------------------------------------------------------------------------- 
1341    This function is mainly used under Windows (as under Unix we always get the 
1342    command line arguments as argc/argv anyhow) and so it tries to follow 
1343    Windows conventions for the command line handling, not Unix ones. For 
1344    instance, backslash is not special except when it precedes double quote when 
1350 wxCmdLineParser::ConvertStringToArgs(const wxString
& cmdline
, 
1351                                      wxCmdLineSplitType type
) 
1358     const wxString::const_iterator end 
= cmdline
.end(); 
1359     wxString::const_iterator p 
= cmdline
.begin(); 
1364         while ( p 
!= end 
&& (*p 
== ' ' || *p 
== '\t') ) 
1371         // parse this parameter 
1372         bool lastBS 
= false, 
1373              isInsideQuotes 
= false; 
1374         wxChar chDelim 
= '\0'; 
1375         for ( arg
.clear(); p 
!= end
; ++p 
) 
1377             const wxChar ch 
= *p
; 
1379             if ( type 
== wxCMD_LINE_SPLIT_DOS 
) 
1385                         isInsideQuotes 
= !isInsideQuotes
; 
1387                         // don't put quote in arg 
1390                     //else: quote has no special meaning but the backslash 
1391                     //      still remains -- makes no sense but this is what 
1394                 // note that backslash does *not* quote the space, only quotes do 
1395                 else if ( !isInsideQuotes 
&& (ch 
== ' ' || ch 
== '\t') ) 
1397                     ++p
;    // skip this space anyhow 
1401                 lastBS 
= !lastBS 
&& ch 
== '\\'; 
1403             else // type == wxCMD_LINE_SPLIT_UNIX 
1407                     if ( isInsideQuotes 
) 
1409                         if ( ch 
== chDelim 
) 
1411                             isInsideQuotes 
= false; 
1413                             continue;   // don't use the quote itself 
1416                     else // not in quotes and not escaped 
1418                         if ( ch 
== '\'' || ch 
== '"' ) 
1420                             isInsideQuotes 
= true; 
1423                             continue;   // don't use the quote itself 
1426                         if ( ch 
== ' ' || ch 
== '\t' ) 
1428                             ++p
;    // skip this space anyhow 
1433                     lastBS 
= ch 
== '\\'; 
1437                 else // escaped by backslash, just use as is 
1446         args
.push_back(arg
);