diff options
Diffstat (limited to '3rdParty/Boost/src/libs/program_options/src/cmdline.cpp')
-rw-r--r-- | 3rdParty/Boost/src/libs/program_options/src/cmdline.cpp | 324 |
1 files changed, 192 insertions, 132 deletions
diff --git a/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp b/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp index be31385..cd9a5fe 100644 --- a/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp @@ -34,64 +34,43 @@ namespace boost { namespace program_options { using namespace std; using namespace boost::program_options::command_line_style; - invalid_syntax:: - invalid_syntax(const string& tokens, kind_t kind) - : error(error_message(kind).append(" in '").append(tokens).append("'")) - , m_tokens(tokens) - , m_kind(kind) - {} string - invalid_syntax::error_message(kind_t kind) + invalid_syntax::get_template(kind_t kind) { // Initially, store the message in 'const char*' variable, // to avoid conversion to string in all cases. const char* msg; switch(kind) { + case empty_adjacent_parameter: + msg = "the argument for option '%canonical_option%' should follow immediately after the equal sign"; + break; + case missing_parameter: + msg = "the required argument for option '%canonical_option%' is missing"; + break; + case unrecognized_line: + msg = "the options configuration file contains an invalid line '%invalid_line%'"; + break; + // none of the following are currently used: case long_not_allowed: - msg = "long options are not allowed"; + msg = "the unabbreviated option '%canonical_option%' is not valid"; break; case long_adjacent_not_allowed: - msg = "parameters adjacent to long options not allowed"; + msg = "the unabbreviated option '%canonical_option%' does not take any arguments"; break; case short_adjacent_not_allowed: - msg = "parameters adjust to short options are not allowed"; - break; - case empty_adjacent_parameter: - msg = "adjacent parameter is empty"; - break; - case missing_parameter: - msg = "required parameter is missing"; + msg = "the abbreviated option '%canonical_option%' does not take any arguments"; break; case extra_parameter: - msg = "extra parameter"; - break; - case unrecognized_line: - msg = "unrecognized line"; + msg = "option '%canonical_option%' does not take any arguments"; break; default: - msg = "unknown error"; + msg = "unknown command line syntax error for '%s'"; } return msg; } - invalid_syntax::kind_t - invalid_syntax::kind() const - { - return m_kind; - } - - const string& - invalid_syntax::tokens() const - { - return m_tokens; - } - - invalid_command_line_syntax:: - invalid_command_line_syntax(const string& tokens, kind_t kind) - : invalid_syntax(tokens, kind) - {} }} @@ -156,15 +135,26 @@ namespace boost { namespace program_options { namespace detail { const char* error = 0; if (allow_some_long && !(style & long_allow_adjacent) && !(style & long_allow_next)) - error = "style disallows parameters for long options"; + error = "boost::program_options misconfiguration: " + "choose one or other of 'command_line_style::long_allow_next' " + "(whitespace separated arguments) or " + "'command_line_style::long_allow_adjacent' ('=' separated arguments) for " + "long options."; if (!error && (style & allow_short) && !(style & short_allow_adjacent) && !(style & short_allow_next)) - error = "style disallows parameters for short options"; + error = "boost::program_options misconfiguration: " + "choose one or other of 'command_line_style::short_allow_next' " + "(whitespace separated arguments) or " + "'command_line_style::short_allow_adjacent' ('=' separated arguments) for " + "short options."; if (!error && (style & allow_short) && !(style & allow_dash_for_short) && !(style & allow_slash_for_short)) - error = "style disallows all characters for short options"; + error = "boost::program_options misconfiguration: " + "choose one or other of 'command_line_style::allow_slash_for_short' " + "(slashes) or 'command_line_style::allow_dash_for_short' (dashes) for " + "short options."; if (error) boost::throw_exception(invalid_command_line_style(error)); @@ -192,6 +182,23 @@ namespace boost { namespace program_options { namespace detail { m_positional = &positional; } + int + cmdline::get_canonical_option_prefix() + { + if (m_style & allow_long) + return allow_long; + + if (m_style & allow_long_disguise) + return allow_long_disguise; + + if ((m_style & allow_short) && (m_style & allow_dash_for_short)) + return allow_dash_for_short; + + if ((m_style & allow_short) && (m_style & allow_slash_for_short)) + return allow_slash_for_short; + + return 0; + } vector<option> cmdline::run() @@ -242,7 +249,7 @@ namespace boost { namespace program_options { namespace detail { bool ok = false; for(unsigned i = 0; i < style_parsers.size(); ++i) { - unsigned current_size = args.size(); + unsigned current_size = static_cast<unsigned>(args.size()); vector<option> next = style_parsers[i](args); // Check that option names @@ -277,7 +284,7 @@ namespace boost { namespace program_options { namespace detail { } /* If an key option is followed by a positional option, - can can consume more tokens (e.g. it's multitoke option), + can can consume more tokens (e.g. it's multitoken option), give those tokens to it. */ vector<option> result2; for (unsigned i = 0; i < result.size(); ++i) @@ -288,11 +295,21 @@ namespace boost { namespace program_options { namespace detail { if (opt.string_key.empty()) continue; - const option_description* xd = - m_desc->find_nothrow(opt.string_key, - is_style_active(allow_guessing), - is_style_active(long_case_insensitive), - is_style_active(short_case_insensitive)); + const option_description* xd; + try + { + xd = m_desc->find_nothrow(opt.string_key, + is_style_active(allow_guessing), + is_style_active(long_case_insensitive), + is_style_active(short_case_insensitive)); + } + catch(error_with_option_name& e) + { + // add context and rethrow + e.add_context(opt.string_key, opt.original_tokens[0], get_canonical_option_prefix()); + throw; + } + if (!xd) continue; @@ -304,7 +321,7 @@ namespace boost { namespace program_options { namespace detail { // We only allow to grab tokens that are not already // recognized as key options. - int can_take_more = max_tokens - opt.value.size(); + int can_take_more = max_tokens - static_cast<int>(opt.value.size()); unsigned j = i+1; for (; can_take_more && j < result.size(); --can_take_more, ++j) { @@ -383,92 +400,112 @@ namespace boost { namespace program_options { namespace detail { if (opt.string_key.empty()) return; - // First check that the option is valid, and get its description. - const option_description* xd = m_desc->find_nothrow(opt.string_key, - is_style_active(allow_guessing), - is_style_active(long_case_insensitive), - is_style_active(short_case_insensitive)); + // + // Be defensive: + // will have no original token if option created by handle_additional_parser() + std::string original_token_for_exceptions = opt.string_key; + if (opt.original_tokens.size()) + original_token_for_exceptions = opt.original_tokens[0]; - if (!xd) + try { - if (m_allow_unregistered) { - opt.unregistered = true; - return; - } else { - boost::throw_exception(unknown_option(opt.string_key)); - } - } - const option_description& d = *xd; + // First check that the option is valid, and get its description. + const option_description* xd = m_desc->find_nothrow(opt.string_key, + is_style_active(allow_guessing), + is_style_active(long_case_insensitive), + is_style_active(short_case_insensitive)); - // Canonize the name - opt.string_key = d.key(opt.string_key); + if (!xd) + { + if (m_allow_unregistered) { + opt.unregistered = true; + return; + } else { + boost::throw_exception(unknown_option()); + } + } + const option_description& d = *xd; - // We check that the min/max number of tokens for the option - // agrees with the number of tokens we have. The 'adjacent_value' - // (the value in --foo=1) counts as a separate token, and if present - // must be consumed. The following tokens on the command line may be - // left unconsumed. + // Canonize the name + opt.string_key = d.key(opt.string_key); - // We don't check if those tokens look like option, or not! + // We check that the min/max number of tokens for the option + // agrees with the number of tokens we have. The 'adjacent_value' + // (the value in --foo=1) counts as a separate token, and if present + // must be consumed. The following tokens on the command line may be + // left unconsumed. - unsigned min_tokens = d.semantic()->min_tokens(); - unsigned max_tokens = d.semantic()->max_tokens(); - - unsigned present_tokens = opt.value.size() + other_tokens.size(); - - if (present_tokens >= min_tokens) - { - 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, - // 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(); - } - else - { - min_tokens = 0; - } + // We don't check if those tokens look like option, or not! - // Everything's OK, move the values to the result. - for(;!other_tokens.empty() && min_tokens--; ) + unsigned min_tokens = d.semantic()->min_tokens(); + unsigned max_tokens = d.semantic()->max_tokens(); + + unsigned present_tokens = static_cast<unsigned>(opt.value.size() + other_tokens.size()); + + if (present_tokens >= 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) + if (!opt.value.empty() && max_tokens == 0) + { + boost::throw_exception( + invalid_command_line_syntax(invalid_command_line_syntax::extra_parameter)); + } + + // 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) { - followed_option = style_parsers[i](next_token); + min_tokens -= static_cast<unsigned>(opt.value.size()); } - if (!followed_option.empty()) + else { - const option_description* od = m_desc->find_nothrow(other_tokens[0], - is_style_active(allow_guessing), - is_style_active(long_case_insensitive), - is_style_active(short_case_insensitive)); - if (od) - boost::throw_exception(invalid_command_line_syntax(opt.string_key, - invalid_command_line_syntax::missing_parameter)); + min_tokens = 0; + } + + // Everything's OK, move the values to the result. + 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()) + { + original_token_for_exceptions = other_tokens[0]; + const option_description* od = m_desc->find_nothrow(other_tokens[0], + is_style_active(allow_guessing), + is_style_active(long_case_insensitive), + is_style_active(short_case_insensitive)); + if (od) + boost::throw_exception( + invalid_command_line_syntax(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()); } - opt.value.push_back(other_tokens[0]); - opt.original_tokens.push_back(other_tokens[0]); - other_tokens.erase(other_tokens.begin()); } - } - else - { - boost::throw_exception(invalid_command_line_syntax(opt.string_key, - invalid_command_line_syntax::missing_parameter)); + else + { + boost::throw_exception( + invalid_command_line_syntax(invalid_command_line_syntax::missing_parameter)); + } + } + // use only original token for unknown_option / ambiguous_option since by definition + // they are unrecognised / unparsable + catch(error_with_option_name& e) + { + // add context and rethrow + e.add_context(opt.string_key, original_token_for_exceptions, get_canonical_option_prefix()); + throw; } + } vector<option> @@ -486,8 +523,11 @@ namespace boost { namespace program_options { namespace detail { name = tok.substr(2, p-2); adjacent = tok.substr(p+1); if (adjacent.empty()) - boost::throw_exception( invalid_command_line_syntax(name, - invalid_command_line_syntax::empty_adjacent_parameter) ); + boost::throw_exception( invalid_command_line_syntax( + invalid_command_line_syntax::empty_adjacent_parameter, + name, + name, + get_canonical_option_prefix()) ); } else { @@ -523,9 +563,20 @@ 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_nothrow(name, false, false, - is_style_active(short_case_insensitive)); + const option_description* d; + try + { + + d = m_desc->find_nothrow(name, false, false, + is_style_active(short_case_insensitive)); + } + catch(error_with_option_name& e) + { + // add context and rethrow + e.add_context(name, name, get_canonical_option_prefix()); + throw; + } + // FIXME: check for 'allow_sticky'. if (d && (m_style & allow_sticky) && @@ -589,15 +640,24 @@ namespace boost { namespace program_options { namespace detail { ((tok[0] == '-' && tok[1] != '-') || ((m_style & allow_slash_for_short) && tok[0] == '/'))) { - if (m_desc->find_nothrow(tok.substr(1, tok.find('=')-1), - is_style_active(allow_guessing), - is_style_active(long_case_insensitive), - is_style_active(short_case_insensitive))) + try + { + if (m_desc->find_nothrow(tok.substr(1, tok.find('=')-1), + is_style_active(allow_guessing), + is_style_active(long_case_insensitive), + is_style_active(short_case_insensitive))) + { + args[0].insert(0, "-"); + if (args[0][1] == '/') + args[0][1] = '-'; + return parse_long_option(args); + } + } + catch(error_with_option_name& e) { - args[0].insert(0, "-"); - if (args[0][1] == '/') - args[0][1] = '-'; - return parse_long_option(args); + // add context and rethrow + e.add_context(tok, tok, get_canonical_option_prefix()); + throw; } } return vector<option>(); |