Boost logo

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