|
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