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 long GetLongVal() const
115 { Check(wxCMD_LINE_VAL_NUMBER
); return m_longVal
; }
116 const wxString
& GetStrVal() const
117 { Check(wxCMD_LINE_VAL_STRING
); return m_strVal
; }
119 const wxDateTime
& GetDateVal() const
120 { Check(wxCMD_LINE_VAL_DATE
); return m_dateVal
; }
121 #endif // wxUSE_DATETIME
123 void SetLongVal(long val
)
124 { Check(wxCMD_LINE_VAL_NUMBER
); m_longVal
= val
; m_hasVal
= true; }
125 void SetStrVal(const wxString
& val
)
126 { Check(wxCMD_LINE_VAL_STRING
); m_strVal
= val
; m_hasVal
= true; }
128 void SetDateVal(const wxDateTime
& val
)
129 { Check(wxCMD_LINE_VAL_DATE
); m_dateVal
= val
; m_hasVal
= true; }
130 #endif // wxUSE_DATETIME
132 void SetHasValue(bool hasValue
= true) { m_hasVal
= hasValue
; }
133 bool HasValue() const { return m_hasVal
; }
136 wxCmdLineEntryType kind
;
140 wxCmdLineParamType type
;
149 wxDateTime m_dateVal
;
150 #endif // wxUSE_DATETIME
153 struct wxCmdLineParam
155 wxCmdLineParam(const wxString
& desc
,
156 wxCmdLineParamType typ
,
164 wxString description
;
165 wxCmdLineParamType type
;
169 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
);
170 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
);
172 #include "wx/arrimpl.cpp"
174 WX_DEFINE_OBJARRAY(wxArrayOptions
)
175 WX_DEFINE_OBJARRAY(wxArrayParams
)
177 // the parser internal state
178 struct wxCmdLineParserData
181 wxString m_switchChars
; // characters which may start an option
182 bool m_enableLongOptions
; // true if long options are enabled
183 wxString m_logo
; // some extra text to show in Usage()
186 wxArrayString m_arguments
; // == argv, argc == m_arguments.GetCount()
187 wxArrayOptions m_options
; // all possible options and switches
188 wxArrayParams m_paramDesc
; // description of all possible params
189 wxArrayString m_parameters
; // all params found
192 wxCmdLineParserData();
193 void SetArguments(int argc
, char **argv
);
195 void SetArguments(int argc
, wxChar
**argv
);
196 void SetArguments(int argc
, const wxCmdLineArgsArray
& argv
);
197 #endif // wxUSE_UNICODE
198 void SetArguments(const wxString
& cmdline
);
200 int FindOption(const wxString
& name
);
201 int FindOptionByLongName(const wxString
& name
);
204 // ============================================================================
206 // ============================================================================
208 // ----------------------------------------------------------------------------
209 // wxCmdLineParserData
210 // ----------------------------------------------------------------------------
212 wxCmdLineParserData::wxCmdLineParserData()
214 m_enableLongOptions
= true;
216 m_switchChars
= _T("-");
218 m_switchChars
= _T("/-");
222 void wxCmdLineParserData::SetArguments(int argc
, char **argv
)
226 for ( int n
= 0; n
< argc
; n
++ )
228 m_arguments
.push_back(wxString::FromAscii(argv
[n
]));
234 void wxCmdLineParserData::SetArguments(int argc
, wxChar
**argv
)
238 for ( int n
= 0; n
< argc
; n
++ )
240 m_arguments
.push_back(argv
[n
]);
244 void wxCmdLineParserData::SetArguments(int WXUNUSED(argc
),
245 const wxCmdLineArgsArray
& argv
)
247 m_arguments
= argv
.GetArguments();
250 #endif // wxUSE_UNICODE
252 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
)
256 if(wxTheApp
&& wxTheApp
->argc
> 0)
257 m_arguments
.push_back(wxTheApp
->argv
[0]);
259 m_arguments
.push_back(wxEmptyString
);
261 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
263 WX_APPEND_ARRAY(m_arguments
, args
);
266 int wxCmdLineParserData::FindOption(const wxString
& name
)
270 size_t count
= m_options
.GetCount();
271 for ( size_t n
= 0; n
< count
; n
++ )
273 if ( m_options
[n
].shortName
== name
)
284 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
286 size_t count
= m_options
.GetCount();
287 for ( size_t n
= 0; n
< count
; n
++ )
289 if ( m_options
[n
].longName
== name
)
299 // ----------------------------------------------------------------------------
300 // construction and destruction
301 // ----------------------------------------------------------------------------
303 void wxCmdLineParser::Init()
305 m_data
= new wxCmdLineParserData
;
308 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
310 m_data
->SetArguments(argc
, argv
);
315 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
317 m_data
->SetArguments(argc
, argv
);
320 void wxCmdLineParser::SetCmdLine(int argc
, const wxCmdLineArgsArray
& argv
)
322 m_data
->SetArguments(argc
, argv
);
325 #endif // wxUSE_UNICODE
327 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
329 m_data
->SetArguments(cmdline
);
332 wxCmdLineParser::~wxCmdLineParser()
337 // ----------------------------------------------------------------------------
339 // ----------------------------------------------------------------------------
341 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
343 m_data
->m_switchChars
= switchChars
;
346 void wxCmdLineParser::EnableLongOptions(bool enable
)
348 m_data
->m_enableLongOptions
= enable
;
351 bool wxCmdLineParser::AreLongOptionsEnabled()
353 return m_data
->m_enableLongOptions
;
356 void wxCmdLineParser::SetLogo(const wxString
& logo
)
358 m_data
->m_logo
= logo
;
361 // ----------------------------------------------------------------------------
362 // command line construction
363 // ----------------------------------------------------------------------------
365 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
369 switch ( desc
->kind
)
371 case wxCMD_LINE_SWITCH
:
372 AddSwitch(desc
->shortName
, desc
->longName
, desc
->description
,
376 case wxCMD_LINE_OPTION
:
377 AddOption(desc
->shortName
, desc
->longName
, desc
->description
,
378 desc
->type
, desc
->flags
);
381 case wxCMD_LINE_PARAM
:
382 AddParam(desc
->description
, desc
->type
, desc
->flags
);
386 wxFAIL_MSG( _T("unknown command line entry type") );
387 // still fall through
389 case wxCMD_LINE_NONE
:
395 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
396 const wxString
& longName
,
397 const wxString
& desc
,
400 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
401 _T("duplicate switch") );
403 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
404 shortName
, longName
, desc
,
405 wxCMD_LINE_VAL_NONE
, flags
);
407 m_data
->m_options
.Add(option
);
410 void wxCmdLineParser::AddOption(const wxString
& shortName
,
411 const wxString
& longName
,
412 const wxString
& desc
,
413 wxCmdLineParamType type
,
416 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
417 _T("duplicate option") );
419 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
420 shortName
, longName
, desc
,
423 m_data
->m_options
.Add(option
);
426 void wxCmdLineParser::AddParam(const wxString
& desc
,
427 wxCmdLineParamType type
,
430 // do some consistency checks: a required parameter can't follow an
431 // optional one and nothing should follow a parameter with MULTIPLE flag
433 if ( !m_data
->m_paramDesc
.IsEmpty() )
435 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
437 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
438 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
440 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
442 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
443 _T("a required parameter can't follow an optional one") );
448 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
450 m_data
->m_paramDesc
.Add(param
);
453 // ----------------------------------------------------------------------------
454 // access to parse command line
455 // ----------------------------------------------------------------------------
457 bool wxCmdLineParser::Found(const wxString
& name
) const
459 int i
= m_data
->FindOption(name
);
460 if ( i
== wxNOT_FOUND
)
461 i
= m_data
->FindOptionByLongName(name
);
463 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown switch") );
465 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
466 if ( !opt
.HasValue() )
472 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
474 int i
= m_data
->FindOption(name
);
475 if ( i
== wxNOT_FOUND
)
476 i
= m_data
->FindOptionByLongName(name
);
478 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
480 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
481 if ( !opt
.HasValue() )
484 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
486 *value
= opt
.GetStrVal();
491 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
493 int i
= m_data
->FindOption(name
);
494 if ( i
== wxNOT_FOUND
)
495 i
= m_data
->FindOptionByLongName(name
);
497 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
499 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
500 if ( !opt
.HasValue() )
503 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
505 *value
= opt
.GetLongVal();
511 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
513 int i
= m_data
->FindOption(name
);
514 if ( i
== wxNOT_FOUND
)
515 i
= m_data
->FindOptionByLongName(name
);
517 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
519 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
520 if ( !opt
.HasValue() )
523 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
525 *value
= opt
.GetDateVal();
529 #endif // wxUSE_DATETIME
531 size_t wxCmdLineParser::GetParamCount() const
533 return m_data
->m_parameters
.size();
536 wxString
wxCmdLineParser::GetParam(size_t n
) const
538 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, _T("invalid param index") );
540 return m_data
->m_parameters
[n
];
543 // Resets switches and options
544 void wxCmdLineParser::Reset()
546 for ( size_t i
= 0; i
< m_data
->m_options
.GetCount(); i
++ )
548 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
549 opt
.SetHasValue(false);
554 // ----------------------------------------------------------------------------
555 // the real work is done here
556 // ----------------------------------------------------------------------------
558 int wxCmdLineParser::Parse(bool showUsage
)
560 bool maybeOption
= true; // can the following arg be an option?
561 bool ok
= true; // true until an error is detected
562 bool helpRequested
= false; // true if "-h" was given
563 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
565 size_t currentParam
= 0; // the index in m_paramDesc
567 size_t countParam
= m_data
->m_paramDesc
.GetCount();
574 size_t count
= m_data
->m_arguments
.size();
575 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
577 arg
= m_data
->m_arguments
[n
];
579 // special case: "--" should be discarded and all following arguments
580 // should be considered as parameters, even if they start with '-' and
581 // not like options (this is POSIX-like)
582 if ( arg
== _T("--") )
589 // empty argument or just '-' is not an option but a parameter
590 if ( maybeOption
&& arg
.length() > 1 &&
591 // FIXME-UTF8: use wc_str() after removing ANSI build
592 wxStrchr(m_data
->m_switchChars
.c_str(), arg
[0u]) )
596 int optInd
= wxNOT_FOUND
; // init to suppress warnings
598 // an option or a switch: find whether it's a long or a short one
599 if ( arg
.length() >= 3 && arg
[0u] == _T('-') && arg
[1u] == _T('-') )
605 wxString::const_iterator p
= arg
.begin() + 2;
607 bool longOptionsEnabled
= AreLongOptionsEnabled();
609 name
= GetLongOptionName(p
, arg
.end());
611 if (longOptionsEnabled
)
613 optInd
= m_data
->FindOptionByLongName(name
);
614 if ( optInd
== wxNOT_FOUND
)
616 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str())
622 optInd
= wxNOT_FOUND
; // Sanity check
624 // Print the argument including leading "--"
625 name
.Prepend( wxT("--") );
626 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
631 else // not a long option
635 // a short one: as they can be cumulated, we try to find the
636 // longest substring which is a valid option
637 wxString::const_iterator p
= arg
.begin() + 1;
639 name
= GetShortOptionName(p
, arg
.end());
641 size_t len
= name
.length();
646 // we couldn't find a valid option name in the
647 // beginning of this string
648 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
655 optInd
= m_data
->FindOption(name
.Left(len
));
657 // will try with one character less the next time
661 while ( optInd
== wxNOT_FOUND
);
663 len
++; // compensates extra len-- above
664 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
666 // first of all, the option name is only part of this
668 name
= name
.Left(len
);
670 // our option is only part of this argument, there is
671 // something else in it - it is either the value of this
672 // option or other switches if it is a switch
673 if ( m_data
->m_options
[(size_t)optInd
].kind
674 == wxCMD_LINE_SWITCH
)
676 // pretend that all the rest of the argument is the
677 // next argument, in fact
678 wxString arg2
= arg
[0u];
679 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
681 m_data
->m_arguments
.insert
682 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
685 //else: it's our value, we'll deal with it below
689 if ( optInd
== wxNOT_FOUND
)
693 continue; // will break, in fact
696 // look at what follows:
698 // +1 for leading '-'
699 wxString::const_iterator p
= arg
.begin() + 1 + name
.length();
700 wxString::const_iterator end
= arg
.end();
703 ++p
; // for another leading '-'
705 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
706 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
708 // we must check that there is no value following the switch
709 if ( p
!= arg
.end() )
711 errorMsg
<< wxString::Format(_("Unexpected characters following option '%s'."), name
.c_str())
715 else // no value, as expected
717 // nothing more to do
720 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
722 helpRequested
= true;
724 // it's not an error, but we still stop here
729 else // it's an option. not a switch
731 switch ( (*p
).GetValue() )
740 // the value is in the next argument
743 // ... but there is none
744 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
752 // ... take it from there
753 p
= m_data
->m_arguments
[n
].begin();
754 end
= m_data
->m_arguments
[n
].end();
759 // the value is right here: this may be legal or
760 // not depending on the option style
761 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
763 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
773 wxString
value(p
, end
);
777 wxFAIL_MSG( _T("unknown option type") );
778 // still fall through
780 case wxCMD_LINE_VAL_STRING
:
781 opt
.SetStrVal(value
);
784 case wxCMD_LINE_VAL_NUMBER
:
787 if ( value
.ToLong(&val
) )
793 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
794 value
.c_str(), name
.c_str())
803 case wxCMD_LINE_VAL_DATE
:
806 // FIXME-UTF8: ParseDate API will need changes
807 const wxChar
*res
= dt
.ParseDate(value
.c_str());
810 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
811 name
.c_str(), value
.c_str())
822 #endif // wxUSE_DATETIME
827 else // not an option, must be a parameter
829 if ( currentParam
< countParam
)
831 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
833 // TODO check the param type
835 m_data
->m_parameters
.push_back(arg
);
837 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
843 wxASSERT_MSG( currentParam
== countParam
- 1,
844 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
846 // remember that we did have this last repeatable parameter
847 hadRepeatableParam
= true;
852 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str())
860 // verify that all mandatory options were given
863 size_t countOpt
= m_data
->m_options
.GetCount();
864 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
866 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
867 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
872 optName
= opt
.shortName
;
876 if ( AreLongOptionsEnabled() )
878 optName
.Printf( _("%s (or %s)"),
879 opt
.shortName
.c_str(),
880 opt
.longName
.c_str() );
884 optName
.Printf( wxT("%s"),
885 opt
.shortName
.c_str() );
889 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
897 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
899 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
900 if ( (currentParam
== countParam
- 1) &&
901 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
904 // special case: currentParam wasn't incremented, but we did
905 // have it, so don't give error
909 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
911 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
912 param
.description
.c_str())
920 // if there was an error during parsing the command line, show this error
921 // and also the usage message if it had been requested
922 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
924 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
929 usage
= GetUsageString();
931 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
935 wxFAIL_MSG( _T("no wxMessageOutput object?") );
939 return ok
? 0 : helpRequested
? -1 : 1;
942 // ----------------------------------------------------------------------------
943 // give the usage message
944 // ----------------------------------------------------------------------------
946 void wxCmdLineParser::Usage()
948 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
951 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
955 wxFAIL_MSG( _T("no wxMessageOutput object?") );
959 wxString
wxCmdLineParser::GetUsageString()
962 if ( m_data
->m_arguments
.empty() )
965 appname
= wxTheApp
->GetAppName();
969 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
972 // we construct the brief cmd line desc on the fly, but not the detailed
973 // help message below because we want to align the options descriptions
974 // and for this we must first know the longest one of them
976 wxArrayString namesOptions
, descOptions
;
978 if ( !m_data
->m_logo
.empty() )
980 usage
<< m_data
->m_logo
<< _T('\n');
983 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
985 // the switch char is usually '-' but this can be changed with
986 // SetSwitchChars() and then the first one of possible chars is used
987 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
988 : m_data
->m_switchChars
[0u];
990 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
991 size_t n
, count
= m_data
->m_options
.GetCount();
992 for ( n
= 0; n
< count
; n
++ )
994 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
997 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1002 if ( !opt
.shortName
.empty() )
1004 usage
<< chSwitch
<< opt
.shortName
;
1006 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1008 usage
<< _T("--") << opt
.longName
;
1012 if (!opt
.longName
.empty())
1014 wxFAIL_MSG( wxT("option with only a long name while long ")
1015 wxT("options are disabled") );
1019 wxFAIL_MSG( _T("option without neither short nor long name") );
1025 if ( !opt
.shortName
.empty() )
1027 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
1030 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1032 option
<< (option
.empty() ? _T(" ") : _T(", "))
1033 << _T("--") << opt
.longName
;
1036 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1039 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1040 usage
<< _T(' ') << val
;
1041 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1044 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1049 namesOptions
.push_back(option
);
1050 descOptions
.push_back(opt
.description
);
1053 count
= m_data
->m_paramDesc
.GetCount();
1054 for ( n
= 0; n
< count
; n
++ )
1056 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1059 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1064 usage
<< param
.description
;
1066 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1071 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1079 // set to number of our own options, not counting the standard ones
1080 count
= namesOptions
.size();
1082 // get option names & descriptions for standard options, if any:
1083 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
1086 stdDesc
= traits
->GetStandardCmdLineOptions(namesOptions
, descOptions
);
1088 // now construct the detailed help message
1089 size_t len
, lenMax
= 0;
1090 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1092 len
= namesOptions
[n
].length();
1097 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1100 usage
<< _T('\n') << stdDesc
;
1102 len
= namesOptions
[n
].length();
1103 usage
<< namesOptions
[n
]
1104 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1112 // ----------------------------------------------------------------------------
1113 // private functions
1114 // ----------------------------------------------------------------------------
1116 static wxString
GetTypeName(wxCmdLineParamType type
)
1122 wxFAIL_MSG( _T("unknown option type") );
1123 // still fall through
1125 case wxCMD_LINE_VAL_STRING
:
1129 case wxCMD_LINE_VAL_NUMBER
:
1133 case wxCMD_LINE_VAL_DATE
:
1142 Returns a string which is equal to the string pointed to by p, but up to the
1143 point where p contains an character that's not allowed.
1144 Allowable characters are letters and numbers, and characters pointed to by
1145 the parameter allowedChars.
1147 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1148 this function returns "abcde-".
1150 static wxString
GetOptionName(wxString::const_iterator p
,
1151 wxString::const_iterator end
,
1152 const wxChar
*allowedChars
)
1156 while ( p
!= end
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1164 // Besides alphanumeric characters, short and long options can
1165 // have other characters.
1167 // A short option additionally can have these
1168 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1170 // A long option can have the same characters as a short option and a '-'.
1171 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1172 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1174 static wxString
GetShortOptionName(wxString::const_iterator p
,
1175 wxString::const_iterator end
)
1177 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1180 static wxString
GetLongOptionName(wxString::const_iterator p
,
1181 wxString::const_iterator end
)
1183 return GetOptionName(p
, end
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1186 #endif // wxUSE_CMDLINE_PARSER
1188 // ----------------------------------------------------------------------------
1190 // ----------------------------------------------------------------------------
1193 This function is mainly used under Windows (as under Unix we always get the
1194 command line arguments as argc/argv anyhow) and so it tries to follow
1195 Windows conventions for the command line handling, not Unix ones. For
1196 instance, backslash is not special except when it precedes double quote when
1201 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxString
& cmdline
)
1208 bool isInsideQuotes
= false;
1210 wxString::const_iterator p
= cmdline
.begin();
1215 while ( p
!= cmdline
.end() && (*p
== _T(' ') || *p
== _T('\t')) )
1219 if ( p
== cmdline
.end() )
1222 // parse this parameter
1223 bool endParam
= false;
1224 bool lastBS
= false;
1225 for ( arg
.clear(); !endParam
; p
++ )
1227 switch ( (*p
).GetValue() )
1232 isInsideQuotes
= !isInsideQuotes
;
1234 // don't put quote in arg
1237 //else: quote has no special meaning but the backslash
1238 // still remains -- makes no sense but this is what
1244 // backslash does *not* quote the space, only quotes do
1245 if ( isInsideQuotes
)
1247 // skip assignment below
1263 lastBS
= *p
== _T('\\');
1268 args
.push_back(arg
);