Line data Source code
1 : // Author(s): Jeroen van der Wulp
2 : // Copyright: see the accompanying file COPYING or copy at
3 : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4 : //
5 : // Distributed under the Boost Software License, Version 1.0.
6 : // (See accompanying file LICENSE_1_0.txt or copy at
7 : // http://www.boost.org/LICENSE_1_0.txt)
8 : //
9 : /// \file mcrl2/utilities/command_line_interface.h
10 : /// \brief Components for command line interfaces of mCRL2 tools
11 :
12 : #ifndef MCRL2_UTILITIES_COMMAND_LINE_INTERFACE_H
13 : #define MCRL2_UTILITIES_COMMAND_LINE_INTERFACE_H
14 : #include <cstdlib>
15 : #include <cstring>
16 : #include <fstream>
17 : #include <map>
18 : #include <memory>
19 :
20 : #include "mcrl2/utilities/exception.h"
21 : #include "mcrl2/utilities/text_utility.h"
22 : #include "mcrl2/utilities/toolset_version.h"
23 :
24 : namespace mcrl2
25 : {
26 : namespace utilities
27 : {
28 :
29 : class interface_description;
30 : class command_line_parser;
31 :
32 : /** \brief toolset copyright period description */
33 0 : inline std::string copyright_period()
34 : {
35 : // We assume that the version number always starts with a four digit year
36 : // in which the version was released.
37 0 : if (get_toolset_version().size() >= 4)
38 0 : return get_toolset_version().substr(0, 4);
39 0 : return "Today";
40 : }
41 :
42 : /**
43 : * \brief Command line interface description component.
44 : *
45 : * This component can be used to specify the command-line interface of
46 : * tools in terms of options and arguments to options. The scope is command
47 : * line interfaces of mCRL2 tools.
48 : *
49 : * Options that are standard (prescribed by convention) are automatically
50 : * added to the interface. Options for functionality in toolset libraries
51 : * that are shared amongst multiple tools can be predefined in this
52 : * component and included on demand for individual tools.
53 : *
54 : * The following examples illustrate use of the interface description
55 : * class. Construction of an interface description object.
56 : * \code
57 : * interface_description interface(
58 : * "/path/to/demo-tool",
59 : * "demo-tool",
60 : * "Rincewind",
61 : * "demonstrate the interface_description class",
62 : * "[OPTIONS]... [INFILE]",
63 : * "Demonstrate the features of the interface_description class using INFILE as input.");
64 : * \endcode
65 : *
66 : * Adding options to an interface description.
67 : *
68 : * \code
69 : * cli.
70 : * add_option("recursive", "option without argument", 'r').
71 : * add_option("timeout", make_optional_argument("SEC", "2"), "option with optional argument (default 2)").
72 : * add_option("tool", make_mandatory_argument("FOO"), "option with mandatory argument").
73 : * add_option("language", make_mandatory_argument("LANG", "english"), "option with mandatory argument (default english)").
74 : * \endcode
75 : *
76 : * Printing an interface description.
77 : *
78 : * \code
79 : * std::cerr << cli.textual_description() << std::endl;
80 : * \endcode
81 : *
82 : * Prints:
83 : * \verbatim
84 : interface description:
85 : /path/to/demo-tool [OPTIONS]... [PATHS]
86 : Serves as demonstration of the features of the interface_description
87 : class.
88 :
89 : Options:
90 : -r, --recursive option without argument
91 : -t[SEC], --timeout=[SEC] option optional argument (default 2)
92 : --tool=FOO option with mandatory argument
93 : --language=LANG option with mandatory argument (default english)
94 :
95 : Standard options:
96 : -q, --quiet do not display warning messages
97 : -v, --verbose display short intermediate messages
98 : -d, --debug display detailed intermediate messages
99 : -h, --help display help information
100 : --version display version information
101 :
102 : Report bugs at <http://www.mcrl2.org/issuetracker>.
103 :
104 : See also the manual at <http://www.mcrl2.org/web/user_manual/tools/release/demo-tool.html>.
105 : \endverbatim
106 : * Printing version information.
107 : *
108 : * \code
109 : *
110 : * std::cerr << "VERSION INFORMATION:" << std::endl
111 : * << std::endl
112 : * << cli.version_information() << std::endl;
113 : * \endcode
114 : * Prints:
115 : * \verbatim
116 : demo-tool July 2008 (development) (revision 4624M-shared)
117 : Copyright (c) 2008 Technische Universiteit Eindhoven.
118 : This is free software. You may redistribute copies of it under the
119 : terms of the Boost Software License <http://www.boost.org/LICENSE_1_0.txt>.
120 : There is NO WARRANTY, to the extent permitted by law.
121 :
122 : Written by Rincewind. \endverbatim
123 : **/
124 : class interface_description
125 : {
126 : friend class command_line_parser;
127 :
128 : public:
129 :
130 : /// \cond INTERNAL
131 : /**
132 : * \brief Option argument.
133 : *
134 : * The boolean type parameter represents whether the argument is optional or not
135 : **/
136 : class basic_argument
137 : {
138 :
139 : protected:
140 :
141 : /// name of the argument (for reference purposes in option description)
142 : std::string m_name;
143 :
144 : /// type of the argument
145 : std::string m_type;
146 :
147 : protected:
148 :
149 : /// sets the name for the argument
150 12 : void set_name(std::string const& n)
151 : {
152 12 : m_name = n;
153 12 : }
154 :
155 : /// sets the type for the argument
156 24 : void set_type(std::string const& t)
157 : {
158 24 : m_type = t;
159 24 : }
160 :
161 : public:
162 :
163 : class argument_description
164 : {
165 : protected:
166 : std::string m_long;
167 : std::string m_short;
168 : std::string m_description;
169 :
170 : public:
171 2 : argument_description(const std::string& long_, const std::string& short_, const std::string& description)
172 2 : : m_long(long_), m_short(short_), m_description(description)
173 2 : {}
174 :
175 : argument_description(const std::string& long_, const std::string& description)
176 : : m_long(long_), m_description(description)
177 : {}
178 :
179 4 : const std::string& get_long() const
180 : {
181 4 : return m_long;
182 : }
183 :
184 2 : const std::string& get_short() const
185 : {
186 2 : return m_short;
187 : }
188 :
189 0 : const std::string& get_description() const
190 : {
191 0 : return m_description;
192 : }
193 : };
194 :
195 : /// returns a copy of the object
196 : virtual basic_argument* clone() const = 0;
197 :
198 : /// returns the name for the argument
199 0 : std::string get_name() const
200 : {
201 0 : return m_name;
202 : }
203 :
204 : /// returns the type for the argument
205 0 : std::string get_type() const
206 : {
207 0 : return m_type;
208 : }
209 :
210 : /// whether the argument has a description or not
211 : virtual bool has_description() const = 0;
212 :
213 : /// Gets the description of the argument(s), as key-description pairs;
214 : virtual std::vector< argument_description > const& get_description() const = 0;
215 :
216 : /// Gets default value for option argument
217 : virtual std::string const& get_default() const = 0;
218 :
219 : /// verifies that a string is a valid argument
220 : virtual bool validate(std::string const&) const = 0;
221 :
222 : /// whether the argument is optional or not
223 : virtual bool is_optional() const = 0;
224 :
225 : /// whether the argument is optional or not
226 : virtual bool has_default() const = 0;
227 :
228 : /// Destructor
229 22 : virtual ~basic_argument()
230 22 : {
231 22 : }
232 : };
233 :
234 : /// Argument to an option
235 : template < typename T >
236 : class typed_argument;
237 :
238 : /// Represents an optional argument to an option
239 : template < typename T = std::string >
240 : class optional_argument;
241 :
242 : /// Represents a mandatory argument to an option
243 : template < typename T = std::string >
244 : class mandatory_argument;
245 :
246 : template < typename T = std::string >
247 : class enum_argument;
248 :
249 : /// Represents a file argument
250 : class file_argument;
251 :
252 : private:
253 :
254 : /**
255 : * \brief Describes a single option
256 : *
257 : * Objects of this type represent option specifications. They consist of: a
258 : * long description (the option identifier) an optional short description,
259 : * a description of the option, and optionally an argument. The argument
260 : * itself can be optional or mandatory. An optional argument has a default
261 : * value that is taken instead of the argument when the option is found on
262 : * the command line without an argument. A mandatory argument requires the
263 : * user to specify an argument to the option.
264 : **/
265 : class option_descriptor
266 : {
267 : friend class command_line_parser;
268 : friend class interface_description;
269 :
270 : private:
271 :
272 : /// Long representation for the option
273 : std::string m_long;
274 :
275 : /// Description for the option
276 : std::string m_description;
277 :
278 : /// Option argument
279 : std::shared_ptr< basic_argument > m_argument;
280 :
281 : /// Short representation for the option or 0
282 : char m_short;
283 :
284 : /// whether the option is printed as part of the tool-specific interface
285 : bool m_show;
286 :
287 : protected:
288 :
289 : /// Returns a textual description of the option
290 : std::string textual_description(const std::size_t left_width, const std::size_t right_width) const;
291 :
292 : /// Returns a man page description for the option
293 : std::string man_page_description() const;
294 :
295 : /// Returns a man page description for the option
296 : std::ostream& xml_page_description(std::ostream& s, const bool is_standard = false, unsigned int indentation = 0) const;
297 :
298 : public:
299 :
300 : /**
301 : * \brief Constructor
302 : * \param[in] d description of the option
303 : * \param[in] l the long option representation of the option
304 : * \param[in] s an optional single-character short representation of the option
305 : * \pre l should be a non-empty string that only contain characters from [0-9a-Z] or `-'
306 : **/
307 41 : option_descriptor(std::string const& l, std::string const& d, const char s) :
308 41 : m_long(l), m_description(d), m_short(s), m_show(true)
309 : {
310 :
311 41 : assert(!l.empty());
312 41 : assert(l.find_first_not_of("_-0123456789abcdefghijklmnopqrstuvwxyz") == std::string::npos);
313 41 : }
314 :
315 : /// copy constructor
316 82 : option_descriptor(option_descriptor const& o) : m_long(o.m_long),
317 82 : m_description(o.m_description), m_argument(o.m_argument), m_short(o.m_short), m_show(true)
318 : {
319 82 : }
320 :
321 : option_descriptor operator=(option_descriptor const& o)
322 : {
323 : return option_descriptor(o);
324 : }
325 :
326 0 : basic_argument const& argument() const
327 : {
328 0 : return *m_argument;
329 : }
330 :
331 : /**
332 : * \brief Sets option argument
333 : * \param[in] a an optional argument specifier object
334 : **/
335 : template < typename T >
336 10 : void set_argument(T* a)
337 : {
338 10 : m_argument.reset(a);
339 10 : }
340 :
341 : /**
342 : * \brief Get the long name of the argument
343 : **/
344 0 : inline const std::string& get_long() const
345 : {
346 0 : return m_long;
347 : }
348 :
349 : /**
350 : * \brief Gets default
351 : **/
352 0 : inline std::string const& get_default() const
353 : {
354 0 : return m_argument->get_default();
355 : }
356 :
357 : /**
358 : * \brief Gets the option description
359 : **/
360 : inline std::string get_description() const
361 : {
362 : return m_description;
363 : }
364 :
365 : /**
366 : * \brief Whether the option takes a mandatory argument
367 : **/
368 16 : inline bool needs_argument() const
369 : {
370 16 : return !(m_argument.get() == nullptr || m_argument->is_optional());
371 : }
372 :
373 : /**
374 : * \brief Whether the option takes an argument
375 : **/
376 41 : inline bool accepts_argument() const
377 : {
378 41 : return m_argument.get() != nullptr;
379 : }
380 : };
381 :
382 : /**
383 : * \brief Compare identifiers using case insensitive compare.
384 : */
385 : struct option_identifier_less
386 : {
387 322 : bool operator()(char const& c1, char const& c2) const
388 : {
389 322 : char c1u = toupper(c1);
390 322 : char c2u = toupper(c2);
391 :
392 322 : return c1u < c2u || (c1u == c2u && c2 < c1);
393 : }
394 :
395 : template < typename S >
396 : bool operator()(S const& s1, S const& s2) const
397 : {
398 : std::string s1u = s1;
399 : std::string s2u = s2;
400 : std::transform(s1u.begin(), s1u.end(), s1u.begin(), ::toupper);
401 : std::transform(s2u.begin(), s2u.end(), s2u.begin(), ::toupper);
402 :
403 : return s1u < s2u || (s1u == s2u && s2 < s1);
404 : }
405 : };
406 : /// \endcond
407 :
408 : typedef std::map< std::string, option_descriptor > option_map;
409 :
410 : typedef std::map< const char, std::string, option_identifier_less > short_to_long_map;
411 :
412 : /// \brief Maps long option identifiers to option descriptor objects
413 : option_map m_options;
414 :
415 : private:
416 :
417 : /// \brief Path to executable (as in the first command line argument)
418 : std::string m_path;
419 :
420 : /// \brief Name of the tool for usage and tool description
421 : std::string m_name;
422 :
423 : /// \brief Comma separated list of authors
424 : std::string m_authors;
425 :
426 : /// \brief One-line "what is" information (used only in man pages)
427 : std::string m_what_is;
428 :
429 : /// \brief Usage and description
430 : std::string m_usage;
431 :
432 : /// \brief Tool description
433 : std::string m_description;
434 :
435 : /// \brief Description of known issues
436 : std::string m_known_issues;
437 :
438 :
439 :
440 : /// \brief Maps a short option to its associated long option
441 : short_to_long_map m_short_to_long;
442 :
443 : private:
444 :
445 : /**
446 : * \brief Searches a short option for a given long option
447 : * \param[in] n string representing a long option
448 : * \return the short option, or '\0' in case no short option was found
449 : **/
450 2 : char long_to_short(std::string const& n) const
451 : {
452 2 : char result = '\0';
453 :
454 10 : for (short_to_long_map::const_iterator i = m_short_to_long.begin(); result == '\0' && i != m_short_to_long.end(); ++i)
455 : {
456 8 : if (i->second == n)
457 : {
458 2 : result = i->first;
459 : }
460 : }
461 :
462 2 : return result;
463 : }
464 :
465 : option_descriptor const& find_option(std::string const& long_identifier) const;
466 :
467 : /// \brief Stores a sequence of actions that automatically add options (used in constructor)
468 : static interface_description& get_standard_description();
469 :
470 : /// \brief Registers option that should be added to every interface
471 : template < typename T >
472 : inline static void register_initialiser()
473 : {
474 : T::add_options(get_standard_description());
475 : }
476 :
477 : /// \brief Internal use only
478 1 : inline interface_description()
479 1 : {
480 1 : }
481 :
482 : public:
483 :
484 : /**
485 : * \brief Constructor
486 : *
487 : * \param[in] path path or name that identifies the executable
488 : * \param[in] name the name of the tool
489 : * \param[in] authors string with the names of the authors
490 : * \param[in] what_is one-line description of the program (used only in man pages, must not refer to the synopsis)
491 : * \param[in] synopsis message that gives an abstract summary of tool usage
492 : * \param[in] description message that explains tool usage and description (may refer to the synopsis)
493 : * \param[in] known_issues textual description of known issues with the tool
494 : **/
495 : interface_description(std::string const& path, std::string const& name, std::string const& authors,
496 : std::string const& what_is, std::string const& synopsis, std::string const& description,
497 : std::string const& known_issues = "");
498 :
499 : /**
500 : * \brief Composes a copyright message
501 : * \return formatted string that represents the copyright message
502 : **/
503 : static std::string copyright_message();
504 :
505 : /**
506 : * \brief Composes a version information message
507 : * \return formatted string that represents version information
508 : *
509 : * The following example shows the effect of this method for a tool named test and author John Doe.
510 : *
511 : * \code
512 : * std::cout << version_information();
513 : * \endcode
514 : *
515 : * The output is:
516 : *
517 : * \verbatim
518 : test January 2008 (revision 4321M-shared)
519 : Copyright (C) 2008 Technische Universiteit Eindhoven.
520 : This is free software. You may redistribute copies of it under the
521 : terms of the Boost Software License <http://www.boost.org/LICENSE_1_0.txt>.
522 : There is NO WARRANTY, to the extent permitted by law.
523 :
524 : Written by John Doe \endverbatim
525 : *
526 : * Where toolset version, revision and copyright year are constants
527 : * supplied internally at compile time.
528 : **/
529 : std::string version_information() const;
530 :
531 : /**
532 : * \brief Adds an option with argument identified by a long-identifier to the interface
533 : *
534 : * Adds an option identified by a long-identifier with an argument to
535 : * the interface. The argument to the option is either optional, or
536 : * mandatory. In the former case a default value is assumed when the
537 : * option is found on a command line command. Method parameters:
538 : *
539 : * \param[in] long_identifier the long option representation of the option
540 : * \param[in] argument_specification a mandatory or optional argument to the option
541 : * \param[in] description description of the option
542 : * \param[in] short_identifier an optional single-character short representation of the option
543 : *
544 : * the type parameter T represents is type of the argument. That is the
545 : * argument to the option must be convertible (using <<) to T.
546 : *
547 : * The argument_specification parameter is an object of a class derived
548 : * from basic_argument. Appropriate argument specification objects can
549 : * be obtained by using the friend functions make_mandatory_argument()
550 : * and make_optional_argument().
551 : *
552 : * More specifically it specifies one of the two template types:
553 : * \li interface_description::optional_argument< std::string >
554 : * representing a untyped optional option argument or,
555 : * \li interface_description::mandatory_argument< std::string > representing a untyped
556 : * mandatory option argument.
557 : *
558 : * The current implementation does not perform type checking of
559 : * arguments. More concretely it does not check whether a value
560 : * representing an argument with type mandatory_argument< int > to type
561 : * int.
562 : *
563 : * \return *this
564 : * \pre long_identifier must be a non-empty string that only contain characters from [a-z0-9] or `-'
565 : * \pre short_identifier must a single character [a-zA-Z0-9]
566 : * \throw std::runtime_error when an option with long_identifier is already part of the interface
567 : * \throw std::runtime_error when an option with short_identifier is already part of the interface
568 : * \see add_option(std::string const&, std::string const&, char const)
569 : *
570 : * The following example shows how to add mandatory and optional options:
571 : * \code
572 : * add_option("timeout", make_mandatory_argument("SEC"), "timeout occurs after SEC number of seconds", 't');
573 : * add_option("recursive", make_optional_argument("DEPTH", "2"), "stop at recursion level DEPTH (default 2)", 'r');
574 : * \endcode
575 : * The result is a command line interface with parser behaviour:
576 : * \verbatim
577 : tool --timeout=2 --recursive (pass)
578 : tool -t2 -r3 (pass)
579 : tool --timeout=bla --recursive=bla (pass)
580 : tool --timeout (failure)
581 : tool -t (failure) \endverbatim
582 : *
583 : * The human readable interface specification for these options is as follows:
584 : *
585 : * \verbatim
586 : -tSEC, --timeout=SEC timeout occurs after SEC number of seconds
587 : -rDEPTH, --recursive=[DEPTH] stop at recursion level DEPTH (default 2) \endverbatim
588 : **/
589 : template < typename T >
590 12 : interface_description& add_option(std::string const& long_identifier,
591 : typed_argument< T > const& argument_specification,
592 : std::string const& description,
593 : char const short_identifier = '\0')
594 : {
595 :
596 12 : add_option(long_identifier, description, short_identifier);
597 :
598 10 : m_options.find(long_identifier)->second.set_argument(argument_specification.clone());
599 :
600 10 : return *this;
601 : }
602 :
603 : /**
604 : * \brief Adds an option identified by a long-identifier to the interface
605 : * \param[in] long_identifier the long option representation of the option
606 : * \param[in] description description of the option
607 : * \param[in] short_identifier an optional single-character short representation of the option
608 : * \return *this
609 : * \pre long_identifier must be a non-empty string that only contain characters from [a-z0-9] or `-' '_'
610 : * \pre short_identifier must a single character [a-zA-Z0-9]
611 : * \throw std::runtime_error when an option with long_identifier is already part of the interface
612 : * \throw std::runtime_error when an option with short_identifier is already part of the interface
613 : *
614 : * The following example shows how to add an option without arguments
615 : * \code
616 : * add_option("recursive", "recursively scans a directory", 'r');
617 : * add_option("test", "tests\n a lot");
618 : * \endcode
619 : * The result is a command line interface with the following example parsing behaviour:
620 : * \verbatim
621 : tool --test (pass)
622 : tool --test --test (pass)
623 : tool -r --recursive (pass)
624 : tool --r (failure)
625 : tool -t (failure) \endverbatim
626 : *
627 : * The human readable interface specification for these options is as follows:
628 : *
629 : * \verbatim
630 : -r, --recursive recursively scans a directory
631 : --test tests
632 : a lot \endverbatim
633 : **/
634 45 : interface_description& add_option(std::string const& long_identifier,
635 : std::string const& description,
636 : char const short_identifier = '\0')
637 : {
638 :
639 45 : if (m_options.find(long_identifier) != m_options.end())
640 : {
641 4 : throw std::logic_error("Duplicate long option (--" + long_identifier + "); this is a serious program error!");
642 : }
643 :
644 41 : if (short_identifier != '\0')
645 : {
646 25 : if (m_short_to_long.find(short_identifier) != m_short_to_long.end())
647 : {
648 0 : throw std::logic_error("Duplicate short option (-" + std::string(1, short_identifier) + "); this is a serious program error!");
649 : }
650 :
651 25 : m_short_to_long[short_identifier] = long_identifier;
652 : }
653 :
654 41 : m_options.insert(std::make_pair(long_identifier, option_descriptor(long_identifier, description, short_identifier)));
655 :
656 41 : return *this;
657 : }
658 :
659 : /**
660 : * \brief adds a hidden option
661 : *
662 : * A hidden option is not advertised as being part of the interface.
663 : * As a consequence the result of class methods such as textual_description,
664 : * man_page and xml will not contain information about these options.
665 : *
666 : * \see add_option(std::string const&, basic_argument const& std::string const&, char const)
667 : **/
668 : template < typename T >
669 5 : void add_hidden_option(
670 : std::string const& long_identifier,
671 : typed_argument< T > const& argument_specification,
672 : std::string const& description,
673 : char const short_identifier = '\0')
674 : {
675 :
676 5 : add_option(long_identifier, argument_specification, description, short_identifier);
677 :
678 5 : m_options.find(long_identifier)->second.m_show = false;
679 5 : }
680 :
681 : /**
682 : * \brief adds a hidden option
683 : * \see add_hidden_option(std::string const&, basic_argument const& std::string const&, char const)
684 : * \see add_option(std::string const&, std::string const&, char const)
685 : **/
686 30 : void add_hidden_option(std::string const& long_identifier,
687 : std::string const& description,
688 : char const short_identifier = '\0')
689 : {
690 :
691 30 : add_option(long_identifier, description, short_identifier);
692 :
693 30 : m_options.find(long_identifier)->second.m_show = false;
694 30 : }
695 :
696 : /**
697 : * \brief Generates a human readable interface description (used for -h,--help)
698 : * \return string containing a description of the interface
699 : **/
700 : std::string textual_description(bool show_hidden) const;
701 :
702 : /**
703 : * \brief Returns the text of a man page
704 : * \return string containing a man page description of the interface
705 : **/
706 : std::string man_page() const;
707 :
708 : /**
709 : * \brief Returns the text of an page
710 : * \return string containing an xml description
711 : **/
712 : std::ostream& xml_page(std::ostream&) const;
713 :
714 : /**
715 : * \brief Returns the available long arguments with their associated help description
716 : * \return mapping consisting of strings where the key represent the long argument and the mapped value the help description
717 : **/
718 : std::map<std::string, std::string> get_long_argument_with_description();
719 :
720 : /**
721 : * \brief Returns the toolname
722 : * \return string containing the name of the tool
723 : **/
724 : std::string get_toolname()
725 : {
726 : return m_name;
727 : }
728 : };
729 :
730 : /**
731 : * \brief Main parsing component for command line strings as well as
732 : * interface to the results of parsing. The input is a specification of an
733 : * interface.
734 : *
735 : * This class represents one of the two main interface components
736 : * responsible for actual parsing of the command line and communicating the
737 : * results. The other component the interface_description class provides an
738 : * interface description along with functionality to format messages to the
739 : * user of the tool.
740 : *
741 : * Access to parse results is provided through the STL multimap options
742 : * (type std::multimap) and the STL vector arguments (type std::vector).
743 : * The former is mapping between an option (through long-option identifier)
744 : * found on the command line to the string that represents its argument.
745 : * The latter contains from left-to-right the command line arguments that
746 : * were not recognised as option or argument to option.
747 : *
748 : * The following example illustrates the use of parsing results:
749 : * \code
750 : * interface_description interface("tool", "tool-name", "John Doe", "[OPTIONS]... [PATHS]");
751 : *
752 : * // Note default options: --help,(-h), --version, --verbose, --debug (-d) and --quiet (-q)
753 : * cli.
754 : * add_option("recursive", "recursively test all files in directories", 'r').
755 : * add_option("tool", make_mandatory_argument("FOO"), "path that identifies the tool executable to test with", 't').
756 : * add_option("language", make_mandatory_argument("LANG", "english"), "language for output").
757 : * add_option("timeout", make_optional_argument("SEC", "2"), "optional timeout period");
758 : *
759 : * try {
760 : * // parse command line
761 : * command_line_parser parser(cli, "test -v --verbose -r --timeout --tool=foo bar1 bar2");
762 : *
763 : * std::cerr << parser.options.count("recursive"); // prints: 1
764 : * std::cerr << parser.options.count("verbose"); // prints: 2
765 : * std::cerr << parser.options.count("tool"); // prints: 1
766 : * std::cerr << parser.options.count("timeout"); // prints: 1
767 : * std::cerr << parser.options.count("bar1"); // prints: 0
768 : *
769 : * std::cerr << parser.option_argument("tool"); // prints: "foo"
770 : * std::cerr << parser.option_argument_as< int >("tool"); // prints: 2
771 : * std::cerr << parser.option_argument("recursive"); // prints: ""
772 : *
773 : * std::cerr << parser.arguments.size(); // prints: 2
774 : * std::cerr << parser.arguments[0]; // prints: "bar1"
775 : * std::cerr << parser.arguments[1]; // prints: "bar2"
776 : *
777 : * std::cerr << parser.options.count("language"); // prints: 0
778 : * std::cerr << parser.option_argument("language"); // prints: "english"
779 : * }
780 : * catch (std::exception& e) {
781 : * std::cerr << e.what() << std::endl;
782 : * }
783 : * \endcode
784 : *
785 : * Note the use of the option_argument method. It simplifies argument
786 : * extraction in the case that the same option does not occur multiple
787 : * times the auxiliary functions option_argument() and option_argument_as()
788 : * are provided.
789 : **/
790 : class command_line_parser
791 : {
792 : public:
793 :
794 : /// Used to map options to arguments
795 : typedef std::multimap< std::string, std::string > option_map;
796 :
797 : /// Used to store command line arguments that were not recognised as option or arguments to options
798 : typedef std::vector< std::string > argument_list;
799 :
800 : private:
801 :
802 : /// \brief The list of options found on the command line
803 : option_map m_options;
804 :
805 : /// \brief The list of arguments that have not been matched with an option
806 : argument_list m_arguments;
807 :
808 : /// \brief The command line interface specification
809 : interface_description& m_interface;
810 :
811 : /// \brief Whether the actions after parsing indicate that program execution should continue
812 : bool m_continue;
813 :
814 : public:
815 :
816 : /// \brief Maps options found on the command line to their argument or the empty string
817 : option_map const& options;
818 :
819 : /// \brief The list of arguments that have not been matched with an option
820 : argument_list const& arguments;
821 :
822 : /// \brief Returns true if option is set.
823 0 : bool has_option(const std::string& option) const
824 : {
825 0 : return options.find(option) != options.end();
826 : }
827 :
828 : private:
829 :
830 : /// \brief Parses string as if it is an unparsed command line
831 : static std::vector< std::string > parse_command_line(char const* const arguments);
832 :
833 : /// \brief Converts C-style array with specified length to STL vector of strings
834 : static std::vector< std::string > convert(const int count, char const* const* const arguments);
835 :
836 : /// \brief Converts C-style array with specified length to STL vector of strings
837 : static std::vector< std::string > convert(const int count, wchar_t const* const* const arguments);
838 :
839 : /// \brief Identifies all options and option arguments
840 : void collect(interface_description& d, std::vector< std::string > const& arguments);
841 :
842 : /// \brief Executes actions for default options
843 : void process_default_options(interface_description& d);
844 :
845 : /// \brief Stores a sequence of actions that are automatically executed after parsing completes
846 26 : static std::vector< bool (*)(command_line_parser&) >& get_registered_actions()
847 : {
848 26 : static std::vector< bool (*)(command_line_parser&) > actions;
849 :
850 26 : return actions;
851 : }
852 :
853 : /// \brief Registers default actions after successful parsing
854 : static void register_action(bool (*action)(command_line_parser&))
855 : {
856 : get_registered_actions().push_back(action);
857 : }
858 :
859 : /**
860 : * \brief Overload for std::string that just returns the value.
861 : * \overload
862 : *
863 : * Note that this is essential for handling arguments with spaces.
864 : **/
865 : inline void
866 0 : option_argument_as_impl(std::string const& long_identifier, std::string& res) const
867 : {
868 0 : res = option_argument(long_identifier);
869 0 : }
870 :
871 : /**
872 : * \brief Returns the converted argument of the first option matching a name
873 : * \param[in] long_identifier the long identifier for the option
874 : * \pre 0 < options.count(long_identifier) and !options.find(long_identifier)->second.empty()
875 : * \throw std::runtime_error containing a message that the argument cannot be converted to the specified type
876 : * \return t : T where t << std::istringstream(option_argument_as(long_identifier))
877 : * \see std::string const& option_argument(std::string const& long_identifier)
878 : **/
879 : template < typename T >
880 : inline void
881 2 : option_argument_as_impl(std::string const& long_identifier, T& result) const
882 : {
883 2 : std::istringstream in(option_argument(long_identifier));
884 :
885 2 : result = T();
886 :
887 2 : in >> result;
888 :
889 2 : if (in.fail())
890 : {
891 0 : const char short_option(m_interface.long_to_short(long_identifier));
892 :
893 0 : error("argument `" + option_argument(long_identifier) + "' to option --" + long_identifier +
894 0 : ((short_option == '\0') ? " " : " or -" + std::string(1, short_option)) + " is invalid");
895 : }
896 2 : }
897 :
898 : public:
899 :
900 : /**
901 : * \brief Parses a string that represents a command on the command
902 : * line, and executes default procedures for default options.
903 : * \param[in] interface_specification the interface description
904 : * \param[in] command_line the string that represents the unparsed command line
905 : * \throws std::runtime_error
906 : **/
907 28 : inline command_line_parser(interface_description& interface_specification, char const* const command_line) :
908 28 : m_interface(interface_specification), m_continue(true), options(m_options), arguments(m_arguments)
909 : {
910 32 : collect(interface_specification, parse_command_line(command_line));
911 :
912 24 : process_default_options(interface_specification);
913 33 : }
914 :
915 : /**
916 : * \brief Recognises options from an array that represents a pre-parsed
917 : * command on the command line, and executes default procedures for
918 : * default options.
919 : * \param[in] interface_specification the interface description
920 : * \param[in] argument_count amount of arguments
921 : * \param[in] arguments C-style array with arguments
922 : * \throws std::runtime_error
923 : **/
924 : template < typename CharacterType >
925 : command_line_parser(interface_description& interface_specification,
926 : const int argument_count, CharacterType const* const* const arguments);
927 :
928 : /**
929 : * \brief Throws standard formatted std::runtime_error exception
930 : * \param[in] message mandatory message indicating what went wrong
931 : *
932 : * The following example shows the output of this method for a tool named test.
933 : *
934 : * \code
935 : * try {
936 : * error("Parse error: option -b unknown");
937 : * }
938 : * catch (std::exception& e) {
939 : * std::cerr << e.what();
940 : * }
941 : * \endcode
942 : *
943 : * The output is:
944 : *
945 : * \verbatim
946 : * tool: Parse error: option -b unknown
947 : * Try `tool --help' for more information. \endverbatim
948 : **/
949 6 : void error(std::string const& message) const
950 : {
951 6 : throw mcrl2::command_line_error(m_interface.m_name, message);
952 : }
953 :
954 : /**
955 : * \brief Checks that all arguments are passed at most once
956 : */
957 0 : void check_no_duplicate_arguments() const
958 : {
959 0 : for (option_map::const_iterator i = m_options.begin(); i != m_options.end(); ++i)
960 : {
961 0 : if (1 < m_options.count(i->first))
962 : {
963 0 : error("option -" + (m_interface.long_to_short(i->first) != '\0' ?
964 0 : std::string(1, m_interface.long_to_short(i->first)).append(", --") : "-") + i->first + " specified more than once");
965 : }
966 : }
967 0 : }
968 :
969 : /**
970 : * \brief Returns the argument of the first option matching a name
971 : * \param[in] long_identifier the long identifier for the option
972 : * Finds and returns the argument of an option with long identifier
973 : * matching long_identifier in this.options. There may be more than one
974 : * occurence of the option in this.options, if so the first argument
975 : * to the option will be returned. A default value is returned when a
976 : * user did not specify the option matching long_identifier on the
977 : * command line. A default value is only returned when the option
978 : * matching long_identifier is either an option with optional argument
979 : * or when it is an option with mandatory argument and a standard value.
980 : * \return options.find(long_identifier)->second
981 : * \pre 0 < options.count(long_identifier)
982 : * \throw std::logic_error containing a message that the option was not part of the command
983 : * \throw std::logic_error containing a message that the option does not take argument
984 : **/
985 : std::string const& option_argument(std::string const& long_identifier) const;
986 :
987 : /**
988 : * \brief Whether main program execution should continue
989 : **/
990 0 : inline bool continue_execution() const
991 : {
992 0 : return m_continue;
993 : }
994 :
995 : /**
996 : * \brief Returns the converted argument of the first option matching a name
997 : * \param[in] long_identifier the long identifier for the option
998 : * \pre 0 < options.count(long_identifier) and !options.find(long_identifier)->second.empty()
999 : * \throw std::runtime_error containing a message that the argument cannot be converted to the specified type
1000 : * \return t : T where t << std::istringstream(option_argument_as(long_identifier))
1001 : * \see std::string const& option_argument(std::string const& long_identifier)
1002 : **/
1003 : template < typename T >
1004 2 : inline T option_argument_as(std::string const& long_identifier) const
1005 : {
1006 0 : T result;
1007 2 : option_argument_as_impl(long_identifier, result);
1008 2 : return result;
1009 0 : }
1010 :
1011 : };
1012 :
1013 : /// Creates an optional option argument specification object
1014 : template < typename ArgumentType >
1015 0 : interface_description::optional_argument< ArgumentType > make_optional_argument(std::string const& name, std::string const& default_value)
1016 : {
1017 0 : return interface_description::optional_argument< ArgumentType >(name, default_value);
1018 : }
1019 :
1020 : /** \brief Creates an optional option argument specification object
1021 : *
1022 : * Creates an object that specifies an option with an optional typed argument.
1023 : * The default value is automatically substituted when the user specifies
1024 : * the option but does not specify an option argument.
1025 : *
1026 : * \param[in] name a placeholder for referencing the argument in textual descriptions
1027 : * \param[in] default_value the default value
1028 : * \return a basic_argument derived object that represents an untyped optional option argument
1029 : *
1030 : * The following example demonstrates the effect of an option with optional argument:
1031 : * \code
1032 : * add_option("recursive", make_optional_argument("DEPTH", "2"),
1033 : * "stop at recursion level DEPTH (default 2)", 'r');
1034 : * \endcode
1035 : * The result is a command line interface with parsing behaviour:
1036 : * \verbatim
1037 : tool (effect: options("recursive").count() == 0)
1038 : tool --recursive (effect: options("recursive").count() == 1 && option_argument("recursive") == 2)
1039 : tool -r (effect: options("recursive").count() == 1 && option_argument("recursive") == 2)
1040 : tool --recursive=3 (effect: options("recursive").count() == 1 && option_argument("recursive") == 3)
1041 : tool -r3 (effect: options("recursive").count() == 1 && option_argument("recursive") == 3)
1042 : */
1043 : interface_description::optional_argument< std::string > make_optional_argument(std::string const& name, std::string const& default_value);
1044 :
1045 : /// Creates a mandatory option argument specification object
1046 : template < typename ArgumentType >
1047 : interface_description::mandatory_argument< ArgumentType > make_mandatory_argument(std::string const& name)
1048 : {
1049 : return interface_description::mandatory_argument< ArgumentType >(name);
1050 : }
1051 :
1052 : /**
1053 : * Creates an object that specifies an option with a mandatory argument.
1054 : * Specifying the option in a command also requires specification of an
1055 : * option argument.
1056 : *
1057 : * \param[in] name a placeholder for referencing the argument in textual descriptions
1058 : * \return a basic_argument derived object that represents an untyped mandatory option argument
1059 : *
1060 : * The following example demonstrates the effect of an option with optional argument:
1061 : * \code
1062 : * add_option("recursive", make_mandatory_argument("DEPTH"),
1063 : * "stop at recursion level DEPTH", 'r');
1064 : * \endcode
1065 : * The result is a command line interface with parsing behaviour:
1066 : * \verbatim
1067 : tool (effect: options("recursive").count() == 0)
1068 : tool --recursive (effect: parsing fails)
1069 : tool -r (effect: parsing fails)
1070 : tool --recursive=3 (effect: options("recursive").count() == 1 && option_argument("recursive") == 3)
1071 : tool -r3 (effect: options("recursive").count() == 1 && option_argument("recursive") == 3)
1072 : **/
1073 : interface_description::mandatory_argument< std::string >
1074 : make_mandatory_argument(std::string const& name);
1075 :
1076 : /** \brief Creates a mandatory typed option argument specification object
1077 : *
1078 : * \see make_mandatory_argument(std::string const&)
1079 : **/
1080 : template < typename ArgumentType >
1081 : interface_description::mandatory_argument< ArgumentType >
1082 5 : make_mandatory_argument(std::string const& name, std::string const& standard_value)
1083 : {
1084 5 : return interface_description::mandatory_argument< ArgumentType >(name, standard_value);
1085 : }
1086 :
1087 : /**
1088 : * Creates an object that specifies an option with a mandatory argument.
1089 : * Specifying the option in a command also requires specification of an
1090 : * option argument. The default value is substituted by the
1091 : * option_argument() and option_argument_as() methods when the option is
1092 : * not part of the parsed command.
1093 : *
1094 : * \param[in] name a placeholder for referencing the argument in textual descriptions
1095 : * \return a basic_argument derived object that represents an untyped mandatory option argument
1096 : *
1097 : * The following example demonstrates the effect of an option with optional argument:
1098 : * \code
1099 : * add_option("recursive", make_mandatory_argument("DEPTH", "2"),
1100 : * "stop at recursion level DEPTH (default 2)", 'r');
1101 : * \endcode
1102 : * The result is a command line interface with parsing behaviour:
1103 : * \verbatim
1104 : tool (effect: options("recursive").count() == 0 && option_argument("recursive") == 2)
1105 : tool --recursive (effect: options("recursive").count() == 0 && option_argument("recursive") == 2)
1106 : tool -r (effect: options("recursive").count() == 0 && option_argument("recursive") == 2)
1107 : tool --recursive=3 (effect: options("recursive").count() == 1 && option_argument("recursive") == 3)
1108 : tool -r3 (effect: options("recursive").count() == 1 && option_argument("recursive") == 3)
1109 : *
1110 : **/
1111 : interface_description::mandatory_argument< std::string >
1112 : make_mandatory_argument(std::string const& name, std::string const& default_value);
1113 : /// \cond INTERNAL
1114 :
1115 : /// Creates a option argument specification object for an enumerated type
1116 : template < typename ArgumentType >
1117 1 : interface_description::enum_argument< ArgumentType > make_enum_argument(std::string const& name)
1118 : {
1119 1 : return interface_description::enum_argument< ArgumentType >(name);
1120 : }
1121 :
1122 : /**
1123 : * \brief Represents a typed argument
1124 : *
1125 : * A typed argument is more specific than an untyped argument. All
1126 : * arguments are represented by strings, but typed arguments have the
1127 : * additional restriction that the string is checked to be convertible
1128 : * (with >>) to the type specified by the type parameter T.
1129 : **/
1130 : template < typename T >
1131 : class interface_description::typed_argument : public basic_argument
1132 : {
1133 :
1134 : public:
1135 12 : typed_argument()
1136 12 : {
1137 12 : set_type("typed");
1138 12 : }
1139 :
1140 : /// Checks whether string is convertible to a value of a specific type
1141 0 : inline bool validate(std::string const& s) const
1142 : {
1143 0 : std::istringstream test(s);
1144 :
1145 : T result;
1146 :
1147 0 : test >> result;
1148 :
1149 0 : return !test.fail();
1150 0 : }
1151 : };
1152 :
1153 : /**
1154 : * \brief specialisation for type std::string
1155 : * \param[in] s the string to validate
1156 : *
1157 : * Specialisation for the case of a string. Every string is convertible to
1158 : * a string so the implementation is trivial.
1159 : **/
1160 : template < >
1161 9 : inline bool interface_description::typed_argument< std::string >::validate(std::string const&) const
1162 : {
1163 9 : return true;
1164 : }
1165 :
1166 : /**
1167 : * \brief Represents an argument with a limited number of allowed values.
1168 : *
1169 : */
1170 : template < typename T >
1171 : class interface_description::enum_argument : public typed_argument< T >
1172 : {
1173 : protected:
1174 :
1175 : std::vector< basic_argument::argument_description > m_enum;
1176 :
1177 : std::string m_default;
1178 : bool m_has_default;
1179 :
1180 : /// \brief Implementation that adds the value of an enum type
1181 2 : enum_argument& add_value_with_short(const std::string& long_arg, const std::string& short_arg, const std::string& description, const bool is_default = false)
1182 : {
1183 2 : m_enum.push_back(basic_argument::argument_description(long_arg, short_arg, description));
1184 :
1185 2 : if(is_default)
1186 : {
1187 1 : if(has_default())
1188 : {
1189 0 : throw std::runtime_error("cannot define duplicate default value to enum argument");
1190 : }
1191 1 : m_default = long_arg;
1192 1 : m_has_default = true;
1193 : }
1194 :
1195 2 : return (*this);
1196 : }
1197 :
1198 : public:
1199 :
1200 : /// Constructor
1201 1 : enum_argument(std::string const& name) :
1202 1 : m_has_default(false)
1203 : {
1204 1 : basic_argument::set_type("enum");
1205 1 : basic_argument::set_name(name);
1206 1 : }
1207 :
1208 : /// \overload
1209 : virtual
1210 1 : enum_argument* clone() const
1211 : {
1212 1 : return new enum_argument< T >(*this);
1213 : }
1214 :
1215 : /// \overload
1216 : virtual
1217 1 : bool has_default() const
1218 : {
1219 1 : return m_has_default;
1220 : }
1221 :
1222 : /// \overload
1223 : virtual
1224 0 : const std::string& get_default() const
1225 : {
1226 0 : return m_default;
1227 : }
1228 :
1229 : /// \overload
1230 : virtual
1231 1 : bool is_optional() const
1232 : {
1233 1 : return false;
1234 : }
1235 :
1236 : /// \overload
1237 3 : inline bool validate(std::string const& s) const
1238 : {
1239 5 : for(typename std::vector< basic_argument::argument_description >::const_iterator i = m_enum.begin(); i != m_enum.end(); ++i)
1240 : {
1241 4 : if(i->get_long() == s || i->get_short() == s)
1242 : {
1243 2 : std::istringstream test(s);
1244 0 : T result;
1245 2 : test >> result;
1246 :
1247 2 : return !test.fail();
1248 2 : }
1249 : }
1250 1 : return false;
1251 : }
1252 :
1253 : /**
1254 : * \brief Add an enum value as a valid argument.
1255 : *
1256 : * \param[in] arg a value of the enumerated type T
1257 : * \param[in] is_default whether \a arg is the default value of the option
1258 : *
1259 : * \pre T has an operator <<, giving a textual description of \a arg
1260 : * \pre The function description is defined on T
1261 : * \pre If a short option must be available, then the function short_option
1262 : * is overloaded for T.
1263 : */
1264 0 : enum_argument& add_value(const T& arg, const bool is_default = false)
1265 : {
1266 0 : return add_value_with_short(to_string(arg), std::string(), description(arg), is_default);
1267 : }
1268 :
1269 : /**
1270 : * \brief Add an enum value as a valid argument.
1271 : *
1272 : * \param[in] arg a value of the enumerated type T
1273 : * \param[in] description a description of the value
1274 : * \param[in] is_default whether \a arg is the default value of the option
1275 : *
1276 : * \pre T has an operator <<, giving a textual description of \a arg
1277 : * \pre The function description is defined on T
1278 : * \pre If a short option must be available, then the function short_option
1279 : * is overloaded for T.
1280 : */
1281 2 : enum_argument& add_value_desc(const T& arg, const std::string& description, const bool is_default = false)
1282 : {
1283 2 : return add_value_with_short(to_string(arg), std::string(), description, is_default);
1284 : }
1285 :
1286 : /**
1287 : * \brief Add an enum value as a valid argument.
1288 : *
1289 : * \param[in] arg a value of the enumerated type T
1290 : * \param[in] short_argument the short version of the argument
1291 : * \param[in] is_default whether \a arg is the default value of the option
1292 : *
1293 : * \pre T has an operator <<, giving a textual description of \a arg
1294 : * \pre The function description is defined on T
1295 : * \pre If a short option must be available, then the function short_option
1296 : * is overloaded for T.
1297 : */
1298 : enum_argument& add_value_short(const T& arg, const std::string& short_argument, const bool is_default = false)
1299 : {
1300 : return add_value_with_short(to_string(arg), short_argument, description(arg), is_default);
1301 : }
1302 :
1303 :
1304 :
1305 : /// \overload
1306 0 : virtual bool has_description() const
1307 : {
1308 0 : return true;
1309 : }
1310 :
1311 : /// \overload
1312 0 : virtual const std::vector< basic_argument::argument_description >& get_description() const
1313 : {
1314 0 : return m_enum;
1315 : }
1316 :
1317 : };
1318 :
1319 : /// Represents an optional argument to an option
1320 : template < typename T >
1321 : class interface_description::optional_argument : public typed_argument< T >
1322 : {
1323 : friend class interface_description;
1324 : friend class interface_description::option_descriptor;
1325 : friend class command_line_parser;
1326 :
1327 : protected:
1328 :
1329 : /// default value
1330 : std::string m_default;
1331 :
1332 : /// description
1333 : std::vector< basic_argument::argument_description > m_description;
1334 :
1335 : public:
1336 :
1337 2 : virtual basic_argument* clone() const
1338 : {
1339 2 : return new optional_argument< T >(*this);
1340 : }
1341 :
1342 : /**
1343 : * Constructor
1344 : * \param[in] n the name of the argument
1345 : * \param[in] d the default value for the argument
1346 : **/
1347 3 : inline optional_argument(std::string const& name, std::string const& d) : m_default(d)
1348 : {
1349 3 : basic_argument::set_type("optional");
1350 3 : basic_argument::set_name(name);
1351 3 : }
1352 :
1353 : /**
1354 : * \brief Throws because mandatory arguments have no default
1355 : **/
1356 0 : inline bool has_default() const
1357 : {
1358 0 : return true;
1359 : }
1360 :
1361 : /**
1362 : * \brief Returns the default argument
1363 : **/
1364 4 : inline std::string const& get_default() const
1365 : {
1366 4 : return m_default;
1367 : }
1368 :
1369 : /// whether the argument is optional or not
1370 4 : inline bool is_optional() const
1371 : {
1372 4 : return true;
1373 : }
1374 :
1375 0 : inline bool has_description() const
1376 : {
1377 0 : return false;
1378 : }
1379 :
1380 0 : inline const std::vector< basic_argument::argument_description >& get_description() const
1381 : {
1382 0 : return m_description;
1383 : }
1384 : };
1385 :
1386 : /// Represents a mandatory argument to an option
1387 : template < typename T >
1388 : class interface_description::mandatory_argument : public typed_argument< T >
1389 : {
1390 :
1391 : protected:
1392 :
1393 : /// default value
1394 : std::string m_default;
1395 :
1396 : /// whether a default value has been specified
1397 : bool m_has_default;
1398 :
1399 : /// description
1400 : std::vector< basic_argument::argument_description > m_description;
1401 :
1402 : public:
1403 :
1404 7 : virtual basic_argument* clone() const
1405 : {
1406 7 : return new mandatory_argument< T >(*this);
1407 : }
1408 :
1409 : /**
1410 : * Constructor
1411 : * \param[in] n the name of the argument
1412 : **/
1413 3 : inline mandatory_argument(std::string const& name) : m_has_default(false)
1414 : {
1415 3 : basic_argument::set_type("mandatory");
1416 3 : basic_argument::set_name(name);
1417 3 : }
1418 :
1419 : /**
1420 : * Constructor
1421 : * \param[in] n the name of the argument
1422 : **/
1423 5 : inline mandatory_argument(std::string const& name, std::string const& d) : m_default(d), m_has_default(true)
1424 : {
1425 5 : basic_argument::set_type("mandatory");
1426 5 : basic_argument::set_name(name);
1427 5 : }
1428 :
1429 : /**
1430 : * \brief Throws because mandatory arguments have no default
1431 : **/
1432 0 : inline std::string const& get_default() const
1433 : {
1434 0 : return m_default;
1435 : }
1436 :
1437 : /**
1438 : * \brief Throws because mandatory arguments have no default
1439 : **/
1440 0 : inline bool has_default() const
1441 : {
1442 0 : return m_has_default;
1443 : }
1444 :
1445 : /// whether the argument is optional or not
1446 3 : inline bool is_optional() const
1447 : {
1448 3 : return false;
1449 : }
1450 :
1451 0 : inline bool has_description() const
1452 : {
1453 0 : return false;
1454 : }
1455 :
1456 0 : inline const std::vector< basic_argument::argument_description >& get_description() const
1457 : {
1458 0 : return m_description;
1459 : }
1460 : };
1461 :
1462 : /// Represents a file argument to an option
1463 : class interface_description::file_argument : public typed_argument<std::string>
1464 : {
1465 :
1466 : protected:
1467 :
1468 : /// default value
1469 : std::string m_default;
1470 :
1471 : /// whether a default value has been specified
1472 : bool m_has_default;
1473 :
1474 : /// description
1475 : std::vector< basic_argument::argument_description > m_description;
1476 :
1477 : public:
1478 :
1479 : virtual basic_argument* clone() const
1480 : {
1481 : return new file_argument(*this);
1482 : }
1483 :
1484 :
1485 : /// \overload
1486 : inline bool validate(std::string const& /*s*/) const
1487 : {
1488 : return true;
1489 : }
1490 :
1491 : /**
1492 : * Constructor
1493 : * \param[in] n the name of the argument
1494 : **/
1495 : inline file_argument(std::string const& name) : m_has_default(false)
1496 : {
1497 : basic_argument::set_type("file");
1498 : basic_argument::set_name(name);
1499 : }
1500 :
1501 : /**
1502 : * \brief Throws because mandatory arguments have no default
1503 : **/
1504 : inline std::string const& get_default() const
1505 : {
1506 : return m_default;
1507 : }
1508 :
1509 : /**
1510 : * \brief Throws because mandatory arguments have no default
1511 : **/
1512 : inline bool has_default() const
1513 : {
1514 : return m_has_default;
1515 : }
1516 :
1517 : /// whether the argument is optional or not
1518 : inline bool is_optional() const
1519 : {
1520 : return false;
1521 : }
1522 :
1523 : inline bool has_description() const
1524 : {
1525 : return false;
1526 : }
1527 :
1528 : inline const std::vector< basic_argument::argument_description >& get_description() const
1529 : {
1530 : return m_description;
1531 : }
1532 : };
1533 :
1534 : /// Creates a file option argument specification object
1535 : inline
1536 : interface_description::file_argument make_file_argument(std::string const& name)
1537 : {
1538 : return interface_description::file_argument(name);
1539 : }
1540 :
1541 : #if !defined(__COMMAND_LINE_INTERFACE__)
1542 :
1543 : template <>
1544 1 : inline command_line_parser::command_line_parser(interface_description& d, const int c, char const* const* const a) :
1545 1 : m_interface(d), m_continue(true), options(m_options), arguments(m_arguments)
1546 : {
1547 :
1548 1 : collect(d, convert(c, a));
1549 :
1550 1 : process_default_options(d);
1551 1 : }
1552 : # ifndef __CYGWIN__ // std::wstring is not available for Cygwin
1553 : template <>
1554 3 : inline command_line_parser::command_line_parser(interface_description& d, const int c, wchar_t const* const* const a) :
1555 3 : m_interface(d), m_continue(true), options(m_options), arguments(m_arguments)
1556 : {
1557 :
1558 4 : collect(d, convert(c, a));
1559 :
1560 2 : process_default_options(d);
1561 4 : }
1562 : # endif // __CYGWIN__
1563 : #endif
1564 : /// \endcond
1565 : } // namespace utilities
1566 : } // namespace mcrl2
1567 :
1568 : #endif
|