Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r58152 - in trunk: boost/program_options libs/program_options/src libs/program_options/test
From: s.ochsenknecht_at_[hidden]
Date: 2009-12-05 03:08:46


Author: s_ochsenknecht
Date: 2009-12-05 03:08:45 EST (Sat, 05 Dec 2009)
New Revision: 58152
URL: http://svn.boost.org/trac/boost/changeset/58152

Log:
better detection of ambiguous options, see Ticket #3423
Text files modified:
   trunk/boost/program_options/errors.hpp | 6 +++-
   trunk/libs/program_options/src/options_description.cpp | 35 ++++++++++++++++++-------------
   trunk/libs/program_options/src/value_semantic.cpp | 6 +++++
   trunk/libs/program_options/test/exception_test.cpp | 44 +++++++++++++++++++++++----------------
   4 files changed, 56 insertions(+), 35 deletions(-)

Modified: trunk/boost/program_options/errors.hpp
==============================================================================
--- trunk/boost/program_options/errors.hpp (original)
+++ trunk/boost/program_options/errors.hpp 2009-12-05 03:08:45 EST (Sat, 05 Dec 2009)
@@ -78,17 +78,19 @@
         ambiguous_option(const std::string& name,
                          const std::vector<std::string>& alternatives)
         : error(std::string("ambiguous option ").append(name))
- , alternatives(alternatives)
+ , m_alternatives(alternatives)
         , m_option_name(name)
         {}
 
         ~ambiguous_option() throw() {}
         
         const std::string& get_option_name() const throw();
+
+ const std::vector<std::string>& alternatives() const throw();
 
     private:
         // TODO: copy ctor might throw
- std::vector<std::string> alternatives;
+ std::vector<std::string> m_alternatives;
         std::string m_option_name;
     };
 

Modified: trunk/libs/program_options/src/options_description.cpp
==============================================================================
--- trunk/libs/program_options/src/options_description.cpp (original)
+++ trunk/libs/program_options/src/options_description.cpp 2009-12-05 03:08:45 EST (Sat, 05 Dec 2009)
@@ -273,6 +273,8 @@
     {
         shared_ptr<option_description> found;
         vector<string> approximate_matches;
+ vector<string> full_matches;
+
         // We use linear search because matching specified option
         // name with the declared option name need to take care about
         // case sensitivity and trailing '*' and so we can't use simple map.
@@ -284,26 +286,29 @@
             if (r == option_description::no_match)
                 continue;
 
- // If we have a full patch, and an approximate match,
- // ignore approximate match instead of reporting error.
- // Say, if we have options "all" and "all-chroots", then
- // "--all" on the command line should select the first one,
- // without ambiguity.
- //
- // For now, we don't check the situation when there are
- // two full matches.
-
             if (r == option_description::full_match)
- {
- return m_options[i].get();
+ {
+ full_matches.push_back(m_options[i]->key(name));
+ }
+ else
+ {
+ // FIXME: the use of 'key' here might not
+ // be the best approach.
+ approximate_matches.push_back(m_options[i]->key(name));
             }
 
             found = m_options[i];
- // FIXME: the use of 'key' here might not
- // be the best approach.
- approximate_matches.push_back(m_options[i]->key(name));
         }
- if (approximate_matches.size() > 1)
+ if (full_matches.size() > 1)
+ boost::throw_exception(
+ ambiguous_option(name, full_matches));
+
+ // If we have a full match, and an approximate match,
+ // ignore approximate match instead of reporting error.
+ // Say, if we have options "all" and "all-chroots", then
+ // "--all" on the command line should select the first one,
+ // without ambiguity.
+ if (full_matches.empty() && approximate_matches.size() > 1)
             boost::throw_exception(
                 ambiguous_option(name, approximate_matches));
 

Modified: trunk/libs/program_options/src/value_semantic.cpp
==============================================================================
--- trunk/libs/program_options/src/value_semantic.cpp (original)
+++ trunk/libs/program_options/src/value_semantic.cpp 2009-12-05 03:08:45 EST (Sat, 05 Dec 2009)
@@ -227,6 +227,12 @@
     {
         return m_option_name;
     }
+
+ const std::vector<std::string>&
+ ambiguous_option::alternatives() const throw()
+ {
+ return m_alternatives;
+ }
 
     void
     multiple_values::set_option_name(const std::string& option_name)

Modified: trunk/libs/program_options/test/exception_test.cpp
==============================================================================
--- trunk/libs/program_options/test/exception_test.cpp (original)
+++ trunk/libs/program_options/test/exception_test.cpp 2009-12-05 03:08:45 EST (Sat, 05 Dec 2009)
@@ -19,6 +19,30 @@
 #include "minitest.hpp"
 
 
+void test_ambiguous()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>()->multitoken(), "the config file")
+ ("output,c", value<string>(), "the output file")
+ ("output,o", value<string>(), "the output file")
+ ;
+
+ const char* cmdline[] = {"program", "-c", "file", "-o", "anotherfile"};
+
+ variables_map vm;
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ }
+ catch (ambiguous_option& e)
+ {
+ BOOST_CHECK_EQUAL(e.alternatives().size(), 2);
+ BOOST_CHECK_EQUAL(e.get_option_name(), "-c");
+ BOOST_CHECK_EQUAL(e.alternatives()[0], "cfgfile");
+ BOOST_CHECK_EQUAL(e.alternatives()[1], "output");
+ }
+}
 
 void test_unknown_option()
 {
@@ -101,27 +125,11 @@
 
 int main(int /*ac*/, char** /*av*/)
 {
+ test_ambiguous();
    test_unknown_option();
    test_multiple_values();
    test_multiple_occurrences();
 
- bool helpflag = false;
-
- options_description desc;
- desc.add_options()
- ("cfgfile,c", value<string>(), "the configfile")
- ("help,h", value<bool>(&helpflag)->implicit_value(true), "help")
- ;
-
- const char* cmdline[] = {"program", "--cfgfile", "hugo", "-h", "yes" };
-
- variables_map vm;
- store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
- const_cast<char**>(cmdline), desc), vm);
- notify(vm);
-
- cout << " help: " << (helpflag ? "true" : "false") << endl;
-
-
    return 0;
 }
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk