Changed code to allow for removal of the #include <windows.h> from wxprec.h for windows
[wxWidgets.git] / src / common / cmdline.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: common/cmdline.cpp
3 // Purpose: wxCmdLineParser implementation
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 05.01.00
7 // RCS-ID: $Id$
8 // Copyright: (c) 2000 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "cmdline.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/string.h"
33 #include "wx/log.h"
34 #include "wx/intl.h"
35 #include "wx/app.h"
36 #include "wx/dynarray.h"
37 #include "wx/filefn.h"
38 #endif //WX_PRECOMP
39
40 #include <ctype.h>
41
42 #include "wx/datetime.h"
43 #include "wx/cmdline.h"
44
45 // ----------------------------------------------------------------------------
46 // private functions
47 // ----------------------------------------------------------------------------
48
49 static wxString GetTypeName(wxCmdLineParamType type);
50
51 // ----------------------------------------------------------------------------
52 // private classes
53 // ----------------------------------------------------------------------------
54
55 // an internal representation of an option
56 struct wxCmdLineOption
57 {
58 wxCmdLineOption(wxCmdLineEntryType k,
59 const wxString& shrt,
60 const wxString& lng,
61 const wxString& desc,
62 wxCmdLineParamType typ,
63 int fl)
64 {
65 kind = k;
66
67 shortName = shrt;
68 longName = lng;
69 description = desc;
70
71 type = typ;
72 flags = fl;
73
74 m_hasVal = FALSE;
75 }
76
77 // can't use union easily here, so just store all possible data fields, we
78 // don't waste much (might still use union later if the number of supported
79 // types increases, so always use the accessor functions and don't access
80 // the fields directly!)
81
82 void Check(wxCmdLineParamType WXUNUSED_UNLESS_DEBUG(typ)) const
83 {
84 wxASSERT_MSG( type == typ, _T("type mismatch in wxCmdLineOption") );
85 }
86
87 long GetLongVal() const
88 { Check(wxCMD_LINE_VAL_NUMBER); return m_longVal; }
89 const wxString& GetStrVal() const
90 { Check(wxCMD_LINE_VAL_STRING); return m_strVal; }
91 const wxDateTime& GetDateVal() const
92 { Check(wxCMD_LINE_VAL_DATE); return m_dateVal; }
93
94 void SetLongVal(long val)
95 { Check(wxCMD_LINE_VAL_NUMBER); m_longVal = val; m_hasVal = TRUE; }
96 void SetStrVal(const wxString& val)
97 { Check(wxCMD_LINE_VAL_STRING); m_strVal = val; m_hasVal = TRUE; }
98 void SetDateVal(const wxDateTime val)
99 { Check(wxCMD_LINE_VAL_DATE); m_dateVal = val; m_hasVal = TRUE; }
100
101 void SetHasValue() { m_hasVal = TRUE; }
102 bool HasValue() const { return m_hasVal; }
103
104 public:
105 wxCmdLineEntryType kind;
106 wxString shortName, longName, description;
107 wxCmdLineParamType type;
108 int flags;
109
110 private:
111 bool m_hasVal;
112
113 long m_longVal;
114 wxString m_strVal;
115 wxDateTime m_dateVal;
116 };
117
118 struct wxCmdLineParam
119 {
120 wxCmdLineParam(const wxString& desc,
121 wxCmdLineParamType typ,
122 int fl)
123 : description(desc)
124 {
125 type = typ;
126 flags = fl;
127 }
128
129 wxString description;
130 wxCmdLineParamType type;
131 int flags;
132 };
133
134 WX_DECLARE_OBJARRAY(wxCmdLineOption, wxArrayOptions);
135 WX_DECLARE_OBJARRAY(wxCmdLineParam, wxArrayParams);
136
137 #include "wx/arrimpl.cpp"
138
139 WX_DEFINE_OBJARRAY(wxArrayOptions);
140 WX_DEFINE_OBJARRAY(wxArrayParams);
141
142 // the parser internal state
143 struct wxCmdLineParserData
144 {
145 // options
146 wxString m_switchChars; // characters which may start an option
147 bool m_enableLongOptions; // TRUE if long options are enabled
148 wxString m_logo; // some extra text to show in Usage()
149
150 // cmd line data
151 wxArrayString m_arguments; // == argv, argc == m_arguments.GetCount()
152 wxArrayOptions m_options; // all possible options and switchrs
153 wxArrayParams m_paramDesc; // description of all possible params
154 wxArrayString m_parameters; // all params found
155
156 // methods
157 wxCmdLineParserData();
158 void SetArguments(int argc, char **argv);
159 void SetArguments(const wxString& cmdline);
160
161 int FindOption(const wxString& name);
162 int FindOptionByLongName(const wxString& name);
163 };
164
165 // ============================================================================
166 // implementation
167 // ============================================================================
168
169 // ----------------------------------------------------------------------------
170 // wxCmdLineParserData
171 // ----------------------------------------------------------------------------
172
173 wxCmdLineParserData::wxCmdLineParserData()
174 {
175 m_enableLongOptions = TRUE;
176 #ifdef __UNIX_LIKE__
177 m_switchChars = _T("-");
178 #else // !Unix
179 m_switchChars = _T("/-");
180 #endif
181 }
182
183 void wxCmdLineParserData::SetArguments(int argc, char **argv)
184 {
185 m_arguments.Empty();
186
187 for ( int n = 0; n < argc; n++ )
188 {
189 m_arguments.Add(argv[n]);
190 }
191 }
192
193 void wxCmdLineParserData::SetArguments(const wxString& WXUNUSED(cmdline))
194 {
195 // either use wxMSW wxApp::ConvertToStandardCommandArgs() or move its logic
196 // here and use this method from it - but don't duplicate the code
197
198 wxFAIL_MSG(_T("TODO"));
199 }
200
201 int wxCmdLineParserData::FindOption(const wxString& name)
202 {
203 size_t count = m_options.GetCount();
204 for ( size_t n = 0; n < count; n++ )
205 {
206 if ( m_options[n].shortName == name )
207 {
208 // found
209 return n;
210 }
211 }
212
213 return wxNOT_FOUND;
214 }
215
216 int wxCmdLineParserData::FindOptionByLongName(const wxString& name)
217 {
218 size_t count = m_options.GetCount();
219 for ( size_t n = 0; n < count; n++ )
220 {
221 if ( m_options[n].longName == name )
222 {
223 // found
224 return n;
225 }
226 }
227
228 return wxNOT_FOUND;
229 }
230
231 // ----------------------------------------------------------------------------
232 // construction and destruction
233 // ----------------------------------------------------------------------------
234
235 void wxCmdLineParser::Init()
236 {
237 m_data = new wxCmdLineParserData;
238 }
239
240 void wxCmdLineParser::SetCmdLine(int argc, char **argv)
241 {
242 m_data->SetArguments(argc, argv);
243 }
244
245 void wxCmdLineParser::SetCmdLine(const wxString& cmdline)
246 {
247 m_data->SetArguments(cmdline);
248 }
249
250 wxCmdLineParser::~wxCmdLineParser()
251 {
252 delete m_data;
253 }
254
255 // ----------------------------------------------------------------------------
256 // options
257 // ----------------------------------------------------------------------------
258
259 void wxCmdLineParser::SetSwitchChars(const wxString& switchChars)
260 {
261 m_data->m_switchChars = switchChars;
262 }
263
264 void wxCmdLineParser::EnableLongOptions(bool enable)
265 {
266 m_data->m_enableLongOptions = enable;
267 }
268
269 void wxCmdLineParser::SetLogo(const wxString& logo)
270 {
271 m_data->m_logo = logo;
272 }
273
274 // ----------------------------------------------------------------------------
275 // command line construction
276 // ----------------------------------------------------------------------------
277
278 void wxCmdLineParser::SetDesc(const wxCmdLineEntryDesc *desc)
279 {
280 for ( ;; desc++ )
281 {
282 switch ( desc->kind )
283 {
284 case wxCMD_LINE_SWITCH:
285 AddSwitch(desc->shortName, desc->longName, desc->description,
286 desc->flags);
287 break;
288
289 case wxCMD_LINE_OPTION:
290 AddOption(desc->shortName, desc->longName, desc->description,
291 desc->type, desc->flags);
292 break;
293
294 case wxCMD_LINE_PARAM:
295 AddParam(desc->description, desc->type, desc->flags);
296 break;
297
298 default:
299 wxFAIL_MSG( _T("unknown command line entry type") );
300 // still fall through
301
302 case wxCMD_LINE_NONE:
303 return;
304 }
305 }
306 }
307
308 void wxCmdLineParser::AddSwitch(const wxString& shortName,
309 const wxString& longName,
310 const wxString& desc,
311 int flags)
312 {
313 wxASSERT_MSG( m_data->FindOption(shortName) == wxNOT_FOUND,
314 _T("duplicate switch") );
315
316 wxCmdLineOption *option = new wxCmdLineOption(wxCMD_LINE_SWITCH,
317 shortName, longName, desc,
318 wxCMD_LINE_VAL_NONE, flags);
319
320 m_data->m_options.Add(option);
321 }
322
323 void wxCmdLineParser::AddOption(const wxString& shortName,
324 const wxString& longName,
325 const wxString& desc,
326 wxCmdLineParamType type,
327 int flags)
328 {
329 wxASSERT_MSG( m_data->FindOption(shortName) == wxNOT_FOUND,
330 _T("duplicate option") );
331
332 wxCmdLineOption *option = new wxCmdLineOption(wxCMD_LINE_OPTION,
333 shortName, longName, desc,
334 type, flags);
335
336 m_data->m_options.Add(option);
337 }
338
339 void wxCmdLineParser::AddParam(const wxString& desc,
340 wxCmdLineParamType type,
341 int flags)
342 {
343 // do some consistency checks: a required parameter can't follow an
344 // optional one and nothing should follow a parameter with MULTIPLE flag
345 #ifdef __WXDEBUG__
346 if ( !m_data->m_paramDesc.IsEmpty() )
347 {
348 wxCmdLineParam& param = m_data->m_paramDesc.Last();
349
350 wxASSERT_MSG( !(param.flags & wxCMD_LINE_PARAM_MULTIPLE),
351 _T("all parameters after the one with "
352 "wxCMD_LINE_PARAM_MULTIPLE style will be ignored") );
353
354 if ( !(flags & wxCMD_LINE_PARAM_OPTIONAL) )
355 {
356 wxASSERT_MSG( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL),
357 _T("a required parameter can't follow an "
358 "optional one") );
359 }
360 }
361 #endif // Debug
362
363 wxCmdLineParam *param = new wxCmdLineParam(desc, type, flags);
364
365 m_data->m_paramDesc.Add(param);
366 }
367
368 // ----------------------------------------------------------------------------
369 // access to parse command line
370 // ----------------------------------------------------------------------------
371
372 bool wxCmdLineParser::Found(const wxString& name) const
373 {
374 int i = m_data->FindOption(name);
375 wxCHECK_MSG( i != wxNOT_FOUND, FALSE, _T("unknown switch") );
376
377 wxCmdLineOption& opt = m_data->m_options[(size_t)i];
378 if ( !opt.HasValue() )
379 return FALSE;
380
381 return TRUE;
382 }
383
384 bool wxCmdLineParser::Found(const wxString& name, wxString *value) const
385 {
386 int i = m_data->FindOption(name);
387 wxCHECK_MSG( i != wxNOT_FOUND, FALSE, _T("unknown option") );
388
389 wxCmdLineOption& opt = m_data->m_options[(size_t)i];
390 if ( !opt.HasValue() )
391 return FALSE;
392
393 wxCHECK_MSG( value, FALSE, _T("NULL pointer in wxCmdLineOption::Found") );
394
395 *value = opt.GetStrVal();
396
397 return TRUE;
398 }
399
400 bool wxCmdLineParser::Found(const wxString& name, long *value) const
401 {
402 int i = m_data->FindOption(name);
403 wxCHECK_MSG( i != wxNOT_FOUND, FALSE, _T("unknown option") );
404
405 wxCmdLineOption& opt = m_data->m_options[(size_t)i];
406 if ( !opt.HasValue() )
407 return FALSE;
408
409 wxCHECK_MSG( value, FALSE, _T("NULL pointer in wxCmdLineOption::Found") );
410
411 *value = opt.GetLongVal();
412
413 return TRUE;
414 }
415
416 bool wxCmdLineParser::Found(const wxString& name, wxDateTime *value) const
417 {
418 int i = m_data->FindOption(name);
419 wxCHECK_MSG( i != wxNOT_FOUND, FALSE, _T("unknown option") );
420
421 wxCmdLineOption& opt = m_data->m_options[(size_t)i];
422 if ( !opt.HasValue() )
423 return FALSE;
424
425 wxCHECK_MSG( value, FALSE, _T("NULL pointer in wxCmdLineOption::Found") );
426
427 *value = opt.GetDateVal();
428
429 return TRUE;
430 }
431
432 size_t wxCmdLineParser::GetParamCount() const
433 {
434 return m_data->m_parameters.GetCount();
435 }
436
437 wxString wxCmdLineParser::GetParam(size_t n) const
438 {
439 return m_data->m_parameters[n];
440 }
441
442 // ----------------------------------------------------------------------------
443 // the real work is done here
444 // ----------------------------------------------------------------------------
445
446 int wxCmdLineParser::Parse()
447 {
448 bool maybeOption = TRUE; // can the following arg be an option?
449 bool ok = TRUE; // TRUE until an error is detected
450 bool helpRequested = FALSE; // TRUE if "-h" was given
451 bool hadRepeatableParam = FALSE; // TRUE if found param with MULTIPLE flag
452
453 size_t currentParam = 0; // the index in m_paramDesc
454
455 size_t countParam = m_data->m_paramDesc.GetCount();
456
457 // parse everything
458 wxString arg;
459 size_t count = m_data->m_arguments.GetCount();
460 for ( size_t n = 1; ok && (n < count); n++ ) // 0 is program name
461 {
462 arg = m_data->m_arguments[n];
463
464 // special case: "--" should be discarded and all following arguments
465 // should be considered as parameters, even if they start with '-' and
466 // not like options (this is POSIX-like)
467 if ( arg == _T("--") )
468 {
469 maybeOption = FALSE;
470
471 continue;
472 }
473
474 // empty argument or just '-' is not an option but a parameter
475 if ( maybeOption && arg.length() > 1 &&
476 wxStrchr(m_data->m_switchChars, arg[0u]) )
477 {
478 bool isLong;
479 wxString name;
480 int optInd = wxNOT_FOUND; // init to suppress warnings
481
482 // an option or a switch: find whether it's a long or a short one
483 if ( m_data->m_enableLongOptions &&
484 arg[0u] == _T('-') && arg[1u] == _T('-') )
485 {
486 // a long one
487 isLong = TRUE;
488
489 const wxChar *p = arg.c_str() + 2;
490 while ( wxIsalpha(*p) || (*p == _T('-')) )
491 {
492 name += *p++;
493 }
494
495 optInd = m_data->FindOptionByLongName(name);
496 if ( optInd == wxNOT_FOUND )
497 {
498 wxLogError(_("Unknown long option '%s'"), name.c_str());
499 }
500 }
501 else
502 {
503 isLong = FALSE;
504
505 // a short one: as they can be cumulated, we try to find the
506 // longest substring which is a valid option
507 const wxChar *p = arg.c_str() + 1;
508 while ( wxIsalpha(*p) )
509 {
510 name += *p++;
511 }
512
513 size_t len = name.length();
514 do
515 {
516 if ( len == 0 )
517 {
518 // we couldn't find a valid option name in the
519 // beginning of this string
520 wxLogError(_("Unknown option '%s'"), name.c_str());
521
522 break;
523 }
524 else
525 {
526 optInd = m_data->FindOption(name.Left(len));
527
528 // will try with one character less the next time
529 len--;
530 }
531 }
532 while ( optInd == wxNOT_FOUND );
533
534 len++; // compensates extra len-- above
535 if ( (optInd != wxNOT_FOUND) && (len != name.length()) )
536 {
537 // first of all, the option name is only part of this
538 // string
539 name = name.Left(len);
540
541 // our option is only part of this argument, there is
542 // something else in it - it is either the value of this
543 // option or other switches if it is a switch
544 if ( m_data->m_options[(size_t)optInd].kind
545 == wxCMD_LINE_SWITCH )
546 {
547 // pretend that all the rest of the argument is the
548 // next argument, in fact
549 wxString arg2 = arg[0u];
550 arg2 += arg.Mid(len + 1); // +1 for leading '-'
551
552 m_data->m_arguments.Insert(arg2, n + 1);
553 count++;
554 }
555 //else: it's our value, we'll deal with it below
556 }
557 }
558
559 if ( optInd == wxNOT_FOUND )
560 {
561 ok = FALSE;
562
563 continue; // will break, in fact
564 }
565
566 wxCmdLineOption& opt = m_data->m_options[(size_t)optInd];
567 if ( opt.kind == wxCMD_LINE_SWITCH )
568 {
569 // nothing more to do
570 opt.SetHasValue();
571
572 if ( opt.flags & wxCMD_LINE_OPTION_HELP )
573 {
574 helpRequested = TRUE;
575
576 // it's not an error, but we still stop here
577 ok = FALSE;
578 }
579 }
580 else
581 {
582 // get the value
583
584 // +1 for leading '-'
585 const wxChar *p = arg.c_str() + 1 + name.length();
586 if ( isLong )
587 {
588 p++; // for another leading '-'
589
590 if ( *p++ != _T('=') )
591 {
592 wxLogError(_("Option '%s' requires a value, '=' "
593 "expected."), name.c_str());
594
595 ok = FALSE;
596 }
597 }
598 else
599 {
600 switch ( *p )
601 {
602 case _T(':'):
603 // the value follows
604 p++;
605 break;
606
607 case 0:
608 // the value is in the next argument
609 if ( ++n == count )
610 {
611 // ... but there is none
612 wxLogError(_("Option '%s' requires a value."),
613 name.c_str());
614
615 ok = FALSE;
616 }
617 else
618 {
619 // ... take it from there
620 p = m_data->m_arguments[n].c_str();
621 }
622 break;
623
624 default:
625 // the value is right here
626 ;
627 }
628 }
629
630 if ( ok )
631 {
632 wxString value = p;
633 switch ( opt.type )
634 {
635 default:
636 wxFAIL_MSG( _T("unknown option type") );
637 // still fall through
638
639 case wxCMD_LINE_VAL_STRING:
640 opt.SetStrVal(value);
641 break;
642
643 case wxCMD_LINE_VAL_NUMBER:
644 {
645 long val;
646 if ( value.ToLong(&val) )
647 {
648 opt.SetLongVal(val);
649 }
650 else
651 {
652 wxLogError(_("'%s' is not a correct "
653 "numeric value for option "
654 "'%s'."),
655 value.c_str(), name.c_str());
656
657 ok = FALSE;
658 }
659 }
660 break;
661
662 case wxCMD_LINE_VAL_DATE:
663 {
664 wxDateTime dt;
665 const wxChar *res = dt.ParseDate(value);
666 if ( !res || *res )
667 {
668 wxLogError(_("Option '%s': '%s' cannot "
669 "be converted to a date."),
670 name.c_str(), value.c_str());
671
672 ok = FALSE;
673 }
674 else
675 {
676 opt.SetDateVal(dt);
677 }
678 }
679 break;
680 }
681 }
682 }
683 }
684 else
685 {
686 // a parameter
687 if ( currentParam < countParam )
688 {
689 wxCmdLineParam& param = m_data->m_paramDesc[currentParam];
690
691 // TODO check the param type
692
693 m_data->m_parameters.Add(arg);
694
695 if ( !(param.flags & wxCMD_LINE_PARAM_MULTIPLE) )
696 {
697 currentParam++;
698 }
699 else
700 {
701 wxASSERT_MSG( currentParam == countParam - 1,
702 _T("all parameters after the one with "
703 "wxCMD_LINE_PARAM_MULTIPLE style "
704 "are ignored") );
705
706 // remember that we did have this last repeatable parameter
707 hadRepeatableParam = TRUE;
708 }
709 }
710 else
711 {
712 wxLogError(_("Unexpected parameter '%s'"), arg.c_str());
713
714 ok = FALSE;
715 }
716 }
717 }
718
719 // verify that all mandatory options were given
720 if ( ok )
721 {
722 size_t countOpt = m_data->m_options.GetCount();
723 for ( size_t n = 0; ok && (n < countOpt); n++ )
724 {
725 wxCmdLineOption& opt = m_data->m_options[n];
726 if ( (opt.flags & wxCMD_LINE_OPTION_MANDATORY) && !opt.HasValue() )
727 {
728 wxString optName;
729 if ( !opt.longName )
730 {
731 optName = opt.shortName;
732 }
733 else
734 {
735 optName.Printf(_("%s (or %s)"),
736 opt.shortName.c_str(),
737 opt.longName.c_str());
738 }
739
740 wxLogError(_("The value for the option '%s' must be specified."),
741 optName.c_str());
742
743 ok = FALSE;
744 }
745 }
746
747 for ( ; ok && (currentParam < countParam); currentParam++ )
748 {
749 wxCmdLineParam& param = m_data->m_paramDesc[currentParam];
750 if ( (currentParam == countParam - 1) &&
751 (param.flags & wxCMD_LINE_PARAM_MULTIPLE) &&
752 hadRepeatableParam )
753 {
754 // special case: currentParam wasn't incremented, but we did
755 // have it, so don't give error
756 continue;
757 }
758
759 if ( !(param.flags & wxCMD_LINE_PARAM_OPTIONAL) )
760 {
761 wxLogError(_("The required parameter '%s' was not specified."),
762 param.description.c_str());
763
764 ok = FALSE;
765 }
766 }
767 }
768
769 if ( !ok )
770 {
771 Usage();
772 }
773
774 return ok ? 0 : helpRequested ? -1 : 1;
775 }
776
777 // ----------------------------------------------------------------------------
778 // give the usage message
779 // ----------------------------------------------------------------------------
780
781 void wxCmdLineParser::Usage()
782 {
783 wxString appname = wxTheApp->GetAppName();
784 if ( !appname )
785 {
786 wxCHECK_RET( !m_data->m_arguments.IsEmpty(), _T("no program name") );
787
788 appname = wxFileNameFromPath(m_data->m_arguments[0]);
789 wxStripExtension(appname);
790 }
791
792 wxString brief, detailed;
793 brief.Printf(_("Usage: %s"), appname.c_str());
794
795 size_t n, count = m_data->m_options.GetCount();
796 for ( n = 0; n < count; n++ )
797 {
798 wxCmdLineOption& opt = m_data->m_options[n];
799
800 brief << _T(' ');
801 if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) )
802 {
803 brief << _T('[');
804 }
805
806 brief << _T('-') << opt.shortName;
807 detailed << _T(" -") << opt.shortName;
808 if ( !!opt.longName )
809 {
810 detailed << _T(" --") << opt.longName;
811 }
812
813 if ( opt.kind != wxCMD_LINE_SWITCH )
814 {
815 wxString val;
816 val << _T('<') << GetTypeName(opt.type) << _T('>');
817 brief << _T(' ') << val;
818 detailed << (!opt.longName ? _T(':') : _T('=')) << val;
819 }
820
821 if ( !(opt.flags & wxCMD_LINE_OPTION_MANDATORY) )
822 {
823 brief << _T(']');
824 }
825
826 detailed << _T('\t') << opt.description << _T('\n');
827 }
828
829 count = m_data->m_paramDesc.GetCount();
830 for ( n = 0; n < count; n++ )
831 {
832 wxCmdLineParam& param = m_data->m_paramDesc[n];
833
834 brief << _T(' ');
835 if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL )
836 {
837 brief << _T('[');
838 }
839
840 brief << param.description;
841
842 if ( param.flags & wxCMD_LINE_PARAM_MULTIPLE )
843 {
844 brief << _T("...");
845 }
846
847 if ( param.flags & wxCMD_LINE_PARAM_OPTIONAL )
848 {
849 brief << _T(']');
850 }
851 }
852
853 if ( !!m_data->m_logo )
854 {
855 wxLogMessage(m_data->m_logo);
856 }
857
858 wxLogMessage(brief);
859 wxLogMessage(detailed);
860 }
861
862 // ----------------------------------------------------------------------------
863 // global functions
864 // ----------------------------------------------------------------------------
865
866 static wxString GetTypeName(wxCmdLineParamType type)
867 {
868 wxString s;
869 switch ( type )
870 {
871 default:
872 wxFAIL_MSG( _T("unknown option type") );
873 // still fall through
874
875 case wxCMD_LINE_VAL_STRING: s = _("str"); break;
876 case wxCMD_LINE_VAL_NUMBER: s = _("num"); break;
877 case wxCMD_LINE_VAL_DATE: s = _("date"); break;
878 }
879
880 return s;
881 }