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(
245 (wxTheApp
&& wxTheApp
->argc
> 0) ? wxTheApp
->argv
[0] : wxEmptyString
);
247 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
249 WX_APPEND_ARRAY(m_arguments
, args
);
252 int wxCmdLineParserData::FindOption(const wxString
& name
)
256 size_t count
= m_options
.GetCount();
257 for ( size_t n
= 0; n
< count
; n
++ )
259 if ( m_options
[n
].shortName
== name
)
270 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
272 size_t count
= m_options
.GetCount();
273 for ( size_t n
= 0; n
< count
; n
++ )
275 if ( m_options
[n
].longName
== name
)
285 // ----------------------------------------------------------------------------
286 // construction and destruction
287 // ----------------------------------------------------------------------------
289 void wxCmdLineParser::Init()
291 m_data
= new wxCmdLineParserData
;
294 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
296 m_data
->SetArguments(argc
, argv
);
301 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
303 m_data
->SetArguments(argc
, argv
);
306 #endif // wxUSE_UNICODE
308 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
310 m_data
->SetArguments(cmdline
);
313 wxCmdLineParser::~wxCmdLineParser()
318 // ----------------------------------------------------------------------------
320 // ----------------------------------------------------------------------------
322 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
324 m_data
->m_switchChars
= switchChars
;
327 void wxCmdLineParser::EnableLongOptions(bool enable
)
329 m_data
->m_enableLongOptions
= enable
;
332 bool wxCmdLineParser::AreLongOptionsEnabled()
334 return m_data
->m_enableLongOptions
;
337 void wxCmdLineParser::SetLogo(const wxString
& logo
)
339 m_data
->m_logo
= logo
;
342 // ----------------------------------------------------------------------------
343 // command line construction
344 // ----------------------------------------------------------------------------
346 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
350 switch ( desc
->kind
)
352 case wxCMD_LINE_SWITCH
:
353 AddSwitch(desc
->shortName
, desc
->longName
, desc
->description
,
357 case wxCMD_LINE_OPTION
:
358 AddOption(desc
->shortName
, desc
->longName
, desc
->description
,
359 desc
->type
, desc
->flags
);
362 case wxCMD_LINE_PARAM
:
363 AddParam(desc
->description
, desc
->type
, desc
->flags
);
367 wxFAIL_MSG( _T("unknown command line entry type") );
368 // still fall through
370 case wxCMD_LINE_NONE
:
376 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
377 const wxString
& longName
,
378 const wxString
& desc
,
381 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
382 _T("duplicate switch") );
384 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
385 shortName
, longName
, desc
,
386 wxCMD_LINE_VAL_NONE
, flags
);
388 m_data
->m_options
.Add(option
);
391 void wxCmdLineParser::AddOption(const wxString
& shortName
,
392 const wxString
& longName
,
393 const wxString
& desc
,
394 wxCmdLineParamType type
,
397 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
398 _T("duplicate option") );
400 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
401 shortName
, longName
, desc
,
404 m_data
->m_options
.Add(option
);
407 void wxCmdLineParser::AddParam(const wxString
& desc
,
408 wxCmdLineParamType type
,
411 // do some consistency checks: a required parameter can't follow an
412 // optional one and nothing should follow a parameter with MULTIPLE flag
414 if ( !m_data
->m_paramDesc
.IsEmpty() )
416 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
418 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
419 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
421 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
423 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
424 _T("a required parameter can't follow an optional one") );
429 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
431 m_data
->m_paramDesc
.Add(param
);
434 // ----------------------------------------------------------------------------
435 // access to parse command line
436 // ----------------------------------------------------------------------------
438 bool wxCmdLineParser::Found(const wxString
& name
) const
440 int i
= m_data
->FindOption(name
);
441 if ( i
== wxNOT_FOUND
)
442 i
= m_data
->FindOptionByLongName(name
);
444 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown switch") );
446 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
447 if ( !opt
.HasValue() )
453 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
455 int i
= m_data
->FindOption(name
);
456 if ( i
== wxNOT_FOUND
)
457 i
= m_data
->FindOptionByLongName(name
);
459 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
461 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
462 if ( !opt
.HasValue() )
465 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
467 *value
= opt
.GetStrVal();
472 bool wxCmdLineParser::Found(const wxString
& name
, long *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
.GetLongVal();
492 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
494 int i
= m_data
->FindOption(name
);
495 if ( i
== wxNOT_FOUND
)
496 i
= m_data
->FindOptionByLongName(name
);
498 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
500 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
501 if ( !opt
.HasValue() )
504 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
506 *value
= opt
.GetDateVal();
510 #endif // wxUSE_DATETIME
512 size_t wxCmdLineParser::GetParamCount() const
514 return m_data
->m_parameters
.size();
517 wxString
wxCmdLineParser::GetParam(size_t n
) const
519 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, _T("invalid param index") );
521 return m_data
->m_parameters
[n
];
524 // Resets switches and options
525 void wxCmdLineParser::Reset()
527 for ( size_t i
= 0; i
< m_data
->m_options
.Count(); i
++ )
529 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
530 opt
.SetHasValue(false);
535 // ----------------------------------------------------------------------------
536 // the real work is done here
537 // ----------------------------------------------------------------------------
539 int wxCmdLineParser::Parse(bool showUsage
)
541 bool maybeOption
= true; // can the following arg be an option?
542 bool ok
= true; // true until an error is detected
543 bool helpRequested
= false; // true if "-h" was given
544 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
546 size_t currentParam
= 0; // the index in m_paramDesc
548 size_t countParam
= m_data
->m_paramDesc
.GetCount();
555 size_t count
= m_data
->m_arguments
.size();
556 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
558 arg
= m_data
->m_arguments
[n
];
560 // special case: "--" should be discarded and all following arguments
561 // should be considered as parameters, even if they start with '-' and
562 // not like options (this is POSIX-like)
563 if ( arg
== _T("--") )
570 // empty argument or just '-' is not an option but a parameter
571 if ( maybeOption
&& arg
.length() > 1 &&
572 wxStrchr(m_data
->m_switchChars
, arg
[0u]) )
576 int optInd
= wxNOT_FOUND
; // init to suppress warnings
578 // an option or a switch: find whether it's a long or a short one
579 if ( arg
[0u] == _T('-') && arg
[1u] == _T('-') )
585 const wxChar
*p
= arg
.c_str() + 2;
587 bool longOptionsEnabled
= AreLongOptionsEnabled();
589 name
= GetLongOptionName(p
);
591 if (longOptionsEnabled
)
593 optInd
= m_data
->FindOptionByLongName(name
);
594 if ( optInd
== wxNOT_FOUND
)
596 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str()) << wxT("\n");
601 optInd
= wxNOT_FOUND
; // Sanity check
603 // Print the argument including leading "--"
604 name
.Prepend( wxT("--") );
605 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n");
613 // a short one: as they can be cumulated, we try to find the
614 // longest substring which is a valid option
615 const wxChar
*p
= arg
.c_str() + 1;
617 name
= GetShortOptionName(p
);
619 size_t len
= name
.length();
624 // we couldn't find a valid option name in the
625 // beginning of this string
626 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n");
632 optInd
= m_data
->FindOption(name
.Left(len
));
634 // will try with one character less the next time
638 while ( optInd
== wxNOT_FOUND
);
640 len
++; // compensates extra len-- above
641 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
643 // first of all, the option name is only part of this
645 name
= name
.Left(len
);
647 // our option is only part of this argument, there is
648 // something else in it - it is either the value of this
649 // option or other switches if it is a switch
650 if ( m_data
->m_options
[(size_t)optInd
].kind
651 == wxCMD_LINE_SWITCH
)
653 // pretend that all the rest of the argument is the
654 // next argument, in fact
655 wxString arg2
= arg
[0u];
656 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
658 m_data
->m_arguments
.insert
659 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
662 //else: it's our value, we'll deal with it below
666 if ( optInd
== wxNOT_FOUND
)
670 continue; // will break, in fact
673 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
674 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
676 // nothing more to do
679 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
681 helpRequested
= true;
683 // it's not an error, but we still stop here
691 // +1 for leading '-'
692 const wxChar
*p
= arg
.c_str() + 1 + name
.length();
695 p
++; // for another leading '-'
697 if ( *p
++ != _T('=') )
699 errorMsg
<< wxString::Format(_("Option '%s' requires a value, '=' expected."), name
.c_str()) << wxT("\n");
715 // the value is in the next argument
718 // ... but there is none
719 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
720 name
.c_str()) << wxT("\n");
726 // ... take it from there
727 p
= m_data
->m_arguments
[n
].c_str();
732 // the value is right here: this may be legal or
733 // not depending on the option style
734 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
736 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
737 name
.c_str()) << wxT("\n");
750 wxFAIL_MSG( _T("unknown option type") );
751 // still fall through
753 case wxCMD_LINE_VAL_STRING
:
754 opt
.SetStrVal(value
);
757 case wxCMD_LINE_VAL_NUMBER
:
760 if ( value
.ToLong(&val
) )
766 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
767 value
.c_str(), name
.c_str()) << wxT("\n");
775 case wxCMD_LINE_VAL_DATE
:
778 const wxChar
*res
= dt
.ParseDate(value
);
781 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
782 name
.c_str(), value
.c_str()) << wxT("\n");
792 #endif // wxUSE_DATETIME
800 if ( currentParam
< countParam
)
802 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
804 // TODO check the param type
806 m_data
->m_parameters
.push_back(arg
);
808 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
814 wxASSERT_MSG( currentParam
== countParam
- 1,
815 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
817 // remember that we did have this last repeatable parameter
818 hadRepeatableParam
= true;
823 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str()) << wxT("\n");
830 // verify that all mandatory options were given
833 size_t countOpt
= m_data
->m_options
.GetCount();
834 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
836 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
837 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
842 optName
= opt
.shortName
;
846 if ( AreLongOptionsEnabled() )
848 optName
.Printf( _("%s (or %s)"),
849 opt
.shortName
.c_str(),
850 opt
.longName
.c_str() );
854 optName
.Printf( wxT("%s"),
855 opt
.shortName
.c_str() );
859 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
860 optName
.c_str()) << wxT("\n");
866 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
868 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
869 if ( (currentParam
== countParam
- 1) &&
870 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
873 // special case: currentParam wasn't incremented, but we did
874 // have it, so don't give error
878 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
880 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
881 param
.description
.c_str()) << wxT("\n");
888 // if there was an error during parsing the command line, show this error
889 // and also the usage message if it had been requested
890 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
892 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
897 usage
= GetUsageString();
899 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
903 wxFAIL_MSG( _T("no wxMessageOutput object?") );
907 return ok
? 0 : helpRequested
? -1 : 1;
910 // ----------------------------------------------------------------------------
911 // give the usage message
912 // ----------------------------------------------------------------------------
914 void wxCmdLineParser::Usage()
916 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
919 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
923 wxFAIL_MSG( _T("no wxMessageOutput object?") );
927 wxString
wxCmdLineParser::GetUsageString()
930 if ( m_data
->m_arguments
.empty() )
933 appname
= wxTheApp
->GetAppName();
937 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
940 // we construct the brief cmd line desc on the fly, but not the detailed
941 // help message below because we want to align the options descriptions
942 // and for this we must first know the longest one of them
944 wxArrayString namesOptions
, descOptions
;
946 if ( !m_data
->m_logo
.empty() )
948 usage
<< m_data
->m_logo
<< _T('\n');
951 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
953 // the switch char is usually '-' but this can be changed with
954 // SetSwitchChars() and then the first one of possible chars is used
955 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
956 : m_data
->m_switchChars
[0u];
958 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
959 size_t n
, count
= m_data
->m_options
.GetCount();
960 for ( n
= 0; n
< count
; n
++ )
962 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
965 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
970 if ( !opt
.shortName
.empty() )
972 usage
<< chSwitch
<< opt
.shortName
;
974 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
976 usage
<< _T("--") << opt
.longName
;
980 if (!opt
.longName
.empty())
982 wxFAIL_MSG( wxT("option with only a long name while long ")
983 wxT("options are disabled") );
987 wxFAIL_MSG( _T("option without neither short nor long name") );
993 if ( !opt
.shortName
.empty() )
995 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
998 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1000 option
<< (option
.empty() ? _T(" ") : _T(", "))
1001 << _T("--") << opt
.longName
;
1004 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1007 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1008 usage
<< _T(' ') << val
;
1009 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1012 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1017 namesOptions
.push_back(option
);
1018 descOptions
.push_back(opt
.description
);
1021 count
= m_data
->m_paramDesc
.GetCount();
1022 for ( n
= 0; n
< count
; n
++ )
1024 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1027 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1032 usage
<< param
.description
;
1034 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1039 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1047 // now construct the detailed help message
1048 size_t len
, lenMax
= 0;
1049 count
= namesOptions
.size();
1050 for ( n
= 0; n
< count
; n
++ )
1052 len
= namesOptions
[n
].length();
1057 for ( n
= 0; n
< count
; n
++ )
1059 len
= namesOptions
[n
].length();
1060 usage
<< namesOptions
[n
]
1061 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1069 // ----------------------------------------------------------------------------
1070 // private functions
1071 // ----------------------------------------------------------------------------
1073 static wxString
GetTypeName(wxCmdLineParamType type
)
1079 wxFAIL_MSG( _T("unknown option type") );
1080 // still fall through
1082 case wxCMD_LINE_VAL_STRING
:
1086 case wxCMD_LINE_VAL_NUMBER
:
1090 case wxCMD_LINE_VAL_DATE
:
1099 Returns a string which is equal to the string pointed to by p, but up to the
1100 point where p contains an character that's not allowed.
1101 Allowable characters are letters and numbers, and characters pointed to by
1102 the parameter allowedChars.
1104 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1105 this function returns "abcde-".
1107 static wxString
GetOptionName(const wxChar
*p
,
1108 const wxChar
*allowedChars
)
1112 while ( *p
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1120 // Besides alphanumeric characters, short and long options can
1121 // have other characters.
1123 // A short option additionally can have these
1124 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1126 // A long option can have the same characters as a short option and a '-'.
1127 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1128 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1130 static wxString
GetShortOptionName(const wxChar
*p
)
1132 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1135 static wxString
GetLongOptionName(const wxChar
*p
)
1137 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1140 #endif // wxUSE_CMDLINE_PARSER
1142 // ----------------------------------------------------------------------------
1144 // ----------------------------------------------------------------------------
1147 This function is mainly used under Windows (as under Unix we always get the
1148 command line arguments as argc/argv anyhow) and so it tries to follow
1149 Windows conventions for the command line handling, not Unix ones. For
1150 instance, backslash is not special except when it precedes double quote when
1155 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxChar
*p
)
1162 bool isInsideQuotes
= false;
1166 while ( *p
== _T(' ') || *p
== _T('\t') )
1170 if ( *p
== _T('\0') )
1173 // parse this parameter
1174 bool endParam
= false;
1175 bool lastBS
= false;
1176 for ( arg
.clear(); !endParam
; p
++ )
1183 isInsideQuotes
= !isInsideQuotes
;
1185 // don't put quote in arg
1188 //else: quote has no special meaning but the backslash
1189 // still remains -- makes no sense but this is what
1195 // backslash does *not* quote the space, only quotes do
1196 if ( isInsideQuotes
)
1198 // skip assignment below
1214 lastBS
= *p
== _T('\\');
1219 args
.push_back(arg
);