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"
45 #include "wx/datetime.h"
46 #include "wx/msgout.h"
47 #include "wx/filename.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
, char **argv
);
194 void SetArguments(int argc
, wxChar
**argv
);
195 #endif // wxUSE_UNICODE
196 void SetArguments(const wxString
& cmdline
);
198 int FindOption(const wxString
& name
);
199 int FindOptionByLongName(const wxString
& name
);
202 // ============================================================================
204 // ============================================================================
206 // ----------------------------------------------------------------------------
207 // wxCmdLineParserData
208 // ----------------------------------------------------------------------------
210 wxCmdLineParserData::wxCmdLineParserData()
212 m_enableLongOptions
= true;
214 m_switchChars
= _T("-");
216 m_switchChars
= _T("/-");
220 void wxCmdLineParserData::SetArguments(int argc
, char **argv
)
224 for ( int n
= 0; n
< argc
; n
++ )
226 m_arguments
.push_back(wxString::FromAscii(argv
[n
]));
232 void wxCmdLineParserData::SetArguments(int argc
, wxChar
**argv
)
236 for ( int n
= 0; n
< argc
; n
++ )
238 m_arguments
.push_back(argv
[n
]);
242 #endif // wxUSE_UNICODE
244 void wxCmdLineParserData::SetArguments(const wxString
& cmdLine
)
248 m_arguments
.push_back(wxTheApp
? wxTheApp
->argv
[0] : _T(""));
250 wxArrayString args
= wxCmdLineParser::ConvertStringToArgs(cmdLine
);
252 WX_APPEND_ARRAY(m_arguments
, args
);
255 int wxCmdLineParserData::FindOption(const wxString
& name
)
259 size_t count
= m_options
.GetCount();
260 for ( size_t n
= 0; n
< count
; n
++ )
262 if ( m_options
[n
].shortName
== name
)
273 int wxCmdLineParserData::FindOptionByLongName(const wxString
& name
)
275 size_t count
= m_options
.GetCount();
276 for ( size_t n
= 0; n
< count
; n
++ )
278 if ( m_options
[n
].longName
== name
)
288 // ----------------------------------------------------------------------------
289 // construction and destruction
290 // ----------------------------------------------------------------------------
292 void wxCmdLineParser::Init()
294 m_data
= new wxCmdLineParserData
;
297 void wxCmdLineParser::SetCmdLine(int argc
, char **argv
)
299 m_data
->SetArguments(argc
, argv
);
304 void wxCmdLineParser::SetCmdLine(int argc
, wxChar
**argv
)
306 m_data
->SetArguments(argc
, argv
);
309 #endif // wxUSE_UNICODE
311 void wxCmdLineParser::SetCmdLine(const wxString
& cmdline
)
313 m_data
->SetArguments(cmdline
);
316 wxCmdLineParser::~wxCmdLineParser()
321 // ----------------------------------------------------------------------------
323 // ----------------------------------------------------------------------------
325 void wxCmdLineParser::SetSwitchChars(const wxString
& switchChars
)
327 m_data
->m_switchChars
= switchChars
;
330 void wxCmdLineParser::EnableLongOptions(bool enable
)
332 m_data
->m_enableLongOptions
= enable
;
335 bool wxCmdLineParser::AreLongOptionsEnabled()
337 return m_data
->m_enableLongOptions
;
340 void wxCmdLineParser::SetLogo(const wxString
& logo
)
342 m_data
->m_logo
= logo
;
345 // ----------------------------------------------------------------------------
346 // command line construction
347 // ----------------------------------------------------------------------------
349 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc
*desc
)
353 switch ( desc
->kind
)
355 case wxCMD_LINE_SWITCH
:
356 AddSwitch(desc
->shortName
, desc
->longName
, desc
->description
,
360 case wxCMD_LINE_OPTION
:
361 AddOption(desc
->shortName
, desc
->longName
, desc
->description
,
362 desc
->type
, desc
->flags
);
365 case wxCMD_LINE_PARAM
:
366 AddParam(desc
->description
, desc
->type
, desc
->flags
);
370 wxFAIL_MSG( _T("unknown command line entry type") );
371 // still fall through
373 case wxCMD_LINE_NONE
:
379 void wxCmdLineParser::AddSwitch(const wxString
& shortName
,
380 const wxString
& longName
,
381 const wxString
& desc
,
384 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
385 _T("duplicate switch") );
387 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_SWITCH
,
388 shortName
, longName
, desc
,
389 wxCMD_LINE_VAL_NONE
, flags
);
391 m_data
->m_options
.Add(option
);
394 void wxCmdLineParser::AddOption(const wxString
& shortName
,
395 const wxString
& longName
,
396 const wxString
& desc
,
397 wxCmdLineParamType type
,
400 wxASSERT_MSG( m_data
->FindOption(shortName
) == wxNOT_FOUND
,
401 _T("duplicate option") );
403 wxCmdLineOption
*option
= new wxCmdLineOption(wxCMD_LINE_OPTION
,
404 shortName
, longName
, desc
,
407 m_data
->m_options
.Add(option
);
410 void wxCmdLineParser::AddParam(const wxString
& desc
,
411 wxCmdLineParamType type
,
414 // do some consistency checks: a required parameter can't follow an
415 // optional one and nothing should follow a parameter with MULTIPLE flag
417 if ( !m_data
->m_paramDesc
.IsEmpty() )
419 wxCmdLineParam
& param
= m_data
->m_paramDesc
.Last();
421 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
),
422 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
424 if ( !(flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
426 wxASSERT_MSG( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
),
427 _T("a required parameter can't follow an optional one") );
432 wxCmdLineParam
*param
= new wxCmdLineParam(desc
, type
, flags
);
434 m_data
->m_paramDesc
.Add(param
);
437 // ----------------------------------------------------------------------------
438 // access to parse command line
439 // ----------------------------------------------------------------------------
441 bool wxCmdLineParser::Found(const wxString
& name
) const
443 int i
= m_data
->FindOption(name
);
444 if ( i
== wxNOT_FOUND
)
445 i
= m_data
->FindOptionByLongName(name
);
447 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown switch") );
449 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
450 if ( !opt
.HasValue() )
456 bool wxCmdLineParser::Found(const wxString
& name
, wxString
*value
) const
458 int i
= m_data
->FindOption(name
);
459 if ( i
== wxNOT_FOUND
)
460 i
= m_data
->FindOptionByLongName(name
);
462 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
464 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
465 if ( !opt
.HasValue() )
468 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
470 *value
= opt
.GetStrVal();
475 bool wxCmdLineParser::Found(const wxString
& name
, long *value
) const
477 int i
= m_data
->FindOption(name
);
478 if ( i
== wxNOT_FOUND
)
479 i
= m_data
->FindOptionByLongName(name
);
481 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
483 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
484 if ( !opt
.HasValue() )
487 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
489 *value
= opt
.GetLongVal();
495 bool wxCmdLineParser::Found(const wxString
& name
, wxDateTime
*value
) const
497 int i
= m_data
->FindOption(name
);
498 if ( i
== wxNOT_FOUND
)
499 i
= m_data
->FindOptionByLongName(name
);
501 wxCHECK_MSG( i
!= wxNOT_FOUND
, false, _T("unknown option") );
503 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)i
];
504 if ( !opt
.HasValue() )
507 wxCHECK_MSG( value
, false, _T("NULL pointer in wxCmdLineOption::Found") );
509 *value
= opt
.GetDateVal();
513 #endif // wxUSE_DATETIME
515 size_t wxCmdLineParser::GetParamCount() const
517 return m_data
->m_parameters
.size();
520 wxString
wxCmdLineParser::GetParam(size_t n
) const
522 wxCHECK_MSG( n
< GetParamCount(), wxEmptyString
, _T("invalid param index") );
524 return m_data
->m_parameters
[n
];
527 // Resets switches and options
528 void wxCmdLineParser::Reset()
530 for ( size_t i
= 0; i
< m_data
->m_options
.Count(); i
++ )
532 wxCmdLineOption
& opt
= m_data
->m_options
[i
];
533 opt
.SetHasValue(false);
538 // ----------------------------------------------------------------------------
539 // the real work is done here
540 // ----------------------------------------------------------------------------
542 int wxCmdLineParser::Parse(bool showUsage
)
544 bool maybeOption
= true; // can the following arg be an option?
545 bool ok
= true; // true until an error is detected
546 bool helpRequested
= false; // true if "-h" was given
547 bool hadRepeatableParam
= false; // true if found param with MULTIPLE flag
549 size_t currentParam
= 0; // the index in m_paramDesc
551 size_t countParam
= m_data
->m_paramDesc
.GetCount();
558 size_t count
= m_data
->m_arguments
.size();
559 for ( size_t n
= 1; ok
&& (n
< count
); n
++ ) // 0 is program name
561 arg
= m_data
->m_arguments
[n
];
563 // special case: "--" should be discarded and all following arguments
564 // should be considered as parameters, even if they start with '-' and
565 // not like options (this is POSIX-like)
566 if ( arg
== _T("--") )
573 // empty argument or just '-' is not an option but a parameter
574 if ( maybeOption
&& arg
.length() > 1 &&
575 wxStrchr(m_data
->m_switchChars
, arg
[0u]) )
579 int optInd
= wxNOT_FOUND
; // init to suppress warnings
581 // an option or a switch: find whether it's a long or a short one
582 if ( arg
[0u] == _T('-') && arg
[1u] == _T('-') )
588 const wxChar
*p
= arg
.c_str() + 2;
590 bool longOptionsEnabled
= AreLongOptionsEnabled();
592 name
= GetLongOptionName(p
);
594 if (longOptionsEnabled
)
596 optInd
= m_data
->FindOptionByLongName(name
);
597 if ( optInd
== wxNOT_FOUND
)
599 errorMsg
<< wxString::Format(_("Unknown long option '%s'"), name
.c_str()) << wxT("\n");
604 optInd
= wxNOT_FOUND
; // Sanity check
606 // Print the argument including leading "--"
607 name
.Prepend( wxT("--") );
608 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n");
616 // a short one: as they can be cumulated, we try to find the
617 // longest substring which is a valid option
618 const wxChar
*p
= arg
.c_str() + 1;
620 name
= GetShortOptionName(p
);
622 size_t len
= name
.length();
627 // we couldn't find a valid option name in the
628 // beginning of this string
629 errorMsg
<< wxString::Format(_("Unknown option '%s'"), name
.c_str()) << wxT("\n");
635 optInd
= m_data
->FindOption(name
.Left(len
));
637 // will try with one character less the next time
641 while ( optInd
== wxNOT_FOUND
);
643 len
++; // compensates extra len-- above
644 if ( (optInd
!= wxNOT_FOUND
) && (len
!= name
.length()) )
646 // first of all, the option name is only part of this
648 name
= name
.Left(len
);
650 // our option is only part of this argument, there is
651 // something else in it - it is either the value of this
652 // option or other switches if it is a switch
653 if ( m_data
->m_options
[(size_t)optInd
].kind
654 == wxCMD_LINE_SWITCH
)
656 // pretend that all the rest of the argument is the
657 // next argument, in fact
658 wxString arg2
= arg
[0u];
659 arg2
+= arg
.Mid(len
+ 1); // +1 for leading '-'
661 m_data
->m_arguments
.insert
662 (m_data
->m_arguments
.begin() + n
+ 1, arg2
);
665 //else: it's our value, we'll deal with it below
669 if ( optInd
== wxNOT_FOUND
)
673 continue; // will break, in fact
676 wxCmdLineOption
& opt
= m_data
->m_options
[(size_t)optInd
];
677 if ( opt
.kind
== wxCMD_LINE_SWITCH
)
679 // nothing more to do
682 if ( opt
.flags
& wxCMD_LINE_OPTION_HELP
)
684 helpRequested
= true;
686 // it's not an error, but we still stop here
694 // +1 for leading '-'
695 const wxChar
*p
= arg
.c_str() + 1 + name
.length();
698 p
++; // for another leading '-'
700 if ( *p
++ != _T('=') )
702 errorMsg
<< wxString::Format(_("Option '%s' requires a value, '=' expected."), name
.c_str()) << wxT("\n");
718 // the value is in the next argument
721 // ... but there is none
722 errorMsg
<< wxString::Format(_("Option '%s' requires a value."),
723 name
.c_str()) << wxT("\n");
729 // ... take it from there
730 p
= m_data
->m_arguments
[n
].c_str();
735 // the value is right here: this may be legal or
736 // not depending on the option style
737 if ( opt
.flags
& wxCMD_LINE_NEEDS_SEPARATOR
)
739 errorMsg
<< wxString::Format(_("Separator expected after the option '%s'."),
740 name
.c_str()) << wxT("\n");
753 wxFAIL_MSG( _T("unknown option type") );
754 // still fall through
756 case wxCMD_LINE_VAL_STRING
:
757 opt
.SetStrVal(value
);
760 case wxCMD_LINE_VAL_NUMBER
:
763 if ( value
.ToLong(&val
) )
769 errorMsg
<< wxString::Format(_("'%s' is not a correct numeric value for option '%s'."),
770 value
.c_str(), name
.c_str()) << wxT("\n");
778 case wxCMD_LINE_VAL_DATE
:
781 const wxChar
*res
= dt
.ParseDate(value
);
784 errorMsg
<< wxString::Format(_("Option '%s': '%s' cannot be converted to a date."),
785 name
.c_str(), value
.c_str()) << wxT("\n");
795 #endif // wxUSE_DATETIME
803 if ( currentParam
< countParam
)
805 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
807 // TODO check the param type
809 m_data
->m_parameters
.push_back(arg
);
811 if ( !(param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) )
817 wxASSERT_MSG( currentParam
== countParam
- 1,
818 _T("all parameters after the one with wxCMD_LINE_PARAM_MULTIPLE style are ignored") );
820 // remember that we did have this last repeatable parameter
821 hadRepeatableParam
= true;
826 errorMsg
<< wxString::Format(_("Unexpected parameter '%s'"), arg
.c_str()) << wxT("\n");
833 // verify that all mandatory options were given
836 size_t countOpt
= m_data
->m_options
.GetCount();
837 for ( size_t n
= 0; ok
&& (n
< countOpt
); n
++ )
839 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
840 if ( (opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) && !opt
.HasValue() )
845 optName
= opt
.shortName
;
849 if ( AreLongOptionsEnabled() )
851 optName
.Printf( _("%s (or %s)"),
852 opt
.shortName
.c_str(),
853 opt
.longName
.c_str() );
857 optName
.Printf( wxT("%s"),
858 opt
.shortName
.c_str() );
862 errorMsg
<< wxString::Format(_("The value for the option '%s' must be specified."),
863 optName
.c_str()) << wxT("\n");
869 for ( ; ok
&& (currentParam
< countParam
); currentParam
++ )
871 wxCmdLineParam
& param
= m_data
->m_paramDesc
[currentParam
];
872 if ( (currentParam
== countParam
- 1) &&
873 (param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
) &&
876 // special case: currentParam wasn't incremented, but we did
877 // have it, so don't give error
881 if ( !(param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
) )
883 errorMsg
<< wxString::Format(_("The required parameter '%s' was not specified."),
884 param
.description
.c_str()) << wxT("\n");
891 // if there was an error during parsing the command line, show this error
892 // and also the usage message if it had been requested
893 if ( !ok
&& (!errorMsg
.empty() || (helpRequested
&& showUsage
)) )
895 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
900 usage
= GetUsageString();
902 msgOut
->Printf( wxT("%s%s"), usage
.c_str(), errorMsg
.c_str() );
906 wxFAIL_MSG( _T("no wxMessageOutput object?") );
910 return ok
? 0 : helpRequested
? -1 : 1;
913 // ----------------------------------------------------------------------------
914 // give the usage message
915 // ----------------------------------------------------------------------------
917 void wxCmdLineParser::Usage()
919 wxMessageOutput
* msgOut
= wxMessageOutput::Get();
922 msgOut
->Printf( wxT("%s"), GetUsageString().c_str() );
926 wxFAIL_MSG( _T("no wxMessageOutput object?") );
930 wxString
wxCmdLineParser::GetUsageString()
933 if ( m_data
->m_arguments
.empty() )
936 appname
= wxTheApp
->GetAppName();
940 appname
= wxFileName(m_data
->m_arguments
[0]).GetName();
943 // we construct the brief cmd line desc on the fly, but not the detailed
944 // help message below because we want to align the options descriptions
945 // and for this we must first know the longest one of them
947 wxArrayString namesOptions
, descOptions
;
949 if ( !m_data
->m_logo
.empty() )
951 usage
<< m_data
->m_logo
<< _T('\n');
954 usage
<< wxString::Format(_("Usage: %s"), appname
.c_str());
956 // the switch char is usually '-' but this can be changed with
957 // SetSwitchChars() and then the first one of possible chars is used
958 wxChar chSwitch
= !m_data
->m_switchChars
? _T('-')
959 : m_data
->m_switchChars
[0u];
961 bool areLongOptionsEnabled
= AreLongOptionsEnabled();
962 size_t n
, count
= m_data
->m_options
.GetCount();
963 for ( n
= 0; n
< count
; n
++ )
965 wxCmdLineOption
& opt
= m_data
->m_options
[n
];
968 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
973 if ( !opt
.shortName
.empty() )
975 usage
<< chSwitch
<< opt
.shortName
;
977 else if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
979 usage
<< _T("--") << opt
.longName
;
983 if (!opt
.longName
.empty())
985 wxFAIL_MSG( wxT("option with only a long name while long ")
986 wxT("options are disabled") );
990 wxFAIL_MSG( _T("option without neither short nor long name") );
996 if ( !opt
.shortName
.empty() )
998 option
<< _T(" ") << chSwitch
<< opt
.shortName
;
1001 if ( areLongOptionsEnabled
&& !opt
.longName
.empty() )
1003 option
<< (option
.empty() ? _T(" ") : _T(", "))
1004 << _T("--") << opt
.longName
;
1007 if ( opt
.kind
!= wxCMD_LINE_SWITCH
)
1010 val
<< _T('<') << GetTypeName(opt
.type
) << _T('>');
1011 usage
<< _T(' ') << val
;
1012 option
<< (!opt
.longName
? _T(':') : _T('=')) << val
;
1015 if ( !(opt
.flags
& wxCMD_LINE_OPTION_MANDATORY
) )
1020 namesOptions
.push_back(option
);
1021 descOptions
.push_back(opt
.description
);
1024 count
= m_data
->m_paramDesc
.GetCount();
1025 for ( n
= 0; n
< count
; n
++ )
1027 wxCmdLineParam
& param
= m_data
->m_paramDesc
[n
];
1030 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1035 usage
<< param
.description
;
1037 if ( param
.flags
& wxCMD_LINE_PARAM_MULTIPLE
)
1042 if ( param
.flags
& wxCMD_LINE_PARAM_OPTIONAL
)
1050 // now construct the detailed help message
1051 size_t len
, lenMax
= 0;
1052 count
= namesOptions
.size();
1053 for ( n
= 0; n
< count
; n
++ )
1055 len
= namesOptions
[n
].length();
1060 for ( n
= 0; n
< count
; n
++ )
1062 len
= namesOptions
[n
].length();
1063 usage
<< namesOptions
[n
]
1064 << wxString(_T(' '), lenMax
- len
) << _T('\t')
1072 // ----------------------------------------------------------------------------
1073 // private functions
1074 // ----------------------------------------------------------------------------
1076 static wxString
GetTypeName(wxCmdLineParamType type
)
1082 wxFAIL_MSG( _T("unknown option type") );
1083 // still fall through
1085 case wxCMD_LINE_VAL_STRING
:
1089 case wxCMD_LINE_VAL_NUMBER
:
1093 case wxCMD_LINE_VAL_DATE
:
1102 Returns a string which is equal to the string pointed to by p, but up to the
1103 point where p contains an character that's not allowed.
1104 Allowable characters are letters and numbers, and characters pointed to by
1105 the parameter allowedChars.
1107 For example, if p points to "abcde-@-_", and allowedChars is "-_",
1108 this function returns "abcde-".
1110 static wxString
GetOptionName(const wxChar
*p
,
1111 const wxChar
*allowedChars
)
1115 while ( *p
&& (wxIsalnum(*p
) || wxStrchr(allowedChars
, *p
)) )
1123 // Besides alphanumeric characters, short and long options can
1124 // have other characters.
1126 // A short option additionally can have these
1127 #define wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("_?")
1129 // A long option can have the same characters as a short option and a '-'.
1130 #define wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION \
1131 wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION wxT("-")
1133 static wxString
GetShortOptionName(const wxChar
*p
)
1135 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_SHORT_OPTION
);
1138 static wxString
GetLongOptionName(const wxChar
*p
)
1140 return GetOptionName(p
, wxCMD_LINE_CHARS_ALLOWED_BY_LONG_OPTION
);
1143 #endif // wxUSE_CMDLINE_PARSER
1145 // ----------------------------------------------------------------------------
1147 // ----------------------------------------------------------------------------
1150 This function is mainly used under Windows (as under Unix we always get the
1151 command line arguments as argc/argv anyhow) and so it tries to follow
1152 Windows conventions for the command line handling, not Unix ones. For
1153 instance, backslash is not special except when it precedes double quote when
1158 wxArrayString
wxCmdLineParser::ConvertStringToArgs(const wxChar
*p
)
1165 bool isInsideQuotes
= false;
1169 while ( *p
== _T(' ') || *p
== _T('\t') )
1173 if ( *p
== _T('\0') )
1176 // parse this parameter
1177 bool endParam
= false;
1178 bool lastBS
= false;
1179 for ( arg
.clear(); !endParam
; p
++ )
1186 isInsideQuotes
= !isInsideQuotes
;
1188 // don't put quote in arg
1191 //else: quote has no special meaning but the backslash
1192 // still remains -- makes no sense but this is what
1198 // backslash does *not* quote the space, only quotes do
1199 if ( isInsideQuotes
)
1201 // skip assignment below
1217 lastBS
= *p
== _T('\\');
1222 args
.push_back(arg
);