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(bool hasValue
= true) { m_hasVal
= hasValue
; }
145 bool HasValue() const { return m_hasVal
; }
148 wxCmdLineEntryType kind
;
152 wxCmdLineParamType type
;
162 wxDateTime m_dateVal
;
163 #endif // wxUSE_DATETIME
166 struct wxCmdLineParam
168 wxCmdLineParam(const wxString
& desc
,
169 wxCmdLineParamType typ
,
177 wxString description
;
178 wxCmdLineParamType type
;
182 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
);
183 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
);
185 #include "wx/arrimpl.cpp"
187 WX_DEFINE_OBJARRAY(wxArrayOptions
)
188 WX_DEFINE_OBJARRAY(wxArrayParams
)
190 // the parser internal state
191 struct wxCmdLineParserData
194 wxString m_switchChars
; // characters which may start an option
195 bool m_enableLongOptions
; // true if long options are enabled
196 wxString m_logo
; // some extra text to show in Usage()
199 wxArrayString m_arguments
; // == argv, argc == m_arguments.GetCount()
200 wxArrayOptions m_options
; // all possible options and switches
201 wxArrayParams m_paramDesc
; // description of all possible params
202 wxArrayString m_parameters
; // all params found
205 wxCmdLineParserData();
206 void SetArguments(int argc
, char **argv
);
208 void SetArguments(int argc
, wxChar
**argv
);
209 void SetArguments(int argc
, const wxCmdLineArgsArray
& argv
);
210 #endif // wxUSE_UNICODE
211 void SetArguments(const wxString
& cmdline
);
213 int FindOption(const wxString
& name
);
214 int FindOptionByLongName(const wxString
& name
);
217 // ============================================================================
219 // ============================================================================
221 // ----------------------------------------------------------------------------
222 // wxCmdLineParserData
223 // ----------------------------------------------------------------------------
225 wxCmdLineParserData::wxCmdLineParserData()
227 m_enableLongOptions
= true;
229 m_switchChars
= wxT("-");
231 m_switchChars
= wxT("/-");
238 // Small helper function setting locale for all categories.
240 // We define it because wxSetlocale() can't be easily used with wxScopeGuard as
241 // it has several overloads -- while this one can.
242 inline char *SetAllLocaleFacets(const char *loc
)
244 return wxSetlocale(LC_ALL
, loc
);
247 } // private namespace
249 void wxCmdLineParserData::SetArguments(int argc
, char **argv
)
253 // Command-line arguments are supposed to be in the user locale encoding
254 // (what else?) but wxLocale probably wasn't initialized yet as we're
255 // called early during the program startup and so our locale might not have
256 // been set from the environment yet. To work around this problem we
257 // temporarily change the locale here. The only drawback is that changing
258 // the locale is thread-unsafe but precisely because we're called so early
259 // it's hopefully safe to assume that no other threads had been created yet.
260 char * const locOld
= SetAllLocaleFacets("");
261 wxON_BLOCK_EXIT1( SetAllLocaleFacets
, locOld
);
263 for ( int n
= 0; n
< argc
; n
++ )
265 // try to interpret the string as being in the current locale
266 wxString
arg(argv
[n
]);
268 // but just in case we guessed wrongly and the conversion failed, do
269 // try to salvage at least something
270 if ( arg
.empty() && argv
[n
][0] != '\0' )
271 arg
= wxString(argv
[n
], wxConvISO8859_1
);
273 m_arguments
.push_back(arg
);
279 void wxCmdLineParserData::SetArguments(int argc
, wxChar
**argv
)
283 for ( int n
= 0; n
< argc
; n
++ )
285 m_arguments
.push_back(argv
[n
]);
289 void wxCmdLineParserData::SetArguments(int WXUNUSED(argc
),
290 const wxCmdLineArgsArray
& argv
)
292 m_arguments
= argv
.GetArguments();
295 #endif // wxUSE_UNICODE
297 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
)
301 if(wxTheApp
&& wxTheApp
->argc
> 0)
302 m_arguments
.push_back(wxTheApp
->argv
[0]);
304 m_arguments
.push_back(wxEmptyString
);
306 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
308 WX_APPEND_ARRAY(m_arguments
, args
);
311 int wxCmdLineParserData::FindOption(const wxString
& name
)
315 size_t count
= m_options
.GetCount();
316 for ( size_t n
= 0; n
< count
; n
++ )
318 if ( m_options
[n
].shortName
== name
)
329 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
331 size_t count
= m_options
.GetCount();
332 for ( size_t n
= 0; n
< count
; n
++ )
334 if ( m_options
[n
].longName
== name
)
344 // ----------------------------------------------------------------------------
345 // construction and destruction
346 // ----------------------------------------------------------------------------
348 void wxCmdLineParser::Init()
350 m_data
= new wxCmdLineParserData
;
353 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
355 m_data
->SetArguments(argc
, argv
);
360 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
362 m_data
->SetArguments(argc
, argv
);
365 void wxCmdLineParser::SetCmdLine(int argc
, const wxCmdLineArgsArray
& argv
)
367 m_data
->SetArguments(argc
, argv
);
370 #endif // wxUSE_UNICODE
372 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
374 m_data
->SetArguments(cmdline
);
377 wxCmdLineParser::~wxCmdLineParser()
382 // ----------------------------------------------------------------------------
384 // ----------------------------------------------------------------------------
386 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
388 m_data
->m_switchChars
= switchChars
;
391 void wxCmdLineParser::EnableLongOptions(bool enable
)
393 m_data
->m_enableLongOptions
= enable
;
396 bool wxCmdLineParser::AreLongOptionsEnabled() const
398 return m_data
->m_enableLongOptions
;
401 void wxCmdLineParser::SetLogo(const wxString
& logo
)
403 m_data
->m_logo
= logo
;
406 // ----------------------------------------------------------------------------
407 // command line construction
408 // ----------------------------------------------------------------------------
410 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
414 switch ( desc
->kind
)
416 case wxCMD_LINE_SWITCH
:
417 AddSwitch(desc
->shortName
, desc
->longName
,
418 wxGetTranslation(desc
->description
),
422 case wxCMD_LINE_OPTION
:
423 AddOption(desc
->shortName
, desc
->longName
,
424 wxGetTranslation(desc
->description
),
425 desc
->type
, desc
->flags
);
428 case wxCMD_LINE_PARAM
:
429 AddParam(wxGetTranslation(desc
->description
),
430 desc
->type
, desc
->flags
);
433 case wxCMD_LINE_USAGE_TEXT
:
434 AddUsageText(wxGetTranslation(desc
->description
));
438 wxFAIL_MSG( wxT("unknown command line entry type") );
439 // still fall through
441 case wxCMD_LINE_NONE
:
447 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
448 const wxString
& longName
,
449 const wxString
& desc
,
452 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
453 wxT("duplicate switch") );
455 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
456 shortName
, longName
, desc
,
457 wxCMD_LINE_VAL_NONE
, flags
);
459 m_data
->m_options
.Add(option
);
462 void wxCmdLineParser::AddOption(const wxString
& shortName
,
463 const wxString
& longName
,
464 const wxString
& desc
,
465 wxCmdLineParamType type
,
468 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
469 wxT("duplicate option") );
471 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
472 shortName
, longName
, desc
,
475 m_data
->m_options
.Add(option
);
478 void wxCmdLineParser::AddParam(const wxString
& desc
,
479 wxCmdLineParamType type
,
482 // do some consistency checks: a required parameter can't follow an
483 // optional one and nothing should follow a parameter with MULTIPLE flag
485 if ( !m_data
->m_paramDesc
.IsEmpty() )
487 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
489 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
490 wxT("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
492 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
494 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
495 wxT("a required parameter can't follow an optional one") );
498 #endif // wxDEBUG_LEVEL
500 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
502 m_data
->m_paramDesc
.Add(param
);
505 void wxCmdLineParser::AddUsageText(const wxString
& text
)
507 wxASSERT_MSG( !text
.empty(), wxT("text can't be empty") );
509 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_USAGE_TEXT
,
510 wxEmptyString
, wxEmptyString
,
511 text
, wxCMD_LINE_VAL_NONE
, 0);
513 m_data
->m_options
.Add(option
);
516 // ----------------------------------------------------------------------------
517 // access to parse command line
518 // ----------------------------------------------------------------------------
520 bool wxCmdLineParser::Found(const wxString
& name
) const
522 int i
= m_data
->FindOption(name
);
523 if ( i
== wxNOT_FOUND
)
524 i
= m_data
->FindOptionByLongName(name
);
526 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, wxT("unknown switch") );
528 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
529 if ( !opt
.HasValue() )
535 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
537 int i
= m_data
->FindOption(name
);
538 if ( i
== wxNOT_FOUND
)
539 i
= m_data
->FindOptionByLongName(name
);
541 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, wxT("unknown option") );
543 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
544 if ( !opt
.HasValue() )
547 wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") );
549 *value
= opt
.GetStrVal();
554 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
556 int i
= m_data
->FindOption(name
);
557 if ( i
== wxNOT_FOUND
)
558 i
= m_data
->FindOptionByLongName(name
);
560 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, wxT("unknown option") );
562 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
563 if ( !opt
.HasValue() )
566 wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") );
568 *value
= opt
.GetLongVal();
573 bool wxCmdLineParser::Found(const wxString
& name
, double *value
) const
575 int i
= m_data
->FindOption(name
);
576 if ( i
== wxNOT_FOUND
)
577 i
= m_data
->FindOptionByLongName(name
);
579 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, wxT("unknown option") );
581 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
582 if ( !opt
.HasValue() )
585 wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") );
587 *value
= opt
.GetDoubleVal();
593 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
595 int i
= m_data
->FindOption(name
);
596 if ( i
== wxNOT_FOUND
)
597 i
= m_data
->FindOptionByLongName(name
);
599 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, wxT("unknown option") );
601 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
602 if ( !opt
.HasValue() )
605 wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") );
607 *value
= opt
.GetDateVal();
611 #endif // wxUSE_DATETIME
613 size_t wxCmdLineParser::GetParamCount() const
615 return m_data
->m_parameters
.size();
618 wxString
wxCmdLineParser::GetParam(size_t n
) const
620 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, wxT("invalid param index") );
622 return m_data
->m_parameters
[n
];
625 // Resets switches and options
626 void wxCmdLineParser::Reset()
628 for ( size_t i
= 0; i
< m_data
->m_options
.GetCount(); i
++ )
630 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
631 opt
.SetHasValue(false);
636 // ----------------------------------------------------------------------------
637 // the real work is done here
638 // ----------------------------------------------------------------------------
640 int wxCmdLineParser::Parse(bool showUsage
)
642 bool maybeOption
= true; // can the following arg be an option?
643 bool ok
= true; // true until an error is detected
644 bool helpRequested
= false; // true if "-h" was given
645 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
647 size_t currentParam
= 0; // the index in m_paramDesc
649 size_t countParam
= m_data
->m_paramDesc
.GetCount();
656 size_t count
= m_data
->m_arguments
.size();
657 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
659 arg
= m_data
->m_arguments
[n
];
661 // special case: "--" should be discarded and all following arguments
662 // should be considered as parameters, even if they start with '-' and
663 // not like options (this is POSIX-like)
664 if ( arg
== wxT("--") )
671 // empty argument or just '-' is not an option but a parameter
672 if ( maybeOption
&& arg
.length() > 1 &&
673 // FIXME-UTF8: use wc_str() after removing ANSI build
674 wxStrchr(m_data
->m_switchChars
.c_str(), arg
[0u]) )
678 int optInd
= wxNOT_FOUND
; // init to suppress warnings
680 // an option or a switch: find whether it's a long or a short one
681 if ( arg
.length() >= 3 && arg
[0u] == wxT('-') && arg
[1u] == wxT('-') )
687 wxString::const_iterator p
= arg
.begin() + 2;
689 bool longOptionsEnabled
= AreLongOptionsEnabled();
691 name
= GetLongOptionName(p
, arg
.end());
693 if (longOptionsEnabled
)
695 optInd
= m_data
->FindOptionByLongName(name
);
696 if ( optInd
== wxNOT_FOUND
)
698 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str())
704 optInd
= wxNOT_FOUND
; // Sanity check
706 // Print the argument including leading "--"
707 name
.Prepend( wxT("--") );
708 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
713 else // not a long option
717 // a short one: as they can be cumulated, we try to find the
718 // longest substring which is a valid option
719 wxString::const_iterator p
= arg
.begin() + 1;
721 name
= GetShortOptionName(p
, arg
.end());
723 size_t len
= name
.length();
728 // we couldn't find a valid option name in the
729 // beginning of this string
730 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
737 optInd
= m_data
->FindOption(name
.Left(len
));
739 // will try with one character less the next time
743 while ( optInd
== wxNOT_FOUND
);
745 len
++; // compensates extra len-- above
746 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
748 // first of all, the option name is only part of this
750 name
= name
.Left(len
);
752 // our option is only part of this argument, there is
753 // something else in it - it is either the value of this
754 // option or other switches if it is a switch
755 if ( m_data
->m_options
[(size_t)optInd
].kind
756 == wxCMD_LINE_SWITCH
)
758 // pretend that all the rest of the argument is the
759 // next argument, in fact
760 wxString arg2
= arg
[0u];
761 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
763 m_data
->m_arguments
.insert
764 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
767 // only leave the part which wasn't extracted into the
768 // next argument in this one
769 arg
= arg
.Left(len
+ 1);
771 //else: it's our value, we'll deal with it below
775 if ( optInd
== wxNOT_FOUND
)
779 continue; // will break, in fact
782 // look at what follows:
784 // +1 for leading '-'
785 wxString::const_iterator p
= arg
.begin() + 1 + name
.length();
786 wxString::const_iterator end
= arg
.end();
789 ++p
; // for another leading '-'
791 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
792 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
794 // we must check that there is no value following the switch
795 if ( p
!= arg
.end() )
797 errorMsg
<< wxString::Format(_("Unexpected characters following option '%s'."), name
.c_str())
801 else // no value, as expected
803 // nothing more to do
806 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
808 helpRequested
= true;
810 // it's not an error, but we still stop here
815 else // it's an option. not a switch
817 switch ( p
== end
? '\0' : (*p
).GetValue() )
826 // the value is in the next argument
829 // ... but there is none
830 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
838 // ... take it from there
839 p
= m_data
->m_arguments
[n
].begin();
840 end
= m_data
->m_arguments
[n
].end();
845 // the value is right here: this may be legal or
846 // not depending on the option style
847 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
849 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
859 wxString
value(p
, end
);
863 wxFAIL_MSG( wxT("unknown option type") );
864 // still fall through
866 case wxCMD_LINE_VAL_STRING
:
867 opt
.SetStrVal(value
);
870 case wxCMD_LINE_VAL_NUMBER
:
873 if ( value
.ToLong(&val
) )
879 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
880 value
.c_str(), name
.c_str())
888 case wxCMD_LINE_VAL_DOUBLE
:
891 if ( value
.ToDouble(&val
) )
893 opt
.SetDoubleVal(val
);
897 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
898 value
.c_str(), name
.c_str())
907 case wxCMD_LINE_VAL_DATE
:
910 wxString::const_iterator end
;
911 if ( !dt
.ParseDate(value
, &end
) || end
!= value
.end() )
913 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
914 name
.c_str(), value
.c_str())
925 #endif // wxUSE_DATETIME
930 else // not an option, must be a parameter
932 if ( currentParam
< countParam
)
934 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
936 // TODO check the param type
938 m_data
->m_parameters
.push_back(arg
);
940 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
946 wxASSERT_MSG( currentParam
== countParam
- 1,
947 wxT("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
949 // remember that we did have this last repeatable parameter
950 hadRepeatableParam
= true;
955 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str())
963 // verify that all mandatory options were given
966 size_t countOpt
= m_data
->m_options
.GetCount();
967 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
969 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
970 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
975 optName
= opt
.shortName
;
979 if ( AreLongOptionsEnabled() )
981 optName
.Printf( _("%s (or %s)"),
982 opt
.shortName
.c_str(),
983 opt
.longName
.c_str() );
987 optName
.Printf( wxT("%s"),
988 opt
.shortName
.c_str() );
992 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
1000 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
1002 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
1003 if ( (currentParam
== countParam
- 1) &&
1004 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
1005 hadRepeatableParam
)
1007 // special case: currentParam wasn't incremented, but we did
1008 // have it, so don't give error
1012 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
1014 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
1015 param
.description
.c_str())
1023 // if there was an error during parsing the command line, show this error
1024 // and also the usage message if it had been requested
1025 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
1027 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
1032 usage
= GetUsageString();
1034 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
1038 wxFAIL_MSG( wxT("no wxMessageOutput object?") );
1042 return ok
? 0 : helpRequested
? -1 : 1;
1045 // ----------------------------------------------------------------------------
1046 // give the usage message
1047 // ----------------------------------------------------------------------------
1049 void wxCmdLineParser::Usage() const
1051 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
1054 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
1058 wxFAIL_MSG( wxT("no wxMessageOutput object?") );
1062 wxString
wxCmdLineParser::GetUsageString() const
1065 if ( m_data
->m_arguments
.empty() )
1068 appname
= wxTheApp
->GetAppName();
1072 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
1075 // we construct the brief cmd line desc on the fly, but not the detailed
1076 // help message below because we want to align the options descriptions
1077 // and for this we must first know the longest one of them
1079 wxArrayString namesOptions
, descOptions
;
1081 if ( !m_data
->m_logo
.empty() )
1083 usage
<< m_data
->m_logo
<< wxT('\n');
1086 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
1088 // the switch char is usually '-' but this can be changed with
1089 // SetSwitchChars() and then the first one of possible chars is used
1090 wxChar chSwitch
= !m_data
->m_switchChars
? wxT('-')
1091 : m_data
->m_switchChars
[0u];
1093 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
1094 size_t n
, count
= m_data
->m_options
.GetCount();
1095 for ( n
= 0; n
< count
; n
++ )
1097 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
1100 if ( opt
.kind
!= wxCMD_LINE_USAGE_TEXT
)
1103 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1108 if ( !opt
.shortName
.empty() )
1110 usage
<< chSwitch
<< opt
.shortName
;
1112 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1114 usage
<< wxT("--") << opt
.longName
;
1118 if (!opt
.longName
.empty())
1120 wxFAIL_MSG( wxT("option with only a long name while long ")
1121 wxT("options are disabled") );
1125 wxFAIL_MSG( wxT("option without neither short nor long name") );
1129 if ( !opt
.shortName
.empty() )
1131 option
<< wxT(" ") << chSwitch
<< opt
.shortName
;
1134 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1136 option
<< (option
.empty() ? wxT(" ") : wxT(", "))
1137 << wxT("--") << opt
.longName
;
1140 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1143 val
<< wxT('<') << GetTypeName(opt
.type
) << wxT('>');
1144 usage
<< wxT(' ') << val
;
1145 option
<< (!opt
.longName
? wxT(':') : wxT('=')) << val
;
1148 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1154 namesOptions
.push_back(option
);
1155 descOptions
.push_back(opt
.description
);
1158 count
= m_data
->m_paramDesc
.GetCount();
1159 for ( n
= 0; n
< count
; n
++ )
1161 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1164 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1169 usage
<< param
.description
;
1171 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1173 usage
<< wxT("...");
1176 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1184 // set to number of our own options, not counting the standard ones
1185 count
= namesOptions
.size();
1187 // get option names & descriptions for standard options, if any:
1188 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
1191 stdDesc
= traits
->GetStandardCmdLineOptions(namesOptions
, descOptions
);
1193 // now construct the detailed help message
1194 size_t len
, lenMax
= 0;
1195 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1197 len
= namesOptions
[n
].length();
1202 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1205 usage
<< wxT('\n') << stdDesc
;
1207 len
= namesOptions
[n
].length();
1208 // desc contains text if name is empty
1211 usage
<< descOptions
[n
] << wxT('\n');
1215 usage
<< namesOptions
[n
]
1216 << wxString(wxT(' '), lenMax
- len
) << wxT('\t')
1225 // ----------------------------------------------------------------------------
1226 // private functions
1227 // ----------------------------------------------------------------------------
1229 static wxString
GetTypeName(wxCmdLineParamType type
)
1235 wxFAIL_MSG( wxT("unknown option type") );
1236 // still fall through
1238 case wxCMD_LINE_VAL_STRING
:
1242 case wxCMD_LINE_VAL_NUMBER
:
1246 case wxCMD_LINE_VAL_DOUBLE
:
1250 case wxCMD_LINE_VAL_DATE
:
1259 Returns a string which is equal to the string pointed to by p, but up to the
1260 point where p contains an character that's not allowed.
1261 Allowable characters are letters and numbers, and characters pointed to by
1262 the parameter allowedChars.
1264 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1265 this function returns "abcde-".
1267 static wxString
GetOptionName(wxString::const_iterator p
,
1268 wxString::const_iterator end
,
1269 const wxChar
*allowedChars
)
1273 while ( p
!= end
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1281 // Besides alphanumeric characters, short and long options can
1282 // have other characters.
1284 // A short option additionally can have these
1285 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1287 // A long option can have the same characters as a short option and a '-'.
1288 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1289 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1291 static wxString
GetShortOptionName(wxString::const_iterator p
,
1292 wxString::const_iterator end
)
1294 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1297 static wxString
GetLongOptionName(wxString::const_iterator p
,
1298 wxString::const_iterator end
)
1300 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1303 #endif // wxUSE_CMDLINE_PARSER
1305 // ----------------------------------------------------------------------------
1307 // ----------------------------------------------------------------------------
1310 This function is mainly used under Windows (as under Unix we always get the
1311 command line arguments as argc/argv anyhow) and so it tries to follow
1312 Windows conventions for the command line handling, not Unix ones. For
1313 instance, backslash is not special except when it precedes double quote when
1319 wxCmdLineParser::ConvertStringToArgs(const wxString
& cmdline
,
1320 wxCmdLineSplitType type
)
1327 const wxString::const_iterator end
= cmdline
.end();
1328 wxString::const_iterator p
= cmdline
.begin();
1333 while ( p
!= end
&& (*p
== ' ' || *p
== '\t') )
1340 // parse this parameter
1341 bool lastBS
= false,
1342 isInsideQuotes
= false;
1343 wxChar chDelim
= '\0';
1344 for ( arg
.clear(); p
!= end
; ++p
)
1346 const wxChar ch
= *p
;
1348 if ( type
== wxCMD_LINE_SPLIT_DOS
)
1354 isInsideQuotes
= !isInsideQuotes
;
1356 // don't put quote in arg
1359 //else: quote has no special meaning but the backslash
1360 // still remains -- makes no sense but this is what
1363 // note that backslash does *not* quote the space, only quotes do
1364 else if ( !isInsideQuotes
&& (ch
== ' ' || ch
== '\t') )
1366 ++p
; // skip this space anyhow
1370 lastBS
= !lastBS
&& ch
== '\\';
1372 else // type == wxCMD_LINE_SPLIT_UNIX
1376 if ( isInsideQuotes
)
1378 if ( ch
== chDelim
)
1380 isInsideQuotes
= false;
1382 continue; // don't use the quote itself
1385 else // not in quotes and not escaped
1387 if ( ch
== '\'' || ch
== '"' )
1389 isInsideQuotes
= true;
1392 continue; // don't use the quote itself
1395 if ( ch
== ' ' || ch
== '\t' )
1397 ++p
; // skip this space anyhow
1402 lastBS
= ch
== '\\';
1406 else // escaped by backslash, just use as is
1415 args
.push_back(arg
);