LCOV - code coverage report
Current view: top level - utilities/include/mcrl2/utilities - command_line_interface.h (source / functions) Hit Total Coverage
Test: mcrl2_coverage.info.cleaned Lines: 153 219 69.9 %
Date: 2024-03-08 02:52:28 Functions: 46 126 36.5 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.14