1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/cmdline.cpp
3 // Purpose: wxCmdLineParser implementation
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/dynarray.h"
29 #include "wx/string.h"
35 #include "wx/cmdline.h"
37 #if wxUSE_CMDLINE_PARSER
41 #include "wx/datetime.h"
42 #include "wx/msgout.h"
43 #include "wx/filename.h"
44 #include "wx/apptrait.h"
45 #include "wx/scopeguard.h"
47 // ----------------------------------------------------------------------------
49 // ----------------------------------------------------------------------------
51 static wxString
GetTypeName(wxCmdLineParamType type
);
53 static wxString
GetOptionName(wxString::const_iterator p
,
54 wxString::const_iterator end
,
55 const wxChar
*allowedChars
);
57 static wxString
GetShortOptionName(wxString::const_iterator p
,
58 wxString::const_iterator end
);
60 static wxString
GetLongOptionName(wxString::const_iterator p
,
61 wxString::const_iterator end
);
63 // ----------------------------------------------------------------------------
65 // ----------------------------------------------------------------------------
67 // an internal representation of an option
68 struct wxCmdLineOption
70 wxCmdLineOption(wxCmdLineEntryType k
,
74 wxCmdLineParamType typ
,
77 // wxCMD_LINE_USAGE_TEXT uses only description, shortName and longName is empty
78 if ( k
!= wxCMD_LINE_USAGE_TEXT
)
82 !shrt
.empty() || !lng
.empty(),
83 wxT("option should have at least one name")
88 GetShortOptionName(shrt
.begin(), shrt
.end()).Len() == shrt
.Len(),
89 wxT("Short option contains invalid characters")
94 GetLongOptionName(lng
.begin(), lng
.end()).Len() == lng
.Len(),
95 wxT("Long option contains invalid characters")
111 // can't use union easily here, so just store all possible data fields, we
112 // don't waste much (might still use union later if the number of supported
113 // types increases, so always use the accessor functions and don't access
114 // the fields directly!)
116 void Check(wxCmdLineParamType
WXUNUSED_UNLESS_DEBUG(typ
)) const
118 wxASSERT_MSG( type
== typ
, wxT("type mismatch in wxCmdLineOption") );
121 double GetDoubleVal() const
122 { Check(wxCMD_LINE_VAL_DOUBLE
); return m_doubleVal
; }
123 long GetLongVal() const
124 { Check(wxCMD_LINE_VAL_NUMBER
); return m_longVal
; }
125 const wxString
& GetStrVal() const
126 { Check(wxCMD_LINE_VAL_STRING
); return m_strVal
; }
128 const wxDateTime
& GetDateVal() const
129 { Check(wxCMD_LINE_VAL_DATE
); return m_dateVal
; }
130 #endif // wxUSE_DATETIME
132 void SetDoubleVal(double val
)
133 { Check(wxCMD_LINE_VAL_DOUBLE
); m_doubleVal
= val
; m_hasVal
= true; }
134 void SetLongVal(long val
)
135 { Check(wxCMD_LINE_VAL_NUMBER
); m_longVal
= val
; m_hasVal
= true; }
136 void SetStrVal(const wxString
& val
)
137 { Check(wxCMD_LINE_VAL_STRING
); m_strVal
= val
; m_hasVal
= true; }
139 void SetDateVal(const wxDateTime
& val
)
140 { Check(wxCMD_LINE_VAL_DATE
); m_dateVal
= val
; m_hasVal
= true; }
141 #endif // wxUSE_DATETIME
143 void SetHasValue(bool hasValue
= true) { m_hasVal
= hasValue
; }
144 bool HasValue() const { return m_hasVal
; }
147 wxCmdLineEntryType kind
;
151 wxCmdLineParamType type
;
161 wxDateTime m_dateVal
;
162 #endif // wxUSE_DATETIME
165 struct wxCmdLineParam
167 wxCmdLineParam(const wxString
& desc
,
168 wxCmdLineParamType typ
,
176 wxString description
;
177 wxCmdLineParamType type
;
181 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
);
182 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
);
184 #include "wx/arrimpl.cpp"
186 WX_DEFINE_OBJARRAY(wxArrayOptions
)
187 WX_DEFINE_OBJARRAY(wxArrayParams
)
189 // the parser internal state
190 struct wxCmdLineParserData
193 wxString m_switchChars
; // characters which may start an option
194 bool m_enableLongOptions
; // true if long options are enabled
195 wxString m_logo
; // some extra text to show in Usage()
198 wxArrayString m_arguments
; // == argv, argc == m_arguments.GetCount()
199 wxArrayOptions m_options
; // all possible options and switches
200 wxArrayParams m_paramDesc
; // description of all possible params
201 wxArrayString m_parameters
; // all params found
204 wxCmdLineParserData();
205 void SetArguments(int argc
, char **argv
);
207 void SetArguments(int argc
, wxChar
**argv
);
208 void SetArguments(int argc
, const wxCmdLineArgsArray
& argv
);
209 #endif // wxUSE_UNICODE
210 void SetArguments(const wxString
& cmdline
);
212 int FindOption(const wxString
& name
);
213 int FindOptionByLongName(const wxString
& name
);
216 // ============================================================================
218 // ============================================================================
220 // ----------------------------------------------------------------------------
221 // wxCmdLineParserData
222 // ----------------------------------------------------------------------------
224 wxCmdLineParserData::wxCmdLineParserData()
226 m_enableLongOptions
= true;
228 m_switchChars
= wxT("-");
230 m_switchChars
= wxT("/-");
237 // Small helper function setting locale for all categories.
239 // We define it because wxSetlocale() can't be easily used with wxScopeGuard as
240 // it has several overloads -- while this one can.
241 inline char *SetAllLocaleFacets(const char *loc
)
243 return wxSetlocale(LC_ALL
, loc
);
246 } // private namespace
248 void wxCmdLineParserData::SetArguments(int argc
, char **argv
)
252 // Command-line arguments are supposed to be in the user locale encoding
253 // (what else?) but wxLocale probably wasn't initialized yet as we're
254 // called early during the program startup and so our locale might not have
255 // been set from the environment yet. To work around this problem we
256 // temporarily change the locale here. The only drawback is that changing
257 // the locale is thread-unsafe but precisely because we're called so early
258 // it's hopefully safe to assume that no other threads had been created yet.
259 char * const locOld
= SetAllLocaleFacets("");
260 wxON_BLOCK_EXIT1( SetAllLocaleFacets
, locOld
);
262 for ( int n
= 0; n
< argc
; n
++ )
264 // try to interpret the string as being in the current locale
265 wxString
arg(argv
[n
]);
267 // but just in case we guessed wrongly and the conversion failed, do
268 // try to salvage at least something
269 if ( arg
.empty() && argv
[n
][0] != '\0' )
270 arg
= wxString(argv
[n
], wxConvISO8859_1
);
272 m_arguments
.push_back(arg
);
278 void wxCmdLineParserData::SetArguments(int argc
, wxChar
**argv
)
282 for ( int n
= 0; n
< argc
; n
++ )
284 m_arguments
.push_back(argv
[n
]);
288 void wxCmdLineParserData::SetArguments(int WXUNUSED(argc
),
289 const wxCmdLineArgsArray
& argv
)
291 m_arguments
= argv
.GetArguments();
294 #endif // wxUSE_UNICODE
296 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
)
300 if(wxTheApp
&& wxTheApp
->argc
> 0)
301 m_arguments
.push_back(wxTheApp
->argv
[0]);
303 m_arguments
.push_back(wxEmptyString
);
305 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
307 WX_APPEND_ARRAY(m_arguments
, args
);
310 int wxCmdLineParserData::FindOption(const wxString
& name
)
314 size_t count
= m_options
.GetCount();
315 for ( size_t n
= 0; n
< count
; n
++ )
317 if ( m_options
[n
].shortName
== name
)
328 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
330 size_t count
= m_options
.GetCount();
331 for ( size_t n
= 0; n
< count
; n
++ )
333 if ( m_options
[n
].longName
== name
)
343 // ----------------------------------------------------------------------------
344 // construction and destruction
345 // ----------------------------------------------------------------------------
347 void wxCmdLineParser::Init()
349 m_data
= new wxCmdLineParserData
;
352 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
354 m_data
->SetArguments(argc
, argv
);
359 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
361 m_data
->SetArguments(argc
, argv
);
364 void wxCmdLineParser::SetCmdLine(int argc
, const wxCmdLineArgsArray
& argv
)
366 m_data
->SetArguments(argc
, argv
);
369 #endif // wxUSE_UNICODE
371 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
373 m_data
->SetArguments(cmdline
);
376 wxCmdLineParser::~wxCmdLineParser()
381 // ----------------------------------------------------------------------------
383 // ----------------------------------------------------------------------------
385 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
387 m_data
->m_switchChars
= switchChars
;
390 void wxCmdLineParser::EnableLongOptions(bool enable
)
392 m_data
->m_enableLongOptions
= enable
;
395 bool wxCmdLineParser::AreLongOptionsEnabled() const
397 return m_data
->m_enableLongOptions
;
400 void wxCmdLineParser::SetLogo(const wxString
& logo
)
402 m_data
->m_logo
= logo
;
405 // ----------------------------------------------------------------------------
406 // command line construction
407 // ----------------------------------------------------------------------------
409 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
413 switch ( desc
->kind
)
415 case wxCMD_LINE_SWITCH
:
416 AddSwitch(desc
->shortName
, desc
->longName
,
417 wxGetTranslation(desc
->description
),
421 case wxCMD_LINE_OPTION
:
422 AddOption(desc
->shortName
, desc
->longName
,
423 wxGetTranslation(desc
->description
),
424 desc
->type
, desc
->flags
);
427 case wxCMD_LINE_PARAM
:
428 AddParam(wxGetTranslation(desc
->description
),
429 desc
->type
, desc
->flags
);
432 case wxCMD_LINE_USAGE_TEXT
:
433 AddUsageText(wxGetTranslation(desc
->description
));
437 wxFAIL_MSG( wxT("unknown command line entry type") );
438 // still fall through
440 case wxCMD_LINE_NONE
:
446 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
447 const wxString
& longName
,
448 const wxString
& desc
,
451 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
452 wxT("duplicate switch") );
454 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
455 shortName
, longName
, desc
,
456 wxCMD_LINE_VAL_NONE
, flags
);
458 m_data
->m_options
.Add(option
);
461 void wxCmdLineParser::AddOption(const wxString
& shortName
,
462 const wxString
& longName
,
463 const wxString
& desc
,
464 wxCmdLineParamType type
,
467 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
468 wxT("duplicate option") );
470 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
471 shortName
, longName
, desc
,
474 m_data
->m_options
.Add(option
);
477 void wxCmdLineParser::AddParam(const wxString
& desc
,
478 wxCmdLineParamType type
,
481 // do some consistency checks: a required parameter can't follow an
482 // optional one and nothing should follow a parameter with MULTIPLE flag
484 if ( !m_data
->m_paramDesc
.IsEmpty() )
486 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
488 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
489 wxT("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
491 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
493 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
494 wxT("a required parameter can't follow an optional one") );
497 #endif // wxDEBUG_LEVEL
499 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
501 m_data
->m_paramDesc
.Add(param
);
504 void wxCmdLineParser::AddUsageText(const wxString
& text
)
506 wxASSERT_MSG( !text
.empty(), wxT("text can't be empty") );
508 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_USAGE_TEXT
,
509 wxEmptyString
, wxEmptyString
,
510 text
, wxCMD_LINE_VAL_NONE
, 0);
512 m_data
->m_options
.Add(option
);
515 // ----------------------------------------------------------------------------
516 // access to parse command line
517 // ----------------------------------------------------------------------------
519 bool wxCmdLineParser::Found(const wxString
& name
) const
521 int i
= m_data
->FindOption(name
);
522 if ( i
== wxNOT_FOUND
)
523 i
= m_data
->FindOptionByLongName(name
);
525 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, wxT("unknown switch") );
527 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
528 if ( !opt
.HasValue() )
534 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
536 int i
= m_data
->FindOption(name
);
537 if ( i
== wxNOT_FOUND
)
538 i
= m_data
->FindOptionByLongName(name
);
540 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, wxT("unknown option") );
542 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
543 if ( !opt
.HasValue() )
546 wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") );
548 *value
= opt
.GetStrVal();
553 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
555 int i
= m_data
->FindOption(name
);
556 if ( i
== wxNOT_FOUND
)
557 i
= m_data
->FindOptionByLongName(name
);
559 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, wxT("unknown option") );
561 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
562 if ( !opt
.HasValue() )
565 wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") );
567 *value
= opt
.GetLongVal();
572 bool wxCmdLineParser::Found(const wxString
& name
, double *value
) const
574 int i
= m_data
->FindOption(name
);
575 if ( i
== wxNOT_FOUND
)
576 i
= m_data
->FindOptionByLongName(name
);
578 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, wxT("unknown option") );
580 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
581 if ( !opt
.HasValue() )
584 wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") );
586 *value
= opt
.GetDoubleVal();
592 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
594 int i
= m_data
->FindOption(name
);
595 if ( i
== wxNOT_FOUND
)
596 i
= m_data
->FindOptionByLongName(name
);
598 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, wxT("unknown option") );
600 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
601 if ( !opt
.HasValue() )
604 wxCHECK_MSG( value
, false, wxT("NULL pointer in wxCmdLineOption::Found") );
606 *value
= opt
.GetDateVal();
610 #endif // wxUSE_DATETIME
612 size_t wxCmdLineParser::GetParamCount() const
614 return m_data
->m_parameters
.size();
617 wxString
wxCmdLineParser::GetParam(size_t n
) const
619 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, wxT("invalid param index") );
621 return m_data
->m_parameters
[n
];
624 // Resets switches and options
625 void wxCmdLineParser::Reset()
627 for ( size_t i
= 0; i
< m_data
->m_options
.GetCount(); i
++ )
629 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
630 opt
.SetHasValue(false);
635 // ----------------------------------------------------------------------------
636 // the real work is done here
637 // ----------------------------------------------------------------------------
639 int wxCmdLineParser::Parse(bool showUsage
)
641 bool maybeOption
= true; // can the following arg be an option?
642 bool ok
= true; // true until an error is detected
643 bool helpRequested
= false; // true if "-h" was given
644 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
646 size_t currentParam
= 0; // the index in m_paramDesc
648 size_t countParam
= m_data
->m_paramDesc
.GetCount();
655 size_t count
= m_data
->m_arguments
.size();
656 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
658 arg
= m_data
->m_arguments
[n
];
660 // special case: "--" should be discarded and all following arguments
661 // should be considered as parameters, even if they start with '-' and
662 // not like options (this is POSIX-like)
663 if ( arg
== wxT("--") )
670 // empty argument or just '-' is not an option but a parameter
671 if ( maybeOption
&& arg
.length() > 1 &&
672 // FIXME-UTF8: use wc_str() after removing ANSI build
673 wxStrchr(m_data
->m_switchChars
.c_str(), arg
[0u]) )
677 int optInd
= wxNOT_FOUND
; // init to suppress warnings
679 // an option or a switch: find whether it's a long or a short one
680 if ( arg
.length() >= 3 && arg
[0u] == wxT('-') && arg
[1u] == wxT('-') )
686 wxString::const_iterator p
= arg
.begin() + 2;
688 bool longOptionsEnabled
= AreLongOptionsEnabled();
690 name
= GetLongOptionName(p
, arg
.end());
692 if (longOptionsEnabled
)
694 optInd
= m_data
->FindOptionByLongName(name
);
695 if ( optInd
== wxNOT_FOUND
)
697 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str())
703 optInd
= wxNOT_FOUND
; // Sanity check
705 // Print the argument including leading "--"
706 name
.Prepend( wxT("--") );
707 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
712 else // not a long option
716 // a short one: as they can be cumulated, we try to find the
717 // longest substring which is a valid option
718 wxString::const_iterator p
= arg
.begin() + 1;
720 name
= GetShortOptionName(p
, arg
.end());
722 size_t len
= name
.length();
727 // we couldn't find a valid option name in the
728 // beginning of this string
729 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
736 optInd
= m_data
->FindOption(name
.Left(len
));
738 // will try with one character less the next time
742 while ( optInd
== wxNOT_FOUND
);
744 len
++; // compensates extra len-- above
745 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
747 // first of all, the option name is only part of this
749 name
= name
.Left(len
);
751 // our option is only part of this argument, there is
752 // something else in it - it is either the value of this
753 // option or other switches if it is a switch
754 if ( m_data
->m_options
[(size_t)optInd
].kind
755 == wxCMD_LINE_SWITCH
)
757 // pretend that all the rest of the argument is the
758 // next argument, in fact
759 wxString arg2
= arg
[0u];
760 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
762 m_data
->m_arguments
.insert
763 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
766 // only leave the part which wasn't extracted into the
767 // next argument in this one
768 arg
= arg
.Left(len
+ 1);
770 //else: it's our value, we'll deal with it below
774 if ( optInd
== wxNOT_FOUND
)
778 continue; // will break, in fact
781 // look at what follows:
783 // +1 for leading '-'
784 wxString::const_iterator p
= arg
.begin() + 1 + name
.length();
785 wxString::const_iterator end
= arg
.end();
788 ++p
; // for another leading '-'
790 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
791 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
793 // we must check that there is no value following the switch
794 if ( p
!= arg
.end() )
796 errorMsg
<< wxString::Format(_("Unexpected characters following option '%s'."), name
.c_str())
800 else // no value, as expected
802 // nothing more to do
805 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
807 helpRequested
= true;
809 // it's not an error, but we still stop here
814 else // it's an option. not a switch
816 switch ( p
== end
? '\0' : (*p
).GetValue() )
825 // the value is in the next argument
828 // ... but there is none
829 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
837 // ... take it from there
838 p
= m_data
->m_arguments
[n
].begin();
839 end
= m_data
->m_arguments
[n
].end();
844 // the value is right here: this may be legal or
845 // not depending on the option style
846 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
848 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
858 wxString
value(p
, end
);
862 wxFAIL_MSG( wxT("unknown option type") );
863 // still fall through
865 case wxCMD_LINE_VAL_STRING
:
866 opt
.SetStrVal(value
);
869 case wxCMD_LINE_VAL_NUMBER
:
872 if ( value
.ToLong(&val
) )
878 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
879 value
.c_str(), name
.c_str())
887 case wxCMD_LINE_VAL_DOUBLE
:
890 if ( value
.ToDouble(&val
) )
892 opt
.SetDoubleVal(val
);
896 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
897 value
.c_str(), name
.c_str())
906 case wxCMD_LINE_VAL_DATE
:
909 wxString::const_iterator end
;
910 if ( !dt
.ParseDate(value
, &end
) || end
!= value
.end() )
912 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
913 name
.c_str(), value
.c_str())
924 #endif // wxUSE_DATETIME
929 else // not an option, must be a parameter
931 if ( currentParam
< countParam
)
933 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
935 // TODO check the param type
937 m_data
->m_parameters
.push_back(arg
);
939 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
945 wxASSERT_MSG( currentParam
== countParam
- 1,
946 wxT("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
948 // remember that we did have this last repeatable parameter
949 hadRepeatableParam
= true;
954 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str())
962 // verify that all mandatory options were given
965 size_t countOpt
= m_data
->m_options
.GetCount();
966 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
968 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
969 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
974 optName
= opt
.shortName
;
978 if ( AreLongOptionsEnabled() )
980 optName
.Printf( _("%s (or %s)"),
981 opt
.shortName
.c_str(),
982 opt
.longName
.c_str() );
986 optName
.Printf( wxT("%s"),
987 opt
.shortName
.c_str() );
991 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
999 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
1001 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
1002 if ( (currentParam
== countParam
- 1) &&
1003 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
1004 hadRepeatableParam
)
1006 // special case: currentParam wasn't incremented, but we did
1007 // have it, so don't give error
1011 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
1013 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
1014 param
.description
.c_str())
1022 // if there was an error during parsing the command line, show this error
1023 // and also the usage message if it had been requested
1024 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
1026 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
1031 usage
= GetUsageString();
1033 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
1037 wxFAIL_MSG( wxT("no wxMessageOutput object?") );
1041 return ok
? 0 : helpRequested
? -1 : 1;
1044 // ----------------------------------------------------------------------------
1045 // give the usage message
1046 // ----------------------------------------------------------------------------
1048 void wxCmdLineParser::Usage() const
1050 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
1053 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
1057 wxFAIL_MSG( wxT("no wxMessageOutput object?") );
1061 wxString
wxCmdLineParser::GetUsageString() const
1064 if ( m_data
->m_arguments
.empty() )
1067 appname
= wxTheApp
->GetAppName();
1071 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
1074 // we construct the brief cmd line desc on the fly, but not the detailed
1075 // help message below because we want to align the options descriptions
1076 // and for this we must first know the longest one of them
1078 wxArrayString namesOptions
, descOptions
;
1080 if ( !m_data
->m_logo
.empty() )
1082 usage
<< m_data
->m_logo
<< wxT('\n');
1085 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
1087 // the switch char is usually '-' but this can be changed with
1088 // SetSwitchChars() and then the first one of possible chars is used
1089 wxChar chSwitch
= !m_data
->m_switchChars
? wxT('-')
1090 : m_data
->m_switchChars
[0u];
1092 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
1093 size_t n
, count
= m_data
->m_options
.GetCount();
1094 for ( n
= 0; n
< count
; n
++ )
1096 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
1099 if ( opt
.kind
!= wxCMD_LINE_USAGE_TEXT
)
1102 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1107 if ( !opt
.shortName
.empty() )
1109 usage
<< chSwitch
<< opt
.shortName
;
1111 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1113 usage
<< wxT("--") << opt
.longName
;
1117 if (!opt
.longName
.empty())
1119 wxFAIL_MSG( wxT("option with only a long name while long ")
1120 wxT("options are disabled") );
1124 wxFAIL_MSG( wxT("option without neither short nor long name") );
1128 if ( !opt
.shortName
.empty() )
1130 option
<< wxT(" ") << chSwitch
<< opt
.shortName
;
1133 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1135 option
<< (option
.empty() ? wxT(" ") : wxT(", "))
1136 << wxT("--") << opt
.longName
;
1139 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1142 val
<< wxT('<') << GetTypeName(opt
.type
) << wxT('>');
1143 usage
<< wxT(' ') << val
;
1144 option
<< (!opt
.longName
? wxT(':') : wxT('=')) << val
;
1147 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1153 namesOptions
.push_back(option
);
1154 descOptions
.push_back(opt
.description
);
1157 count
= m_data
->m_paramDesc
.GetCount();
1158 for ( n
= 0; n
< count
; n
++ )
1160 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1163 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1168 usage
<< param
.description
;
1170 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1172 usage
<< wxT("...");
1175 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1183 // set to number of our own options, not counting the standard ones
1184 count
= namesOptions
.size();
1186 // get option names & descriptions for standard options, if any:
1187 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
1190 stdDesc
= traits
->GetStandardCmdLineOptions(namesOptions
, descOptions
);
1192 // now construct the detailed help message
1193 size_t len
, lenMax
= 0;
1194 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1196 len
= namesOptions
[n
].length();
1201 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1204 usage
<< wxT('\n') << stdDesc
;
1206 len
= namesOptions
[n
].length();
1207 // desc contains text if name is empty
1210 usage
<< descOptions
[n
] << wxT('\n');
1214 usage
<< namesOptions
[n
]
1215 << wxString(wxT(' '), lenMax
- len
) << wxT('\t')
1224 // ----------------------------------------------------------------------------
1225 // private functions
1226 // ----------------------------------------------------------------------------
1228 static wxString
GetTypeName(wxCmdLineParamType type
)
1234 wxFAIL_MSG( wxT("unknown option type") );
1235 // still fall through
1237 case wxCMD_LINE_VAL_STRING
:
1241 case wxCMD_LINE_VAL_NUMBER
:
1245 case wxCMD_LINE_VAL_DOUBLE
:
1249 case wxCMD_LINE_VAL_DATE
:
1258 Returns a string which is equal to the string pointed to by p, but up to the
1259 point where p contains an character that's not allowed.
1260 Allowable characters are letters and numbers, and characters pointed to by
1261 the parameter allowedChars.
1263 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1264 this function returns "abcde-".
1266 static wxString
GetOptionName(wxString::const_iterator p
,
1267 wxString::const_iterator end
,
1268 const wxChar
*allowedChars
)
1272 while ( p
!= end
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1280 // Besides alphanumeric characters, short and long options can
1281 // have other characters.
1283 // A short option additionally can have these
1284 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1286 // A long option can have the same characters as a short option and a '-'.
1287 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1288 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1290 static wxString
GetShortOptionName(wxString::const_iterator p
,
1291 wxString::const_iterator end
)
1293 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1296 static wxString
GetLongOptionName(wxString::const_iterator p
,
1297 wxString::const_iterator end
)
1299 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1302 #endif // wxUSE_CMDLINE_PARSER
1304 // ----------------------------------------------------------------------------
1306 // ----------------------------------------------------------------------------
1309 This function is mainly used under Windows (as under Unix we always get the
1310 command line arguments as argc/argv anyhow) and so it tries to follow
1311 Windows conventions for the command line handling, not Unix ones. For
1312 instance, backslash is not special except when it precedes double quote when
1318 wxCmdLineParser::ConvertStringToArgs(const wxString
& cmdline
,
1319 wxCmdLineSplitType type
)
1326 const wxString::const_iterator end
= cmdline
.end();
1327 wxString::const_iterator p
= cmdline
.begin();
1332 while ( p
!= end
&& (*p
== ' ' || *p
== '\t') )
1339 // parse this parameter
1340 bool lastBS
= false,
1341 isInsideQuotes
= false;
1342 wxChar chDelim
= '\0';
1343 for ( arg
.clear(); p
!= end
; ++p
)
1345 const wxChar ch
= *p
;
1347 if ( type
== wxCMD_LINE_SPLIT_DOS
)
1353 isInsideQuotes
= !isInsideQuotes
;
1355 // don't put quote in arg
1358 //else: quote has no special meaning but the backslash
1359 // still remains -- makes no sense but this is what
1362 // note that backslash does *not* quote the space, only quotes do
1363 else if ( !isInsideQuotes
&& (ch
== ' ' || ch
== '\t') )
1365 ++p
; // skip this space anyhow
1369 lastBS
= !lastBS
&& ch
== '\\';
1371 else // type == wxCMD_LINE_SPLIT_UNIX
1375 if ( isInsideQuotes
)
1377 if ( ch
== chDelim
)
1379 isInsideQuotes
= false;
1381 continue; // don't use the quote itself
1384 else // not in quotes and not escaped
1386 if ( ch
== '\'' || ch
== '"' )
1388 isInsideQuotes
= true;
1391 continue; // don't use the quote itself
1394 if ( ch
== ' ' || ch
== '\t' )
1396 ++p
; // skip this space anyhow
1401 lastBS
= ch
== '\\';
1405 else // escaped by backslash, just use as is
1414 args
.push_back(arg
);