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 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()) << wxT("\n");
603 optInd
= wxNOT_FOUND
; // Sanity check
605 // Print the argument including leading "--"
606 name
.Prepend( wxT("--") );
607 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n");
615 // a short one: as they can be cumulated, we try to find the
616 // longest substring which is a valid option
617 const wxChar
*p
= arg
.c_str() + 1;
619 name
= GetShortOptionName(p
);
621 size_t len
= name
.length();
626 // we couldn't find a valid option name in the
627 // beginning of this string
628 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n");
634 optInd
= m_data
->FindOption(name
.Left(len
));
636 // will try with one character less the next time
640 while ( optInd
== wxNOT_FOUND
);
642 len
++; // compensates extra len-- above
643 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
645 // first of all, the option name is only part of this
647 name
= name
.Left(len
);
649 // our option is only part of this argument, there is
650 // something else in it - it is either the value of this
651 // option or other switches if it is a switch
652 if ( m_data
->m_options
[(size_t)optInd
].kind
653 == wxCMD_LINE_SWITCH
)
655 // pretend that all the rest of the argument is the
656 // next argument, in fact
657 wxString arg2
= arg
[0u];
658 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
660 m_data
->m_arguments
.insert
661 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
664 //else: it's our value, we'll deal with it below
668 if ( optInd
== wxNOT_FOUND
)
672 continue; // will break, in fact
675 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
676 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
678 // nothing more to do
681 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
683 helpRequested
= true;
685 // it's not an error, but we still stop here
693 // +1 for leading '-'
694 const wxChar
*p
= arg
.c_str() + 1 + name
.length();
697 p
++; // for another leading '-'
699 if ( *p
++ != _T('=') )
701 errorMsg
<< wxString::Format(_("Option '%s' requires a value, '=' expected."), name
.c_str()) << wxT("\n");
717 // the value is in the next argument
720 // ... but there is none
721 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
722 name
.c_str()) << wxT("\n");
728 // ... take it from there
729 p
= m_data
->m_arguments
[n
].c_str();
734 // the value is right here: this may be legal or
735 // not depending on the option style
736 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
738 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
739 name
.c_str()) << wxT("\n");
752 wxFAIL_MSG( _T("unknown option type") );
753 // still fall through
755 case wxCMD_LINE_VAL_STRING
:
756 opt
.SetStrVal(value
);
759 case wxCMD_LINE_VAL_NUMBER
:
762 if ( value
.ToLong(&val
) )
768 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
769 value
.c_str(), name
.c_str()) << wxT("\n");
777 case wxCMD_LINE_VAL_DATE
:
780 const wxChar
*res
= dt
.ParseDate(value
);
783 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
784 name
.c_str(), value
.c_str()) << wxT("\n");
794 #endif // wxUSE_DATETIME
802 if ( currentParam
< countParam
)
804 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
806 // TODO check the param type
808 m_data
->m_parameters
.push_back(arg
);
810 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
816 wxASSERT_MSG( currentParam
== countParam
- 1,
817 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
819 // remember that we did have this last repeatable parameter
820 hadRepeatableParam
= true;
825 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str()) << wxT("\n");
832 // verify that all mandatory options were given
835 size_t countOpt
= m_data
->m_options
.GetCount();
836 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
838 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
839 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
844 optName
= opt
.shortName
;
848 if ( AreLongOptionsEnabled() )
850 optName
.Printf( _("%s (or %s)"),
851 opt
.shortName
.c_str(),
852 opt
.longName
.c_str() );
856 optName
.Printf( wxT("%s"),
857 opt
.shortName
.c_str() );
861 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
862 optName
.c_str()) << wxT("\n");
868 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
870 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
871 if ( (currentParam
== countParam
- 1) &&
872 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
875 // special case: currentParam wasn't incremented, but we did
876 // have it, so don't give error
880 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
882 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
883 param
.description
.c_str()) << wxT("\n");
890 // if there was an error during parsing the command line, show this error
891 // and also the usage message if it had been requested
892 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
894 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
899 usage
= GetUsageString();
901 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
905 wxFAIL_MSG( _T("no wxMessageOutput object?") );
909 return ok
? 0 : helpRequested
? -1 : 1;
912 // ----------------------------------------------------------------------------
913 // give the usage message
914 // ----------------------------------------------------------------------------
916 void wxCmdLineParser::Usage()
918 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
921 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
925 wxFAIL_MSG( _T("no wxMessageOutput object?") );
929 wxString
wxCmdLineParser::GetUsageString()
932 if ( m_data
->m_arguments
.empty() )
935 appname
= wxTheApp
->GetAppName();
939 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
942 // we construct the brief cmd line desc on the fly, but not the detailed
943 // help message below because we want to align the options descriptions
944 // and for this we must first know the longest one of them
946 wxArrayString namesOptions
, descOptions
;
948 if ( !m_data
->m_logo
.empty() )
950 usage
<< m_data
->m_logo
<< _T('\n');
953 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
955 // the switch char is usually '-' but this can be changed with
956 // SetSwitchChars() and then the first one of possible chars is used
957 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
958 : m_data
->m_switchChars
[0u];
960 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
961 size_t n
, count
= m_data
->m_options
.GetCount();
962 for ( n
= 0; n
< count
; n
++ )
964 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
967 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
972 if ( !opt
.shortName
.empty() )
974 usage
<< chSwitch
<< opt
.shortName
;
976 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
978 usage
<< _T("--") << opt
.longName
;
982 if (!opt
.longName
.empty())
984 wxFAIL_MSG( wxT("option with only a long name while long ")
985 wxT("options are disabled") );
989 wxFAIL_MSG( _T("option without neither short nor long name") );
995 if ( !opt
.shortName
.empty() )
997 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
1000 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1002 option
<< (option
.empty() ? _T(" ") : _T(", "))
1003 << _T("--") << opt
.longName
;
1006 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1009 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1010 usage
<< _T(' ') << val
;
1011 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1014 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1019 namesOptions
.push_back(option
);
1020 descOptions
.push_back(opt
.description
);
1023 count
= m_data
->m_paramDesc
.GetCount();
1024 for ( n
= 0; n
< count
; n
++ )
1026 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1029 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1034 usage
<< param
.description
;
1036 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1041 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1049 // now construct the detailed help message
1050 size_t len
, lenMax
= 0;
1051 count
= namesOptions
.size();
1052 for ( n
= 0; n
< count
; n
++ )
1054 len
= namesOptions
[n
].length();
1059 for ( n
= 0; n
< count
; n
++ )
1061 len
= namesOptions
[n
].length();
1062 usage
<< namesOptions
[n
]
1063 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1071 // ----------------------------------------------------------------------------
1072 // private functions
1073 // ----------------------------------------------------------------------------
1075 static wxString
GetTypeName(wxCmdLineParamType type
)
1081 wxFAIL_MSG( _T("unknown option type") );
1082 // still fall through
1084 case wxCMD_LINE_VAL_STRING
:
1088 case wxCMD_LINE_VAL_NUMBER
:
1092 case wxCMD_LINE_VAL_DATE
:
1101 Returns a string which is equal to the string pointed to by p, but up to the
1102 point where p contains an character that's not allowed.
1103 Allowable characters are letters and numbers, and characters pointed to by
1104 the parameter allowedChars.
1106 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1107 this function returns "abcde-".
1109 static wxString
GetOptionName(const wxChar
*p
,
1110 const wxChar
*allowedChars
)
1114 while ( *p
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1122 // Besides alphanumeric characters, short and long options can
1123 // have other characters.
1125 // A short option additionally can have these
1126 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1128 // A long option can have the same characters as a short option and a '-'.
1129 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1130 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1132 static wxString
GetShortOptionName(const wxChar
*p
)
1134 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1137 static wxString
GetLongOptionName(const wxChar
*p
)
1139 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1142 #endif // wxUSE_CMDLINE_PARSER
1144 // ----------------------------------------------------------------------------
1146 // ----------------------------------------------------------------------------
1149 This function is mainly used under Windows (as under Unix we always get the
1150 command line arguments as argc/argv anyhow) and so it tries to follow
1151 Windows conventions for the command line handling, not Unix ones. For
1152 instance, backslash is not special except when it precedes double quote when
1157 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxChar
*p
)
1164 bool isInsideQuotes
= false;
1168 while ( *p
== _T(' ') || *p
== _T('\t') )
1172 if ( *p
== _T('\0') )
1175 // parse this parameter
1176 bool endParam
= false;
1177 bool lastBS
= false;
1178 for ( arg
.clear(); !endParam
; p
++ )
1185 isInsideQuotes
= !isInsideQuotes
;
1187 // don't put quote in arg
1190 //else: quote has no special meaning but the backslash
1191 // still remains -- makes no sense but this is what
1197 // backslash does *not* quote the space, only quotes do
1198 if ( isInsideQuotes
)
1200 // skip assignment below
1216 lastBS
= *p
== _T('\\');
1221 args
.push_back(arg
);