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(const wxChar
*p
, const wxChar
*allowedChars
);
54 static wxString
GetShortOptionName(const wxChar
*p
);
56 static wxString
GetLongOptionName(const wxChar
*p
);
58 // ----------------------------------------------------------------------------
60 // ----------------------------------------------------------------------------
62 // an internal representation of an option
63 struct wxCmdLineOption
65 wxCmdLineOption(wxCmdLineEntryType k
,
69 wxCmdLineParamType typ
,
72 wxASSERT_MSG( !shrt
.empty() || !lng
.empty(),
73 _T("option should have at least one name") );
77 GetShortOptionName(shrt
).Len() == shrt
.Len(),
78 wxT("Short option contains invalid characters")
83 GetLongOptionName(lng
).Len() == lng
.Len(),
84 wxT("Long option contains invalid characters")
100 // can't use union easily here, so just store all possible data fields, we
101 // don't waste much (might still use union later if the number of supported
102 // types increases, so always use the accessor functions and don't access
103 // the fields directly!)
105 void Check(wxCmdLineParamType
WXUNUSED_UNLESS_DEBUG(typ
)) const
107 wxASSERT_MSG( type
== typ
, _T("type mismatch in wxCmdLineOption") );
110 long GetLongVal() const
111 { Check(wxCMD_LINE_VAL_NUMBER
); return m_longVal
; }
112 const wxString
& GetStrVal() const
113 { Check(wxCMD_LINE_VAL_STRING
); return m_strVal
; }
115 const wxDateTime
& GetDateVal() const
116 { Check(wxCMD_LINE_VAL_DATE
); return m_dateVal
; }
117 #endif // wxUSE_DATETIME
119 void SetLongVal(long val
)
120 { Check(wxCMD_LINE_VAL_NUMBER
); m_longVal
= val
; m_hasVal
= true; }
121 void SetStrVal(const wxString
& val
)
122 { Check(wxCMD_LINE_VAL_STRING
); m_strVal
= val
; m_hasVal
= true; }
124 void SetDateVal(const wxDateTime
& val
)
125 { Check(wxCMD_LINE_VAL_DATE
); m_dateVal
= val
; m_hasVal
= true; }
126 #endif // wxUSE_DATETIME
128 void SetHasValue(bool hasValue
= true) { m_hasVal
= hasValue
; }
129 bool HasValue() const { return m_hasVal
; }
132 wxCmdLineEntryType kind
;
136 wxCmdLineParamType type
;
145 wxDateTime m_dateVal
;
146 #endif // wxUSE_DATETIME
149 struct wxCmdLineParam
151 wxCmdLineParam(const wxString
& desc
,
152 wxCmdLineParamType typ
,
160 wxString description
;
161 wxCmdLineParamType type
;
165 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
);
166 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
);
168 #include "wx/arrimpl.cpp"
170 WX_DEFINE_OBJARRAY(wxArrayOptions
)
171 WX_DEFINE_OBJARRAY(wxArrayParams
)
173 // the parser internal state
174 struct wxCmdLineParserData
177 wxString m_switchChars
; // characters which may start an option
178 bool m_enableLongOptions
; // true if long options are enabled
179 wxString m_logo
; // some extra text to show in Usage()
182 wxArrayString m_arguments
; // == argv, argc == m_arguments.GetCount()
183 wxArrayOptions m_options
; // all possible options and switches
184 wxArrayParams m_paramDesc
; // description of all possible params
185 wxArrayString m_parameters
; // all params found
188 wxCmdLineParserData();
189 void SetArguments(int argc
, char **argv
);
191 void SetArguments(int argc
, wxChar
**argv
);
192 #endif // wxUSE_UNICODE
193 void SetArguments(const wxString
& cmdline
);
195 int FindOption(const wxString
& name
);
196 int FindOptionByLongName(const wxString
& name
);
199 // ============================================================================
201 // ============================================================================
203 // ----------------------------------------------------------------------------
204 // wxCmdLineParserData
205 // ----------------------------------------------------------------------------
207 wxCmdLineParserData::wxCmdLineParserData()
209 m_enableLongOptions
= true;
211 m_switchChars
= _T("-");
213 m_switchChars
= _T("/-");
217 void wxCmdLineParserData::SetArguments(int argc
, char **argv
)
221 for ( int n
= 0; n
< argc
; n
++ )
223 m_arguments
.push_back(wxString::FromAscii(argv
[n
]));
229 void wxCmdLineParserData::SetArguments(int argc
, wxChar
**argv
)
233 for ( int n
= 0; n
< argc
; n
++ )
235 m_arguments
.push_back(argv
[n
]);
239 #endif // wxUSE_UNICODE
241 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
)
245 if(wxTheApp
&& wxTheApp
->argc
> 0)
246 m_arguments
.push_back(wxTheApp
->argv
[0]);
248 m_arguments
.push_back(wxEmptyString
);
250 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
252 WX_APPEND_ARRAY(m_arguments
, args
);
255 int wxCmdLineParserData::FindOption(const wxString
& name
)
259 size_t count
= m_options
.GetCount();
260 for ( size_t n
= 0; n
< count
; n
++ )
262 if ( m_options
[n
].shortName
== name
)
273 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
275 size_t count
= m_options
.GetCount();
276 for ( size_t n
= 0; n
< count
; n
++ )
278 if ( m_options
[n
].longName
== name
)
288 // ----------------------------------------------------------------------------
289 // construction and destruction
290 // ----------------------------------------------------------------------------
292 void wxCmdLineParser::Init()
294 m_data
= new wxCmdLineParserData
;
297 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
299 m_data
->SetArguments(argc
, argv
);
304 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
306 m_data
->SetArguments(argc
, argv
);
309 #endif // wxUSE_UNICODE
311 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
313 m_data
->SetArguments(cmdline
);
316 wxCmdLineParser::~wxCmdLineParser()
321 // ----------------------------------------------------------------------------
323 // ----------------------------------------------------------------------------
325 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
327 m_data
->m_switchChars
= switchChars
;
330 void wxCmdLineParser::EnableLongOptions(bool enable
)
332 m_data
->m_enableLongOptions
= enable
;
335 bool wxCmdLineParser::AreLongOptionsEnabled()
337 return m_data
->m_enableLongOptions
;
340 void wxCmdLineParser::SetLogo(const wxString
& logo
)
342 m_data
->m_logo
= logo
;
345 // ----------------------------------------------------------------------------
346 // command line construction
347 // ----------------------------------------------------------------------------
349 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
353 switch ( desc
->kind
)
355 case wxCMD_LINE_SWITCH
:
356 AddSwitch(desc
->shortName
, desc
->longName
, desc
->description
,
360 case wxCMD_LINE_OPTION
:
361 AddOption(desc
->shortName
, desc
->longName
, desc
->description
,
362 desc
->type
, desc
->flags
);
365 case wxCMD_LINE_PARAM
:
366 AddParam(desc
->description
, desc
->type
, desc
->flags
);
370 wxFAIL_MSG( _T("unknown command line entry type") );
371 // still fall through
373 case wxCMD_LINE_NONE
:
379 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
380 const wxString
& longName
,
381 const wxString
& desc
,
384 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
385 _T("duplicate switch") );
387 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
388 shortName
, longName
, desc
,
389 wxCMD_LINE_VAL_NONE
, flags
);
391 m_data
->m_options
.Add(option
);
394 void wxCmdLineParser::AddOption(const wxString
& shortName
,
395 const wxString
& longName
,
396 const wxString
& desc
,
397 wxCmdLineParamType type
,
400 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
401 _T("duplicate option") );
403 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
404 shortName
, longName
, desc
,
407 m_data
->m_options
.Add(option
);
410 void wxCmdLineParser::AddParam(const wxString
& desc
,
411 wxCmdLineParamType type
,
414 // do some consistency checks: a required parameter can't follow an
415 // optional one and nothing should follow a parameter with MULTIPLE flag
417 if ( !m_data
->m_paramDesc
.IsEmpty() )
419 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
421 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
422 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
424 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
426 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
427 _T("a required parameter can't follow an optional one") );
432 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
434 m_data
->m_paramDesc
.Add(param
);
437 // ----------------------------------------------------------------------------
438 // access to parse command line
439 // ----------------------------------------------------------------------------
441 bool wxCmdLineParser::Found(const wxString
& name
) const
443 int i
= m_data
->FindOption(name
);
444 if ( i
== wxNOT_FOUND
)
445 i
= m_data
->FindOptionByLongName(name
);
447 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown switch") );
449 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
450 if ( !opt
.HasValue() )
456 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
458 int i
= m_data
->FindOption(name
);
459 if ( i
== wxNOT_FOUND
)
460 i
= m_data
->FindOptionByLongName(name
);
462 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
464 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
465 if ( !opt
.HasValue() )
468 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
470 *value
= opt
.GetStrVal();
475 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
477 int i
= m_data
->FindOption(name
);
478 if ( i
== wxNOT_FOUND
)
479 i
= m_data
->FindOptionByLongName(name
);
481 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
483 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
484 if ( !opt
.HasValue() )
487 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
489 *value
= opt
.GetLongVal();
495 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
497 int i
= m_data
->FindOption(name
);
498 if ( i
== wxNOT_FOUND
)
499 i
= m_data
->FindOptionByLongName(name
);
501 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
503 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
504 if ( !opt
.HasValue() )
507 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
509 *value
= opt
.GetDateVal();
513 #endif // wxUSE_DATETIME
515 size_t wxCmdLineParser::GetParamCount() const
517 return m_data
->m_parameters
.size();
520 wxString
wxCmdLineParser::GetParam(size_t n
) const
522 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, _T("invalid param index") );
524 return m_data
->m_parameters
[n
];
527 // Resets switches and options
528 void wxCmdLineParser::Reset()
530 for ( size_t i
= 0; i
< m_data
->m_options
.GetCount(); i
++ )
532 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
533 opt
.SetHasValue(false);
538 // ----------------------------------------------------------------------------
539 // the real work is done here
540 // ----------------------------------------------------------------------------
542 int wxCmdLineParser::Parse(bool showUsage
)
544 bool maybeOption
= true; // can the following arg be an option?
545 bool ok
= true; // true until an error is detected
546 bool helpRequested
= false; // true if "-h" was given
547 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
549 size_t currentParam
= 0; // the index in m_paramDesc
551 size_t countParam
= m_data
->m_paramDesc
.GetCount();
558 size_t count
= m_data
->m_arguments
.size();
559 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
561 arg
= m_data
->m_arguments
[n
];
563 // special case: "--" should be discarded and all following arguments
564 // should be considered as parameters, even if they start with '-' and
565 // not like options (this is POSIX-like)
566 if ( arg
== _T("--") )
573 // empty argument or just '-' is not an option but a parameter
574 if ( maybeOption
&& arg
.length() > 1 &&
575 wxStrchr(m_data
->m_switchChars
, arg
[0u]) )
579 int optInd
= wxNOT_FOUND
; // init to suppress warnings
581 // an option or a switch: find whether it's a long or a short one
582 if ( arg
[0u] == _T('-') && arg
[1u] == _T('-') )
588 const wxChar
*p
= arg
.c_str() + 2;
590 bool longOptionsEnabled
= AreLongOptionsEnabled();
592 name
= GetLongOptionName(p
);
594 if (longOptionsEnabled
)
596 optInd
= m_data
->FindOptionByLongName(name
);
597 if ( optInd
== wxNOT_FOUND
)
599 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str())
605 optInd
= wxNOT_FOUND
; // Sanity check
607 // Print the argument including leading "--"
608 name
.Prepend( wxT("--") );
609 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
614 else // not a long option
618 // a short one: as they can be cumulated, we try to find the
619 // longest substring which is a valid option
620 const wxChar
*p
= arg
.c_str() + 1;
622 name
= GetShortOptionName(p
);
624 size_t len
= name
.length();
629 // we couldn't find a valid option name in the
630 // beginning of this string
631 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
638 optInd
= m_data
->FindOption(name
.Left(len
));
640 // will try with one character less the next time
644 while ( optInd
== wxNOT_FOUND
);
646 len
++; // compensates extra len-- above
647 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
649 // first of all, the option name is only part of this
651 name
= name
.Left(len
);
653 // our option is only part of this argument, there is
654 // something else in it - it is either the value of this
655 // option or other switches if it is a switch
656 if ( m_data
->m_options
[(size_t)optInd
].kind
657 == wxCMD_LINE_SWITCH
)
659 // pretend that all the rest of the argument is the
660 // next argument, in fact
661 wxString arg2
= arg
[0u];
662 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
664 m_data
->m_arguments
.insert
665 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
668 //else: it's our value, we'll deal with it below
672 if ( optInd
== wxNOT_FOUND
)
676 continue; // will break, in fact
679 // look at what follows:
681 // +1 for leading '-'
682 const wxChar
*p
= arg
.c_str() + 1 + name
.length();
684 p
++; // for another leading '-'
686 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
687 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
689 // we must check that there is no value following the switch
690 if ( *p
!= _T('\0') )
692 errorMsg
<< wxString::Format(_("Unexpected characters following option '%s'."), name
.c_str())
696 else // no value, as expected
698 // nothing more to do
701 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
703 helpRequested
= true;
705 // it's not an error, but we still stop here
710 else // it's an option. not a switch
715 if ( *p
++ != _T('=') )
717 errorMsg
<< wxString::Format(_("Option '%s' requires a value, '=' expected."), name
.c_str())
734 // the value is in the next argument
737 // ... but there is none
738 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
746 // ... take it from there
747 p
= m_data
->m_arguments
[n
].c_str();
752 // the value is right here: this may be legal or
753 // not depending on the option style
754 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
756 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
771 wxFAIL_MSG( _T("unknown option type") );
772 // still fall through
774 case wxCMD_LINE_VAL_STRING
:
775 opt
.SetStrVal(value
);
778 case wxCMD_LINE_VAL_NUMBER
:
781 if ( value
.ToLong(&val
) )
787 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
788 value
.c_str(), name
.c_str())
797 case wxCMD_LINE_VAL_DATE
:
800 const wxChar
*res
= dt
.ParseDate(value
);
803 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
804 name
.c_str(), value
.c_str())
815 #endif // wxUSE_DATETIME
820 else // not an option, must be a parameter
822 if ( currentParam
< countParam
)
824 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
826 // TODO check the param type
828 m_data
->m_parameters
.push_back(arg
);
830 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
836 wxASSERT_MSG( currentParam
== countParam
- 1,
837 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
839 // remember that we did have this last repeatable parameter
840 hadRepeatableParam
= true;
845 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str())
853 // verify that all mandatory options were given
856 size_t countOpt
= m_data
->m_options
.GetCount();
857 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
859 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
860 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
865 optName
= opt
.shortName
;
869 if ( AreLongOptionsEnabled() )
871 optName
.Printf( _("%s (or %s)"),
872 opt
.shortName
.c_str(),
873 opt
.longName
.c_str() );
877 optName
.Printf( wxT("%s"),
878 opt
.shortName
.c_str() );
882 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
890 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
892 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
893 if ( (currentParam
== countParam
- 1) &&
894 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
897 // special case: currentParam wasn't incremented, but we did
898 // have it, so don't give error
902 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
904 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
905 param
.description
.c_str())
913 // if there was an error during parsing the command line, show this error
914 // and also the usage message if it had been requested
915 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
917 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
922 usage
= GetUsageString();
924 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
928 wxFAIL_MSG( _T("no wxMessageOutput object?") );
932 return ok
? 0 : helpRequested
? -1 : 1;
935 // ----------------------------------------------------------------------------
936 // give the usage message
937 // ----------------------------------------------------------------------------
939 void wxCmdLineParser::Usage()
941 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
944 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
948 wxFAIL_MSG( _T("no wxMessageOutput object?") );
952 wxString
wxCmdLineParser::GetUsageString()
955 if ( m_data
->m_arguments
.empty() )
958 appname
= wxTheApp
->GetAppName();
962 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
965 // we construct the brief cmd line desc on the fly, but not the detailed
966 // help message below because we want to align the options descriptions
967 // and for this we must first know the longest one of them
969 wxArrayString namesOptions
, descOptions
;
971 if ( !m_data
->m_logo
.empty() )
973 usage
<< m_data
->m_logo
<< _T('\n');
976 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
978 // the switch char is usually '-' but this can be changed with
979 // SetSwitchChars() and then the first one of possible chars is used
980 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
981 : m_data
->m_switchChars
[0u];
983 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
984 size_t n
, count
= m_data
->m_options
.GetCount();
985 for ( n
= 0; n
< count
; n
++ )
987 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
990 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
995 if ( !opt
.shortName
.empty() )
997 usage
<< chSwitch
<< opt
.shortName
;
999 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1001 usage
<< _T("--") << opt
.longName
;
1005 if (!opt
.longName
.empty())
1007 wxFAIL_MSG( wxT("option with only a long name while long ")
1008 wxT("options are disabled") );
1012 wxFAIL_MSG( _T("option without neither short nor long name") );
1018 if ( !opt
.shortName
.empty() )
1020 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
1023 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1025 option
<< (option
.empty() ? _T(" ") : _T(", "))
1026 << _T("--") << opt
.longName
;
1029 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1032 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1033 usage
<< _T(' ') << val
;
1034 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1037 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1042 namesOptions
.push_back(option
);
1043 descOptions
.push_back(opt
.description
);
1046 count
= m_data
->m_paramDesc
.GetCount();
1047 for ( n
= 0; n
< count
; n
++ )
1049 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1052 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1057 usage
<< param
.description
;
1059 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1064 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1072 // set to number of our own options, not counting the standard ones
1073 count
= namesOptions
.size();
1075 // get option names & descriptions for standard options, if any:
1076 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
1079 stdDesc
= traits
->GetStandardCmdLineOptions(namesOptions
, descOptions
);
1081 // now construct the detailed help message
1082 size_t len
, lenMax
= 0;
1083 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1085 len
= namesOptions
[n
].length();
1090 for ( n
= 0; n
< namesOptions
.size(); n
++ )
1093 usage
<< _T('\n') << stdDesc
;
1095 len
= namesOptions
[n
].length();
1096 usage
<< namesOptions
[n
]
1097 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1105 // ----------------------------------------------------------------------------
1106 // private functions
1107 // ----------------------------------------------------------------------------
1109 static wxString
GetTypeName(wxCmdLineParamType type
)
1115 wxFAIL_MSG( _T("unknown option type") );
1116 // still fall through
1118 case wxCMD_LINE_VAL_STRING
:
1122 case wxCMD_LINE_VAL_NUMBER
:
1126 case wxCMD_LINE_VAL_DATE
:
1135 Returns a string which is equal to the string pointed to by p, but up to the
1136 point where p contains an character that's not allowed.
1137 Allowable characters are letters and numbers, and characters pointed to by
1138 the parameter allowedChars.
1140 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1141 this function returns "abcde-".
1143 static wxString
GetOptionName(const wxChar
*p
,
1144 const wxChar
*allowedChars
)
1148 while ( *p
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1156 // Besides alphanumeric characters, short and long options can
1157 // have other characters.
1159 // A short option additionally can have these
1160 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1162 // A long option can have the same characters as a short option and a '-'.
1163 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1164 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1166 static wxString
GetShortOptionName(const wxChar
*p
)
1168 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1171 static wxString
GetLongOptionName(const wxChar
*p
)
1173 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1176 #endif // wxUSE_CMDLINE_PARSER
1178 // ----------------------------------------------------------------------------
1180 // ----------------------------------------------------------------------------
1183 This function is mainly used under Windows (as under Unix we always get the
1184 command line arguments as argc/argv anyhow) and so it tries to follow
1185 Windows conventions for the command line handling, not Unix ones. For
1186 instance, backslash is not special except when it precedes double quote when
1191 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxChar
*p
)
1198 bool isInsideQuotes
= false;
1202 while ( *p
== _T(' ') || *p
== _T('\t') )
1206 if ( *p
== _T('\0') )
1209 // parse this parameter
1210 bool endParam
= false;
1211 bool lastBS
= false;
1212 for ( arg
.clear(); !endParam
; p
++ )
1219 isInsideQuotes
= !isInsideQuotes
;
1221 // don't put quote in arg
1224 //else: quote has no special meaning but the backslash
1225 // still remains -- makes no sense but this is what
1231 // backslash does *not* quote the space, only quotes do
1232 if ( isInsideQuotes
)
1234 // skip assignment below
1250 lastBS
= *p
== _T('\\');
1255 args
.push_back(arg
);