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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "cmdline.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
31 #include "wx/cmdline.h"
33 #if wxUSE_CMDLINE_PARSER
36 #include "wx/string.h"
40 #include "wx/dynarray.h"
41 #include "wx/filefn.h"
46 #include "wx/datetime.h"
47 #include "wx/msgout.h"
49 // ----------------------------------------------------------------------------
51 // ----------------------------------------------------------------------------
53 static wxString
GetTypeName(wxCmdLineParamType type
);
55 static wxString
GetOptionName(const wxChar
*p
, const wxChar
*allowedChars
);
57 static wxString
GetShortOptionName(const wxChar
*p
);
59 static wxString
GetLongOptionName(const wxChar
*p
);
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
65 // an internal representation of an option
66 struct wxCmdLineOption
68 wxCmdLineOption(wxCmdLineEntryType k
,
72 wxCmdLineParamType typ
,
75 wxASSERT_MSG( !shrt
.empty() || !lng
.empty(),
76 _T("option should have at least one name") );
80 GetShortOptionName(shrt
).Len() == shrt
.Len(),
81 wxT("Short option contains invalid characters")
86 GetLongOptionName(lng
).Len() == lng
.Len(),
87 wxT("Long option contains invalid characters")
103 // can't use union easily here, so just store all possible data fields, we
104 // don't waste much (might still use union later if the number of supported
105 // types increases, so always use the accessor functions and don't access
106 // the fields directly!)
108 void Check(wxCmdLineParamType
WXUNUSED_UNLESS_DEBUG(typ
)) const
110 wxASSERT_MSG( type
== typ
, _T("type mismatch in wxCmdLineOption") );
113 long GetLongVal() const
114 { Check(wxCMD_LINE_VAL_NUMBER
); return m_longVal
; }
115 const wxString
& GetStrVal() const
116 { Check(wxCMD_LINE_VAL_STRING
); return m_strVal
; }
118 const wxDateTime
& GetDateVal() const
119 { Check(wxCMD_LINE_VAL_DATE
); return m_dateVal
; }
120 #endif // wxUSE_DATETIME
122 void SetLongVal(long val
)
123 { Check(wxCMD_LINE_VAL_NUMBER
); m_longVal
= val
; m_hasVal
= true; }
124 void SetStrVal(const wxString
& val
)
125 { Check(wxCMD_LINE_VAL_STRING
); m_strVal
= val
; m_hasVal
= true; }
127 void SetDateVal(const wxDateTime val
)
128 { Check(wxCMD_LINE_VAL_DATE
); m_dateVal
= val
; m_hasVal
= true; }
129 #endif // wxUSE_DATETIME
131 void SetHasValue(bool hasValue
= true) { m_hasVal
= hasValue
; }
132 bool HasValue() const { return m_hasVal
; }
135 wxCmdLineEntryType kind
;
139 wxCmdLineParamType type
;
148 wxDateTime m_dateVal
;
149 #endif // wxUSE_DATETIME
152 struct wxCmdLineParam
154 wxCmdLineParam(const wxString
& desc
,
155 wxCmdLineParamType typ
,
163 wxString description
;
164 wxCmdLineParamType type
;
168 WX_DECLARE_OBJARRAY(wxCmdLineOption
, wxArrayOptions
);
169 WX_DECLARE_OBJARRAY(wxCmdLineParam
, wxArrayParams
);
171 #include "wx/arrimpl.cpp"
173 WX_DEFINE_OBJARRAY(wxArrayOptions
);
174 WX_DEFINE_OBJARRAY(wxArrayParams
);
176 // the parser internal state
177 struct wxCmdLineParserData
180 wxString m_switchChars
; // characters which may start an option
181 bool m_enableLongOptions
; // true if long options are enabled
182 wxString m_logo
; // some extra text to show in Usage()
185 wxArrayString m_arguments
; // == argv, argc == m_arguments.GetCount()
186 wxArrayOptions m_options
; // all possible options and switchrs
187 wxArrayParams m_paramDesc
; // description of all possible params
188 wxArrayString m_parameters
; // all params found
191 wxCmdLineParserData();
192 void SetArguments(int argc
, wxChar
**argv
);
193 void SetArguments(const wxString
& cmdline
);
195 int FindOption(const wxString
& name
);
196 int FindOptionByLongName(const wxString
& name
);
199 // ============================================================================
201 // ============================================================================
203 // ----------------------------------------------------------------------------
204 // wxCmdLineParserData
205 // ----------------------------------------------------------------------------
207 wxCmdLineParserData::wxCmdLineParserData()
209 m_enableLongOptions
= true;
211 m_switchChars
= _T("-");
213 m_switchChars
= _T("/-");
217 void wxCmdLineParserData::SetArguments(int argc
, wxChar
**argv
)
221 for ( int n
= 0; n
< argc
; n
++ )
223 m_arguments
.push_back(argv
[n
]);
227 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
)
231 m_arguments
.push_back(wxTheApp
->GetAppName());
233 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
235 WX_APPEND_ARRAY(m_arguments
, args
);
238 int wxCmdLineParserData::FindOption(const wxString
& name
)
242 size_t count
= m_options
.GetCount();
243 for ( size_t n
= 0; n
< count
; n
++ )
245 if ( m_options
[n
].shortName
== name
)
256 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
258 size_t count
= m_options
.GetCount();
259 for ( size_t n
= 0; n
< count
; n
++ )
261 if ( m_options
[n
].longName
== name
)
271 // ----------------------------------------------------------------------------
272 // construction and destruction
273 // ----------------------------------------------------------------------------
275 void wxCmdLineParser::Init()
277 m_data
= new wxCmdLineParserData
;
280 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
282 m_data
->SetArguments(argc
, argv
);
285 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
287 m_data
->SetArguments(cmdline
);
290 wxCmdLineParser::~wxCmdLineParser()
295 // ----------------------------------------------------------------------------
297 // ----------------------------------------------------------------------------
299 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
301 m_data
->m_switchChars
= switchChars
;
304 void wxCmdLineParser::EnableLongOptions(bool enable
)
306 m_data
->m_enableLongOptions
= enable
;
309 bool wxCmdLineParser::AreLongOptionsEnabled()
311 return m_data
->m_enableLongOptions
;
314 void wxCmdLineParser::SetLogo(const wxString
& logo
)
316 m_data
->m_logo
= logo
;
319 // ----------------------------------------------------------------------------
320 // command line construction
321 // ----------------------------------------------------------------------------
323 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
327 switch ( desc
->kind
)
329 case wxCMD_LINE_SWITCH
:
330 AddSwitch(desc
->shortName
, desc
->longName
, desc
->description
,
334 case wxCMD_LINE_OPTION
:
335 AddOption(desc
->shortName
, desc
->longName
, desc
->description
,
336 desc
->type
, desc
->flags
);
339 case wxCMD_LINE_PARAM
:
340 AddParam(desc
->description
, desc
->type
, desc
->flags
);
344 wxFAIL_MSG( _T("unknown command line entry type") );
345 // still fall through
347 case wxCMD_LINE_NONE
:
353 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
354 const wxString
& longName
,
355 const wxString
& desc
,
358 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
359 _T("duplicate switch") );
361 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
362 shortName
, longName
, desc
,
363 wxCMD_LINE_VAL_NONE
, flags
);
365 m_data
->m_options
.Add(option
);
368 void wxCmdLineParser::AddOption(const wxString
& shortName
,
369 const wxString
& longName
,
370 const wxString
& desc
,
371 wxCmdLineParamType type
,
374 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
375 _T("duplicate option") );
377 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
378 shortName
, longName
, desc
,
381 m_data
->m_options
.Add(option
);
384 void wxCmdLineParser::AddParam(const wxString
& desc
,
385 wxCmdLineParamType type
,
388 // do some consistency checks: a required parameter can't follow an
389 // optional one and nothing should follow a parameter with MULTIPLE flag
391 if ( !m_data
->m_paramDesc
.IsEmpty() )
393 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
395 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
396 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
398 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
400 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
401 _T("a required parameter can't follow an optional one") );
406 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
408 m_data
->m_paramDesc
.Add(param
);
411 // ----------------------------------------------------------------------------
412 // access to parse command line
413 // ----------------------------------------------------------------------------
415 bool wxCmdLineParser::Found(const wxString
& name
) const
417 int i
= m_data
->FindOption(name
);
418 if ( i
== wxNOT_FOUND
)
419 i
= m_data
->FindOptionByLongName(name
);
421 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown switch") );
423 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
424 if ( !opt
.HasValue() )
430 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
432 int i
= m_data
->FindOption(name
);
433 if ( i
== wxNOT_FOUND
)
434 i
= m_data
->FindOptionByLongName(name
);
436 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
438 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
439 if ( !opt
.HasValue() )
442 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
444 *value
= opt
.GetStrVal();
449 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
451 int i
= m_data
->FindOption(name
);
452 if ( i
== wxNOT_FOUND
)
453 i
= m_data
->FindOptionByLongName(name
);
455 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
457 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
458 if ( !opt
.HasValue() )
461 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
463 *value
= opt
.GetLongVal();
469 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
471 int i
= m_data
->FindOption(name
);
472 if ( i
== wxNOT_FOUND
)
473 i
= m_data
->FindOptionByLongName(name
);
475 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
477 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
478 if ( !opt
.HasValue() )
481 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
483 *value
= opt
.GetDateVal();
487 #endif // wxUSE_DATETIME
489 size_t wxCmdLineParser::GetParamCount() const
491 return m_data
->m_parameters
.size();
494 wxString
wxCmdLineParser::GetParam(size_t n
) const
496 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, _T("invalid param index") );
498 return m_data
->m_parameters
[n
];
501 // Resets switches and options
502 void wxCmdLineParser::Reset()
504 for ( size_t i
= 0; i
< m_data
->m_options
.Count(); i
++ )
506 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
507 opt
.SetHasValue(false);
512 // ----------------------------------------------------------------------------
513 // the real work is done here
514 // ----------------------------------------------------------------------------
516 int wxCmdLineParser::Parse(bool showUsage
)
518 bool maybeOption
= true; // can the following arg be an option?
519 bool ok
= true; // true until an error is detected
520 bool helpRequested
= false; // true if "-h" was given
521 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
523 size_t currentParam
= 0; // the index in m_paramDesc
525 size_t countParam
= m_data
->m_paramDesc
.GetCount();
532 size_t count
= m_data
->m_arguments
.size();
533 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
535 arg
= m_data
->m_arguments
[n
];
537 // special case: "--" should be discarded and all following arguments
538 // should be considered as parameters, even if they start with '-' and
539 // not like options (this is POSIX-like)
540 if ( arg
== _T("--") )
547 // empty argument or just '-' is not an option but a parameter
548 if ( maybeOption
&& arg
.length() > 1 &&
549 wxStrchr(m_data
->m_switchChars
, arg
[0u]) )
553 int optInd
= wxNOT_FOUND
; // init to suppress warnings
555 // an option or a switch: find whether it's a long or a short one
556 if ( arg
[0u] == _T('-') && arg
[1u] == _T('-') )
562 const wxChar
*p
= arg
.c_str() + 2;
564 bool longOptionsEnabled
= AreLongOptionsEnabled();
566 name
= GetLongOptionName(p
);
568 if (longOptionsEnabled
)
570 optInd
= m_data
->FindOptionByLongName(name
);
571 if ( optInd
== wxNOT_FOUND
)
573 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str()) << wxT("\n");
578 optInd
= wxNOT_FOUND
; // Sanity check
580 // Print the argument including leading "--"
581 name
.Prepend( wxT("--") );
582 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n");
590 // a short one: as they can be cumulated, we try to find the
591 // longest substring which is a valid option
592 const wxChar
*p
= arg
.c_str() + 1;
594 name
= GetShortOptionName(p
);
596 size_t len
= name
.length();
601 // we couldn't find a valid option name in the
602 // beginning of this string
603 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n");
609 optInd
= m_data
->FindOption(name
.Left(len
));
611 // will try with one character less the next time
615 while ( optInd
== wxNOT_FOUND
);
617 len
++; // compensates extra len-- above
618 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
620 // first of all, the option name is only part of this
622 name
= name
.Left(len
);
624 // our option is only part of this argument, there is
625 // something else in it - it is either the value of this
626 // option or other switches if it is a switch
627 if ( m_data
->m_options
[(size_t)optInd
].kind
628 == wxCMD_LINE_SWITCH
)
630 // pretend that all the rest of the argument is the
631 // next argument, in fact
632 wxString arg2
= arg
[0u];
633 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
635 m_data
->m_arguments
.insert
636 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
639 //else: it's our value, we'll deal with it below
643 if ( optInd
== wxNOT_FOUND
)
647 continue; // will break, in fact
650 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
651 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
653 // nothing more to do
656 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
658 helpRequested
= true;
660 // it's not an error, but we still stop here
668 // +1 for leading '-'
669 const wxChar
*p
= arg
.c_str() + 1 + name
.length();
672 p
++; // for another leading '-'
674 if ( *p
++ != _T('=') )
676 errorMsg
<< wxString::Format(_("Option '%s' requires a value, '=' expected."), name
.c_str()) << wxT("\n");
692 // the value is in the next argument
695 // ... but there is none
696 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
697 name
.c_str()) << wxT("\n");
703 // ... take it from there
704 p
= m_data
->m_arguments
[n
].c_str();
709 // the value is right here: this may be legal or
710 // not depending on the option style
711 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
713 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
714 name
.c_str()) << wxT("\n");
727 wxFAIL_MSG( _T("unknown option type") );
728 // still fall through
730 case wxCMD_LINE_VAL_STRING
:
731 opt
.SetStrVal(value
);
734 case wxCMD_LINE_VAL_NUMBER
:
737 if ( value
.ToLong(&val
) )
743 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
744 value
.c_str(), name
.c_str()) << wxT("\n");
752 case wxCMD_LINE_VAL_DATE
:
755 const wxChar
*res
= dt
.ParseDate(value
);
758 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
759 name
.c_str(), value
.c_str()) << wxT("\n");
769 #endif // wxUSE_DATETIME
777 if ( currentParam
< countParam
)
779 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
781 // TODO check the param type
783 m_data
->m_parameters
.push_back(arg
);
785 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
791 wxASSERT_MSG( currentParam
== countParam
- 1,
792 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
794 // remember that we did have this last repeatable parameter
795 hadRepeatableParam
= true;
800 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str()) << wxT("\n");
807 // verify that all mandatory options were given
810 size_t countOpt
= m_data
->m_options
.GetCount();
811 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
813 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
814 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
819 optName
= opt
.shortName
;
823 if ( AreLongOptionsEnabled() )
825 optName
.Printf( _("%s (or %s)"),
826 opt
.shortName
.c_str(),
827 opt
.longName
.c_str() );
831 optName
.Printf( wxT("%s"),
832 opt
.shortName
.c_str() );
836 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
837 optName
.c_str()) << wxT("\n");
843 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
845 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
846 if ( (currentParam
== countParam
- 1) &&
847 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
850 // special case: currentParam wasn't incremented, but we did
851 // have it, so don't give error
855 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
857 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
858 param
.description
.c_str()) << wxT("\n");
865 // if there was an error during parsing the command line, show this error
866 // and also the usage message if it had been requested
867 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
869 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
874 usage
= GetUsageString();
876 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
880 wxFAIL_MSG( _T("no wxMessageOutput object?") );
884 return ok
? 0 : helpRequested
? -1 : 1;
887 // ----------------------------------------------------------------------------
888 // give the usage message
889 // ----------------------------------------------------------------------------
891 void wxCmdLineParser::Usage()
893 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
896 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
900 wxFAIL_MSG( _T("no wxMessageOutput object?") );
904 wxString
wxCmdLineParser::GetUsageString()
906 wxString appname
= wxTheApp
->GetAppName();
909 wxCHECK_MSG( m_data
->m_arguments
.size() != 0, wxEmptyString
,
910 _T("no program name") );
912 appname
= wxFileNameFromPath(m_data
->m_arguments
[0]);
913 wxStripExtension(appname
);
916 // we construct the brief cmd line desc on the fly, but not the detailed
917 // help message below because we want to align the options descriptions
918 // and for this we must first know the longest one of them
920 wxArrayString namesOptions
, descOptions
;
922 if ( !m_data
->m_logo
.empty() )
924 usage
<< m_data
->m_logo
<< _T('\n');
927 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
929 // the switch char is usually '-' but this can be changed with
930 // SetSwitchChars() and then the first one of possible chars is used
931 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
932 : m_data
->m_switchChars
[0u];
934 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
935 size_t n
, count
= m_data
->m_options
.GetCount();
936 for ( n
= 0; n
< count
; n
++ )
938 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
941 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
946 if ( !opt
.shortName
.empty() )
948 usage
<< chSwitch
<< opt
.shortName
;
950 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
952 usage
<< _T("--") << opt
.longName
;
956 if (!opt
.longName
.empty())
958 wxFAIL_MSG( wxT("option with only a long name while long ")
959 wxT("options are disabled") );
963 wxFAIL_MSG( _T("option without neither short nor long name") );
969 if ( !opt
.shortName
.empty() )
971 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
974 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
976 option
<< (option
.empty() ? _T(" ") : _T(", "))
977 << _T("--") << opt
.longName
;
980 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
983 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
984 usage
<< _T(' ') << val
;
985 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
988 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
993 namesOptions
.push_back(option
);
994 descOptions
.push_back(opt
.description
);
997 count
= m_data
->m_paramDesc
.GetCount();
998 for ( n
= 0; n
< count
; n
++ )
1000 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1003 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1008 usage
<< param
.description
;
1010 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1015 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1023 // now construct the detailed help message
1024 size_t len
, lenMax
= 0;
1025 count
= namesOptions
.size();
1026 for ( n
= 0; n
< count
; n
++ )
1028 len
= namesOptions
[n
].length();
1033 for ( n
= 0; n
< count
; n
++ )
1035 len
= namesOptions
[n
].length();
1036 usage
<< namesOptions
[n
]
1037 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1045 // ----------------------------------------------------------------------------
1046 // private functions
1047 // ----------------------------------------------------------------------------
1049 static wxString
GetTypeName(wxCmdLineParamType type
)
1055 wxFAIL_MSG( _T("unknown option type") );
1056 // still fall through
1058 case wxCMD_LINE_VAL_STRING
:
1062 case wxCMD_LINE_VAL_NUMBER
:
1066 case wxCMD_LINE_VAL_DATE
:
1075 Returns a string which is equal to the string pointed to by p, but up to the
1076 point where p contains an character that's not allowed.
1077 Allowable characters are letters and numbers, and characters pointed to by
1078 the parameter allowedChars.
1080 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1081 this function returns "abcde-".
1083 static wxString
GetOptionName(const wxChar
*p
,
1084 const wxChar
*allowedChars
)
1088 while ( *p
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1096 // Besides alphanumeric characters, short and long options can
1097 // have other characters.
1099 // A short option additionally can have these
1100 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1102 // A long option can have the same characters as a short option and a '-'.
1103 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1104 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1106 static wxString
GetShortOptionName(const wxChar
*p
)
1108 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1111 static wxString
GetLongOptionName(const wxChar
*p
)
1113 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1116 #endif // wxUSE_CMDLINE_PARSER
1118 // ----------------------------------------------------------------------------
1120 // ----------------------------------------------------------------------------
1123 This function is mainly used under Windows (as under Unix we always get the
1124 command line arguments as argc/argv anyhow) and so it tries to follow
1125 Windows conventions for the command line handling, not Unix ones. For
1126 instance, backslash is not special except when it precedes double quote when
1131 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxChar
*p
)
1138 bool isInsideQuotes
= false;
1142 while ( *p
== _T(' ') || *p
== _T('\t') )
1146 if ( *p
== _T('\0') )
1149 // parse this parameter
1150 bool endParam
= false;
1151 bool lastBS
= false;
1152 for ( arg
.clear(); !endParam
; p
++ )
1159 isInsideQuotes
= !isInsideQuotes
;
1161 // don't put quote in arg
1164 //else: quote has no special meaning but the backslash
1165 // still remains -- makes no sense but this is what
1171 // backslash does *not* quote the space, only quotes do
1172 if ( isInsideQuotes
)
1174 // skip assignment below
1190 lastBS
= *p
== _T('\\');
1195 args
.push_back(arg
);