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"
45 // ----------------------------------------------------------------------------
47 // ----------------------------------------------------------------------------
49 static wxString
GetTypeName(wxCmdLineParamType type
);
51 static wxString
GetOptionName(const wxChar
*p
, const wxChar
*allowedChars
);
53 static wxString
GetShortOptionName(const wxChar
*p
);
55 static wxString
GetLongOptionName(const wxChar
*p
);
57 // ----------------------------------------------------------------------------
59 // ----------------------------------------------------------------------------
61 // an internal representation of an option
62 struct wxCmdLineOption
64 wxCmdLineOption(wxCmdLineEntryType k
,
68 wxCmdLineParamType typ
,
71 wxASSERT_MSG( !shrt
.empty() || !lng
.empty(),
72 _T("option should have at least one name") );
76 GetShortOptionName(shrt
).Len() == shrt
.Len(),
77 wxT("Short option contains invalid characters")
82 GetLongOptionName(lng
).Len() == lng
.Len(),
83 wxT("Long option contains invalid characters")
99 // can't use union easily here, so just store all possible data fields, we
100 // don't waste much (might still use union later if the number of supported
101 // types increases, so always use the accessor functions and don't access
102 // the fields directly!)
104 void Check(wxCmdLineParamType
WXUNUSED_UNLESS_DEBUG(typ
)) const
106 wxASSERT_MSG( type
== typ
, _T("type mismatch in wxCmdLineOption") );
109 long GetLongVal() const
110 { Check(wxCMD_LINE_VAL_NUMBER
); return m_longVal
; }
111 const wxString
& GetStrVal() const
112 { Check(wxCMD_LINE_VAL_STRING
); return m_strVal
; }
114 const wxDateTime
& GetDateVal() const
115 { Check(wxCMD_LINE_VAL_DATE
); return m_dateVal
; }
116 #endif // wxUSE_DATETIME
118 void SetLongVal(long val
)
119 { Check(wxCMD_LINE_VAL_NUMBER
); m_longVal
= val
; m_hasVal
= true; }
120 void SetStrVal(const wxString
& val
)
121 { Check(wxCMD_LINE_VAL_STRING
); m_strVal
= val
; m_hasVal
= true; }
123 void SetDateVal(const wxDateTime
& val
)
124 { Check(wxCMD_LINE_VAL_DATE
); m_dateVal
= val
; m_hasVal
= true; }
125 #endif // wxUSE_DATETIME
127 void SetHasValue(bool hasValue
= true) { m_hasVal
= hasValue
; }
128 bool HasValue() const { return m_hasVal
; }
131 wxCmdLineEntryType kind
;
135 wxCmdLineParamType type
;
144 wxDateTime m_dateVal
;
145 #endif // wxUSE_DATETIME
148 struct wxCmdLineParam
150 wxCmdLineParam(const wxString
& desc
,
151 wxCmdLineParamType typ
,
159 wxString description
;
160 wxCmdLineParamType type
;
164 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
);
165 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
);
167 #include "wx/arrimpl.cpp"
169 WX_DEFINE_OBJARRAY(wxArrayOptions
)
170 WX_DEFINE_OBJARRAY(wxArrayParams
)
172 // the parser internal state
173 struct wxCmdLineParserData
176 wxString m_switchChars
; // characters which may start an option
177 bool m_enableLongOptions
; // true if long options are enabled
178 wxString m_logo
; // some extra text to show in Usage()
181 wxArrayString m_arguments
; // == argv, argc == m_arguments.GetCount()
182 wxArrayOptions m_options
; // all possible options and switchrs
183 wxArrayParams m_paramDesc
; // description of all possible params
184 wxArrayString m_parameters
; // all params found
187 wxCmdLineParserData();
188 void SetArguments(int argc
, char **argv
);
190 void SetArguments(int argc
, wxChar
**argv
);
191 #endif // wxUSE_UNICODE
192 void SetArguments(const wxString
& cmdline
);
194 int FindOption(const wxString
& name
);
195 int FindOptionByLongName(const wxString
& name
);
198 // ============================================================================
200 // ============================================================================
202 // ----------------------------------------------------------------------------
203 // wxCmdLineParserData
204 // ----------------------------------------------------------------------------
206 wxCmdLineParserData::wxCmdLineParserData()
208 m_enableLongOptions
= true;
210 m_switchChars
= _T("-");
212 m_switchChars
= _T("/-");
216 void wxCmdLineParserData::SetArguments(int argc
, char **argv
)
220 for ( int n
= 0; n
< argc
; n
++ )
222 m_arguments
.push_back(wxString::FromAscii(argv
[n
]));
228 void wxCmdLineParserData::SetArguments(int argc
, wxChar
**argv
)
232 for ( int n
= 0; n
< argc
; n
++ )
234 m_arguments
.push_back(argv
[n
]);
238 #endif // wxUSE_UNICODE
240 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
)
244 if(wxTheApp
&& wxTheApp
->argc
> 0)
245 m_arguments
.push_back(wxTheApp
->argv
[0]);
247 m_arguments
.push_back(wxEmptyString
);
249 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
251 WX_APPEND_ARRAY(m_arguments
, args
);
254 int wxCmdLineParserData::FindOption(const wxString
& name
)
258 size_t count
= m_options
.GetCount();
259 for ( size_t n
= 0; n
< count
; n
++ )
261 if ( m_options
[n
].shortName
== name
)
272 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
274 size_t count
= m_options
.GetCount();
275 for ( size_t n
= 0; n
< count
; n
++ )
277 if ( m_options
[n
].longName
== name
)
287 // ----------------------------------------------------------------------------
288 // construction and destruction
289 // ----------------------------------------------------------------------------
291 void wxCmdLineParser::Init()
293 m_data
= new wxCmdLineParserData
;
296 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
298 m_data
->SetArguments(argc
, argv
);
303 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
305 m_data
->SetArguments(argc
, argv
);
308 #endif // wxUSE_UNICODE
310 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
312 m_data
->SetArguments(cmdline
);
315 wxCmdLineParser::~wxCmdLineParser()
320 // ----------------------------------------------------------------------------
322 // ----------------------------------------------------------------------------
324 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
326 m_data
->m_switchChars
= switchChars
;
329 void wxCmdLineParser::EnableLongOptions(bool enable
)
331 m_data
->m_enableLongOptions
= enable
;
334 bool wxCmdLineParser::AreLongOptionsEnabled()
336 return m_data
->m_enableLongOptions
;
339 void wxCmdLineParser::SetLogo(const wxString
& logo
)
341 m_data
->m_logo
= logo
;
344 // ----------------------------------------------------------------------------
345 // command line construction
346 // ----------------------------------------------------------------------------
348 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
352 switch ( desc
->kind
)
354 case wxCMD_LINE_SWITCH
:
355 AddSwitch(desc
->shortName
, desc
->longName
, desc
->description
,
359 case wxCMD_LINE_OPTION
:
360 AddOption(desc
->shortName
, desc
->longName
, desc
->description
,
361 desc
->type
, desc
->flags
);
364 case wxCMD_LINE_PARAM
:
365 AddParam(desc
->description
, desc
->type
, desc
->flags
);
369 wxFAIL_MSG( _T("unknown command line entry type") );
370 // still fall through
372 case wxCMD_LINE_NONE
:
378 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
379 const wxString
& longName
,
380 const wxString
& desc
,
383 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
384 _T("duplicate switch") );
386 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
387 shortName
, longName
, desc
,
388 wxCMD_LINE_VAL_NONE
, flags
);
390 m_data
->m_options
.Add(option
);
393 void wxCmdLineParser::AddOption(const wxString
& shortName
,
394 const wxString
& longName
,
395 const wxString
& desc
,
396 wxCmdLineParamType type
,
399 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
400 _T("duplicate option") );
402 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
403 shortName
, longName
, desc
,
406 m_data
->m_options
.Add(option
);
409 void wxCmdLineParser::AddParam(const wxString
& desc
,
410 wxCmdLineParamType type
,
413 // do some consistency checks: a required parameter can't follow an
414 // optional one and nothing should follow a parameter with MULTIPLE flag
416 if ( !m_data
->m_paramDesc
.IsEmpty() )
418 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
420 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
421 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
423 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
425 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
426 _T("a required parameter can't follow an optional one") );
431 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
433 m_data
->m_paramDesc
.Add(param
);
436 // ----------------------------------------------------------------------------
437 // access to parse command line
438 // ----------------------------------------------------------------------------
440 bool wxCmdLineParser::Found(const wxString
& name
) const
442 int i
= m_data
->FindOption(name
);
443 if ( i
== wxNOT_FOUND
)
444 i
= m_data
->FindOptionByLongName(name
);
446 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown switch") );
448 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
449 if ( !opt
.HasValue() )
455 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
457 int i
= m_data
->FindOption(name
);
458 if ( i
== wxNOT_FOUND
)
459 i
= m_data
->FindOptionByLongName(name
);
461 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
463 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
464 if ( !opt
.HasValue() )
467 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
469 *value
= opt
.GetStrVal();
474 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
476 int i
= m_data
->FindOption(name
);
477 if ( i
== wxNOT_FOUND
)
478 i
= m_data
->FindOptionByLongName(name
);
480 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
482 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
483 if ( !opt
.HasValue() )
486 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
488 *value
= opt
.GetLongVal();
494 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
496 int i
= m_data
->FindOption(name
);
497 if ( i
== wxNOT_FOUND
)
498 i
= m_data
->FindOptionByLongName(name
);
500 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
502 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
503 if ( !opt
.HasValue() )
506 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
508 *value
= opt
.GetDateVal();
512 #endif // wxUSE_DATETIME
514 size_t wxCmdLineParser::GetParamCount() const
516 return m_data
->m_parameters
.size();
519 wxString
wxCmdLineParser::GetParam(size_t n
) const
521 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, _T("invalid param index") );
523 return m_data
->m_parameters
[n
];
526 // Resets switches and options
527 void wxCmdLineParser::Reset()
529 for ( size_t i
= 0; i
< m_data
->m_options
.Count(); i
++ )
531 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
532 opt
.SetHasValue(false);
537 // ----------------------------------------------------------------------------
538 // the real work is done here
539 // ----------------------------------------------------------------------------
541 int wxCmdLineParser::Parse(bool showUsage
)
543 bool maybeOption
= true; // can the following arg be an option?
544 bool ok
= true; // true until an error is detected
545 bool helpRequested
= false; // true if "-h" was given
546 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
548 size_t currentParam
= 0; // the index in m_paramDesc
550 size_t countParam
= m_data
->m_paramDesc
.GetCount();
557 size_t count
= m_data
->m_arguments
.size();
558 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
560 arg
= m_data
->m_arguments
[n
];
562 // special case: "--" should be discarded and all following arguments
563 // should be considered as parameters, even if they start with '-' and
564 // not like options (this is POSIX-like)
565 if ( arg
== _T("--") )
572 // empty argument or just '-' is not an option but a parameter
573 if ( maybeOption
&& arg
.length() > 1 &&
574 wxStrchr(m_data
->m_switchChars
, arg
[0u]) )
578 int optInd
= wxNOT_FOUND
; // init to suppress warnings
580 // an option or a switch: find whether it's a long or a short one
581 if ( arg
[0u] == _T('-') && arg
[1u] == _T('-') )
587 const wxChar
*p
= arg
.c_str() + 2;
589 bool longOptionsEnabled
= AreLongOptionsEnabled();
591 name
= GetLongOptionName(p
);
593 if (longOptionsEnabled
)
595 optInd
= m_data
->FindOptionByLongName(name
);
596 if ( optInd
== wxNOT_FOUND
)
598 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str())
604 optInd
= wxNOT_FOUND
; // Sanity check
606 // Print the argument including leading "--"
607 name
.Prepend( wxT("--") );
608 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
613 else // not a long option
617 // a short one: as they can be cumulated, we try to find the
618 // longest substring which is a valid option
619 const wxChar
*p
= arg
.c_str() + 1;
621 name
= GetShortOptionName(p
);
623 size_t len
= name
.length();
628 // we couldn't find a valid option name in the
629 // beginning of this string
630 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str())
637 optInd
= m_data
->FindOption(name
.Left(len
));
639 // will try with one character less the next time
643 while ( optInd
== wxNOT_FOUND
);
645 len
++; // compensates extra len-- above
646 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
648 // first of all, the option name is only part of this
650 name
= name
.Left(len
);
652 // our option is only part of this argument, there is
653 // something else in it - it is either the value of this
654 // option or other switches if it is a switch
655 if ( m_data
->m_options
[(size_t)optInd
].kind
656 == wxCMD_LINE_SWITCH
)
658 // pretend that all the rest of the argument is the
659 // next argument, in fact
660 wxString arg2
= arg
[0u];
661 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
663 m_data
->m_arguments
.insert
664 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
667 //else: it's our value, we'll deal with it below
671 if ( optInd
== wxNOT_FOUND
)
675 continue; // will break, in fact
678 // look at what follows:
680 // +1 for leading '-'
681 const wxChar
*p
= arg
.c_str() + 1 + name
.length();
683 p
++; // for another leading '-'
685 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
686 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
688 // we must check that there is no value following the switch
689 if ( *p
!= _T('\0') )
691 errorMsg
<< wxString::Format(_("Unexpected characters following option '%s'."), name
.c_str())
695 else // no value, as expected
697 // nothing more to do
700 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
702 helpRequested
= true;
704 // it's not an error, but we still stop here
709 else // it's an option. not a switch
714 if ( *p
++ != _T('=') )
716 errorMsg
<< wxString::Format(_("Option '%s' requires a value, '=' expected."), name
.c_str())
733 // the value is in the next argument
736 // ... but there is none
737 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
745 // ... take it from there
746 p
= m_data
->m_arguments
[n
].c_str();
751 // the value is right here: this may be legal or
752 // not depending on the option style
753 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
755 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
770 wxFAIL_MSG( _T("unknown option type") );
771 // still fall through
773 case wxCMD_LINE_VAL_STRING
:
774 opt
.SetStrVal(value
);
777 case wxCMD_LINE_VAL_NUMBER
:
780 if ( value
.ToLong(&val
) )
786 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
787 value
.c_str(), name
.c_str())
796 case wxCMD_LINE_VAL_DATE
:
799 const wxChar
*res
= dt
.ParseDate(value
);
802 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
803 name
.c_str(), value
.c_str())
814 #endif // wxUSE_DATETIME
819 else // not an option, must be a parameter
821 if ( currentParam
< countParam
)
823 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
825 // TODO check the param type
827 m_data
->m_parameters
.push_back(arg
);
829 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
835 wxASSERT_MSG( currentParam
== countParam
- 1,
836 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
838 // remember that we did have this last repeatable parameter
839 hadRepeatableParam
= true;
844 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str())
852 // verify that all mandatory options were given
855 size_t countOpt
= m_data
->m_options
.GetCount();
856 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
858 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
859 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
864 optName
= opt
.shortName
;
868 if ( AreLongOptionsEnabled() )
870 optName
.Printf( _("%s (or %s)"),
871 opt
.shortName
.c_str(),
872 opt
.longName
.c_str() );
876 optName
.Printf( wxT("%s"),
877 opt
.shortName
.c_str() );
881 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
889 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
891 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
892 if ( (currentParam
== countParam
- 1) &&
893 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
896 // special case: currentParam wasn't incremented, but we did
897 // have it, so don't give error
901 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
903 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
904 param
.description
.c_str())
912 // if there was an error during parsing the command line, show this error
913 // and also the usage message if it had been requested
914 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
916 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
921 usage
= GetUsageString();
923 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
927 wxFAIL_MSG( _T("no wxMessageOutput object?") );
931 return ok
? 0 : helpRequested
? -1 : 1;
934 // ----------------------------------------------------------------------------
935 // give the usage message
936 // ----------------------------------------------------------------------------
938 void wxCmdLineParser::Usage()
940 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
943 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
947 wxFAIL_MSG( _T("no wxMessageOutput object?") );
951 wxString
wxCmdLineParser::GetUsageString()
954 if ( m_data
->m_arguments
.empty() )
957 appname
= wxTheApp
->GetAppName();
961 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
964 // we construct the brief cmd line desc on the fly, but not the detailed
965 // help message below because we want to align the options descriptions
966 // and for this we must first know the longest one of them
968 wxArrayString namesOptions
, descOptions
;
970 if ( !m_data
->m_logo
.empty() )
972 usage
<< m_data
->m_logo
<< _T('\n');
975 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
977 // the switch char is usually '-' but this can be changed with
978 // SetSwitchChars() and then the first one of possible chars is used
979 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
980 : m_data
->m_switchChars
[0u];
982 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
983 size_t n
, count
= m_data
->m_options
.GetCount();
984 for ( n
= 0; n
< count
; n
++ )
986 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
989 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
994 if ( !opt
.shortName
.empty() )
996 usage
<< chSwitch
<< opt
.shortName
;
998 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1000 usage
<< _T("--") << opt
.longName
;
1004 if (!opt
.longName
.empty())
1006 wxFAIL_MSG( wxT("option with only a long name while long ")
1007 wxT("options are disabled") );
1011 wxFAIL_MSG( _T("option without neither short nor long name") );
1017 if ( !opt
.shortName
.empty() )
1019 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
1022 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1024 option
<< (option
.empty() ? _T(" ") : _T(", "))
1025 << _T("--") << opt
.longName
;
1028 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1031 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1032 usage
<< _T(' ') << val
;
1033 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1036 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1041 namesOptions
.push_back(option
);
1042 descOptions
.push_back(opt
.description
);
1045 count
= m_data
->m_paramDesc
.GetCount();
1046 for ( n
= 0; n
< count
; n
++ )
1048 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1051 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1056 usage
<< param
.description
;
1058 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1063 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1071 // now construct the detailed help message
1072 size_t len
, lenMax
= 0;
1073 count
= namesOptions
.size();
1074 for ( n
= 0; n
< count
; n
++ )
1076 len
= namesOptions
[n
].length();
1081 for ( n
= 0; n
< count
; n
++ )
1083 len
= namesOptions
[n
].length();
1084 usage
<< namesOptions
[n
]
1085 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1093 // ----------------------------------------------------------------------------
1094 // private functions
1095 // ----------------------------------------------------------------------------
1097 static wxString
GetTypeName(wxCmdLineParamType type
)
1103 wxFAIL_MSG( _T("unknown option type") );
1104 // still fall through
1106 case wxCMD_LINE_VAL_STRING
:
1110 case wxCMD_LINE_VAL_NUMBER
:
1114 case wxCMD_LINE_VAL_DATE
:
1123 Returns a string which is equal to the string pointed to by p, but up to the
1124 point where p contains an character that's not allowed.
1125 Allowable characters are letters and numbers, and characters pointed to by
1126 the parameter allowedChars.
1128 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1129 this function returns "abcde-".
1131 static wxString
GetOptionName(const wxChar
*p
,
1132 const wxChar
*allowedChars
)
1136 while ( *p
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1144 // Besides alphanumeric characters, short and long options can
1145 // have other characters.
1147 // A short option additionally can have these
1148 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1150 // A long option can have the same characters as a short option and a '-'.
1151 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1152 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1154 static wxString
GetShortOptionName(const wxChar
*p
)
1156 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1159 static wxString
GetLongOptionName(const wxChar
*p
)
1161 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1164 #endif // wxUSE_CMDLINE_PARSER
1166 // ----------------------------------------------------------------------------
1168 // ----------------------------------------------------------------------------
1171 This function is mainly used under Windows (as under Unix we always get the
1172 command line arguments as argc/argv anyhow) and so it tries to follow
1173 Windows conventions for the command line handling, not Unix ones. For
1174 instance, backslash is not special except when it precedes double quote when
1179 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxChar
*p
)
1186 bool isInsideQuotes
= false;
1190 while ( *p
== _T(' ') || *p
== _T('\t') )
1194 if ( *p
== _T('\0') )
1197 // parse this parameter
1198 bool endParam
= false;
1199 bool lastBS
= false;
1200 for ( arg
.clear(); !endParam
; p
++ )
1207 isInsideQuotes
= !isInsideQuotes
;
1209 // don't put quote in arg
1212 //else: quote has no special meaning but the backslash
1213 // still remains -- makes no sense but this is what
1219 // backslash does *not* quote the space, only quotes do
1220 if ( isInsideQuotes
)
1222 // skip assignment below
1238 lastBS
= *p
== _T('\\');
1243 args
.push_back(arg
);