|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r58184 - in trunk: boost/program_options boost/program_options/detail libs/program_options/src libs/program_options/test
From: s.ochsenknecht_at_[hidden]
Date: 2009-12-06 04:52:55
Author: s_ochsenknecht
Date: 2009-12-06 04:52:53 EST (Sun, 06 Dec 2009)
New Revision: 58184
URL: http://svn.boost.org/trac/boost/changeset/58184
Log:
Better detection of missing values on command line, Fixes #3423
Text files modified:
trunk/boost/program_options/detail/cmdline.hpp | 3 +
trunk/boost/program_options/errors.hpp | 2 +
trunk/libs/program_options/src/cmdline.cpp | 47 ++++++++++++++++++++++++++++++---------
trunk/libs/program_options/test/cmdline_test.cpp | 6 +++-
trunk/libs/program_options/test/exception_test.cpp | 29 ++++++++++++++++++++++++
5 files changed, 73 insertions(+), 14 deletions(-)
Modified: trunk/boost/program_options/detail/cmdline.hpp
==============================================================================
--- trunk/boost/program_options/detail/cmdline.hpp (original)
+++ trunk/boost/program_options/detail/cmdline.hpp 2009-12-06 04:52:53 EST (Sun, 06 Dec 2009)
@@ -114,7 +114,8 @@
void
finish_option(option& opt,
- std::vector<std::string>& other_tokens);
+ std::vector<std::string>& other_tokens,
+ const std::vector<style_parser>& style_parsers);
// Copies of input.
std::vector<std::string> args;
Modified: trunk/boost/program_options/errors.hpp
==============================================================================
--- trunk/boost/program_options/errors.hpp (original)
+++ trunk/boost/program_options/errors.hpp 2009-12-06 04:52:53 EST (Sun, 06 Dec 2009)
@@ -43,6 +43,8 @@
kind_t kind() const;
+ const std::string& tokens() const;
+
protected:
/** Used to convert kind_t to a related error text */
static std::string error_message(kind_t kind);
Modified: trunk/libs/program_options/src/cmdline.cpp
==============================================================================
--- trunk/libs/program_options/src/cmdline.cpp (original)
+++ trunk/libs/program_options/src/cmdline.cpp 2009-12-06 04:52:53 EST (Sun, 06 Dec 2009)
@@ -81,6 +81,12 @@
{
return m_kind;
}
+
+ const string&
+ invalid_syntax::tokens() const
+ {
+ return m_tokens;
+ }
invalid_command_line_syntax::
invalid_command_line_syntax(const std::string& tokens, kind_t kind)
@@ -239,12 +245,12 @@
{
vector<string> e;
for(unsigned k = 0; k < next.size()-1; ++k) {
- finish_option(next[k], e);
+ finish_option(next[k], e, style_parsers);
}
// For the last option, pass the unparsed tokens
// so that they can be added to next.back()'s values
// if appropriate.
- finish_option(next.back(), args);
+ finish_option(next.back(), args, style_parsers);
for (unsigned j = 0; j < next.size(); ++j)
result.push_back(next[j]);
}
@@ -348,8 +354,9 @@
void
cmdline::finish_option(option& opt,
- vector<string>& other_tokens)
- {
+ vector<string>& other_tokens,
+ const vector<style_parser>& style_parsers)
+ {
if (opt.string_key.empty())
return;
@@ -387,16 +394,16 @@
if (present_tokens >= min_tokens)
{
- if (!opt.value.empty() && max_tokens == 0) {
+ if (!opt.value.empty() && max_tokens == 0)
+ {
boost::throw_exception(invalid_command_line_syntax(opt.string_key,
invalid_command_line_syntax::extra_parameter));
}
- // If an option wants, at minimum, N tokens, we grab them
- // there and don't care if they look syntactically like an
- // option.
-
- if (opt.value.size() <= min_tokens)
+ // If an option wants, at minimum, N tokens, we grab them there,
+ // when adding these tokens as values to current option we check
+ // if they look like options
+ if (opt.value.size() <= min_tokens)
{
min_tokens -= opt.value.size();
}
@@ -406,7 +413,25 @@
}
// Everything's OK, move the values to the result.
- for(;!other_tokens.empty() && min_tokens--; ) {
+ for(;!other_tokens.empty() && min_tokens--; )
+ {
+ // check if extra parameter looks like a known option
+ // we use style parsers to check if it is syntactically an option,
+ // additionally we check if an option_description exists
+ vector<option> followed_option;
+ vector<string> next_token(1, other_tokens[0]);
+ for (unsigned i = 0; followed_option.empty() && i < style_parsers.size(); ++i)
+ {
+ followed_option = style_parsers[i](next_token);
+ }
+ if (!followed_option.empty())
+ {
+ const option_description* od = m_desc->find_nothrow(other_tokens[0],
+ (m_style & allow_guessing) ? true : false);
+ if (od)
+ boost::throw_exception(invalid_command_line_syntax(opt.string_key,
+ invalid_command_line_syntax::missing_parameter));
+ }
opt.value.push_back(other_tokens[0]);
opt.original_tokens.push_back(other_tokens[0]);
other_tokens.erase(other_tokens.begin());
Modified: trunk/libs/program_options/test/cmdline_test.cpp
==============================================================================
--- trunk/libs/program_options/test/cmdline_test.cpp (original)
+++ trunk/libs/program_options/test/cmdline_test.cpp 2009-12-06 04:52:53 EST (Sun, 06 Dec 2009)
@@ -30,6 +30,7 @@
const int s_empty_adjacent_parameter = 6;
const int s_missing_parameter = 7;
const int s_extra_parameter = 8;
+const int s_unrecognized_line = 9;
int translate_syntax_error_kind(invalid_command_line_syntax::kind_t k)
{
@@ -40,6 +41,7 @@
invalid_command_line_syntax::empty_adjacent_parameter,
invalid_command_line_syntax::missing_parameter,
invalid_command_line_syntax::extra_parameter,
+ invalid_command_line_syntax::unrecognized_line
};
invalid_command_line_syntax::kind_t *b, *e, *i;
b = table;
@@ -262,7 +264,7 @@
{"-f -13", s_success, "-f:-13"},
{"-f", s_missing_parameter, ""},
{"-f /foo", s_success, "-f:/foo"},
- {"-f -d", s_success, "-f:-d"},
+ {"-f -d", s_missing_parameter, ""},
{0, 0, 0}
};
test_cmdline(",d ,f=", style, test_cases2);
@@ -274,7 +276,7 @@
test_case test_cases3[] = {
{"-f10", s_success, "-f:10"},
{"-f 10", s_success, "-f:10"},
- {"-f -d", s_success, "-f:-d"},
+ {"-f -d", s_missing_parameter, ""},
{0, 0, 0}
};
test_cmdline(",d ,f=", style, test_cases3);
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-06 04:52:53 EST (Sun, 06 Dec 2009)
@@ -44,6 +44,8 @@
}
}
+
+
void test_unknown_option()
{
options_description desc;
@@ -98,6 +100,7 @@
}
+
void test_multiple_occurrences()
{
options_description desc;
@@ -122,6 +125,31 @@
+void test_missing_value()
+{
+ options_description desc;
+ desc.add_options()
+ ("cfgfile,c", value<string>()->multitoken(), "the config file")
+ ("output,o", value<string>(), "the output file")
+ ;
+ // missing value for option '-c'
+ const char* cmdline[] = { "program", "-c", "-c", "output.txt"};
+
+ variables_map vm;
+
+ try {
+ store(parse_command_line(sizeof(cmdline)/sizeof(const char*),
+ const_cast<char**>(cmdline), desc), vm);
+ notify(vm);
+ }
+ catch (invalid_command_line_syntax& e)
+ {
+ BOOST_CHECK_EQUAL(e.kind(), invalid_syntax::missing_parameter);
+ BOOST_CHECK_EQUAL(e.tokens(), "cfgfile");
+ }
+}
+
+
int main(int /*ac*/, char** /*av*/)
{
@@ -129,6 +157,7 @@
test_unknown_option();
test_multiple_values();
test_multiple_occurrences();
+ test_missing_value();
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