diff --git a/include/boost/program_options/option.hpp b/include/boost/program_options/option.hpp index dd7e133..e5eb0ad 100644 --- a/include/boost/program_options/option.hpp +++ b/include/boost/program_options/option.hpp @@ -23,10 +23,10 @@ namespace boost { namespace program_options { template class basic_option { public: - basic_option() : position_key(-1) {} + basic_option() : position_key(-1), unregistered(false) {} basic_option(const std::string& string_key, const std::vector< std::string> &value) - : string_key(string_key), value(value) + : string_key(string_key), value(value), unregistered(false) {} /** String key of this option. Intentionally independent of the template @@ -41,6 +41,10 @@ namespace boost { namespace program_options { int position_key; /** Option's value */ std::vector< std::basic_string > value; + /** True if option was not recognized. In that case, + 'string_key' and 'value' are results of purely + syntactic parsing of source. */ + bool unregistered; }; typedef basic_option option; typedef basic_option woption; diff --git a/src/cmdline.cpp b/src/cmdline.cpp index 1b2e4aa..5d3f7d7 100644 --- a/src/cmdline.cpp +++ b/src/cmdline.cpp @@ -112,6 +112,7 @@ namespace boost { namespace program_options { namespace detail { m_style = command_line_style::default_style; m_desc = 0; m_positional = 0; + m_allow_unregistered = false; } void @@ -288,8 +289,19 @@ namespace boost { namespace program_options { namespace detail { // First check that the option is valid, and get its description. // TODO: case-sensitivity. - const option_description& d = - m_desc->find(opt.string_key, (m_style & allow_guessing)); + const option_description* xd = + m_desc->find_nothrow(opt.string_key, (m_style & allow_guessing)); + + if (!xd) + { + if (m_allow_unregistered) { + opt.unregistered = true; + return; + } else { + throw_exception(unknown_option(opt.string_key)); + } + } + const option_description& d = *xd; // Canonize the name opt.string_key = d.key(opt.string_key); @@ -381,11 +393,12 @@ namespace boost { namespace program_options { namespace detail { // of token is considered to be value, not further grouped // option. for(;;) { - const option_description& d = m_desc->find(name, false); + const option_description* d + = m_desc->find_nothrow(name, false); // FIXME: check for 'allow_sticky'. - if ((m_style & allow_sticky) && - d.semantic()->max_tokens() == 0 && !adjacent.empty()) { + if (d && (m_style & allow_sticky) && + d->semantic()->max_tokens() == 0 && !adjacent.empty()) { // 'adjacent' is in fact further option. option opt; opt.string_key = name;