1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: 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"
27 #include "wx/cmdline.h"
29 #if wxUSE_CMDLINE_PARSER
32 #include "wx/string.h"
36 #include "wx/dynarray.h"
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 m_arguments
.push_back(wxTheApp
? wxTheApp
->argv
[0] : _T(""));
246 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
248 WX_APPEND_ARRAY(m_arguments
, args
);
251 int wxCmdLineParserData::FindOption(const wxString
& name
)
255 size_t count
= m_options
.GetCount();
256 for ( size_t n
= 0; n
< count
; n
++ )
258 if ( m_options
[n
].shortName
== name
)
269 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
271 size_t count
= m_options
.GetCount();
272 for ( size_t n
= 0; n
< count
; n
++ )
274 if ( m_options
[n
].longName
== name
)
284 // ----------------------------------------------------------------------------
285 // construction and destruction
286 // ----------------------------------------------------------------------------
288 void wxCmdLineParser::Init()
290 m_data
= new wxCmdLineParserData
;
293 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
295 m_data
->SetArguments(argc
, argv
);
300 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
302 m_data
->SetArguments(argc
, argv
);
305 #endif // wxUSE_UNICODE
307 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
309 m_data
->SetArguments(cmdline
);
312 wxCmdLineParser::~wxCmdLineParser()
317 // ----------------------------------------------------------------------------
319 // ----------------------------------------------------------------------------
321 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
323 m_data
->m_switchChars
= switchChars
;
326 void wxCmdLineParser::EnableLongOptions(bool enable
)
328 m_data
->m_enableLongOptions
= enable
;
331 bool wxCmdLineParser::AreLongOptionsEnabled()
333 return m_data
->m_enableLongOptions
;
336 void wxCmdLineParser::SetLogo(const wxString
& logo
)
338 m_data
->m_logo
= logo
;
341 // ----------------------------------------------------------------------------
342 // command line construction
343 // ----------------------------------------------------------------------------
345 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
349 switch ( desc
->kind
)
351 case wxCMD_LINE_SWITCH
:
352 AddSwitch(desc
->shortName
, desc
->longName
, desc
->description
,
356 case wxCMD_LINE_OPTION
:
357 AddOption(desc
->shortName
, desc
->longName
, desc
->description
,
358 desc
->type
, desc
->flags
);
361 case wxCMD_LINE_PARAM
:
362 AddParam(desc
->description
, desc
->type
, desc
->flags
);
366 wxFAIL_MSG( _T("unknown command line entry type") );
367 // still fall through
369 case wxCMD_LINE_NONE
:
375 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
376 const wxString
& longName
,
377 const wxString
& desc
,
380 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
381 _T("duplicate switch") );
383 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
384 shortName
, longName
, desc
,
385 wxCMD_LINE_VAL_NONE
, flags
);
387 m_data
->m_options
.Add(option
);
390 void wxCmdLineParser::AddOption(const wxString
& shortName
,
391 const wxString
& longName
,
392 const wxString
& desc
,
393 wxCmdLineParamType type
,
396 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
397 _T("duplicate option") );
399 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
400 shortName
, longName
, desc
,
403 m_data
->m_options
.Add(option
);
406 void wxCmdLineParser::AddParam(const wxString
& desc
,
407 wxCmdLineParamType type
,
410 // do some consistency checks: a required parameter can't follow an
411 // optional one and nothing should follow a parameter with MULTIPLE flag
413 if ( !m_data
->m_paramDesc
.IsEmpty() )
415 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
417 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
418 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
420 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
422 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
423 _T("a required parameter can't follow an optional one") );
428 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
430 m_data
->m_paramDesc
.Add(param
);
433 // ----------------------------------------------------------------------------
434 // access to parse command line
435 // ----------------------------------------------------------------------------
437 bool wxCmdLineParser::Found(const wxString
& name
) const
439 int i
= m_data
->FindOption(name
);
440 if ( i
== wxNOT_FOUND
)
441 i
= m_data
->FindOptionByLongName(name
);
443 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown switch") );
445 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
446 if ( !opt
.HasValue() )
452 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
454 int i
= m_data
->FindOption(name
);
455 if ( i
== wxNOT_FOUND
)
456 i
= m_data
->FindOptionByLongName(name
);
458 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
460 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
461 if ( !opt
.HasValue() )
464 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
466 *value
= opt
.GetStrVal();
471 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
473 int i
= m_data
->FindOption(name
);
474 if ( i
== wxNOT_FOUND
)
475 i
= m_data
->FindOptionByLongName(name
);
477 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
479 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
480 if ( !opt
.HasValue() )
483 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
485 *value
= opt
.GetLongVal();
491 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*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
.GetDateVal();
509 #endif // wxUSE_DATETIME
511 size_t wxCmdLineParser::GetParamCount() const
513 return m_data
->m_parameters
.size();
516 wxString
wxCmdLineParser::GetParam(size_t n
) const
518 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, _T("invalid param index") );
520 return m_data
->m_parameters
[n
];
523 // Resets switches and options
524 void wxCmdLineParser::Reset()
526 for ( size_t i
= 0; i
< m_data
->m_options
.Count(); i
++ )
528 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
529 opt
.SetHasValue(false);
534 // ----------------------------------------------------------------------------
535 // the real work is done here
536 // ----------------------------------------------------------------------------
538 int wxCmdLineParser::Parse(bool showUsage
)
540 bool maybeOption
= true; // can the following arg be an option?
541 bool ok
= true; // true until an error is detected
542 bool helpRequested
= false; // true if "-h" was given
543 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
545 size_t currentParam
= 0; // the index in m_paramDesc
547 size_t countParam
= m_data
->m_paramDesc
.GetCount();
554 size_t count
= m_data
->m_arguments
.size();
555 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
557 arg
= m_data
->m_arguments
[n
];
559 // special case: "--" should be discarded and all following arguments
560 // should be considered as parameters, even if they start with '-' and
561 // not like options (this is POSIX-like)
562 if ( arg
== _T("--") )
569 // empty argument or just '-' is not an option but a parameter
570 if ( maybeOption
&& arg
.length() > 1 &&
571 wxStrchr(m_data
->m_switchChars
, arg
[0u]) )
575 int optInd
= wxNOT_FOUND
; // init to suppress warnings
577 // an option or a switch: find whether it's a long or a short one
578 if ( arg
[0u] == _T('-') && arg
[1u] == _T('-') )
584 const wxChar
*p
= arg
.c_str() + 2;
586 bool longOptionsEnabled
= AreLongOptionsEnabled();
588 name
= GetLongOptionName(p
);
590 if (longOptionsEnabled
)
592 optInd
= m_data
->FindOptionByLongName(name
);
593 if ( optInd
== wxNOT_FOUND
)
595 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str()) << wxT("\n");
600 optInd
= wxNOT_FOUND
; // Sanity check
602 // Print the argument including leading "--"
603 name
.Prepend( wxT("--") );
604 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n");
612 // a short one: as they can be cumulated, we try to find the
613 // longest substring which is a valid option
614 const wxChar
*p
= arg
.c_str() + 1;
616 name
= GetShortOptionName(p
);
618 size_t len
= name
.length();
623 // we couldn't find a valid option name in the
624 // beginning of this string
625 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n");
631 optInd
= m_data
->FindOption(name
.Left(len
));
633 // will try with one character less the next time
637 while ( optInd
== wxNOT_FOUND
);
639 len
++; // compensates extra len-- above
640 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
642 // first of all, the option name is only part of this
644 name
= name
.Left(len
);
646 // our option is only part of this argument, there is
647 // something else in it - it is either the value of this
648 // option or other switches if it is a switch
649 if ( m_data
->m_options
[(size_t)optInd
].kind
650 == wxCMD_LINE_SWITCH
)
652 // pretend that all the rest of the argument is the
653 // next argument, in fact
654 wxString arg2
= arg
[0u];
655 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
657 m_data
->m_arguments
.insert
658 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
661 //else: it's our value, we'll deal with it below
665 if ( optInd
== wxNOT_FOUND
)
669 continue; // will break, in fact
672 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
673 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
675 // nothing more to do
678 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
680 helpRequested
= true;
682 // it's not an error, but we still stop here
690 // +1 for leading '-'
691 const wxChar
*p
= arg
.c_str() + 1 + name
.length();
694 p
++; // for another leading '-'
696 if ( *p
++ != _T('=') )
698 errorMsg
<< wxString::Format(_("Option '%s' requires a value, '=' expected."), name
.c_str()) << wxT("\n");
714 // the value is in the next argument
717 // ... but there is none
718 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
719 name
.c_str()) << wxT("\n");
725 // ... take it from there
726 p
= m_data
->m_arguments
[n
].c_str();
731 // the value is right here: this may be legal or
732 // not depending on the option style
733 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
735 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
736 name
.c_str()) << wxT("\n");
749 wxFAIL_MSG( _T("unknown option type") );
750 // still fall through
752 case wxCMD_LINE_VAL_STRING
:
753 opt
.SetStrVal(value
);
756 case wxCMD_LINE_VAL_NUMBER
:
759 if ( value
.ToLong(&val
) )
765 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
766 value
.c_str(), name
.c_str()) << wxT("\n");
774 case wxCMD_LINE_VAL_DATE
:
777 const wxChar
*res
= dt
.ParseDate(value
);
780 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
781 name
.c_str(), value
.c_str()) << wxT("\n");
791 #endif // wxUSE_DATETIME
799 if ( currentParam
< countParam
)
801 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
803 // TODO check the param type
805 m_data
->m_parameters
.push_back(arg
);
807 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
813 wxASSERT_MSG( currentParam
== countParam
- 1,
814 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
816 // remember that we did have this last repeatable parameter
817 hadRepeatableParam
= true;
822 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str()) << wxT("\n");
829 // verify that all mandatory options were given
832 size_t countOpt
= m_data
->m_options
.GetCount();
833 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
835 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
836 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
841 optName
= opt
.shortName
;
845 if ( AreLongOptionsEnabled() )
847 optName
.Printf( _("%s (or %s)"),
848 opt
.shortName
.c_str(),
849 opt
.longName
.c_str() );
853 optName
.Printf( wxT("%s"),
854 opt
.shortName
.c_str() );
858 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
859 optName
.c_str()) << wxT("\n");
865 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
867 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
868 if ( (currentParam
== countParam
- 1) &&
869 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
872 // special case: currentParam wasn't incremented, but we did
873 // have it, so don't give error
877 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
879 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
880 param
.description
.c_str()) << wxT("\n");
887 // if there was an error during parsing the command line, show this error
888 // and also the usage message if it had been requested
889 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
891 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
896 usage
= GetUsageString();
898 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
902 wxFAIL_MSG( _T("no wxMessageOutput object?") );
906 return ok
? 0 : helpRequested
? -1 : 1;
909 // ----------------------------------------------------------------------------
910 // give the usage message
911 // ----------------------------------------------------------------------------
913 void wxCmdLineParser::Usage()
915 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
918 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
922 wxFAIL_MSG( _T("no wxMessageOutput object?") );
926 wxString
wxCmdLineParser::GetUsageString()
929 if ( m_data
->m_arguments
.empty() )
932 appname
= wxTheApp
->GetAppName();
936 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
939 // we construct the brief cmd line desc on the fly, but not the detailed
940 // help message below because we want to align the options descriptions
941 // and for this we must first know the longest one of them
943 wxArrayString namesOptions
, descOptions
;
945 if ( !m_data
->m_logo
.empty() )
947 usage
<< m_data
->m_logo
<< _T('\n');
950 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
952 // the switch char is usually '-' but this can be changed with
953 // SetSwitchChars() and then the first one of possible chars is used
954 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
955 : m_data
->m_switchChars
[0u];
957 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
958 size_t n
, count
= m_data
->m_options
.GetCount();
959 for ( n
= 0; n
< count
; n
++ )
961 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
964 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
969 if ( !opt
.shortName
.empty() )
971 usage
<< chSwitch
<< opt
.shortName
;
973 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
975 usage
<< _T("--") << opt
.longName
;
979 if (!opt
.longName
.empty())
981 wxFAIL_MSG( wxT("option with only a long name while long ")
982 wxT("options are disabled") );
986 wxFAIL_MSG( _T("option without neither short nor long name") );
992 if ( !opt
.shortName
.empty() )
994 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
997 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
999 option
<< (option
.empty() ? _T(" ") : _T(", "))
1000 << _T("--") << opt
.longName
;
1003 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1006 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1007 usage
<< _T(' ') << val
;
1008 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1011 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1016 namesOptions
.push_back(option
);
1017 descOptions
.push_back(opt
.description
);
1020 count
= m_data
->m_paramDesc
.GetCount();
1021 for ( n
= 0; n
< count
; n
++ )
1023 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1026 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1031 usage
<< param
.description
;
1033 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1038 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1046 // now construct the detailed help message
1047 size_t len
, lenMax
= 0;
1048 count
= namesOptions
.size();
1049 for ( n
= 0; n
< count
; n
++ )
1051 len
= namesOptions
[n
].length();
1056 for ( n
= 0; n
< count
; n
++ )
1058 len
= namesOptions
[n
].length();
1059 usage
<< namesOptions
[n
]
1060 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1068 // ----------------------------------------------------------------------------
1069 // private functions
1070 // ----------------------------------------------------------------------------
1072 static wxString
GetTypeName(wxCmdLineParamType type
)
1078 wxFAIL_MSG( _T("unknown option type") );
1079 // still fall through
1081 case wxCMD_LINE_VAL_STRING
:
1085 case wxCMD_LINE_VAL_NUMBER
:
1089 case wxCMD_LINE_VAL_DATE
:
1098 Returns a string which is equal to the string pointed to by p, but up to the
1099 point where p contains an character that's not allowed.
1100 Allowable characters are letters and numbers, and characters pointed to by
1101 the parameter allowedChars.
1103 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1104 this function returns "abcde-".
1106 static wxString
GetOptionName(const wxChar
*p
,
1107 const wxChar
*allowedChars
)
1111 while ( *p
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1119 // Besides alphanumeric characters, short and long options can
1120 // have other characters.
1122 // A short option additionally can have these
1123 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1125 // A long option can have the same characters as a short option and a '-'.
1126 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1127 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1129 static wxString
GetShortOptionName(const wxChar
*p
)
1131 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1134 static wxString
GetLongOptionName(const wxChar
*p
)
1136 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1139 #endif // wxUSE_CMDLINE_PARSER
1141 // ----------------------------------------------------------------------------
1143 // ----------------------------------------------------------------------------
1146 This function is mainly used under Windows (as under Unix we always get the
1147 command line arguments as argc/argv anyhow) and so it tries to follow
1148 Windows conventions for the command line handling, not Unix ones. For
1149 instance, backslash is not special except when it precedes double quote when
1154 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxChar
*p
)
1161 bool isInsideQuotes
= false;
1165 while ( *p
== _T(' ') || *p
== _T('\t') )
1169 if ( *p
== _T('\0') )
1172 // parse this parameter
1173 bool endParam
= false;
1174 bool lastBS
= false;
1175 for ( arg
.clear(); !endParam
; p
++ )
1182 isInsideQuotes
= !isInsideQuotes
;
1184 // don't put quote in arg
1187 //else: quote has no special meaning but the backslash
1188 // still remains -- makes no sense but this is what
1194 // backslash does *not* quote the space, only quotes do
1195 if ( isInsideQuotes
)
1197 // skip assignment below
1213 lastBS
= *p
== _T('\\');
1218 args
.push_back(arg
);