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"
46 // ----------------------------------------------------------------------------
48 // ----------------------------------------------------------------------------
50 static wxString
GetTypeName(wxCmdLineParamType type
);
52 static wxString
GetOptionName(wxString::const_iterator p
,
53 wxString::const_iterator end
,
54 const wxChar
*allowedChars
);
56 static wxString
GetShortOptionName(wxString::const_iterator p
,
57 wxString::const_iterator end
);
59 static wxString
GetLongOptionName(wxString::const_iterator p
,
60 wxString::const_iterator end
);
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 // an internal representation of an option
67 struct wxCmdLineOption
69 wxCmdLineOption(wxCmdLineEntryType k
,
73 wxCmdLineParamType typ
,
76 wxASSERT_MSG( !shrt
.empty() || !lng
.empty(),
77 _T("option should have at least one name") );
81 GetShortOptionName(shrt
.begin(), shrt
.end()).Len() == shrt
.Len(),
82 wxT("Short option contains invalid characters")
87 GetLongOptionName(lng
.begin(), lng
.end()).Len() == lng
.Len(),
88 wxT("Long option contains invalid characters")
104 // can't use union easily here, so just store all possible data fields, we
105 // don't waste much (might still use union later if the number of supported
106 // types increases, so always use the accessor functions and don't access
107 // the fields directly!)
109 void Check(wxCmdLineParamType
WXUNUSED_UNLESS_DEBUG(typ
)) const
111 wxASSERT_MSG( type
== typ
, _T("type mismatch in wxCmdLineOption") );
114 double GetDoubleVal() const
115 { Check(wxCMD_LINE_VAL_DOUBLE
); return m_doubleVal
; }
116 long GetLongVal() const
117 { Check(wxCMD_LINE_VAL_NUMBER
); return m_longVal
; }
118 const wxString
& GetStrVal() const
119 { Check(wxCMD_LINE_VAL_STRING
); return m_strVal
; }
121 const wxDateTime
& GetDateVal() const
122 { Check(wxCMD_LINE_VAL_DATE
); return m_dateVal
; }
123 #endif // wxUSE_DATETIME
125 void SetDoubleVal(double val
)
126 { Check(wxCMD_LINE_VAL_DOUBLE
); m_doubleVal
= val
; m_hasVal
= true; }
127 void SetLongVal(long val
)
128 { Check(wxCMD_LINE_VAL_NUMBER
); m_longVal
= val
; m_hasVal
= true; }
129 void SetStrVal(const wxString
& val
)
130 { Check(wxCMD_LINE_VAL_STRING
); m_strVal
= val
; m_hasVal
= true; }
132 void SetDateVal(const wxDateTime
& val
)
133 { Check(wxCMD_LINE_VAL_DATE
); m_dateVal
= val
; m_hasVal
= true; }
134 #endif // wxUSE_DATETIME
136 void SetHasValue(bool hasValue
= true) { m_hasVal
= hasValue
; }
137 bool HasValue() const { return m_hasVal
; }
140 wxCmdLineEntryType kind
;
144 wxCmdLineParamType type
;
154 wxDateTime m_dateVal
;
155 #endif // wxUSE_DATETIME
158 struct wxCmdLineParam
160 wxCmdLineParam(const wxString
& desc
,
161 wxCmdLineParamType typ
,
169 wxString description
;
170 wxCmdLineParamType type
;
174 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
);
175 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
);
177 #include "wx/arrimpl.cpp"
179 WX_DEFINE_OBJARRAY(wxArrayOptions
)
180 WX_DEFINE_OBJARRAY(wxArrayParams
)
182 // the parser internal state
183 struct wxCmdLineParserData
186 wxString m_switchChars
; // characters which may start an option
187 bool m_enableLongOptions
; // true if long options are enabled
188 wxString m_logo
; // some extra text to show in Usage()
191 wxArrayString m_arguments
; // == argv, argc == m_arguments.GetCount()
192 wxArrayOptions m_options
; // all possible options and switches
193 wxArrayParams m_paramDesc
; // description of all possible params
194 wxArrayString m_parameters
; // all params found
197 wxCmdLineParserData();
198 void SetArguments(int argc
, char **argv
);
200 void SetArguments(int argc
, wxChar
**argv
);
201 void SetArguments(int argc
, const wxCmdLineArgsArray
& argv
);
202 #endif // wxUSE_UNICODE
203 void SetArguments(const wxString
& cmdline
);
205 int FindOption(const wxString
& name
);
206 int FindOptionByLongName(const wxString
& name
);
209 // ============================================================================
211 // ============================================================================
213 // ----------------------------------------------------------------------------
214 // wxCmdLineParserData
215 // ----------------------------------------------------------------------------
217 wxCmdLineParserData::wxCmdLineParserData()
219 m_enableLongOptions
= true;
221 m_switchChars
= _T("-");
223 m_switchChars
= _T("/-");
227 void wxCmdLineParserData::SetArguments(int argc
, char **argv
)
231 for ( int n
= 0; n
< argc
; n
++ )
233 m_arguments
.push_back(wxString::FromAscii(argv
[n
]));
239 void wxCmdLineParserData::SetArguments(int argc
, wxChar
**argv
)
243 for ( int n
= 0; n
< argc
; n
++ )
245 m_arguments
.push_back(argv
[n
]);
249 void wxCmdLineParserData::SetArguments(int WXUNUSED(argc
),
250 const wxCmdLineArgsArray
& argv
)
252 m_arguments
= argv
.GetArguments();
255 #endif // wxUSE_UNICODE
257 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
)
261 if(wxTheApp
&& wxTheApp
->argc
> 0)
262 m_arguments
.push_back(wxTheApp
->argv
[0]);
264 m_arguments
.push_back(wxEmptyString
);
266 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
268 WX_APPEND_ARRAY(m_arguments
, args
);
271 int wxCmdLineParserData::FindOption(const wxString
& name
)
275 size_t count
= m_options
.GetCount();
276 for ( size_t n
= 0; n
< count
; n
++ )
278 if ( m_options
[n
].shortName
== name
)
289 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
291 size_t count
= m_options
.GetCount();
292 for ( size_t n
= 0; n
< count
; n
++ )
294 if ( m_options
[n
].longName
== name
)
304 // ----------------------------------------------------------------------------
305 // construction and destruction
306 // ----------------------------------------------------------------------------
308 void wxCmdLineParser::Init()
310 m_data
= new wxCmdLineParserData
;
313 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
315 m_data
->SetArguments(argc
, argv
);
320 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
322 m_data
->SetArguments(argc
, argv
);
325 void wxCmdLineParser::SetCmdLine(int argc
, const wxCmdLineArgsArray
& argv
)
327 m_data
->SetArguments(argc
, argv
);
330 #endif // wxUSE_UNICODE
332 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
334 m_data
->SetArguments(cmdline
);
337 wxCmdLineParser::~wxCmdLineParser()
342 // ----------------------------------------------------------------------------
344 // ----------------------------------------------------------------------------
346 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
348 m_data
->m_switchChars
= switchChars
;
351 void wxCmdLineParser::EnableLongOptions(bool enable
)
353 m_data
->m_enableLongOptions
= enable
;
356 bool wxCmdLineParser::AreLongOptionsEnabled() const
358 return m_data
->m_enableLongOptions
;
361 void wxCmdLineParser::SetLogo(const wxString
& logo
)
363 m_data
->m_logo
= logo
;
366 // ----------------------------------------------------------------------------
367 // command line construction
368 // ----------------------------------------------------------------------------
370 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
374 switch ( desc
->kind
)
376 case wxCMD_LINE_SWITCH
:
377 AddSwitch(desc
->shortName
, desc
->longName
,
378 wxGetTranslation(desc
->description
),
382 case wxCMD_LINE_OPTION
:
383 AddOption(desc
->shortName
, desc
->longName
,
384 wxGetTranslation(desc
->description
),
385 desc
->type
, desc
->flags
);
388 case wxCMD_LINE_PARAM
:
389 AddParam(wxGetTranslation(desc
->description
),
390 desc
->type
, desc
->flags
);
394 wxFAIL_MSG( _T("unknown command line entry type") );
395 // still fall through
397 case wxCMD_LINE_NONE
:
403 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
404 const wxString
& longName
,
405 const wxString
& desc
,
408 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
409 _T("duplicate switch") );
411 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
412 shortName
, longName
, desc
,
413 wxCMD_LINE_VAL_NONE
, flags
);
415 m_data
->m_options
.Add(option
);
418 void wxCmdLineParser::AddOption(const wxString
& shortName
,
419 const wxString
& longName
,
420 const wxString
& desc
,
421 wxCmdLineParamType type
,
424 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
425 _T("duplicate option") );
427 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
428 shortName
, longName
, desc
,
431 m_data
->m_options
.Add(option
);
434 void wxCmdLineParser::AddParam(const wxString
& desc
,
435 wxCmdLineParamType type
,
438 // do some consistency checks: a required parameter can't follow an
439 // optional one and nothing should follow a parameter with MULTIPLE flag
441 if ( !m_data
->m_paramDesc
.IsEmpty() )
443 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
445 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
446 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
448 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
450 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
451 _T("a required parameter can't follow an optional one") );
456 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
458 m_data
->m_paramDesc
.Add(param
);
461 // ----------------------------------------------------------------------------
462 // access to parse command line
463 // ----------------------------------------------------------------------------
465 bool wxCmdLineParser::Found(const wxString
& name
) const
467 int i
= m_data
->FindOption(name
);
468 if ( i
== wxNOT_FOUND
)
469 i
= m_data
->FindOptionByLongName(name
);
471 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown switch") );
473 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
474 if ( !opt
.HasValue() )
480 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
482 int i
= m_data
->FindOption(name
);
483 if ( i
== wxNOT_FOUND
)
484 i
= m_data
->FindOptionByLongName(name
);
486 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
488 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
489 if ( !opt
.HasValue() )
492 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
494 *value
= opt
.GetStrVal();
499 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
501 int i
= m_data
->FindOption(name
);
502 if ( i
== wxNOT_FOUND
)
503 i
= m_data
->FindOptionByLongName(name
);
505 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
507 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
508 if ( !opt
.HasValue() )
511 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
513 *value
= opt
.GetLongVal();
518 bool wxCmdLineParser::Found(const wxString
& name
, double *value
) const
520 int i
= m_data
->FindOption(name
);
521 if ( i
== wxNOT_FOUND
)
522 i
= m_data
->FindOptionByLongName(name
);
524 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
526 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
527 if ( !opt
.HasValue() )
530 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
532 *value
= opt
.GetDoubleVal();
538 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
540 int i
= m_data
->FindOption(name
);
541 if ( i
== wxNOT_FOUND
)
542 i
= m_data
->FindOptionByLongName(name
);
544 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
546 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
547 if ( !opt
.HasValue() )
550 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
552 *value
= opt
.GetDateVal();
556 #endif // wxUSE_DATETIME
558 size_t wxCmdLineParser::GetParamCount() const
560 return m_data
->m_parameters
.size();
563 wxString
wxCmdLineParser::GetParam(size_t n
) const
565 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, _T("invalid param index") );
567 return m_data
->m_parameters
[n
];
570 // Resets switches and options
571 void wxCmdLineParser::Reset()
573 for ( size_t i
= 0; i
< m_data
->m_options
.GetCount(); i
++ )
575 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
576 opt
.SetHasValue(false);
581 // ----------------------------------------------------------------------------
582 // the real work is done here
583 // ----------------------------------------------------------------------------
585 int wxCmdLineParser::Parse(bool showUsage
)
587 bool maybeOption
= true; // can the following arg be an option?
588 bool ok
= true; // true until an error is detected
589 bool helpRequested
= false; // true if "-h" was given
590 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
592 size_t currentParam
= 0; // the index in m_paramDesc
594 size_t countParam
= m_data
->m_paramDesc
.GetCount();
601 size_t count
= m_data
->m_arguments
.size();
602 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
604 arg
= m_data
->m_arguments
[n
];
606 // special case: "--" should be discarded and all following arguments
607 // should be considered as parameters, even if they start with '-' and
608 // not like options (this is POSIX-like)
609 if ( arg
== _T("--") )
616 // empty argument or just '-' is not an option but a parameter
617 if ( maybeOption
&& arg
.length() > 1 &&
618 // FIXME-UTF8: use wc_str() after removing ANSI build
619 wxStrchr(m_data
->m_switchChars
.c_str(), arg
[0u]) )
623 int optInd
= wxNOT_FOUND
; // init to suppress warnings
625 // an option or a switch: find whether it's a long or a short one
626 if ( arg
.length() >= 3 && arg
[0u] == _T('-') && arg
[1u] == _T('-') )
632 wxString::const_iterator p
= arg
.begin() + 2;
634 bool longOptionsEnabled
= AreLongOptionsEnabled();
636 name
= GetLongOptionName(p
, arg
.end());
638 if (longOptionsEnabled
)
640 optInd
= m_data
->FindOptionByLongName(name
);
641 if ( optInd
== wxNOT_FOUND
)
643 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str())
649 optInd
= wxNOT_FOUND
; // Sanity check
651 // Print the argument including leading "--"
652 name
.Prepend( wxT("--") );
653 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
658 else // not a long option
662 // a short one: as they can be cumulated, we try to find the
663 // longest substring which is a valid option
664 wxString::const_iterator p
= arg
.begin() + 1;
666 name
= GetShortOptionName(p
, arg
.end());
668 size_t len
= name
.length();
673 // we couldn't find a valid option name in the
674 // beginning of this string
675 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
682 optInd
= m_data
->FindOption(name
.Left(len
));
684 // will try with one character less the next time
688 while ( optInd
== wxNOT_FOUND
);
690 len
++; // compensates extra len-- above
691 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
693 // first of all, the option name is only part of this
695 name
= name
.Left(len
);
697 // our option is only part of this argument, there is
698 // something else in it - it is either the value of this
699 // option or other switches if it is a switch
700 if ( m_data
->m_options
[(size_t)optInd
].kind
701 == wxCMD_LINE_SWITCH
)
703 // pretend that all the rest of the argument is the
704 // next argument, in fact
705 wxString arg2
= arg
[0u];
706 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
708 m_data
->m_arguments
.insert
709 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
712 //else: it's our value, we'll deal with it below
716 if ( optInd
== wxNOT_FOUND
)
720 continue; // will break, in fact
723 // look at what follows:
725 // +1 for leading '-'
726 wxString::const_iterator p
= arg
.begin() + 1 + name
.length();
727 wxString::const_iterator end
= arg
.end();
730 ++p
; // for another leading '-'
732 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
733 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
735 // we must check that there is no value following the switch
736 if ( p
!= arg
.end() )
738 errorMsg
<< wxString::Format(_("Unexpected characters following option '%s'."), name
.c_str())
742 else // no value, as expected
744 // nothing more to do
747 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
749 helpRequested
= true;
751 // it's not an error, but we still stop here
756 else // it's an option. not a switch
758 switch ( (*p
).GetValue() )
767 // the value is in the next argument
770 // ... but there is none
771 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
779 // ... take it from there
780 p
= m_data
->m_arguments
[n
].begin();
781 end
= m_data
->m_arguments
[n
].end();
786 // the value is right here: this may be legal or
787 // not depending on the option style
788 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
790 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
800 wxString
value(p
, end
);
804 wxFAIL_MSG( _T("unknown option type") );
805 // still fall through
807 case wxCMD_LINE_VAL_STRING
:
808 opt
.SetStrVal(value
);
811 case wxCMD_LINE_VAL_NUMBER
:
814 if ( value
.ToLong(&val
) )
820 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
821 value
.c_str(), name
.c_str())
829 case wxCMD_LINE_VAL_DOUBLE
:
832 if ( value
.ToDouble(&val
) )
834 opt
.SetDoubleVal(val
);
838 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
839 value
.c_str(), name
.c_str())
848 case wxCMD_LINE_VAL_DATE
:
851 const char *res
= dt
.ParseDate(value
);
854 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
855 name
.c_str(), value
.c_str())
866 #endif // wxUSE_DATETIME
871 else // not an option, must be a parameter
873 if ( currentParam
< countParam
)
875 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
877 // TODO check the param type
879 m_data
->m_parameters
.push_back(arg
);
881 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
887 wxASSERT_MSG( currentParam
== countParam
- 1,
888 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
890 // remember that we did have this last repeatable parameter
891 hadRepeatableParam
= true;
896 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str())
904 // verify that all mandatory options were given
907 size_t countOpt
= m_data
->m_options
.GetCount();
908 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
910 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
911 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
916 optName
= opt
.shortName
;
920 if ( AreLongOptionsEnabled() )
922 optName
.Printf( _("%s (or %s)"),
923 opt
.shortName
.c_str(),
924 opt
.longName
.c_str() );
928 optName
.Printf( wxT("%s"),
929 opt
.shortName
.c_str() );
933 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
941 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
943 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
944 if ( (currentParam
== countParam
- 1) &&
945 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
948 // special case: currentParam wasn't incremented, but we did
949 // have it, so don't give error
953 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
955 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
956 param
.description
.c_str())
964 // if there was an error during parsing the command line, show this error
965 // and also the usage message if it had been requested
966 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
968 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
973 usage
= GetUsageString();
975 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
979 wxFAIL_MSG( _T("no wxMessageOutput object?") );
983 return ok
? 0 : helpRequested
? -1 : 1;
986 // ----------------------------------------------------------------------------
987 // give the usage message
988 // ----------------------------------------------------------------------------
990 void wxCmdLineParser::Usage() const
992 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
995 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
999 wxFAIL_MSG( _T("no wxMessageOutput object?") );
1003 wxString
wxCmdLineParser::GetUsageString() const
1006 if ( m_data
->m_arguments
.empty() )
1009 appname
= wxTheApp
->GetAppName();
1013 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
1016 // we construct the brief cmd line desc on the fly, but not the detailed
1017 // help message below because we want to align the options descriptions
1018 // and for this we must first know the longest one of them
1020 wxArrayString namesOptions
, descOptions
;
1022 if ( !m_data
->m_logo
.empty() )
1024 usage
<< m_data
->m_logo
<< _T('\n');
1027 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
1029 // the switch char is usually '-' but this can be changed with
1030 // SetSwitchChars() and then the first one of possible chars is used
1031 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
1032 : m_data
->m_switchChars
[0u];
1034 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
1035 size_t n
, count
= m_data
->m_options
.GetCount();
1036 for ( n
= 0; n
< count
; n
++ )
1038 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
1041 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1046 if ( !opt
.shortName
.empty() )
1048 usage
<< chSwitch
<< opt
.shortName
;
1050 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1052 usage
<< _T("--") << opt
.longName
;
1056 if (!opt
.longName
.empty())
1058 wxFAIL_MSG( wxT("option with only a long name while long ")
1059 wxT("options are disabled") );
1063 wxFAIL_MSG( _T("option without neither short nor long name") );
1069 if ( !opt
.shortName
.empty() )
1071 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
1074 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1076 option
<< (option
.empty() ? _T(" ") : _T(", "))
1077 << _T("--") << opt
.longName
;
1080 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1083 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1084 usage
<< _T(' ') << val
;
1085 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1088 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1093 namesOptions
.push_back(option
);
1094 descOptions
.push_back(opt
.description
);
1097 count
= m_data
->m_paramDesc
.GetCount();
1098 for ( n
= 0; n
< count
; n
++ )
1100 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1103 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1108 usage
<< param
.description
;
1110 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1115 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1123 // set to number of our own options, not counting the standard ones
1124 count
= namesOptions
.size();
1126 // get option names & descriptions for standard options, if any:
1127 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
1130 stdDesc
= traits
->GetStandardCmdLineOptions(namesOptions
, descOptions
);
1132 // now construct the detailed help message
1133 size_t len
, lenMax
= 0;
1134 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1136 len
= namesOptions
[n
].length();
1141 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1144 usage
<< _T('\n') << stdDesc
;
1146 len
= namesOptions
[n
].length();
1147 usage
<< namesOptions
[n
]
1148 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1156 // ----------------------------------------------------------------------------
1157 // private functions
1158 // ----------------------------------------------------------------------------
1160 static wxString
GetTypeName(wxCmdLineParamType type
)
1166 wxFAIL_MSG( _T("unknown option type") );
1167 // still fall through
1169 case wxCMD_LINE_VAL_STRING
:
1173 case wxCMD_LINE_VAL_NUMBER
:
1177 case wxCMD_LINE_VAL_DOUBLE
:
1181 case wxCMD_LINE_VAL_DATE
:
1190 Returns a string which is equal to the string pointed to by p, but up to the
1191 point where p contains an character that's not allowed.
1192 Allowable characters are letters and numbers, and characters pointed to by
1193 the parameter allowedChars.
1195 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1196 this function returns "abcde-".
1198 static wxString
GetOptionName(wxString::const_iterator p
,
1199 wxString::const_iterator end
,
1200 const wxChar
*allowedChars
)
1204 while ( p
!= end
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1212 // Besides alphanumeric characters, short and long options can
1213 // have other characters.
1215 // A short option additionally can have these
1216 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1218 // A long option can have the same characters as a short option and a '-'.
1219 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1220 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1222 static wxString
GetShortOptionName(wxString::const_iterator p
,
1223 wxString::const_iterator end
)
1225 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1228 static wxString
GetLongOptionName(wxString::const_iterator p
,
1229 wxString::const_iterator end
)
1231 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1234 #endif // wxUSE_CMDLINE_PARSER
1236 // ----------------------------------------------------------------------------
1238 // ----------------------------------------------------------------------------
1241 This function is mainly used under Windows (as under Unix we always get the
1242 command line arguments as argc/argv anyhow) and so it tries to follow
1243 Windows conventions for the command line handling, not Unix ones. For
1244 instance, backslash is not special except when it precedes double quote when
1249 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxString
& cmdline
)
1256 bool isInsideQuotes
= false;
1258 const wxString::const_iterator end
= cmdline
.end();
1259 wxString::const_iterator p
= cmdline
.begin();
1264 while ( p
!= end
&& (*p
== ' ' || *p
== '\t') )
1271 // parse this parameter
1272 bool lastBS
= false;
1273 for ( arg
.clear(); p
!= end
; ++p
)
1275 const wxChar ch
= *p
;
1280 isInsideQuotes
= !isInsideQuotes
;
1282 // don't put quote in arg
1285 //else: quote has no special meaning but the backslash
1286 // still remains -- makes no sense but this is what
1289 // note that backslash does *not* quote the space, only quotes do
1290 else if ( !isInsideQuotes
&& (ch
== ' ' || ch
== '\t') )
1292 ++p
; // skip this space anyhow
1296 lastBS
= ch
== '\\';
1301 args
.push_back(arg
);