]> Dogcows Code - chaz/yoink/blobdiff - src/stlplus/subsystems/cli_parser.cpp
testing new non-autotools build system
[chaz/yoink] / src / stlplus / subsystems / cli_parser.cpp
diff --git a/src/stlplus/subsystems/cli_parser.cpp b/src/stlplus/subsystems/cli_parser.cpp
new file mode 100644 (file)
index 0000000..1088f38
--- /dev/null
@@ -0,0 +1,637 @@
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+//   Author:    Andy Rushton\r
+//   Copyright: (c) Southampton University 1999-2004\r
+//              (c) Andy Rushton           2004-2009\r
+//   License:   BSD License, see ../docs/license.html\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+#include "cli_parser.hpp"\r
+#include "file_system.hpp"\r
+#include "dprintf.hpp"\r
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+namespace stlplus \r
+{\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // cli_definition internals\r
+\r
+  const std::string& stlplus::cli_definition::name(void) const\r
+  {\r
+    return m_name;\r
+  }\r
+\r
+  stlplus::cli_kind_t stlplus::cli_definition::kind(void) const\r
+  { \r
+    return m_kind;\r
+  }\r
+\r
+  stlplus::cli_mode_t stlplus::cli_definition::mode(void) const\r
+  {\r
+    return m_mode;\r
+  }\r
+\r
+  const std::string& stlplus::cli_definition::message(void) const\r
+  {\r
+    return m_message;\r
+  }\r
+\r
+  const std::string& stlplus::cli_definition::default_value(void) const\r
+  {\r
+    return m_default;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // internal data structures\r
+\r
+  class cli_value\r
+  {\r
+  public:\r
+    unsigned m_definition;\r
+    std::string m_value;\r
+    unsigned m_level;\r
+    std::string m_source;\r
+\r
+    cli_value(unsigned definition, const std::string& value, unsigned level, const std::string& source) :\r
+      m_definition(definition), m_value(value), m_level(level), m_source(source) \r
+      {\r
+      }\r
+  };\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+  class cli_parser_data\r
+  {\r
+  public:\r
+    message_handler& m_messages;\r
+    std::string m_executable;\r
+    cli_parser::definitions m_definitions;\r
+    std::vector<cli_value> m_values;\r
+    unsigned m_level;\r
+    bool m_valid;\r
+    std::vector<std::string> m_ini_files;\r
+\r
+  public:\r
+\r
+    cli_parser_data(message_handler& messages) : \r
+      m_messages(messages), m_level(1), m_valid(true)\r
+      {\r
+        // ensure that the CLI's messages are in the message handler - these\r
+        // can be overridden from a file later - see message_handler\r
+        if (!m_messages.message_present("CLI_VALUE_MISSING"))\r
+          m_messages.add_message("CLI_VALUE_MISSING", "option @0 requires a value - end of line was reached instead");\r
+        if (!m_messages.message_present("CLI_UNRECOGNISED_OPTION"))\r
+          m_messages.add_message("CLI_UNRECOGNISED_OPTION", "@0 is not a recognised option for this command");\r
+        if (!m_messages.message_present("CLI_NO_VALUES"))\r
+          m_messages.add_message("CLI_NO_VALUES", "argument @0 is invalid - this program doesn't take command-line arguments");\r
+        if (!m_messages.message_present("CLI_USAGE_PROGRAM"))\r
+          m_messages.add_message("CLI_USAGE_PROGRAM", "usage:\n\t@0 { arguments }");\r
+        if (!m_messages.message_present("CLI_USAGE_DEFINITIONS"))\r
+          m_messages.add_message("CLI_USAGE_DEFINITIONS", "arguments:");\r
+        if (!m_messages.message_present("CLI_USAGE_VALUES"))\r
+          m_messages.add_message("CLI_USAGE_VALUES", "values:");\r
+        if (!m_messages.message_present("CLI_USAGE_VALUE_RESULT"))\r
+          m_messages.add_message("CLI_USAGE_VALUE_RESULT", "\t@0 : from @1");\r
+        if (!m_messages.message_present("CLI_USAGE_SWITCH_RESULT"))\r
+          m_messages.add_message("CLI_USAGE_SWITCH_RESULT", "\t-@0 : from @1");\r
+        if (!m_messages.message_present("CLI_USAGE_OPTION_RESULT"))\r
+          m_messages.add_message("CLI_USAGE_OPTION_RESULT", "\t-@0 @1 : from @2");\r
+        if (!m_messages.message_present("CLI_INI_HEADER"))\r
+          m_messages.add_message("CLI_INI_HEADER", "configuration files:");\r
+        if (!m_messages.message_present("CLI_INI_FILE_PRESENT"))\r
+          m_messages.add_message("CLI_INI_FILE_PRESENT", "\t@0");\r
+        if (!m_messages.message_present("CLI_INI_FILE_ABSENT"))\r
+          m_messages.add_message("CLI_INI_FILE_ABSENT", "\t@0 (not found)");\r
+        if (!m_messages.message_present("CLI_INI_VARIABLE"))\r
+          m_messages.add_message("CLI_INI_VARIABLE", "unknown variable \"@0\" found in Ini file");\r
+      }\r
+\r
+    unsigned add_definition(const cli_parser::definition& definition)\r
+      {\r
+        m_definitions.push_back(definition);\r
+        return m_definitions.size()-1;\r
+      }\r
+\r
+    std::string name(unsigned i) const throw(cli_index_error)\r
+      {\r
+        if (i >= m_values.size()) throw cli_index_error("Index " + dformat("%u",i) + " out of range");\r
+        return m_definitions[m_values[i].m_definition].name();\r
+      }\r
+\r
+    unsigned id(unsigned i) const throw(cli_index_error)\r
+      {\r
+        if (i >= m_values.size()) throw cli_index_error("Index " + dformat("%u",i) + " out of range");\r
+        return m_values[i].m_definition;\r
+      }\r
+\r
+    cli_parser::kind_t kind(unsigned i) const throw(cli_index_error)\r
+      {\r
+        if (i >= m_values.size()) throw cli_index_error("Index " + dformat("%u",i) + " out of range");\r
+        return m_definitions[m_values[i].m_definition].kind();\r
+      }\r
+\r
+    cli_parser::mode_t mode(unsigned i) const throw(cli_index_error)\r
+      {\r
+        if (i >= m_values.size()) throw cli_index_error("Index " + dformat("%u",i) + " out of range");\r
+        return m_definitions[m_values[i].m_definition].mode();\r
+      }\r
+\r
+//     unsigned add_definition(const std::string& name,\r
+//                             cli_parser::kind_t kind,\r
+//                             cli_parser::mode_t mode,\r
+//                             const std::string& message)\r
+//       {\r
+//         return add_definition(cli_parser::definition(name, kind, mode, message));\r
+//       }\r
+\r
+    unsigned find_definition(const std::string& name)\r
+      {\r
+        // this does substring matching on the definitions and returns the first\r
+        // match - however, it requires at least one character in the substring so\r
+        // that the "" convention for command line arguments doesn't match with\r
+        // anything. It returns size() if it fails\r
+        for (unsigned i = 0; i < m_definitions.size(); i++)\r
+        {\r
+          std::string candidate = m_definitions[i].name();\r
+          if ((candidate.empty() && name.empty()) ||\r
+              (!name.empty() && candidate.size() >= name.size() && candidate.substr(0,name.size()) == name))\r
+            return i;\r
+        }\r
+        return m_definitions.size();\r
+      }\r
+\r
+    void clear_definitions(void)\r
+      {\r
+        m_definitions.clear();\r
+        m_values.clear();\r
+        reset_level();\r
+        set_valid();\r
+      }\r
+\r
+    void reset_level(void)\r
+      {\r
+        // the starting level is 1 so that later functions can call clear_level with\r
+        // a value of m_level-1 without causing underflow\r
+        m_level = 1;\r
+      }\r
+\r
+    void increase_level(void)\r
+      {\r
+        m_level++;\r
+      }\r
+\r
+    void clear_level(unsigned definition, unsigned level)\r
+      {\r
+        // clears all values with this definition at the specified level or below\r
+        for (std::vector<cli_value>::iterator i = m_values.begin(); i != m_values.end(); )\r
+        {\r
+          if (i->m_definition == definition && i->m_level <= level)\r
+            i = m_values.erase(i);\r
+          else\r
+            i++;\r
+        }\r
+      }\r
+\r
+    void set_valid(void)\r
+      {\r
+        m_valid = true;\r
+      }\r
+\r
+    void set_invalid(void)\r
+      {\r
+        m_valid = false;\r
+      }\r
+\r
+    bool valid(void) const\r
+      {\r
+        return m_valid;\r
+      }\r
+\r
+    unsigned add_value(unsigned definition, const std::string& value, const std::string& source)\r
+      {\r
+        // behaviour depends on mode:\r
+        //  - single: erase all previous values\r
+        //  - multiple: erase values at a lower level than current\r
+        //  - cumulative: erase no previous values\r
+        switch (m_definitions[definition].mode())\r
+        {\r
+        case cli_single_mode:\r
+          clear_level(definition, m_level);\r
+          break;\r
+        case cli_multiple_mode:\r
+          clear_level(definition, m_level-1);\r
+          break;\r
+        case cli_cumulative_mode:\r
+          break;\r
+        }\r
+        m_values.push_back(cli_value(definition,value,m_level,source));\r
+        return m_values.size()-1;\r
+      }\r
+\r
+    unsigned add_switch(unsigned definition, bool value, const std::string& source)\r
+      {\r
+        return add_value(definition, value ? "on" : "off", source);\r
+      }\r
+\r
+    void erase_value(unsigned definition)\r
+      {\r
+        // this simply erases all previous values\r
+        clear_level(definition, m_level);\r
+      }\r
+\r
+    void add_ini_file(const std::string& file)\r
+      {\r
+        m_ini_files.push_back(file);\r
+      }\r
+\r
+    unsigned ini_file_size(void) const\r
+      {\r
+        return m_ini_files.size();\r
+      }\r
+\r
+    const std::string& ini_file(unsigned i) const\r
+      {\r
+        return m_ini_files[i];\r
+      }\r
+\r
+    unsigned add_checked_definition(const cli_parser::definition& definition) throw(cli_mode_error)\r
+      {\r
+        // check for stupid combinations\r
+        // at this stage the only really stupid one is to declare command line arguments to be switch mode\r
+        if (definition.name().empty() && definition.kind() == cli_switch_kind) \r
+        {\r
+          set_invalid();\r
+          throw cli_mode_error("CLI arguments cannot be switch kind");\r
+        }\r
+        // add the definition to the set of all definitions\r
+        unsigned i = add_definition(definition);\r
+        // also add it to the list of values, but only if it has a default value\r
+        if (!definition.default_value().empty())\r
+          add_value(i, definition.default_value(), "builtin default");\r
+        return i;\r
+      }\r
+\r
+    bool switch_value(unsigned i) const throw(cli_mode_error,cli_index_error)\r
+      {\r
+        if (i >= m_values.size()) throw cli_index_error("Index " + dformat("%u",i) + " out of range");\r
+        if (kind(i) != cli_switch_kind) throw cli_mode_error(name(i) + " is not a switch kind");\r
+        std::string value = m_values[i].m_value;\r
+        return value == "on" || value == "true" || value == "1";\r
+      }\r
+\r
+    std::string string_value(unsigned i) const throw(cli_mode_error,cli_index_error)\r
+      {\r
+        if (i >= m_values.size()) throw cli_index_error("Index " + dformat("%u",i) + " out of range");\r
+        if (kind(i) != cli_value_kind) throw cli_mode_error(name(i) + " is not a value kind");\r
+        return m_values[i].m_value;\r
+      }\r
+\r
+    void set_defaults(const ini_manager& defaults, const std::string& ini_section) throw()\r
+      {\r
+        // import default values from the Ini Manager\r
+        increase_level();\r
+        // get the set of all names from the Ini manager so that illegal names generate meaningful error messages\r
+        std::vector<std::string> names = defaults.variable_names(ini_section);\r
+        for (unsigned i = 0; i < names.size(); i++)\r
+        {\r
+          std::string name = names[i];\r
+          unsigned definition = find_definition(name);\r
+          if (definition == (unsigned)-1)\r
+          {\r
+            // not found - give an error report\r
+            message_position position(defaults.variable_filename(ini_section,name),\r
+                                      defaults.variable_linenumber(ini_section,name),\r
+                                      0);\r
+            m_messages.error(position,"CLI_INI_VARIABLE", name);\r
+          }\r
+          else\r
+          {\r
+            // found - so add the value\r
+            // multi-valued variables are entered as a comma-separated list and this is then turned into a vector\r
+            // the vector is empty if the value was empty\r
+            std::vector<std::string> values = defaults.variable_values(ini_section, name);\r
+            // an empty string is used to negate the value\r
+            if (values.empty())\r
+              erase_value(definition);\r
+            else\r
+            {\r
+              std::string source = filespec_to_relative_path(defaults.variable_filename(ini_section, name));\r
+              for (unsigned j = 0; j < values.size(); j++)\r
+                add_value(definition, values[j], source);\r
+            }\r
+          }\r
+        }\r
+        // add the set of ini files to the list for usage reports\r
+        for (unsigned j = 0; j < defaults.size(); j++)\r
+          add_ini_file(defaults.filename(j));\r
+      }\r
+\r
+    bool parse(char* argv[]) throw(cli_argument_error,message_handler_id_error,message_handler_format_error)\r
+      {\r
+        bool result = true;\r
+        if (!argv) throw cli_argument_error("Argument vector cannot be null");\r
+        increase_level();\r
+        if (argv[0])\r
+          m_executable = argv[0];\r
+        for (unsigned i = 1; argv[i]; i++)\r
+        {\r
+          std::string name = argv[i];\r
+          if (!name.empty() && name[0] == '-')\r
+          {\r
+            // we have a command line option\r
+            unsigned found = find_definition(name.substr(1, name.size()-1));\r
+            if (found < m_definitions.size())\r
+            {\r
+              // found it in its positive form\r
+              switch (m_definitions[found].kind())\r
+              {\r
+              case cli_switch_kind:\r
+                add_switch(found, true, "command line");\r
+                break;\r
+              case cli_value_kind:\r
+                // get the next argument in argv as the value of this option\r
+                // first check that there is a next value\r
+                if (!argv[i+1])\r
+                  result &= m_messages.error("CLI_VALUE_MISSING", name);\r
+                else\r
+                  add_value(found, argv[++i], "command line");\r
+                break;\r
+              }\r
+            }\r
+            else if (name.size() > 3 && name.substr(1,2) == "no")\r
+            {\r
+              found = find_definition(name.substr(3, name.size()-3));\r
+              if (found < m_definitions.size())\r
+              {\r
+                // found it in its negated form\r
+                switch (m_definitions[found].kind())\r
+                {\r
+                case cli_switch_kind:\r
+                  add_switch(found, false, "command line");\r
+                  break;\r
+                case cli_value_kind:\r
+                  erase_value(found);\r
+                  break;\r
+                }\r
+              }\r
+              else\r
+              {\r
+                // could not find this option in either its true or negated form\r
+                result &= m_messages.error("CLI_UNRECOGNISED_OPTION", name);\r
+              }\r
+            }\r
+            else\r
+            {\r
+              // could not find this option and it could not be negated\r
+              result &= m_messages.error("CLI_UNRECOGNISED_OPTION", name);\r
+            }\r
+          }\r
+          else\r
+          {\r
+            // we have a command-line value which is represented internally as an option with an empty string as its name\r
+            // some very obscure commands do not have values - only options, so allow for that case too\r
+            unsigned found = find_definition("");\r
+            if (found < m_definitions.size())\r
+              add_value(found, name, "command line");\r
+            else\r
+              result &= m_messages.error("CLI_NO_VALUES", name);\r
+          }\r
+        }\r
+        if (!result) set_invalid();\r
+        return result;\r
+      }\r
+\r
+    void usage(void) const throw(std::runtime_error)\r
+      {\r
+        m_messages.information("CLI_USAGE_PROGRAM", m_executable);\r
+        m_messages.information("CLI_USAGE_DEFINITIONS");\r
+        for (unsigned d = 0; d < m_definitions.size(); d++)\r
+          m_messages.information(m_definitions[d].message());\r
+        if (m_values.size() != 0)\r
+        {\r
+          m_messages.information("CLI_USAGE_VALUES");\r
+          for (unsigned v = 0; v < m_values.size(); v++)\r
+          {\r
+            std::string source = m_values[v].m_source;\r
+            std::string key = name(v);\r
+            if (key.empty())\r
+            {\r
+              // command-line values\r
+              m_messages.information("CLI_USAGE_VALUE_RESULT", string_value(v), source);\r
+            }\r
+            else if (kind(v) == cli_switch_kind)\r
+            {\r
+              // a switch\r
+              m_messages.information("CLI_USAGE_SWITCH_RESULT", (switch_value(v) ? name(v) : "no" + name(v)), source);\r
+            }\r
+            else\r
+            {\r
+              // other values\r
+              std::vector<std::string> args;\r
+              args.push_back(name(v));\r
+              args.push_back(string_value(v));\r
+              args.push_back(source);\r
+              m_messages.information("CLI_USAGE_OPTION_RESULT", args);\r
+            }\r
+          }\r
+        }\r
+        if (ini_file_size() > 0)\r
+        {\r
+          m_messages.information("CLI_INI_HEADER");\r
+          for (unsigned i = 0; i < ini_file_size(); i++)\r
+          {\r
+            if (file_exists(ini_file(i)))\r
+              m_messages.information("CLI_INI_FILE_PRESENT", filespec_to_relative_path(ini_file(i)));\r
+            else\r
+              m_messages.information("CLI_INI_FILE_ABSENT", filespec_to_relative_path(ini_file(i)));\r
+          }\r
+        }\r
+      }\r
+\r
+  private:\r
+    // make this class uncopyable\r
+    cli_parser_data(const cli_parser_data&);\r
+    cli_parser_data& operator = (const cli_parser_data&);\r
+  };\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+  cli_parser::cli_parser(message_handler& messages) throw() : \r
+    m_data(new cli_parser_data(messages))\r
+  {\r
+  }\r
+\r
+  cli_parser::cli_parser(cli_parser::definitions_t definitions, message_handler& messages) throw(cli_mode_error) : \r
+    m_data(new cli_parser_data(messages))\r
+  {\r
+    add_definitions(definitions);\r
+  }\r
+\r
+  cli_parser::cli_parser(cli_parser::definitions_t definitions, const ini_manager& defaults, const std::string& ini_section, message_handler& messages)  throw(cli_mode_error) : \r
+    m_data(new cli_parser_data(messages))\r
+  {\r
+    add_definitions(definitions);\r
+    set_defaults(defaults, ini_section);\r
+  }\r
+\r
+  cli_parser::cli_parser(char* argv[], cli_parser::definitions_t definitions, message_handler& messages)  throw(cli_mode_error,message_handler_id_error,message_handler_format_error) : \r
+    m_data(new cli_parser_data(messages))\r
+  {\r
+    add_definitions(definitions);\r
+    parse(argv);\r
+  }\r
+\r
+  cli_parser::cli_parser(char* argv[], cli_parser::definitions_t definitions, const ini_manager& defaults, const std::string& ini_section, message_handler& messages)  throw(cli_mode_error,message_handler_id_error,message_handler_format_error) : \r
+    m_data(new cli_parser_data(messages))\r
+  {\r
+    add_definitions(definitions);\r
+    set_defaults(defaults, ini_section);\r
+    parse(argv);\r
+  }\r
+\r
+  cli_parser::cli_parser(cli_parser::definitions definitions, message_handler& messages) throw(cli_mode_error) : \r
+    m_data(new cli_parser_data(messages))\r
+  {\r
+    add_definitions(definitions);\r
+  }\r
+\r
+  cli_parser::cli_parser(cli_parser::definitions definitions, const ini_manager& defaults, const std::string& ini_section, message_handler& messages)  throw(cli_mode_error) : \r
+    m_data(new cli_parser_data(messages))\r
+  {\r
+    add_definitions(definitions);\r
+    set_defaults(defaults, ini_section);\r
+  }\r
+\r
+  cli_parser::cli_parser(char* argv[], cli_parser::definitions definitions, message_handler& messages)  throw(cli_mode_error,message_handler_id_error,message_handler_format_error) : \r
+    m_data(new cli_parser_data(messages))\r
+  {\r
+    add_definitions(definitions);\r
+    parse(argv);\r
+  }\r
+\r
+  cli_parser::cli_parser(char* argv[], cli_parser::definitions definitions, const ini_manager& defaults, const std::string& ini_section, message_handler& messages)  throw(cli_mode_error,message_handler_id_error,message_handler_format_error) : \r
+    m_data(new cli_parser_data(messages))\r
+  {\r
+    add_definitions(definitions);\r
+    set_defaults(defaults, ini_section);\r
+    parse(argv);\r
+  }\r
+\r
+  cli_parser::~cli_parser(void) throw()\r
+  {\r
+  }\r
+\r
+  void cli_parser::add_definitions(cli_parser::definitions_t definitions) throw(cli_mode_error)\r
+  {\r
+    m_data->clear_definitions();\r
+    // the definitions array is terminated by a definition with a null name pointer\r
+    for (unsigned i = 0; definitions[i].m_name; i++)\r
+      add_definition(definitions[i]);\r
+  }\r
+\r
+  unsigned cli_parser::add_definition(const cli_parser::definition_t& definition) throw(cli_mode_error,cli_argument_error)\r
+  {\r
+    std::string name = definition.m_name ? definition.m_name : "";\r
+    std::string message = definition.m_message ? definition.m_message : "";\r
+    std::string value = definition.m_default ? definition.m_default : "";\r
+    return add_definition(cli_parser::definition(name, definition.m_kind, definition.m_mode, message, value));\r
+  }\r
+\r
+  void cli_parser::add_definitions(cli_parser::definitions definitions) throw(cli_mode_error)\r
+  {\r
+    m_data->clear_definitions();\r
+    for (unsigned i = 0; i < definitions.size(); i++)\r
+      add_definition(definitions[i]);\r
+  }\r
+\r
+  unsigned cli_parser::add_definition(const cli_parser::definition& definition) throw(cli_mode_error)\r
+  {\r
+    return m_data->add_checked_definition(definition);\r
+  }\r
+\r
+  void cli_parser::set_defaults(const ini_manager& defaults, const std::string& ini_section) throw()\r
+  {\r
+    m_data->set_defaults(defaults, ini_section);\r
+  }\r
+\r
+  bool cli_parser::parse(char* argv[]) throw(cli_argument_error,message_handler_id_error,message_handler_format_error)\r
+  {\r
+    return m_data->parse(argv);\r
+  }\r
+\r
+  bool cli_parser::valid(void) throw()\r
+  {\r
+    return m_data->valid();\r
+  }\r
+\r
+  unsigned cli_parser::size(void) const throw()\r
+  {\r
+    return m_data->m_values.size();\r
+  }\r
+\r
+  std::string cli_parser::name(unsigned i) const throw(cli_index_error)\r
+  {\r
+    return m_data->name(i);\r
+  }\r
+\r
+  unsigned cli_parser::id(unsigned i) const throw(cli_index_error)\r
+  {\r
+    return m_data->id(i);\r
+  }\r
+\r
+  cli_parser::kind_t cli_parser::kind(unsigned i) const throw(cli_index_error)\r
+  {\r
+    return m_data->kind(i);\r
+  }\r
+\r
+  bool cli_parser::switch_kind(unsigned i) const throw(cli_index_error)\r
+  {\r
+    return kind(i) == cli_switch_kind;\r
+  }\r
+\r
+  bool cli_parser::value_kind(unsigned i) const throw(cli_index_error)\r
+  {\r
+    return kind(i) == cli_value_kind;\r
+  }\r
+\r
+  cli_parser::mode_t cli_parser::mode(unsigned i) const throw(cli_index_error)\r
+  {\r
+    return m_data->mode(i);\r
+  }\r
+\r
+  bool cli_parser::single_mode(unsigned i) const throw(cli_index_error)\r
+  {\r
+    return mode(i) == cli_single_mode;\r
+  }\r
+\r
+  bool cli_parser::multiple_mode(unsigned i) const throw(cli_index_error)\r
+  {\r
+    return mode(i) == cli_multiple_mode;\r
+  }\r
+\r
+  bool cli_parser::cumulative_mode(unsigned i) const throw(cli_index_error)\r
+  {\r
+    return mode(i) == cli_cumulative_mode;\r
+  }\r
+\r
+  bool cli_parser::switch_value(unsigned i) const throw(cli_mode_error,cli_index_error)\r
+  {\r
+    return m_data->switch_value(i);\r
+  }\r
+\r
+  std::string cli_parser::string_value(unsigned i) const throw(cli_mode_error,cli_index_error)\r
+  {\r
+    return m_data->string_value(i);\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+  void cli_parser::usage(void) const throw(std::runtime_error)\r
+  {\r
+    m_data->usage();\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+} // end namespace stlplus\r
This page took 0.038237 seconds and 4 git commands to generate.