diff options
author | neksard <neksard@yandex-team.ru> | 2022-02-10 16:45:23 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:23 +0300 |
commit | 8f7cf138264e0caa318144bf8a2c950e0b0a8593 (patch) | |
tree | 83bf5c8c8047c42d8475e6095df90ccdc3d1b57f /contrib/restricted/boost/libs/program_options | |
parent | d3a398281c6fd1d3672036cb2d63f842d2cb28c5 (diff) | |
download | ydb-8f7cf138264e0caa318144bf8a2c950e0b0a8593.tar.gz |
Restoring authorship annotation for <neksard@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/restricted/boost/libs/program_options')
11 files changed, 2885 insertions, 2885 deletions
diff --git a/contrib/restricted/boost/libs/program_options/src/cmdline.cpp b/contrib/restricted/boost/libs/program_options/src/cmdline.cpp index c2cf1da11f..e1ddccea9a 100644 --- a/contrib/restricted/boost/libs/program_options/src/cmdline.cpp +++ b/contrib/restricted/boost/libs/program_options/src/cmdline.cpp @@ -1,713 +1,713 @@ -// Copyright Vladimir Prus 2002-2004. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_PROGRAM_OPTIONS_SOURCE -#include <boost/program_options/config.hpp> - -#include <boost/config.hpp> - -#include <boost/program_options/detail/cmdline.hpp> -#include <boost/program_options/errors.hpp> -#include <boost/program_options/value_semantic.hpp> -#include <boost/program_options/options_description.hpp> -#include <boost/program_options/positional_options.hpp> -#include <boost/throw_exception.hpp> - -#include <boost/bind.hpp> - -#include <string> -#include <utility> -#include <vector> -#include <cassert> -#include <cstring> -#include <cctype> -#include <climits> - -#include <cstdio> - -#include <iostream> - -namespace boost { namespace program_options { - - using namespace std; - using namespace boost::program_options::command_line_style; - - - string - 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 = "the unabbreviated option '%canonical_option%' is not valid"; - break; - case long_adjacent_not_allowed: - msg = "the unabbreviated option '%canonical_option%' does not take any arguments"; - break; - case short_adjacent_not_allowed: - msg = "the abbreviated option '%canonical_option%' does not take any arguments"; - break; - case extra_parameter: - msg = "option '%canonical_option%' does not take any arguments"; - break; - default: - msg = "unknown command line syntax error for '%s'"; - } - return msg; - } - - -}} - - -namespace boost { namespace program_options { namespace detail { - - // vc6 needs this, but borland chokes when this is added. -#if BOOST_WORKAROUND(_MSC_VER, < 1300) - using namespace std; - using namespace program_options; -#endif - - - cmdline::cmdline(const vector<string>& args) - { - init(args); - } - - cmdline::cmdline(int argc, const char*const * argv) - { -#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) - vector<string> args; - copy(argv+1, argv+argc+!argc, inserter(args, args.end())); - init(args); -#else - init(vector<string>(argv+1, argv+argc+!argc)); -#endif - } - - void - cmdline::init(const vector<string>& args) - { - this->m_args = args; - m_style = command_line_style::default_style; - m_desc = 0; - m_positional = 0; - m_allow_unregistered = false; - } - - void - cmdline::style(int style) - { - if (style == 0) - style = default_style; - - check_style(style); - this->m_style = style_t(style); - } - - void - cmdline::allow_unregistered() - { - this->m_allow_unregistered = true; - } - - void - cmdline::check_style(int style) const - { - bool allow_some_long = - (style & allow_long) || (style & allow_long_disguise); - - const char* error = 0; - if (allow_some_long && - !(style & long_allow_adjacent) && !(style & long_allow_next)) - 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 = "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 = "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)); - - // Need to check that if guessing and long disguise are enabled - // -f will mean the same as -foo - } - - bool - cmdline::is_style_active(style_t style) const - { - return ((m_style & style) ? true : false); - } - - void - cmdline::set_options_description(const options_description& desc) - { - m_desc = &desc; - } - +// Copyright Vladimir Prus 2002-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> + +#include <boost/config.hpp> + +#include <boost/program_options/detail/cmdline.hpp> +#include <boost/program_options/errors.hpp> +#include <boost/program_options/value_semantic.hpp> +#include <boost/program_options/options_description.hpp> +#include <boost/program_options/positional_options.hpp> +#include <boost/throw_exception.hpp> + +#include <boost/bind.hpp> + +#include <string> +#include <utility> +#include <vector> +#include <cassert> +#include <cstring> +#include <cctype> +#include <climits> + +#include <cstdio> + +#include <iostream> + +namespace boost { namespace program_options { + + using namespace std; + using namespace boost::program_options::command_line_style; + + + string + 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 = "the unabbreviated option '%canonical_option%' is not valid"; + break; + case long_adjacent_not_allowed: + msg = "the unabbreviated option '%canonical_option%' does not take any arguments"; + break; + case short_adjacent_not_allowed: + msg = "the abbreviated option '%canonical_option%' does not take any arguments"; + break; + case extra_parameter: + msg = "option '%canonical_option%' does not take any arguments"; + break; + default: + msg = "unknown command line syntax error for '%s'"; + } + return msg; + } + + +}} + + +namespace boost { namespace program_options { namespace detail { + + // vc6 needs this, but borland chokes when this is added. +#if BOOST_WORKAROUND(_MSC_VER, < 1300) + using namespace std; + using namespace program_options; +#endif + + + cmdline::cmdline(const vector<string>& args) + { + init(args); + } + + cmdline::cmdline(int argc, const char*const * argv) + { +#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) + vector<string> args; + copy(argv+1, argv+argc+!argc, inserter(args, args.end())); + init(args); +#else + init(vector<string>(argv+1, argv+argc+!argc)); +#endif + } + void - cmdline::set_positional_options( - const positional_options_description& positional) - { - 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() - { - // The parsing is done by having a set of 'style parsers' - // and trying then in order. Each parser is passed a vector - // of unparsed tokens and can consume some of them (by - // removing elements on front) and return a vector of options. - // - // We try each style parser in turn, untill some input - // is consumed. The returned vector of option may contain the - // result of just syntactic parsing of token, say --foo will - // be parsed as option with name 'foo', and the style parser - // is not required to care if that option is defined, and how - // many tokens the value may take. - // So, after vector is returned, we validate them. - assert(m_desc); - - vector<style_parser> style_parsers; - - if (m_style_parser) - style_parsers.push_back(m_style_parser); - - if (m_additional_parser) - style_parsers.push_back( - boost::bind(&cmdline::handle_additional_parser, this, _1)); - - if (m_style & allow_long) - style_parsers.push_back( - boost::bind(&cmdline::parse_long_option, this, _1)); - - if ((m_style & allow_long_disguise)) - style_parsers.push_back( - boost::bind(&cmdline::parse_disguised_long_option, this, _1)); - - if ((m_style & allow_short) && (m_style & allow_dash_for_short)) - style_parsers.push_back( - boost::bind(&cmdline::parse_short_option, this, _1)); - - if ((m_style & allow_short) && (m_style & allow_slash_for_short)) - style_parsers.push_back(boost::bind(&cmdline::parse_dos_option, this, _1)); - - style_parsers.push_back(boost::bind(&cmdline::parse_terminator, this, _1)); - - vector<option> result; - vector<string>& args = m_args; - while(!args.empty()) - { - bool ok = false; - for(unsigned i = 0; i < style_parsers.size(); ++i) - { - unsigned current_size = static_cast<unsigned>(args.size()); - vector<option> next = style_parsers[i](args); - - // Check that option names - // are valid, and that all values are in place. - if (!next.empty()) - { - vector<string> e; - for(unsigned k = 0; k < next.size()-1; ++k) { - 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, style_parsers); - for (unsigned j = 0; j < next.size(); ++j) - result.push_back(next[j]); - } - - if (args.size() != current_size) { - ok = true; - break; + cmdline::init(const vector<string>& args) + { + this->m_args = args; + m_style = command_line_style::default_style; + m_desc = 0; + m_positional = 0; + m_allow_unregistered = false; + } + + void + cmdline::style(int style) + { + if (style == 0) + style = default_style; + + check_style(style); + this->m_style = style_t(style); + } + + void + cmdline::allow_unregistered() + { + this->m_allow_unregistered = true; + } + + void + cmdline::check_style(int style) const + { + bool allow_some_long = + (style & allow_long) || (style & allow_long_disguise); + + const char* error = 0; + if (allow_some_long && + !(style & long_allow_adjacent) && !(style & long_allow_next)) + 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 = "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 = "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)); + + // Need to check that if guessing and long disguise are enabled + // -f will mean the same as -foo + } + + bool + cmdline::is_style_active(style_t style) const + { + return ((m_style & style) ? true : false); + } + + void + cmdline::set_options_description(const options_description& desc) + { + m_desc = &desc; + } + + void + cmdline::set_positional_options( + const positional_options_description& positional) + { + 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() + { + // The parsing is done by having a set of 'style parsers' + // and trying then in order. Each parser is passed a vector + // of unparsed tokens and can consume some of them (by + // removing elements on front) and return a vector of options. + // + // We try each style parser in turn, untill some input + // is consumed. The returned vector of option may contain the + // result of just syntactic parsing of token, say --foo will + // be parsed as option with name 'foo', and the style parser + // is not required to care if that option is defined, and how + // many tokens the value may take. + // So, after vector is returned, we validate them. + assert(m_desc); + + vector<style_parser> style_parsers; + + if (m_style_parser) + style_parsers.push_back(m_style_parser); + + if (m_additional_parser) + style_parsers.push_back( + boost::bind(&cmdline::handle_additional_parser, this, _1)); + + if (m_style & allow_long) + style_parsers.push_back( + boost::bind(&cmdline::parse_long_option, this, _1)); + + if ((m_style & allow_long_disguise)) + style_parsers.push_back( + boost::bind(&cmdline::parse_disguised_long_option, this, _1)); + + if ((m_style & allow_short) && (m_style & allow_dash_for_short)) + style_parsers.push_back( + boost::bind(&cmdline::parse_short_option, this, _1)); + + if ((m_style & allow_short) && (m_style & allow_slash_for_short)) + style_parsers.push_back(boost::bind(&cmdline::parse_dos_option, this, _1)); + + style_parsers.push_back(boost::bind(&cmdline::parse_terminator, this, _1)); + + vector<option> result; + vector<string>& args = m_args; + while(!args.empty()) + { + bool ok = false; + for(unsigned i = 0; i < style_parsers.size(); ++i) + { + unsigned current_size = static_cast<unsigned>(args.size()); + vector<option> next = style_parsers[i](args); + + // Check that option names + // are valid, and that all values are in place. + if (!next.empty()) + { + vector<string> e; + for(unsigned k = 0; k < next.size()-1; ++k) { + 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, style_parsers); + for (unsigned j = 0; j < next.size(); ++j) + result.push_back(next[j]); } - } - - if (!ok) { - option opt; - opt.value.push_back(args[0]); - opt.original_tokens.push_back(args[0]); - result.push_back(opt); - args.erase(args.begin()); - } - } - - /* If an key option is followed by a positional 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) - { - result2.push_back(result[i]); - option& opt = result2.back(); - - if (opt.string_key.empty()) - continue; - - 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)); + + if (args.size() != current_size) { + ok = true; + break; + } + } + + if (!ok) { + option opt; + opt.value.push_back(args[0]); + opt.original_tokens.push_back(args[0]); + result.push_back(opt); + args.erase(args.begin()); } - 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; - - unsigned min_tokens = xd->semantic()->min_tokens(); - unsigned max_tokens = xd->semantic()->max_tokens(); - if (min_tokens < max_tokens && opt.value.size() < max_tokens) - { - // This option may grab some more tokens. - // We only allow to grab tokens that are not already - // recognized as key options. - - 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) - { - option& opt2 = result[j]; - if (!opt2.string_key.empty()) - break; - - if (opt2.position_key == INT_MAX) - { - // We use INT_MAX to mark positional options that - // were found after the '--' terminator and therefore - // should stay positional forever. - break; - } - - assert(opt2.value.size() == 1); - - opt.value.push_back(opt2.value[0]); - - assert(opt2.original_tokens.size() == 1); - - opt.original_tokens.push_back(opt2.original_tokens[0]); - } - i = j-1; - } - } - result.swap(result2); - - - // Assign position keys to positional options. - int position_key = 0; - for(unsigned i = 0; i < result.size(); ++i) { - if (result[i].string_key.empty()) - result[i].position_key = position_key++; - } - - if (m_positional) - { - unsigned position = 0; - for (unsigned i = 0; i < result.size(); ++i) { - option& opt = result[i]; - if (opt.position_key != -1) { - if (position >= m_positional->max_total_count()) - { - boost::throw_exception(too_many_positional_options_error()); - } - opt.string_key = m_positional->name_for_position(position); - ++position; - } - } - } - - // set case sensitive flag - for (unsigned i = 0; i < result.size(); ++i) { - if (result[i].string_key.size() > 2 || - (result[i].string_key.size() > 1 && result[i].string_key[0] != '-')) - { - // it is a long option - result[i].case_insensitive = is_style_active(long_case_insensitive); - } - else - { - // it is a short option - result[i].case_insensitive = is_style_active(short_case_insensitive); - } - } - - return result; - } - - void - cmdline::finish_option(option& opt, - vector<string>& other_tokens, - const vector<style_parser>& style_parsers) - { - if (opt.string_key.empty()) - return; - - // - // 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]; - - try - { - // 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)); - - if (!xd) - { - if (m_allow_unregistered) { - opt.unregistered = true; - return; - } else { - boost::throw_exception(unknown_option()); - } - } - const option_description& d = *xd; - - // Canonize the name - opt.string_key = d.key(opt.string_key); - - // 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 = static_cast<unsigned>(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(invalid_command_line_syntax::extra_parameter)); - } - - // Grab min_tokens values from other_tokens, but only if those tokens - // are not recognized as options themselves. - if (opt.value.size() <= min_tokens) - { - min_tokens -= static_cast<unsigned>(opt.value.size()); - } - else - { - 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()); - } - } - 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> - cmdline::parse_long_option(vector<string>& args) - { - vector<option> result; - const string& tok = args[0]; - if (tok.size() >= 3 && tok[0] == '-' && tok[1] == '-') - { - string name, adjacent; - - string::size_type p = tok.find('='); - if (p != tok.npos) - { - name = tok.substr(2, p-2); - adjacent = tok.substr(p+1); - if (adjacent.empty()) - boost::throw_exception( invalid_command_line_syntax( - invalid_command_line_syntax::empty_adjacent_parameter, - name, - name, - get_canonical_option_prefix()) ); - } - else - { - name = tok.substr(2); - } - option opt; - opt.string_key = name; - if (!adjacent.empty()) - opt.value.push_back(adjacent); - opt.original_tokens.push_back(tok); - result.push_back(opt); - args.erase(args.begin()); - } - return result; - } - - - vector<option> - cmdline::parse_short_option(vector<string>& args) - { - const string& tok = args[0]; - if (tok.size() >= 2 && tok[0] == '-' && tok[1] != '-') - { - vector<option> result; - - string name = tok.substr(0,2); - string adjacent = tok.substr(2); - - // Short options can be 'grouped', so that - // "-d -a" becomes "-da". Loop, processing one - // option at a time. We exit the loop when either - // we've processed all the token, or when the remainder - // of token is considered to be value, not further grouped - // option. - for(;;) { - const option_description* d; - try - { + + /* If an key option is followed by a positional 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) + { + result2.push_back(result[i]); + option& opt = result2.back(); + + if (opt.string_key.empty()) + continue; + + 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; + + unsigned min_tokens = xd->semantic()->min_tokens(); + unsigned max_tokens = xd->semantic()->max_tokens(); + if (min_tokens < max_tokens && opt.value.size() < max_tokens) + { + // This option may grab some more tokens. + // We only allow to grab tokens that are not already + // recognized as key options. + + 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) + { + option& opt2 = result[j]; + if (!opt2.string_key.empty()) + break; + + if (opt2.position_key == INT_MAX) + { + // We use INT_MAX to mark positional options that + // were found after the '--' terminator and therefore + // should stay positional forever. + break; + } + + assert(opt2.value.size() == 1); - d = m_desc->find_nothrow(name, false, false, - is_style_active(short_case_insensitive)); + opt.value.push_back(opt2.value[0]); + + assert(opt2.original_tokens.size() == 1); + + opt.original_tokens.push_back(opt2.original_tokens[0]); } - 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) && - d->semantic()->max_tokens() == 0 && !adjacent.empty()) { - // 'adjacent' is in fact further option. - option opt; - opt.string_key = name; - result.push_back(opt); - - if (adjacent.empty()) - { - args.erase(args.begin()); - break; - } - - name = string("-") + adjacent[0]; - adjacent.erase(adjacent.begin()); - } else { - - option opt; - opt.string_key = name; - opt.original_tokens.push_back(tok); - if (!adjacent.empty()) - opt.value.push_back(adjacent); - result.push_back(opt); - args.erase(args.begin()); - break; - } - } - return result; - } - return vector<option>(); - } - - vector<option> - cmdline::parse_dos_option(vector<string>& args) - { - vector<option> result; - const string& tok = args[0]; - if (tok.size() >= 2 && tok[0] == '/') - { - string name = "-" + tok.substr(1,1); - string adjacent = tok.substr(2); - - option opt; - opt.string_key = name; - if (!adjacent.empty()) - opt.value.push_back(adjacent); - opt.original_tokens.push_back(tok); - result.push_back(opt); - args.erase(args.begin()); - } - return result; - } - - vector<option> - cmdline::parse_disguised_long_option(vector<string>& args) - { - const string& tok = args[0]; - if (tok.size() >= 2 && - ((tok[0] == '-' && tok[1] != '-') || - ((m_style & allow_slash_for_short) && tok[0] == '/'))) - { - 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); - } + i = j-1; } - catch(error_with_option_name& e) - { - // add context and rethrow - e.add_context(tok, tok, get_canonical_option_prefix()); - throw; - } - } - return vector<option>(); - } - - vector<option> - cmdline::parse_terminator(vector<string>& args) - { - vector<option> result; - const string& tok = args[0]; - if (tok == "--") - { - for(unsigned i = 1; i < args.size(); ++i) - { - option opt; - opt.value.push_back(args[i]); - opt.original_tokens.push_back(args[i]); - opt.position_key = INT_MAX; - result.push_back(opt); - } - args.clear(); - } - return result; - } - - vector<option> - cmdline::handle_additional_parser(vector<string>& args) - { - vector<option> result; - pair<string, string> r = m_additional_parser(args[0]); - if (!r.first.empty()) { - option next; - next.string_key = r.first; - if (!r.second.empty()) - next.value.push_back(r.second); - result.push_back(next); - args.erase(args.begin()); - } - return result; - } - - void - cmdline::set_additional_parser(additional_parser p) - { - m_additional_parser = p; - } - + } + result.swap(result2); + + + // Assign position keys to positional options. + int position_key = 0; + for(unsigned i = 0; i < result.size(); ++i) { + if (result[i].string_key.empty()) + result[i].position_key = position_key++; + } + + if (m_positional) + { + unsigned position = 0; + for (unsigned i = 0; i < result.size(); ++i) { + option& opt = result[i]; + if (opt.position_key != -1) { + if (position >= m_positional->max_total_count()) + { + boost::throw_exception(too_many_positional_options_error()); + } + opt.string_key = m_positional->name_for_position(position); + ++position; + } + } + } + + // set case sensitive flag + for (unsigned i = 0; i < result.size(); ++i) { + if (result[i].string_key.size() > 2 || + (result[i].string_key.size() > 1 && result[i].string_key[0] != '-')) + { + // it is a long option + result[i].case_insensitive = is_style_active(long_case_insensitive); + } + else + { + // it is a short option + result[i].case_insensitive = is_style_active(short_case_insensitive); + } + } + + return result; + } + void - cmdline::extra_style_parser(style_parser s) - { - m_style_parser = s; - } - - - -}}} + cmdline::finish_option(option& opt, + vector<string>& other_tokens, + const vector<style_parser>& style_parsers) + { + if (opt.string_key.empty()) + return; + + // + // 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]; + + try + { + // 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)); + + if (!xd) + { + if (m_allow_unregistered) { + opt.unregistered = true; + return; + } else { + boost::throw_exception(unknown_option()); + } + } + const option_description& d = *xd; + + // Canonize the name + opt.string_key = d.key(opt.string_key); + + // 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 = static_cast<unsigned>(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(invalid_command_line_syntax::extra_parameter)); + } + + // Grab min_tokens values from other_tokens, but only if those tokens + // are not recognized as options themselves. + if (opt.value.size() <= min_tokens) + { + min_tokens -= static_cast<unsigned>(opt.value.size()); + } + else + { + 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()); + } + } + 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> + cmdline::parse_long_option(vector<string>& args) + { + vector<option> result; + const string& tok = args[0]; + if (tok.size() >= 3 && tok[0] == '-' && tok[1] == '-') + { + string name, adjacent; + + string::size_type p = tok.find('='); + if (p != tok.npos) + { + name = tok.substr(2, p-2); + adjacent = tok.substr(p+1); + if (adjacent.empty()) + boost::throw_exception( invalid_command_line_syntax( + invalid_command_line_syntax::empty_adjacent_parameter, + name, + name, + get_canonical_option_prefix()) ); + } + else + { + name = tok.substr(2); + } + option opt; + opt.string_key = name; + if (!adjacent.empty()) + opt.value.push_back(adjacent); + opt.original_tokens.push_back(tok); + result.push_back(opt); + args.erase(args.begin()); + } + return result; + } + + + vector<option> + cmdline::parse_short_option(vector<string>& args) + { + const string& tok = args[0]; + if (tok.size() >= 2 && tok[0] == '-' && tok[1] != '-') + { + vector<option> result; + + string name = tok.substr(0,2); + string adjacent = tok.substr(2); + + // Short options can be 'grouped', so that + // "-d -a" becomes "-da". Loop, processing one + // option at a time. We exit the loop when either + // we've processed all the token, or when the remainder + // of token is considered to be value, not further grouped + // option. + for(;;) { + 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) && + d->semantic()->max_tokens() == 0 && !adjacent.empty()) { + // 'adjacent' is in fact further option. + option opt; + opt.string_key = name; + result.push_back(opt); + + if (adjacent.empty()) + { + args.erase(args.begin()); + break; + } + + name = string("-") + adjacent[0]; + adjacent.erase(adjacent.begin()); + } else { + + option opt; + opt.string_key = name; + opt.original_tokens.push_back(tok); + if (!adjacent.empty()) + opt.value.push_back(adjacent); + result.push_back(opt); + args.erase(args.begin()); + break; + } + } + return result; + } + return vector<option>(); + } + + vector<option> + cmdline::parse_dos_option(vector<string>& args) + { + vector<option> result; + const string& tok = args[0]; + if (tok.size() >= 2 && tok[0] == '/') + { + string name = "-" + tok.substr(1,1); + string adjacent = tok.substr(2); + + option opt; + opt.string_key = name; + if (!adjacent.empty()) + opt.value.push_back(adjacent); + opt.original_tokens.push_back(tok); + result.push_back(opt); + args.erase(args.begin()); + } + return result; + } + + vector<option> + cmdline::parse_disguised_long_option(vector<string>& args) + { + const string& tok = args[0]; + if (tok.size() >= 2 && + ((tok[0] == '-' && tok[1] != '-') || + ((m_style & allow_slash_for_short) && tok[0] == '/'))) + { + 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) + { + // add context and rethrow + e.add_context(tok, tok, get_canonical_option_prefix()); + throw; + } + } + return vector<option>(); + } + + vector<option> + cmdline::parse_terminator(vector<string>& args) + { + vector<option> result; + const string& tok = args[0]; + if (tok == "--") + { + for(unsigned i = 1; i < args.size(); ++i) + { + option opt; + opt.value.push_back(args[i]); + opt.original_tokens.push_back(args[i]); + opt.position_key = INT_MAX; + result.push_back(opt); + } + args.clear(); + } + return result; + } + + vector<option> + cmdline::handle_additional_parser(vector<string>& args) + { + vector<option> result; + pair<string, string> r = m_additional_parser(args[0]); + if (!r.first.empty()) { + option next; + next.string_key = r.first; + if (!r.second.empty()) + next.value.push_back(r.second); + result.push_back(next); + args.erase(args.begin()); + } + return result; + } + + void + cmdline::set_additional_parser(additional_parser p) + { + m_additional_parser = p; + } + + void + cmdline::extra_style_parser(style_parser s) + { + m_style_parser = s; + } + + + +}}} diff --git a/contrib/restricted/boost/libs/program_options/src/config_file.cpp b/contrib/restricted/boost/libs/program_options/src/config_file.cpp index f2a57b4b82..e33143987a 100644 --- a/contrib/restricted/boost/libs/program_options/src/config_file.cpp +++ b/contrib/restricted/boost/libs/program_options/src/config_file.cpp @@ -1,198 +1,198 @@ -// Copyright Vladimir Prus 2002-2004. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - - -#define BOOST_PROGRAM_OPTIONS_SOURCE -#include <boost/program_options/config.hpp> - -#include <boost/program_options/detail/config_file.hpp> -#include <boost/program_options/errors.hpp> -#include <boost/program_options/detail/convert.hpp> -#include <boost/throw_exception.hpp> - -#include <iostream> -#include <fstream> -#include <cassert> - -namespace boost { namespace program_options { namespace detail { - - using namespace std; - - common_config_file_iterator::common_config_file_iterator( - const std::set<std::string>& allowed_options, - bool allow_unregistered) - : allowed_options(allowed_options), - m_allow_unregistered(allow_unregistered) - { - for(std::set<std::string>::const_iterator i = allowed_options.begin(); - i != allowed_options.end(); - ++i) - { - add_option(i->c_str()); - } - } - - void - common_config_file_iterator::add_option(const char* name) - { - string s(name); - assert(!s.empty()); - if (*s.rbegin() == '*') { - s.resize(s.size()-1); - bool bad_prefixes(false); - // If 's' is a prefix of one of allowed suffix, then - // lower_bound will return that element. - // If some element is prefix of 's', then lower_bound will - // return the next element. - set<string>::iterator i = allowed_prefixes.lower_bound(s); - if (i != allowed_prefixes.end()) { - if (i->find(s) == 0) - bad_prefixes = true; - } - if (i != allowed_prefixes.begin()) { - --i; - if (s.find(*i) == 0) - bad_prefixes = true; - } - if (bad_prefixes) - boost::throw_exception(error("options '" + string(name) + "' and '" + - *i + "*' will both match the same " - "arguments from the configuration file")); - allowed_prefixes.insert(s); - } - } - - namespace { - string trim_ws(const string& s) - { - string::size_type n, n2; - n = s.find_first_not_of(" \t\r\n"); - if (n == string::npos) - return string(); - else { - n2 = s.find_last_not_of(" \t\r\n"); - return s.substr(n, n2-n+1); - } - } - } - - - void common_config_file_iterator::get() - { - string s; - string::size_type n; - bool found = false; - - while(this->getline(s)) { - - // strip '#' comments and whitespace - if ((n = s.find('#')) != string::npos) - s = s.substr(0, n); - s = trim_ws(s); - - if (!s.empty()) { - // Handle section name - if (*s.begin() == '[' && *s.rbegin() == ']') { - m_prefix = s.substr(1, s.size()-2); - if (*m_prefix.rbegin() != '.') - m_prefix += '.'; - } - else if ((n = s.find('=')) != string::npos) { - - string name = m_prefix + trim_ws(s.substr(0, n)); - string value = trim_ws(s.substr(n+1)); - - bool registered = allowed_option(name); - if (!registered && !m_allow_unregistered) - boost::throw_exception(unknown_option(name)); - - found = true; - this->value().string_key = name; - this->value().value.clear(); - this->value().value.push_back(value); - this->value().unregistered = !registered; - this->value().original_tokens.clear(); - this->value().original_tokens.push_back(name); - this->value().original_tokens.push_back(value); - break; - - } else { - boost::throw_exception(invalid_config_file_syntax(s, invalid_syntax::unrecognized_line)); - } - } - } - if (!found) - found_eof(); - } - - +// Copyright Vladimir Prus 2002-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> + +#include <boost/program_options/detail/config_file.hpp> +#include <boost/program_options/errors.hpp> +#include <boost/program_options/detail/convert.hpp> +#include <boost/throw_exception.hpp> + +#include <iostream> +#include <fstream> +#include <cassert> + +namespace boost { namespace program_options { namespace detail { + + using namespace std; + + common_config_file_iterator::common_config_file_iterator( + const std::set<std::string>& allowed_options, + bool allow_unregistered) + : allowed_options(allowed_options), + m_allow_unregistered(allow_unregistered) + { + for(std::set<std::string>::const_iterator i = allowed_options.begin(); + i != allowed_options.end(); + ++i) + { + add_option(i->c_str()); + } + } + + void + common_config_file_iterator::add_option(const char* name) + { + string s(name); + assert(!s.empty()); + if (*s.rbegin() == '*') { + s.resize(s.size()-1); + bool bad_prefixes(false); + // If 's' is a prefix of one of allowed suffix, then + // lower_bound will return that element. + // If some element is prefix of 's', then lower_bound will + // return the next element. + set<string>::iterator i = allowed_prefixes.lower_bound(s); + if (i != allowed_prefixes.end()) { + if (i->find(s) == 0) + bad_prefixes = true; + } + if (i != allowed_prefixes.begin()) { + --i; + if (s.find(*i) == 0) + bad_prefixes = true; + } + if (bad_prefixes) + boost::throw_exception(error("options '" + string(name) + "' and '" + + *i + "*' will both match the same " + "arguments from the configuration file")); + allowed_prefixes.insert(s); + } + } + + namespace { + string trim_ws(const string& s) + { + string::size_type n, n2; + n = s.find_first_not_of(" \t\r\n"); + if (n == string::npos) + return string(); + else { + n2 = s.find_last_not_of(" \t\r\n"); + return s.substr(n, n2-n+1); + } + } + } + + + void common_config_file_iterator::get() + { + string s; + string::size_type n; + bool found = false; + + while(this->getline(s)) { + + // strip '#' comments and whitespace + if ((n = s.find('#')) != string::npos) + s = s.substr(0, n); + s = trim_ws(s); + + if (!s.empty()) { + // Handle section name + if (*s.begin() == '[' && *s.rbegin() == ']') { + m_prefix = s.substr(1, s.size()-2); + if (*m_prefix.rbegin() != '.') + m_prefix += '.'; + } + else if ((n = s.find('=')) != string::npos) { + + string name = m_prefix + trim_ws(s.substr(0, n)); + string value = trim_ws(s.substr(n+1)); + + bool registered = allowed_option(name); + if (!registered && !m_allow_unregistered) + boost::throw_exception(unknown_option(name)); + + found = true; + this->value().string_key = name; + this->value().value.clear(); + this->value().value.push_back(value); + this->value().unregistered = !registered; + this->value().original_tokens.clear(); + this->value().original_tokens.push_back(name); + this->value().original_tokens.push_back(value); + break; + + } else { + boost::throw_exception(invalid_config_file_syntax(s, invalid_syntax::unrecognized_line)); + } + } + } + if (!found) + found_eof(); + } + + + bool + common_config_file_iterator::allowed_option(const std::string& s) const + { + set<string>::const_iterator i = allowed_options.find(s); + if (i != allowed_options.end()) + return true; + // If s is "pa" where "p" is allowed prefix then + // lower_bound should find the element after "p". + // This depends on 'allowed_prefixes' invariant. + i = allowed_prefixes.lower_bound(s); + if (i != allowed_prefixes.begin() && s.find(*--i) == 0) + return true; + return false; + } + +#if BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4303)) || \ + (defined(__sgi) && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(741))) + template<> bool - common_config_file_iterator::allowed_option(const std::string& s) const - { - set<string>::const_iterator i = allowed_options.find(s); - if (i != allowed_options.end()) - return true; - // If s is "pa" where "p" is allowed prefix then - // lower_bound should find the element after "p". - // This depends on 'allowed_prefixes' invariant. - i = allowed_prefixes.lower_bound(s); - if (i != allowed_prefixes.begin() && s.find(*--i) == 0) - return true; - return false; - } - -#if BOOST_WORKAROUND(__COMO_VERSION__, BOOST_TESTED_AT(4303)) || \ - (defined(__sgi) && BOOST_WORKAROUND(_COMPILER_VERSION, BOOST_TESTED_AT(741))) - template<> - bool - basic_config_file_iterator<wchar_t>::getline(std::string& s) - { - std::wstring ws; - // On Comeau, using two-argument version causes - // call to some internal function with std::wstring, and '\n' - // (not L'\n') and compile can't resolve that call. - - if (std::getline(*is, ws, L'\n')) { - s = to_utf8(ws); - return true; - } else { - return false; - } - } -#endif - -}}} - -#if 0 -using boost::program_options::config_file; - -#include <sstream> -#include <cassert> - -int main() -{ - try { - stringstream s( - "a = 1\n" - "b = 2\n"); - - config_file cf(s); - cf.add_option("a"); - cf.add_option("b"); - - assert(++cf); - assert(cf.name() == "a"); - assert(cf.value() == "1"); - assert(++cf); - assert(cf.name() == "b"); - assert(cf.value() == "2"); - assert(!++cf); - } - catch(exception& e) - { - cout << e.what() << "\n"; - } -} -#endif + basic_config_file_iterator<wchar_t>::getline(std::string& s) + { + std::wstring ws; + // On Comeau, using two-argument version causes + // call to some internal function with std::wstring, and '\n' + // (not L'\n') and compile can't resolve that call. + + if (std::getline(*is, ws, L'\n')) { + s = to_utf8(ws); + return true; + } else { + return false; + } + } +#endif + +}}} + +#if 0 +using boost::program_options::config_file; + +#include <sstream> +#include <cassert> + +int main() +{ + try { + stringstream s( + "a = 1\n" + "b = 2\n"); + + config_file cf(s); + cf.add_option("a"); + cf.add_option("b"); + + assert(++cf); + assert(cf.name() == "a"); + assert(cf.value() == "1"); + assert(++cf); + assert(cf.name() == "b"); + assert(cf.value() == "2"); + assert(!++cf); + } + catch(exception& e) + { + cout << e.what() << "\n"; + } +} +#endif diff --git a/contrib/restricted/boost/libs/program_options/src/convert.cpp b/contrib/restricted/boost/libs/program_options/src/convert.cpp index 9be759e260..fc21772cf3 100644 --- a/contrib/restricted/boost/libs/program_options/src/convert.cpp +++ b/contrib/restricted/boost/libs/program_options/src/convert.cpp @@ -1,161 +1,161 @@ -// Copyright Vladimir Prus 2004. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - -#include <fstream> -#include <locale.h> -#include <locale> -#include <iostream> -#include <string> -#include <locale> -#include <stdexcept> - -#include <boost/config.hpp> - -#define BOOST_PROGRAM_OPTIONS_SOURCE -#include <boost/program_options/config.hpp> -#include <boost/program_options/detail/convert.hpp> -#include <boost/program_options/detail/utf8_codecvt_facet.hpp> -#include <boost/throw_exception.hpp> - -#include <boost/bind.hpp> - -using namespace std; - -namespace boost { namespace detail { - - /* Internal function to actually perform conversion. - The logic in from_8_bit and to_8_bit function is exactly - the same, except that one calls 'in' method of codecvt and another - calls the 'out' method, and that syntax difference makes straightforward - template implementation impossible. - - This functions takes a 'fun' argument, which should have the same - parameters and return type and the in/out methods. The actual converting - function will pass functional objects created with boost::bind. - Experiments show that the performance loss is less than 10%. - */ - template<class ToChar, class FromChar, class Fun> - std::basic_string<ToChar> - convert(const std::basic_string<FromChar>& s, Fun fun) - - { - std::basic_string<ToChar> result; - - std::mbstate_t state = std::mbstate_t(); - - const FromChar* from = s.data(); - const FromChar* from_end = s.data() + s.size(); - // The interface of cvt is not really iterator-like, and it's - // not possible the tell the required output size without the conversion. - // All we can is convert data by pieces. - while(from != from_end) { - - // std::basic_string does not provide non-const pointers to the data, - // so converting directly into string is not possible. - ToChar buffer[32]; - - ToChar* to_next = buffer; - // Need variable because boost::bind doesn't work with rvalues. - ToChar* to_end = buffer + 32; - std::codecvt_base::result r = - fun(state, from, from_end, from, buffer, to_end, to_next); - - if (r == std::codecvt_base::error) - boost::throw_exception( - std::logic_error("character conversion failed")); - // 'partial' is not an error, it just means not all source - // characters were converted. However, we need to check that at - // least one new target character was produced. If not, it means - // the source data is incomplete, and since we don't have extra - // data to add to source, it's error. - if (to_next == buffer) - boost::throw_exception( - std::logic_error("character conversion failed")); - - // Add converted characters - result.append(buffer, to_next); - } - - return result; - } -}} - -namespace boost { - -#ifndef BOOST_NO_STD_WSTRING +// Copyright Vladimir Prus 2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <fstream> +#include <locale.h> +#include <locale> +#include <iostream> +#include <string> +#include <locale> +#include <stdexcept> + +#include <boost/config.hpp> + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> +#include <boost/program_options/detail/convert.hpp> +#include <boost/program_options/detail/utf8_codecvt_facet.hpp> +#include <boost/throw_exception.hpp> + +#include <boost/bind.hpp> + +using namespace std; + +namespace boost { namespace detail { + + /* Internal function to actually perform conversion. + The logic in from_8_bit and to_8_bit function is exactly + the same, except that one calls 'in' method of codecvt and another + calls the 'out' method, and that syntax difference makes straightforward + template implementation impossible. + + This functions takes a 'fun' argument, which should have the same + parameters and return type and the in/out methods. The actual converting + function will pass functional objects created with boost::bind. + Experiments show that the performance loss is less than 10%. + */ + template<class ToChar, class FromChar, class Fun> + std::basic_string<ToChar> + convert(const std::basic_string<FromChar>& s, Fun fun) + + { + std::basic_string<ToChar> result; + + std::mbstate_t state = std::mbstate_t(); + + const FromChar* from = s.data(); + const FromChar* from_end = s.data() + s.size(); + // The interface of cvt is not really iterator-like, and it's + // not possible the tell the required output size without the conversion. + // All we can is convert data by pieces. + while(from != from_end) { + + // std::basic_string does not provide non-const pointers to the data, + // so converting directly into string is not possible. + ToChar buffer[32]; + + ToChar* to_next = buffer; + // Need variable because boost::bind doesn't work with rvalues. + ToChar* to_end = buffer + 32; + std::codecvt_base::result r = + fun(state, from, from_end, from, buffer, to_end, to_next); + + if (r == std::codecvt_base::error) + boost::throw_exception( + std::logic_error("character conversion failed")); + // 'partial' is not an error, it just means not all source + // characters were converted. However, we need to check that at + // least one new target character was produced. If not, it means + // the source data is incomplete, and since we don't have extra + // data to add to source, it's error. + if (to_next == buffer) + boost::throw_exception( + std::logic_error("character conversion failed")); + + // Add converted characters + result.append(buffer, to_next); + } + + return result; + } +}} + +namespace boost { + +#ifndef BOOST_NO_STD_WSTRING + BOOST_PROGRAM_OPTIONS_DECL std::wstring + from_8_bit(const std::string& s, + const std::codecvt<wchar_t, char, std::mbstate_t>& cvt) + { + return detail::convert<wchar_t>( + s, + boost::bind(&std::codecvt<wchar_t, char, mbstate_t>::in, + &cvt, + _1, _2, _3, _4, _5, _6, _7)); + } + + BOOST_PROGRAM_OPTIONS_DECL std::string + to_8_bit(const std::wstring& s, + const std::codecvt<wchar_t, char, std::mbstate_t>& cvt) + { + return detail::convert<char>( + s, + boost::bind(&codecvt<wchar_t, char, mbstate_t>::out, + &cvt, + _1, _2, _3, _4, _5, _6, _7)); + } + + + namespace { + boost::program_options::detail::utf8_codecvt_facet + utf8_facet; + } + BOOST_PROGRAM_OPTIONS_DECL std::wstring - from_8_bit(const std::string& s, - const std::codecvt<wchar_t, char, std::mbstate_t>& cvt) - { - return detail::convert<wchar_t>( - s, - boost::bind(&std::codecvt<wchar_t, char, mbstate_t>::in, - &cvt, - _1, _2, _3, _4, _5, _6, _7)); - } - + from_utf8(const std::string& s) + { + return from_8_bit(s, utf8_facet); + } + BOOST_PROGRAM_OPTIONS_DECL std::string - to_8_bit(const std::wstring& s, - const std::codecvt<wchar_t, char, std::mbstate_t>& cvt) - { - return detail::convert<char>( - s, - boost::bind(&codecvt<wchar_t, char, mbstate_t>::out, - &cvt, - _1, _2, _3, _4, _5, _6, _7)); - } - - - namespace { - boost::program_options::detail::utf8_codecvt_facet - utf8_facet; - } - - BOOST_PROGRAM_OPTIONS_DECL std::wstring - from_utf8(const std::string& s) - { - return from_8_bit(s, utf8_facet); - } - - BOOST_PROGRAM_OPTIONS_DECL std::string - to_utf8(const std::wstring& s) - { - return to_8_bit(s, utf8_facet); - } - - BOOST_PROGRAM_OPTIONS_DECL std::wstring - from_local_8_bit(const std::string& s) - { - typedef codecvt<wchar_t, char, mbstate_t> facet_type; - return from_8_bit(s, - BOOST_USE_FACET(facet_type, locale())); - } - - BOOST_PROGRAM_OPTIONS_DECL std::string - to_local_8_bit(const std::wstring& s) - { - typedef codecvt<wchar_t, char, mbstate_t> facet_type; - return to_8_bit(s, - BOOST_USE_FACET(facet_type, locale())); - } -#endif - - namespace program_options - { - BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::string& s) - { - return s; - } - -#ifndef BOOST_NO_STD_WSTRING - BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::wstring& s) - { - return to_utf8(s); - } -#endif - } - - -} + to_utf8(const std::wstring& s) + { + return to_8_bit(s, utf8_facet); + } + + BOOST_PROGRAM_OPTIONS_DECL std::wstring + from_local_8_bit(const std::string& s) + { + typedef codecvt<wchar_t, char, mbstate_t> facet_type; + return from_8_bit(s, + BOOST_USE_FACET(facet_type, locale())); + } + + BOOST_PROGRAM_OPTIONS_DECL std::string + to_local_8_bit(const std::wstring& s) + { + typedef codecvt<wchar_t, char, mbstate_t> facet_type; + return to_8_bit(s, + BOOST_USE_FACET(facet_type, locale())); + } +#endif + + namespace program_options + { + BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::string& s) + { + return s; + } + +#ifndef BOOST_NO_STD_WSTRING + BOOST_PROGRAM_OPTIONS_DECL std::string to_internal(const std::wstring& s) + { + return to_utf8(s); + } +#endif + } + + +} diff --git a/contrib/restricted/boost/libs/program_options/src/options_description.cpp b/contrib/restricted/boost/libs/program_options/src/options_description.cpp index 6592a5db30..6fbd8724cb 100644 --- a/contrib/restricted/boost/libs/program_options/src/options_description.cpp +++ b/contrib/restricted/boost/libs/program_options/src/options_description.cpp @@ -1,664 +1,664 @@ -// Copyright Vladimir Prus 2002-2004. -// Copyright Bertolt Mildner 2004. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - - -#define BOOST_PROGRAM_OPTIONS_SOURCE -#include <boost/program_options/config.hpp> -#include <boost/program_options/options_description.hpp> -// FIXME: this is only to get multiple_occurrences class -// should move that to a separate headers. -#include <boost/program_options/parsers.hpp> - - -#include <boost/lexical_cast.hpp> -#include <boost/tokenizer.hpp> -#include <boost/detail/workaround.hpp> -#include <boost/throw_exception.hpp> - -#include <cassert> -#include <climits> -#include <cstring> -#include <cstdarg> -#include <sstream> -#include <iterator> -using namespace std; - -namespace boost { namespace program_options { - - namespace { - - template< class charT > - std::basic_string< charT > tolower_(const std::basic_string< charT >& str) - { - std::basic_string< charT > result; - for (typename std::basic_string< charT >::size_type i = 0; i < str.size(); ++i) - { - result.append(1, static_cast< charT >(std::tolower(str[i]))); - } - return result; - } - - } // unnamed namespace - - - option_description::option_description() - { - } - - option_description:: - option_description(const char* name, - const value_semantic* s) - : m_value_semantic(s) - { - this->set_name(name); - } - - - option_description:: - option_description(const char* name, - const value_semantic* s, - const char* description) - : m_description(description), m_value_semantic(s) - { - this->set_name(name); - } - - option_description::~option_description() - { - } - - option_description::match_result - option_description::match(const std::string& option, - bool approx, - bool long_ignore_case, - bool short_ignore_case) const - { - match_result result = no_match; - - std::string local_long_name((long_ignore_case ? tolower_(m_long_name) : m_long_name)); - - if (!local_long_name.empty()) { - - std::string local_option = (long_ignore_case ? tolower_(option) : option); - - if (*local_long_name.rbegin() == '*') - { - // The name ends with '*'. Any specified name with the given - // prefix is OK. - if (local_option.find(local_long_name.substr(0, local_long_name.length()-1)) - == 0) - result = approximate_match; - } - - if (local_long_name == local_option) - { - result = full_match; - } - else if (approx) - { - if (local_long_name.find(local_option) == 0) - { - result = approximate_match; - } - } - } +// Copyright Vladimir Prus 2002-2004. +// Copyright Bertolt Mildner 2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> +#include <boost/program_options/options_description.hpp> +// FIXME: this is only to get multiple_occurrences class +// should move that to a separate headers. +#include <boost/program_options/parsers.hpp> + + +#include <boost/lexical_cast.hpp> +#include <boost/tokenizer.hpp> +#include <boost/detail/workaround.hpp> +#include <boost/throw_exception.hpp> + +#include <cassert> +#include <climits> +#include <cstring> +#include <cstdarg> +#include <sstream> +#include <iterator> +using namespace std; + +namespace boost { namespace program_options { + + namespace { + + template< class charT > + std::basic_string< charT > tolower_(const std::basic_string< charT >& str) + { + std::basic_string< charT > result; + for (typename std::basic_string< charT >::size_type i = 0; i < str.size(); ++i) + { + result.append(1, static_cast< charT >(std::tolower(str[i]))); + } + return result; + } + + } // unnamed namespace + + + option_description::option_description() + { + } + + option_description:: + option_description(const char* name, + const value_semantic* s) + : m_value_semantic(s) + { + this->set_name(name); + } + + + option_description:: + option_description(const char* name, + const value_semantic* s, + const char* description) + : m_description(description), m_value_semantic(s) + { + this->set_name(name); + } + + option_description::~option_description() + { + } + + option_description::match_result + option_description::match(const std::string& option, + bool approx, + bool long_ignore_case, + bool short_ignore_case) const + { + match_result result = no_match; + + std::string local_long_name((long_ignore_case ? tolower_(m_long_name) : m_long_name)); + + if (!local_long_name.empty()) { - if (result != full_match) - { - std::string local_option(short_ignore_case ? tolower_(option) : option); - std::string local_short_name(short_ignore_case ? tolower_(m_short_name) : m_short_name); - - if (local_short_name == local_option) - { - result = full_match; - } - } - - return result; - } - + std::string local_option = (long_ignore_case ? tolower_(option) : option); + + if (*local_long_name.rbegin() == '*') + { + // The name ends with '*'. Any specified name with the given + // prefix is OK. + if (local_option.find(local_long_name.substr(0, local_long_name.length()-1)) + == 0) + result = approximate_match; + } + + if (local_long_name == local_option) + { + result = full_match; + } + else if (approx) + { + if (local_long_name.find(local_option) == 0) + { + result = approximate_match; + } + } + } + + if (result != full_match) + { + std::string local_option(short_ignore_case ? tolower_(option) : option); + std::string local_short_name(short_ignore_case ? tolower_(m_short_name) : m_short_name); + + if (local_short_name == local_option) + { + result = full_match; + } + } + + return result; + } + + const std::string& + option_description::key(const std::string& option) const + { + if (!m_long_name.empty()) + if (m_long_name.find('*') != string::npos) + // The '*' character means we're long_name + // matches only part of the input. So, returning + // long name will remove some of the information, + // and we have to return the option as specified + // in the source. + return option; + else + return m_long_name; + else + return m_short_name; + } + + std::string + option_description::canonical_display_name(int prefix_style) const + { + if (!m_long_name.empty()) + { + if (prefix_style == command_line_style::allow_long) + return "--" + m_long_name; + if (prefix_style == command_line_style::allow_long_disguise) + return "-" + m_long_name; + } + // sanity check: m_short_name[0] should be '-' or '/' + if (m_short_name.length() == 2) + { + if (prefix_style == command_line_style::allow_slash_for_short) + return string("/") + m_short_name[1]; + if (prefix_style == command_line_style::allow_dash_for_short) + return string("-") + m_short_name[1]; + } + if (!m_long_name.empty()) + return m_long_name; + else + return m_short_name; + } + + const std::string& - option_description::key(const std::string& option) const + option_description::long_name() const + { + return m_long_name; + } + + option_description& + option_description::set_name(const char* _name) + { + std::string name(_name); + string::size_type n = name.find(','); + if (n != string::npos) { + assert(n == name.size()-2); + m_long_name = name.substr(0, n); + m_short_name = '-' + name.substr(n+1,1); + } else { + m_long_name = name; + } + return *this; + } + + const std::string& + option_description::description() const + { + return m_description; + } + + shared_ptr<const value_semantic> + option_description::semantic() const + { + return m_value_semantic; + } + + std::string + option_description::format_name() const + { + if (!m_short_name.empty()) + { + return m_long_name.empty() + ? m_short_name + : string(m_short_name).append(" [ --"). + append(m_long_name).append(" ]"); + } + return string("--").append(m_long_name); + } + + std::string + option_description::format_parameter() const + { + if (m_value_semantic->max_tokens() != 0) + return m_value_semantic->name(); + else + return ""; + } + + options_description_easy_init:: + options_description_easy_init(options_description* owner) + : owner(owner) + {} + + options_description_easy_init& + options_description_easy_init:: + operator()(const char* name, + const char* description) + { + // Create untypes semantic which accepts zero tokens: i.e. + // no value can be specified on command line. + // FIXME: does not look exception-safe + shared_ptr<option_description> d( + new option_description(name, new untyped_value(true), description)); + + owner->add(d); + return *this; + } + + options_description_easy_init& + options_description_easy_init:: + operator()(const char* name, + const value_semantic* s) + { + shared_ptr<option_description> d(new option_description(name, s)); + owner->add(d); + return *this; + } + + options_description_easy_init& + options_description_easy_init:: + operator()(const char* name, + const value_semantic* s, + const char* description) + { + shared_ptr<option_description> d(new option_description(name, s, description)); + + owner->add(d); + return *this; + } + + const unsigned options_description::m_default_line_length = 80; + + options_description::options_description(unsigned line_length, + unsigned min_description_length) + : m_line_length(line_length) + , m_min_description_length(min_description_length) + { + // we require a space between the option and description parts, so add 1. + assert(m_min_description_length < m_line_length - 1); + } + + options_description::options_description(const std::string& caption, + unsigned line_length, + unsigned min_description_length) + : m_caption(caption) + , m_line_length(line_length) + , m_min_description_length(min_description_length) + { + // we require a space between the option and description parts, so add 1. + assert(m_min_description_length < m_line_length - 1); + } + + void + options_description::add(shared_ptr<option_description> desc) + { + m_options.push_back(desc); + belong_to_group.push_back(false); + } + + options_description& + options_description::add(const options_description& desc) + { + shared_ptr<options_description> d(new options_description(desc)); + groups.push_back(d); + + for (size_t i = 0; i < desc.m_options.size(); ++i) { + add(desc.m_options[i]); + belong_to_group.back() = true; + } + + return *this; + } + + options_description_easy_init + options_description::add_options() { - if (!m_long_name.empty()) - if (m_long_name.find('*') != string::npos) - // The '*' character means we're long_name - // matches only part of the input. So, returning - // long name will remove some of the information, - // and we have to return the option as specified - // in the source. - return option; - else - return m_long_name; - else - return m_short_name; - } - - std::string - option_description::canonical_display_name(int prefix_style) const - { - if (!m_long_name.empty()) - { - if (prefix_style == command_line_style::allow_long) - return "--" + m_long_name; - if (prefix_style == command_line_style::allow_long_disguise) - return "-" + m_long_name; - } - // sanity check: m_short_name[0] should be '-' or '/' - if (m_short_name.length() == 2) - { - if (prefix_style == command_line_style::allow_slash_for_short) - return string("/") + m_short_name[1]; - if (prefix_style == command_line_style::allow_dash_for_short) - return string("-") + m_short_name[1]; - } - if (!m_long_name.empty()) - return m_long_name; - else - return m_short_name; - } - - - const std::string& - option_description::long_name() const - { - return m_long_name; - } - - option_description& - option_description::set_name(const char* _name) - { - std::string name(_name); - string::size_type n = name.find(','); - if (n != string::npos) { - assert(n == name.size()-2); - m_long_name = name.substr(0, n); - m_short_name = '-' + name.substr(n+1,1); - } else { - m_long_name = name; - } - return *this; - } - - const std::string& - option_description::description() const - { - return m_description; - } - - shared_ptr<const value_semantic> - option_description::semantic() const - { - return m_value_semantic; - } - - std::string - option_description::format_name() const - { - if (!m_short_name.empty()) - { - return m_long_name.empty() - ? m_short_name - : string(m_short_name).append(" [ --"). - append(m_long_name).append(" ]"); - } - return string("--").append(m_long_name); - } - - std::string - option_description::format_parameter() const - { - if (m_value_semantic->max_tokens() != 0) - return m_value_semantic->name(); - else - return ""; - } - - options_description_easy_init:: - options_description_easy_init(options_description* owner) - : owner(owner) - {} - - options_description_easy_init& - options_description_easy_init:: - operator()(const char* name, - const char* description) - { - // Create untypes semantic which accepts zero tokens: i.e. - // no value can be specified on command line. - // FIXME: does not look exception-safe - shared_ptr<option_description> d( - new option_description(name, new untyped_value(true), description)); - - owner->add(d); - return *this; - } - - options_description_easy_init& - options_description_easy_init:: - operator()(const char* name, - const value_semantic* s) - { - shared_ptr<option_description> d(new option_description(name, s)); - owner->add(d); - return *this; - } - - options_description_easy_init& - options_description_easy_init:: - operator()(const char* name, - const value_semantic* s, - const char* description) - { - shared_ptr<option_description> d(new option_description(name, s, description)); - - owner->add(d); - return *this; - } - - const unsigned options_description::m_default_line_length = 80; - - options_description::options_description(unsigned line_length, - unsigned min_description_length) - : m_line_length(line_length) - , m_min_description_length(min_description_length) - { - // we require a space between the option and description parts, so add 1. - assert(m_min_description_length < m_line_length - 1); - } - - options_description::options_description(const std::string& caption, - unsigned line_length, - unsigned min_description_length) - : m_caption(caption) - , m_line_length(line_length) - , m_min_description_length(min_description_length) - { - // we require a space between the option and description parts, so add 1. - assert(m_min_description_length < m_line_length - 1); - } - - void - options_description::add(shared_ptr<option_description> desc) - { - m_options.push_back(desc); - belong_to_group.push_back(false); - } - - options_description& - options_description::add(const options_description& desc) - { - shared_ptr<options_description> d(new options_description(desc)); - groups.push_back(d); - - for (size_t i = 0; i < desc.m_options.size(); ++i) { - add(desc.m_options[i]); - belong_to_group.back() = true; - } - - return *this; - } - - options_description_easy_init - options_description::add_options() - { - return options_description_easy_init(this); - } - - const option_description& - options_description::find(const std::string& name, - bool approx, - bool long_ignore_case, - bool short_ignore_case) const - { - const option_description* d = find_nothrow(name, approx, - long_ignore_case, short_ignore_case); - if (!d) - boost::throw_exception(unknown_option()); - return *d; - } - - const std::vector< shared_ptr<option_description> >& - options_description::options() const - { - return m_options; - } - - const option_description* - options_description::find_nothrow(const std::string& name, - bool approx, - bool long_ignore_case, - bool short_ignore_case) const - { - shared_ptr<option_description> found; - bool had_full_match = false; - 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. - for(unsigned i = 0; i < m_options.size(); ++i) - { - option_description::match_result r = - m_options[i]->match(name, approx, long_ignore_case, short_ignore_case); - - if (r == option_description::no_match) - continue; - - if (r == option_description::full_match) - { - full_matches.push_back(m_options[i]->key(name)); - found = m_options[i]; - had_full_match = true; + return options_description_easy_init(this); + } + + const option_description& + options_description::find(const std::string& name, + bool approx, + bool long_ignore_case, + bool short_ignore_case) const + { + const option_description* d = find_nothrow(name, approx, + long_ignore_case, short_ignore_case); + if (!d) + boost::throw_exception(unknown_option()); + return *d; + } + + const std::vector< shared_ptr<option_description> >& + options_description::options() const + { + return m_options; + } + + const option_description* + options_description::find_nothrow(const std::string& name, + bool approx, + bool long_ignore_case, + bool short_ignore_case) const + { + shared_ptr<option_description> found; + bool had_full_match = false; + 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. + for(unsigned i = 0; i < m_options.size(); ++i) + { + option_description::match_result r = + m_options[i]->match(name, approx, long_ignore_case, short_ignore_case); + + if (r == option_description::no_match) + continue; + + if (r == option_description::full_match) + { + full_matches.push_back(m_options[i]->key(name)); + found = m_options[i]; + had_full_match = true; + } + else + { + // FIXME: the use of 'key' here might not + // be the best approach. + approximate_matches.push_back(m_options[i]->key(name)); + if (!had_full_match) + found = m_options[i]; + } + } + if (full_matches.size() > 1) + boost::throw_exception(ambiguous_option(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(approximate_matches)); + + return found.get(); + } + + BOOST_PROGRAM_OPTIONS_DECL + std::ostream& operator<<(std::ostream& os, const options_description& desc) + { + desc.print(os); + return os; + } + + namespace { + + /* Given a string 'par', that contains no newline characters + outputs it to 'os' with wordwrapping, that is, as several + line. + + Each output line starts with 'indent' space characters, + following by characters from 'par'. The total length of + line is no longer than 'line_length'. + + */ + void format_paragraph(std::ostream& os, + std::string par, + unsigned indent, + unsigned line_length) + { + // Through reminder of this function, 'line_length' will + // be the length available for characters, not including + // indent. + assert(indent < line_length); + line_length -= indent; + + // index of tab (if present) is used as additional indent relative + // to first_column_width if paragrapth is spanned over multiple + // lines if tab is not on first line it is ignored + string::size_type par_indent = par.find('\t'); + + if (par_indent == string::npos) + { + par_indent = 0; } else - { - // FIXME: the use of 'key' here might not - // be the best approach. - approximate_matches.push_back(m_options[i]->key(name)); - if (!had_full_match) - found = m_options[i]; - } - } - if (full_matches.size() > 1) - boost::throw_exception(ambiguous_option(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(approximate_matches)); - - return found.get(); - } - - BOOST_PROGRAM_OPTIONS_DECL - std::ostream& operator<<(std::ostream& os, const options_description& desc) - { - desc.print(os); - return os; - } - - namespace { - - /* Given a string 'par', that contains no newline characters - outputs it to 'os' with wordwrapping, that is, as several - line. - - Each output line starts with 'indent' space characters, - following by characters from 'par'. The total length of - line is no longer than 'line_length'. - - */ - void format_paragraph(std::ostream& os, - std::string par, - unsigned indent, - unsigned line_length) - { - // Through reminder of this function, 'line_length' will - // be the length available for characters, not including - // indent. - assert(indent < line_length); - line_length -= indent; - - // index of tab (if present) is used as additional indent relative - // to first_column_width if paragrapth is spanned over multiple - // lines if tab is not on first line it is ignored - string::size_type par_indent = par.find('\t'); - - if (par_indent == string::npos) - { - par_indent = 0; - } - else - { - // only one tab per paragraph allowed - if (count(par.begin(), par.end(), '\t') > 1) - { - boost::throw_exception(program_options::error( - "Only one tab per paragraph is allowed in the options description")); - } - - // erase tab from string - par.erase(par_indent, 1); - - // this assert may fail due to user error or - // environment conditions! - assert(par_indent < line_length); - - // ignore tab if not on first line - if (par_indent >= line_length) - { - par_indent = 0; - } - } - - if (par.size() < line_length) - { - os << par; - } - else - { - string::const_iterator line_begin = par.begin(); - const string::const_iterator par_end = par.end(); - - bool first_line = true; // of current paragraph! - - while (line_begin < par_end) // paragraph lines - { - if (!first_line) - { - // If line starts with space, but second character - // is not space, remove the leading space. - // We don't remove double spaces because those - // might be intentianal. - if ((*line_begin == ' ') && - ((line_begin + 1 < par_end) && - (*(line_begin + 1) != ' '))) - { - line_begin += 1; // line_begin != line_end - } - } - - // Take care to never increment the iterator past - // the end, since MSVC 8.0 (brokenly), assumes that - // doing that, even if no access happens, is a bug. - unsigned remaining = static_cast<unsigned>(std::distance(line_begin, par_end)); - string::const_iterator line_end = line_begin + - ((remaining < line_length) ? remaining : line_length); - - // prevent chopped words - // Is line_end between two non-space characters? - if ((*(line_end - 1) != ' ') && - ((line_end < par_end) && (*line_end != ' '))) - { - // find last ' ' in the second half of the current paragraph line - string::const_iterator last_space = - find(reverse_iterator<string::const_iterator>(line_end), - reverse_iterator<string::const_iterator>(line_begin), - ' ') - .base(); - - if (last_space != line_begin) - { - // is last_space within the second half ot the - // current line - if (static_cast<unsigned>(std::distance(last_space, line_end)) < - (line_length / 2)) - { - line_end = last_space; - } - } - } // prevent chopped words + { + // only one tab per paragraph allowed + if (count(par.begin(), par.end(), '\t') > 1) + { + boost::throw_exception(program_options::error( + "Only one tab per paragraph is allowed in the options description")); + } + + // erase tab from string + par.erase(par_indent, 1); + + // this assert may fail due to user error or + // environment conditions! + assert(par_indent < line_length); + + // ignore tab if not on first line + if (par_indent >= line_length) + { + par_indent = 0; + } + } + + if (par.size() < line_length) + { + os << par; + } + else + { + string::const_iterator line_begin = par.begin(); + const string::const_iterator par_end = par.end(); + + bool first_line = true; // of current paragraph! - // write line to stream - copy(line_begin, line_end, ostream_iterator<char>(os)); - - if (first_line) - { - indent += static_cast<unsigned>(par_indent); - line_length -= static_cast<unsigned>(par_indent); // there's less to work with now - first_line = false; - } - - // more lines to follow? - if (line_end != par_end) - { - os << '\n'; - - for(unsigned pad = indent; pad > 0; --pad) - { - os.put(' '); - } - } - - // next line starts after of this line - line_begin = line_end; - } // paragraph lines - } - } - - void format_description(std::ostream& os, - const std::string& desc, - unsigned first_column_width, - unsigned line_length) - { - // we need to use one char less per line to work correctly if actual - // console has longer lines - assert(line_length > 1); - if (line_length > 1) - { - --line_length; - } - - // line_length must be larger than first_column_width - // this assert may fail due to user error or environment conditions! - assert(line_length > first_column_width); - - // Note: can't use 'tokenizer' as name of typedef -- borland - // will consider uses of 'tokenizer' below as uses of - // boost::tokenizer, not typedef. - typedef boost::tokenizer<boost::char_separator<char> > tok; - - tok paragraphs( - desc, - char_separator<char>("\n", "", boost::keep_empty_tokens)); - - tok::const_iterator par_iter = paragraphs.begin(); - const tok::const_iterator par_end = paragraphs.end(); - - while (par_iter != par_end) // paragraphs - { - format_paragraph(os, *par_iter, first_column_width, - line_length); - - ++par_iter; - - // prepair next line if any - if (par_iter != par_end) - { - os << '\n'; + while (line_begin < par_end) // paragraph lines + { + if (!first_line) + { + // If line starts with space, but second character + // is not space, remove the leading space. + // We don't remove double spaces because those + // might be intentianal. + if ((*line_begin == ' ') && + ((line_begin + 1 < par_end) && + (*(line_begin + 1) != ' '))) + { + line_begin += 1; // line_begin != line_end + } + } + + // Take care to never increment the iterator past + // the end, since MSVC 8.0 (brokenly), assumes that + // doing that, even if no access happens, is a bug. + unsigned remaining = static_cast<unsigned>(std::distance(line_begin, par_end)); + string::const_iterator line_end = line_begin + + ((remaining < line_length) ? remaining : line_length); + + // prevent chopped words + // Is line_end between two non-space characters? + if ((*(line_end - 1) != ' ') && + ((line_end < par_end) && (*line_end != ' '))) + { + // find last ' ' in the second half of the current paragraph line + string::const_iterator last_space = + find(reverse_iterator<string::const_iterator>(line_end), + reverse_iterator<string::const_iterator>(line_begin), + ' ') + .base(); + + if (last_space != line_begin) + { + // is last_space within the second half ot the + // current line + if (static_cast<unsigned>(std::distance(last_space, line_end)) < + (line_length / 2)) + { + line_end = last_space; + } + } + } // prevent chopped words - for(unsigned pad = first_column_width; pad > 0; --pad) - { - os.put(' '); - } - } - } // paragraphs - } - - void format_one(std::ostream& os, const option_description& opt, - unsigned first_column_width, unsigned line_length) - { - stringstream ss; - ss << " " << opt.format_name() << ' ' << opt.format_parameter(); - - // Don't use ss.rdbuf() since g++ 2.96 is buggy on it. - os << ss.str(); - - if (!opt.description().empty()) - { - if (ss.str().size() >= first_column_width) - { - os.put('\n'); // first column is too long, lets put description in new line - for (unsigned pad = first_column_width; pad > 0; --pad) - { - os.put(' '); - } - } else { - for(unsigned pad = first_column_width - static_cast<unsigned>(ss.str().size()); pad > 0; --pad) - { - os.put(' '); - } - } - - format_description(os, opt.description(), - first_column_width, line_length); - } - } - } - - unsigned - options_description::get_option_column_width() const - { - /* Find the maximum width of the option column */ - unsigned width(23); - unsigned i; // vc6 has broken for loop scoping - for (i = 0; i < m_options.size(); ++i) - { - const option_description& opt = *m_options[i]; - stringstream ss; - ss << " " << opt.format_name() << ' ' << opt.format_parameter(); - width = (max)(width, static_cast<unsigned>(ss.str().size())); - } - - /* Get width of groups as well*/ - for (unsigned j = 0; j < groups.size(); ++j) - width = max(width, groups[j]->get_option_column_width()); - - /* this is the column were description should start, if first - column is longer, we go to a new line */ - const unsigned start_of_description_column = m_line_length - m_min_description_length; - - width = (min)(width, start_of_description_column-1); - - /* add an additional space to improve readability */ - ++width; - return width; - } - - void - options_description::print(std::ostream& os, unsigned width) const - { - if (!m_caption.empty()) - os << m_caption << ":\n"; - - if (!width) - width = get_option_column_width(); - - /* The options formatting style is stolen from Subversion. */ - for (unsigned i = 0; i < m_options.size(); ++i) - { - if (belong_to_group[i]) - continue; - - const option_description& opt = *m_options[i]; - - format_one(os, opt, width, m_line_length); - - os << "\n"; - } - - for (unsigned j = 0; j < groups.size(); ++j) { - os << "\n"; - groups[j]->print(os, width); - } - } - -}} + // write line to stream + copy(line_begin, line_end, ostream_iterator<char>(os)); + + if (first_line) + { + indent += static_cast<unsigned>(par_indent); + line_length -= static_cast<unsigned>(par_indent); // there's less to work with now + first_line = false; + } + + // more lines to follow? + if (line_end != par_end) + { + os << '\n'; + + for(unsigned pad = indent; pad > 0; --pad) + { + os.put(' '); + } + } + + // next line starts after of this line + line_begin = line_end; + } // paragraph lines + } + } + + void format_description(std::ostream& os, + const std::string& desc, + unsigned first_column_width, + unsigned line_length) + { + // we need to use one char less per line to work correctly if actual + // console has longer lines + assert(line_length > 1); + if (line_length > 1) + { + --line_length; + } + + // line_length must be larger than first_column_width + // this assert may fail due to user error or environment conditions! + assert(line_length > first_column_width); + + // Note: can't use 'tokenizer' as name of typedef -- borland + // will consider uses of 'tokenizer' below as uses of + // boost::tokenizer, not typedef. + typedef boost::tokenizer<boost::char_separator<char> > tok; + + tok paragraphs( + desc, + char_separator<char>("\n", "", boost::keep_empty_tokens)); + + tok::const_iterator par_iter = paragraphs.begin(); + const tok::const_iterator par_end = paragraphs.end(); + + while (par_iter != par_end) // paragraphs + { + format_paragraph(os, *par_iter, first_column_width, + line_length); + + ++par_iter; + + // prepair next line if any + if (par_iter != par_end) + { + os << '\n'; + + for(unsigned pad = first_column_width; pad > 0; --pad) + { + os.put(' '); + } + } + } // paragraphs + } + + void format_one(std::ostream& os, const option_description& opt, + unsigned first_column_width, unsigned line_length) + { + stringstream ss; + ss << " " << opt.format_name() << ' ' << opt.format_parameter(); + + // Don't use ss.rdbuf() since g++ 2.96 is buggy on it. + os << ss.str(); + + if (!opt.description().empty()) + { + if (ss.str().size() >= first_column_width) + { + os.put('\n'); // first column is too long, lets put description in new line + for (unsigned pad = first_column_width; pad > 0; --pad) + { + os.put(' '); + } + } else { + for(unsigned pad = first_column_width - static_cast<unsigned>(ss.str().size()); pad > 0; --pad) + { + os.put(' '); + } + } + + format_description(os, opt.description(), + first_column_width, line_length); + } + } + } + + unsigned + options_description::get_option_column_width() const + { + /* Find the maximum width of the option column */ + unsigned width(23); + unsigned i; // vc6 has broken for loop scoping + for (i = 0; i < m_options.size(); ++i) + { + const option_description& opt = *m_options[i]; + stringstream ss; + ss << " " << opt.format_name() << ' ' << opt.format_parameter(); + width = (max)(width, static_cast<unsigned>(ss.str().size())); + } + + /* Get width of groups as well*/ + for (unsigned j = 0; j < groups.size(); ++j) + width = max(width, groups[j]->get_option_column_width()); + + /* this is the column were description should start, if first + column is longer, we go to a new line */ + const unsigned start_of_description_column = m_line_length - m_min_description_length; + + width = (min)(width, start_of_description_column-1); + + /* add an additional space to improve readability */ + ++width; + return width; + } + + void + options_description::print(std::ostream& os, unsigned width) const + { + if (!m_caption.empty()) + os << m_caption << ":\n"; + + if (!width) + width = get_option_column_width(); + + /* The options formatting style is stolen from Subversion. */ + for (unsigned i = 0; i < m_options.size(); ++i) + { + if (belong_to_group[i]) + continue; + + const option_description& opt = *m_options[i]; + + format_one(os, opt, width, m_line_length); + + os << "\n"; + } + + for (unsigned j = 0; j < groups.size(); ++j) { + os << "\n"; + groups[j]->print(os, width); + } + } + +}} diff --git a/contrib/restricted/boost/libs/program_options/src/parsers.cpp b/contrib/restricted/boost/libs/program_options/src/parsers.cpp index 3e435eea3f..9cd47f0929 100644 --- a/contrib/restricted/boost/libs/program_options/src/parsers.cpp +++ b/contrib/restricted/boost/libs/program_options/src/parsers.cpp @@ -1,258 +1,258 @@ -// Copyright Vladimir Prus 2002-2004. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - - -#include <boost/config.hpp> - -#define BOOST_PROGRAM_OPTIONS_SOURCE -#include <boost/program_options/config.hpp> -#include <boost/program_options/parsers.hpp> -#include <boost/program_options/options_description.hpp> -#include <boost/program_options/positional_options.hpp> -#include <boost/program_options/detail/cmdline.hpp> -#include <boost/program_options/detail/config_file.hpp> -#include <boost/program_options/environment_iterator.hpp> -#include <boost/program_options/detail/convert.hpp> - -#include <boost/bind.hpp> -#include <boost/throw_exception.hpp> - -#include <cctype> -#include <fstream> - -#if !defined(__GNUC__) || __GNUC__ < 3 -#include <iostream> -#else -#include <istream> -#endif - -#ifdef _WIN32 -#include <stdlib.h> -#else -#include <unistd.h> -#endif - -// The 'environ' should be declared in some cases. E.g. Linux man page says: -// (This variable must be declared in the user program, but is declared in -// the header file unistd.h in case the header files came from libc4 or libc5, -// and in case they came from glibc and _GNU_SOURCE was defined.) -// To be safe, declare it here. - -// It appears that on Mac OS X the 'environ' variable is not -// available to dynamically linked libraries. -// See: http://article.gmane.org/gmane.comp.lib.boost.devel/103843 -// See: http://lists.gnu.org/archive/html/bug-guile/2004-01/msg00013.html -#if defined(__APPLE__) && defined(__DYNAMIC__) -// The proper include for this is crt_externs.h, however it's not -// available on iOS. The right replacement is not known. See -// https://svn.boost.org/trac/boost/ticket/5053 -extern "C" { extern char ***_NSGetEnviron(void); } -#define environ (*_NSGetEnviron()) -#else -#if defined(__MWERKS__) -#include <crtl.h> -#else -#if !defined(_WIN32) || defined(__COMO_VERSION__) -extern char** environ; -#endif -#endif -#endif - -using namespace std; - -namespace boost { namespace program_options { - -#ifndef BOOST_NO_STD_WSTRING - namespace { - woption woption_from_option(const option& opt) - { - woption result; - result.string_key = opt.string_key; - result.position_key = opt.position_key; - result.unregistered = opt.unregistered; - - std::transform(opt.value.begin(), opt.value.end(), - back_inserter(result.value), - boost::bind(from_utf8, _1)); - - std::transform(opt.original_tokens.begin(), - opt.original_tokens.end(), - back_inserter(result.original_tokens), - boost::bind(from_utf8, _1)); - return result; - } - } - - basic_parsed_options<wchar_t> - ::basic_parsed_options(const parsed_options& po) - : description(po.description), - utf8_encoded_options(po), - m_options_prefix(po.m_options_prefix) - { - for (unsigned i = 0; i < po.options.size(); ++i) - options.push_back(woption_from_option(po.options[i])); - } -#endif - - template<class charT> - basic_parsed_options<charT> - parse_config_file(std::basic_istream<charT>& is, - const options_description& desc, - bool allow_unregistered) - { - set<string> allowed_options; - - const vector<shared_ptr<option_description> >& options = desc.options(); - for (unsigned i = 0; i < options.size(); ++i) - { - const option_description& d = *options[i]; - - if (d.long_name().empty()) - boost::throw_exception( - error("abbreviated option names are not permitted in options configuration files")); - - allowed_options.insert(d.long_name()); - } - - // Parser return char strings - parsed_options result(&desc); - copy(detail::basic_config_file_iterator<charT>( - is, allowed_options, allow_unregistered), - detail::basic_config_file_iterator<charT>(), - back_inserter(result.options)); - // Convert char strings into desired type. - return basic_parsed_options<charT>(result); - } - - template - BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char> - parse_config_file(std::basic_istream<char>& is, - const options_description& desc, - bool allow_unregistered); - -#ifndef BOOST_NO_STD_WSTRING - template - BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t> - parse_config_file(std::basic_istream<wchar_t>& is, - const options_description& desc, - bool allow_unregistered); -#endif - - template<class charT> - basic_parsed_options<charT> - parse_config_file(const char* filename, - const options_description& desc, - bool allow_unregistered) +// Copyright Vladimir Prus 2002-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#include <boost/config.hpp> + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> +#include <boost/program_options/parsers.hpp> +#include <boost/program_options/options_description.hpp> +#include <boost/program_options/positional_options.hpp> +#include <boost/program_options/detail/cmdline.hpp> +#include <boost/program_options/detail/config_file.hpp> +#include <boost/program_options/environment_iterator.hpp> +#include <boost/program_options/detail/convert.hpp> + +#include <boost/bind.hpp> +#include <boost/throw_exception.hpp> + +#include <cctype> +#include <fstream> + +#if !defined(__GNUC__) || __GNUC__ < 3 +#include <iostream> +#else +#include <istream> +#endif + +#ifdef _WIN32 +#include <stdlib.h> +#else +#include <unistd.h> +#endif + +// The 'environ' should be declared in some cases. E.g. Linux man page says: +// (This variable must be declared in the user program, but is declared in +// the header file unistd.h in case the header files came from libc4 or libc5, +// and in case they came from glibc and _GNU_SOURCE was defined.) +// To be safe, declare it here. + +// It appears that on Mac OS X the 'environ' variable is not +// available to dynamically linked libraries. +// See: http://article.gmane.org/gmane.comp.lib.boost.devel/103843 +// See: http://lists.gnu.org/archive/html/bug-guile/2004-01/msg00013.html +#if defined(__APPLE__) && defined(__DYNAMIC__) +// The proper include for this is crt_externs.h, however it's not +// available on iOS. The right replacement is not known. See +// https://svn.boost.org/trac/boost/ticket/5053 +extern "C" { extern char ***_NSGetEnviron(void); } +#define environ (*_NSGetEnviron()) +#else +#if defined(__MWERKS__) +#include <crtl.h> +#else +#if !defined(_WIN32) || defined(__COMO_VERSION__) +extern char** environ; +#endif +#endif +#endif + +using namespace std; + +namespace boost { namespace program_options { + +#ifndef BOOST_NO_STD_WSTRING + namespace { + woption woption_from_option(const option& opt) + { + woption result; + result.string_key = opt.string_key; + result.position_key = opt.position_key; + result.unregistered = opt.unregistered; + + std::transform(opt.value.begin(), opt.value.end(), + back_inserter(result.value), + boost::bind(from_utf8, _1)); + + std::transform(opt.original_tokens.begin(), + opt.original_tokens.end(), + back_inserter(result.original_tokens), + boost::bind(from_utf8, _1)); + return result; + } + } + + basic_parsed_options<wchar_t> + ::basic_parsed_options(const parsed_options& po) + : description(po.description), + utf8_encoded_options(po), + m_options_prefix(po.m_options_prefix) { - // Parser return char strings - std::basic_ifstream< charT > strm(filename); - if (!strm) - { - boost::throw_exception(reading_file(filename)); - } - - basic_parsed_options<charT> result - = parse_config_file(strm, desc, allow_unregistered); - - if (strm.bad()) - { - boost::throw_exception(reading_file(filename)); - } - - return result; - } - - template - BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char> - parse_config_file(const char* filename, - const options_description& desc, - bool allow_unregistered); - -#ifndef BOOST_NO_STD_WSTRING - template - BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t> - parse_config_file(const char* filename, - const options_description& desc, - bool allow_unregistered); -#endif - - -// This versio, which accepts any options without validation, is disabled, -// in the hope that nobody will need it and we cant drop it altogether. -// Besides, probably the right way to handle all options is the '*' name. -#if 0 - BOOST_PROGRAM_OPTIONS_DECL parsed_options - parse_config_file(std::istream& is) - { - detail::config_file_iterator cf(is, false); - parsed_options result(0); - copy(cf, detail::config_file_iterator(), - back_inserter(result.options)); - return result; - } -#endif - - BOOST_PROGRAM_OPTIONS_DECL parsed_options - parse_environment(const options_description& desc, - const function1<std::string, std::string>& name_mapper) - { - parsed_options result(&desc); - - for(environment_iterator i(environ), e; i != e; ++i) { - string option_name = name_mapper(i->first); - - if (!option_name.empty()) { - option n; - n.string_key = option_name; - n.value.push_back(i->second); - result.options.push_back(n); - } - } - - return result; - } - - namespace detail { - class prefix_name_mapper { - public: - prefix_name_mapper(const std::string& prefix) - : prefix(prefix) - {} - - std::string operator()(const std::string& s) - { - string result; - if (s.find(prefix) == 0) { - for(string::size_type n = prefix.size(); n < s.size(); ++n) - { - // Intel-Win-7.1 does not understand - // push_back on string. - result += static_cast<char>(tolower(s[n])); - } - } - return result; - } - private: - std::string prefix; - }; - } - - BOOST_PROGRAM_OPTIONS_DECL parsed_options - parse_environment(const options_description& desc, - const std::string& prefix) - { - return parse_environment(desc, detail::prefix_name_mapper(prefix)); - } - - BOOST_PROGRAM_OPTIONS_DECL parsed_options - parse_environment(const options_description& desc, const char* prefix) - { - return parse_environment(desc, string(prefix)); - } - - - - -}} + for (unsigned i = 0; i < po.options.size(); ++i) + options.push_back(woption_from_option(po.options[i])); + } +#endif + + template<class charT> + basic_parsed_options<charT> + parse_config_file(std::basic_istream<charT>& is, + const options_description& desc, + bool allow_unregistered) + { + set<string> allowed_options; + + const vector<shared_ptr<option_description> >& options = desc.options(); + for (unsigned i = 0; i < options.size(); ++i) + { + const option_description& d = *options[i]; + + if (d.long_name().empty()) + boost::throw_exception( + error("abbreviated option names are not permitted in options configuration files")); + + allowed_options.insert(d.long_name()); + } + + // Parser return char strings + parsed_options result(&desc); + copy(detail::basic_config_file_iterator<charT>( + is, allowed_options, allow_unregistered), + detail::basic_config_file_iterator<charT>(), + back_inserter(result.options)); + // Convert char strings into desired type. + return basic_parsed_options<charT>(result); + } + + template + BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char> + parse_config_file(std::basic_istream<char>& is, + const options_description& desc, + bool allow_unregistered); + +#ifndef BOOST_NO_STD_WSTRING + template + BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t> + parse_config_file(std::basic_istream<wchar_t>& is, + const options_description& desc, + bool allow_unregistered); +#endif + + template<class charT> + basic_parsed_options<charT> + parse_config_file(const char* filename, + const options_description& desc, + bool allow_unregistered) + { + // Parser return char strings + std::basic_ifstream< charT > strm(filename); + if (!strm) + { + boost::throw_exception(reading_file(filename)); + } + + basic_parsed_options<charT> result + = parse_config_file(strm, desc, allow_unregistered); + + if (strm.bad()) + { + boost::throw_exception(reading_file(filename)); + } + + return result; + } + + template + BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<char> + parse_config_file(const char* filename, + const options_description& desc, + bool allow_unregistered); + +#ifndef BOOST_NO_STD_WSTRING + template + BOOST_PROGRAM_OPTIONS_DECL basic_parsed_options<wchar_t> + parse_config_file(const char* filename, + const options_description& desc, + bool allow_unregistered); +#endif + + +// This versio, which accepts any options without validation, is disabled, +// in the hope that nobody will need it and we cant drop it altogether. +// Besides, probably the right way to handle all options is the '*' name. +#if 0 + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_config_file(std::istream& is) + { + detail::config_file_iterator cf(is, false); + parsed_options result(0); + copy(cf, detail::config_file_iterator(), + back_inserter(result.options)); + return result; + } +#endif + + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_environment(const options_description& desc, + const function1<std::string, std::string>& name_mapper) + { + parsed_options result(&desc); + + for(environment_iterator i(environ), e; i != e; ++i) { + string option_name = name_mapper(i->first); + + if (!option_name.empty()) { + option n; + n.string_key = option_name; + n.value.push_back(i->second); + result.options.push_back(n); + } + } + + return result; + } + + namespace detail { + class prefix_name_mapper { + public: + prefix_name_mapper(const std::string& prefix) + : prefix(prefix) + {} + + std::string operator()(const std::string& s) + { + string result; + if (s.find(prefix) == 0) { + for(string::size_type n = prefix.size(); n < s.size(); ++n) + { + // Intel-Win-7.1 does not understand + // push_back on string. + result += static_cast<char>(tolower(s[n])); + } + } + return result; + } + private: + std::string prefix; + }; + } + + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_environment(const options_description& desc, + const std::string& prefix) + { + return parse_environment(desc, detail::prefix_name_mapper(prefix)); + } + + BOOST_PROGRAM_OPTIONS_DECL parsed_options + parse_environment(const options_description& desc, const char* prefix) + { + return parse_environment(desc, string(prefix)); + } + + + + +}} diff --git a/contrib/restricted/boost/libs/program_options/src/positional_options.cpp b/contrib/restricted/boost/libs/program_options/src/positional_options.cpp index 72dc0d6b0d..5208f09a6f 100644 --- a/contrib/restricted/boost/libs/program_options/src/positional_options.cpp +++ b/contrib/restricted/boost/libs/program_options/src/positional_options.cpp @@ -1,53 +1,53 @@ -// Copyright Vladimir Prus 2004. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_PROGRAM_OPTIONS_SOURCE -#include <boost/program_options/config.hpp> - -#include <boost/program_options/positional_options.hpp> - -#include <boost/limits.hpp> - -#include <cassert> - -namespace boost { namespace program_options { - - positional_options_description::positional_options_description() - {} - - positional_options_description& - positional_options_description::add(const char* name, int max_count) - { - assert(max_count != -1 || m_trailing.empty()); - - if (max_count == -1) - m_trailing = name; - else { - m_names.resize(m_names.size() + max_count, name); - } - return *this; - } - - unsigned - positional_options_description::max_total_count() const - { - return m_trailing.empty() ? - static_cast<unsigned>(m_names.size()) : (std::numeric_limits<unsigned>::max)(); - } - - const std::string& - positional_options_description::name_for_position(unsigned position) const - { - assert(position < max_total_count()); - - if (position < m_names.size()) - return m_names[position]; - else - return m_trailing; - } - - -}} - +// Copyright Vladimir Prus 2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> + +#include <boost/program_options/positional_options.hpp> + +#include <boost/limits.hpp> + +#include <cassert> + +namespace boost { namespace program_options { + + positional_options_description::positional_options_description() + {} + + positional_options_description& + positional_options_description::add(const char* name, int max_count) + { + assert(max_count != -1 || m_trailing.empty()); + + if (max_count == -1) + m_trailing = name; + else { + m_names.resize(m_names.size() + max_count, name); + } + return *this; + } + + unsigned + positional_options_description::max_total_count() const + { + return m_trailing.empty() ? + static_cast<unsigned>(m_names.size()) : (std::numeric_limits<unsigned>::max)(); + } + + const std::string& + positional_options_description::name_for_position(unsigned position) const + { + assert(position < max_total_count()); + + if (position < m_names.size()) + return m_names[position]; + else + return m_trailing; + } + + +}} + diff --git a/contrib/restricted/boost/libs/program_options/src/split.cpp b/contrib/restricted/boost/libs/program_options/src/split.cpp index 96da068b82..ec84c63d71 100644 --- a/contrib/restricted/boost/libs/program_options/src/split.cpp +++ b/contrib/restricted/boost/libs/program_options/src/split.cpp @@ -1,62 +1,62 @@ -// Copyright Sascha Ochsenknecht 2009. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_PROGRAM_OPTIONS_SOURCE - -#include <boost/program_options/parsers.hpp> -#include <boost/tokenizer.hpp> - -#include <string> -#include <vector> - -namespace boost { namespace program_options { namespace detail { - - template< class charT > - std::vector<std::basic_string<charT> > - split_unix( - const std::basic_string<charT>& cmdline, - const std::basic_string<charT>& seperator, - const std::basic_string<charT>& quote, - const std::basic_string<charT>& escape) - { - typedef boost::tokenizer< boost::escaped_list_separator<charT>, - typename std::basic_string<charT>::const_iterator, - std::basic_string<charT> > tokenizerT; - - tokenizerT tok(cmdline.begin(), cmdline.end(), - boost::escaped_list_separator< charT >(escape, seperator, quote)); - - std::vector< std::basic_string<charT> > result; - for (typename tokenizerT::iterator cur_token(tok.begin()), end_token(tok.end()); cur_token != end_token; ++cur_token) { - if (!cur_token->empty()) - result.push_back(*cur_token); - } - return result; - } - -}}} // namespace - -namespace boost { namespace program_options { - - // Take a command line string and splits in into tokens, according - // to the given collection of seperators chars. - BOOST_PROGRAM_OPTIONS_DECL std::vector<std::string> - split_unix(const std::string& cmdline, const std::string& seperator, - const std::string& quote, const std::string& escape) - { - return detail::split_unix< char >(cmdline, seperator, quote, escape); - } - -#ifndef BOOST_NO_STD_WSTRING - BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring> - split_unix(const std::wstring& cmdline, const std::wstring& seperator, - const std::wstring& quote, const std::wstring& escape) - { - return detail::split_unix< wchar_t >(cmdline, seperator, quote, escape); - } -#endif - -}} // namespace - +// Copyright Sascha Ochsenknecht 2009. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_PROGRAM_OPTIONS_SOURCE + +#include <boost/program_options/parsers.hpp> +#include <boost/tokenizer.hpp> + +#include <string> +#include <vector> + +namespace boost { namespace program_options { namespace detail { + + template< class charT > + std::vector<std::basic_string<charT> > + split_unix( + const std::basic_string<charT>& cmdline, + const std::basic_string<charT>& seperator, + const std::basic_string<charT>& quote, + const std::basic_string<charT>& escape) + { + typedef boost::tokenizer< boost::escaped_list_separator<charT>, + typename std::basic_string<charT>::const_iterator, + std::basic_string<charT> > tokenizerT; + + tokenizerT tok(cmdline.begin(), cmdline.end(), + boost::escaped_list_separator< charT >(escape, seperator, quote)); + + std::vector< std::basic_string<charT> > result; + for (typename tokenizerT::iterator cur_token(tok.begin()), end_token(tok.end()); cur_token != end_token; ++cur_token) { + if (!cur_token->empty()) + result.push_back(*cur_token); + } + return result; + } + +}}} // namespace + +namespace boost { namespace program_options { + + // Take a command line string and splits in into tokens, according + // to the given collection of seperators chars. + BOOST_PROGRAM_OPTIONS_DECL std::vector<std::string> + split_unix(const std::string& cmdline, const std::string& seperator, + const std::string& quote, const std::string& escape) + { + return detail::split_unix< char >(cmdline, seperator, quote, escape); + } + +#ifndef BOOST_NO_STD_WSTRING + BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring> + split_unix(const std::wstring& cmdline, const std::wstring& seperator, + const std::wstring& quote, const std::wstring& escape) + { + return detail::split_unix< wchar_t >(cmdline, seperator, quote, escape); + } +#endif + +}} // namespace + diff --git a/contrib/restricted/boost/libs/program_options/src/utf8_codecvt_facet.cpp b/contrib/restricted/boost/libs/program_options/src/utf8_codecvt_facet.cpp index 2e4c532c35..9c8f3d9ca4 100644 --- a/contrib/restricted/boost/libs/program_options/src/utf8_codecvt_facet.cpp +++ b/contrib/restricted/boost/libs/program_options/src/utf8_codecvt_facet.cpp @@ -1,21 +1,21 @@ -// Copyright Vladimir Prus 2004. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_PROGRAM_OPTIONS_SOURCE -#include <boost/program_options/config.hpp> - -#define BOOST_UTF8_BEGIN_NAMESPACE \ - namespace boost { namespace program_options { namespace detail { - -#define BOOST_UTF8_END_NAMESPACE }}} -#define BOOST_UTF8_DECL BOOST_PROGRAM_OPTIONS_DECL - -#include <boost/detail/utf8_codecvt_facet.ipp> - - -#undef BOOST_UTF8_BEGIN_NAMESPACE -#undef BOOST_UTF8_END_NAMESPACE -#undef BOOST_UTF8_DECL - +// Copyright Vladimir Prus 2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> + +#define BOOST_UTF8_BEGIN_NAMESPACE \ + namespace boost { namespace program_options { namespace detail { + +#define BOOST_UTF8_END_NAMESPACE }}} +#define BOOST_UTF8_DECL BOOST_PROGRAM_OPTIONS_DECL + +#include <boost/detail/utf8_codecvt_facet.ipp> + + +#undef BOOST_UTF8_BEGIN_NAMESPACE +#undef BOOST_UTF8_END_NAMESPACE +#undef BOOST_UTF8_DECL + diff --git a/contrib/restricted/boost/libs/program_options/src/value_semantic.cpp b/contrib/restricted/boost/libs/program_options/src/value_semantic.cpp index 6055f62713..8951a0d2f2 100644 --- a/contrib/restricted/boost/libs/program_options/src/value_semantic.cpp +++ b/contrib/restricted/boost/libs/program_options/src/value_semantic.cpp @@ -1,428 +1,428 @@ -// Copyright Vladimir Prus 2004. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_PROGRAM_OPTIONS_SOURCE -#include <boost/program_options/config.hpp> -#include <boost/program_options/value_semantic.hpp> -#include <boost/program_options/detail/convert.hpp> -#include <boost/program_options/detail/cmdline.hpp> -#include <set> - -#include <cctype> - -namespace boost { namespace program_options { - - using namespace std; - - -#ifndef BOOST_NO_STD_WSTRING - namespace - { - std::string convert_value(const std::wstring& s) - { - try { - return to_local_8_bit(s); - } - catch(const std::exception&) { - return "<unrepresentable unicode string>"; - } - } - } -#endif - - void - value_semantic_codecvt_helper<char>:: - parse(boost::any& value_store, - const std::vector<std::string>& new_tokens, - bool utf8) const - { - if (utf8) { -#ifndef BOOST_NO_STD_WSTRING - // Need to convert to local encoding. - std::vector<string> local_tokens; - for (unsigned i = 0; i < new_tokens.size(); ++i) { - std::wstring w = from_utf8(new_tokens[i]); - local_tokens.push_back(to_local_8_bit(w)); - } - xparse(value_store, local_tokens); -#else - boost::throw_exception( - std::runtime_error("UTF-8 conversion not supported.")); -#endif - } else { - // Already in local encoding, pass unmodified - xparse(value_store, new_tokens); - } - } - -#ifndef BOOST_NO_STD_WSTRING - void - value_semantic_codecvt_helper<wchar_t>:: - parse(boost::any& value_store, - const std::vector<std::string>& new_tokens, - bool utf8) const - { - std::vector<wstring> tokens; - if (utf8) { - // Convert from utf8 - for (unsigned i = 0; i < new_tokens.size(); ++i) { - tokens.push_back(from_utf8(new_tokens[i])); - } - - } else { - // Convert from local encoding - for (unsigned i = 0; i < new_tokens.size(); ++i) { - tokens.push_back(from_local_8_bit(new_tokens[i])); - } - } - - xparse(value_store, tokens); - } -#endif - - BOOST_PROGRAM_OPTIONS_DECL std::string arg("arg"); - - std::string - untyped_value::name() const - { - return arg; - } - - unsigned - untyped_value::min_tokens() const - { - if (m_zero_tokens) - return 0; - else - return 1; - } - - unsigned - untyped_value::max_tokens() const - { - if (m_zero_tokens) - return 0; - else - return 1; - } - - - void - untyped_value::xparse(boost::any& value_store, - const std::vector<std::string>& new_tokens) const - { - if (!value_store.empty()) - boost::throw_exception( - multiple_occurrences()); - if (new_tokens.size() > 1) - boost::throw_exception(multiple_values()); - value_store = new_tokens.empty() ? std::string("") : new_tokens.front(); - } - - BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* - bool_switch() - { - return bool_switch(0); - } - - BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* - bool_switch(bool* v) - { - typed_value<bool>* r = new typed_value<bool>(v); - r->default_value(0); - r->zero_tokens(); - - return r; - } - - /* Validates bool value. - Any of "1", "true", "yes", "on" will be converted to "1".<br> - Any of "0", "false", "no", "off" will be converted to "0".<br> - Case is ignored. The 'xs' vector can either be empty, in which - case the value is 'true', or can contain explicit value. - */ - BOOST_PROGRAM_OPTIONS_DECL void validate(any& v, const vector<string>& xs, - bool*, int) - { - check_first_occurrence(v); - string s(get_single_string(xs, true)); - - for (size_t i = 0; i < s.size(); ++i) - s[i] = char(tolower(s[i])); - - if (s.empty() || s == "on" || s == "yes" || s == "1" || s == "true") - v = any(true); - else if (s == "off" || s == "no" || s == "0" || s == "false") - v = any(false); - else - boost::throw_exception(invalid_bool_value(s)); - } - - // This is blatant copy-paste. However, templating this will cause a problem, - // since wstring can't be constructed/compared with char*. We'd need to - // create auxiliary 'widen' routine to convert from char* into - // needed string type, and that's more work. -#if !defined(BOOST_NO_STD_WSTRING) - BOOST_PROGRAM_OPTIONS_DECL - void validate(any& v, const vector<wstring>& xs, bool*, int) - { - check_first_occurrence(v); - wstring s(get_single_string(xs, true)); - - for (size_t i = 0; i < s.size(); ++i) - s[i] = wchar_t(tolower(s[i])); - - if (s.empty() || s == L"on" || s == L"yes" || s == L"1" || s == L"true") - v = any(true); - else if (s == L"off" || s == L"no" || s == L"0" || s == L"false") - v = any(false); - else - boost::throw_exception(invalid_bool_value(convert_value(s))); - } -#endif - BOOST_PROGRAM_OPTIONS_DECL - void validate(any& v, const vector<string>& xs, std::string*, int) - { - check_first_occurrence(v); - v = any(get_single_string(xs)); - } - -#if !defined(BOOST_NO_STD_WSTRING) - BOOST_PROGRAM_OPTIONS_DECL - void validate(any& v, const vector<wstring>& xs, std::string*, int) - { - check_first_occurrence(v); - v = any(get_single_string(xs)); - } -#endif - - namespace validators { - - BOOST_PROGRAM_OPTIONS_DECL - void check_first_occurrence(const boost::any& value) - { - if (!value.empty()) - boost::throw_exception( - multiple_occurrences()); - } - } - - - invalid_option_value:: - invalid_option_value(const std::string& bad_value) - : validation_error(validation_error::invalid_option_value) - { - set_substitute("value", bad_value); - } - -#ifndef BOOST_NO_STD_WSTRING - invalid_option_value:: - invalid_option_value(const std::wstring& bad_value) - : validation_error(validation_error::invalid_option_value) - { - set_substitute("value", convert_value(bad_value)); - } -#endif - - - - invalid_bool_value:: - invalid_bool_value(const std::string& bad_value) - : validation_error(validation_error::invalid_bool_value) - { - set_substitute("value", bad_value); - } - - - - - - - error_with_option_name::error_with_option_name( const std::string& template_, - const std::string& option_name, - const std::string& original_token, - int option_style) : - error(template_), - m_option_style(option_style), - m_error_template(template_) - { - // parameter | placeholder | value - // --------- | ----------- | ----- - set_substitute_default("canonical_option", "option '%canonical_option%'", "option"); - set_substitute_default("value", "argument ('%value%')", "argument"); - set_substitute_default("prefix", "%prefix%", ""); - m_substitutions["option"] = option_name; - m_substitutions["original_token"] = original_token; - } - - +// Copyright Vladimir Prus 2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> +#include <boost/program_options/value_semantic.hpp> +#include <boost/program_options/detail/convert.hpp> +#include <boost/program_options/detail/cmdline.hpp> +#include <set> + +#include <cctype> + +namespace boost { namespace program_options { + + using namespace std; + + +#ifndef BOOST_NO_STD_WSTRING + namespace + { + std::string convert_value(const std::wstring& s) + { + try { + return to_local_8_bit(s); + } + catch(const std::exception&) { + return "<unrepresentable unicode string>"; + } + } + } +#endif + + void + value_semantic_codecvt_helper<char>:: + parse(boost::any& value_store, + const std::vector<std::string>& new_tokens, + bool utf8) const + { + if (utf8) { +#ifndef BOOST_NO_STD_WSTRING + // Need to convert to local encoding. + std::vector<string> local_tokens; + for (unsigned i = 0; i < new_tokens.size(); ++i) { + std::wstring w = from_utf8(new_tokens[i]); + local_tokens.push_back(to_local_8_bit(w)); + } + xparse(value_store, local_tokens); +#else + boost::throw_exception( + std::runtime_error("UTF-8 conversion not supported.")); +#endif + } else { + // Already in local encoding, pass unmodified + xparse(value_store, new_tokens); + } + } + +#ifndef BOOST_NO_STD_WSTRING + void + value_semantic_codecvt_helper<wchar_t>:: + parse(boost::any& value_store, + const std::vector<std::string>& new_tokens, + bool utf8) const + { + std::vector<wstring> tokens; + if (utf8) { + // Convert from utf8 + for (unsigned i = 0; i < new_tokens.size(); ++i) { + tokens.push_back(from_utf8(new_tokens[i])); + } + + } else { + // Convert from local encoding + for (unsigned i = 0; i < new_tokens.size(); ++i) { + tokens.push_back(from_local_8_bit(new_tokens[i])); + } + } + + xparse(value_store, tokens); + } +#endif + + BOOST_PROGRAM_OPTIONS_DECL std::string arg("arg"); + + std::string + untyped_value::name() const + { + return arg; + } + + unsigned + untyped_value::min_tokens() const + { + if (m_zero_tokens) + return 0; + else + return 1; + } + + unsigned + untyped_value::max_tokens() const + { + if (m_zero_tokens) + return 0; + else + return 1; + } + + + void + untyped_value::xparse(boost::any& value_store, + const std::vector<std::string>& new_tokens) const + { + if (!value_store.empty()) + boost::throw_exception( + multiple_occurrences()); + if (new_tokens.size() > 1) + boost::throw_exception(multiple_values()); + value_store = new_tokens.empty() ? std::string("") : new_tokens.front(); + } + + BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* + bool_switch() + { + return bool_switch(0); + } + + BOOST_PROGRAM_OPTIONS_DECL typed_value<bool>* + bool_switch(bool* v) + { + typed_value<bool>* r = new typed_value<bool>(v); + r->default_value(0); + r->zero_tokens(); + + return r; + } + + /* Validates bool value. + Any of "1", "true", "yes", "on" will be converted to "1".<br> + Any of "0", "false", "no", "off" will be converted to "0".<br> + Case is ignored. The 'xs' vector can either be empty, in which + case the value is 'true', or can contain explicit value. + */ + BOOST_PROGRAM_OPTIONS_DECL void validate(any& v, const vector<string>& xs, + bool*, int) + { + check_first_occurrence(v); + string s(get_single_string(xs, true)); + + for (size_t i = 0; i < s.size(); ++i) + s[i] = char(tolower(s[i])); + + if (s.empty() || s == "on" || s == "yes" || s == "1" || s == "true") + v = any(true); + else if (s == "off" || s == "no" || s == "0" || s == "false") + v = any(false); + else + boost::throw_exception(invalid_bool_value(s)); + } + + // This is blatant copy-paste. However, templating this will cause a problem, + // since wstring can't be constructed/compared with char*. We'd need to + // create auxiliary 'widen' routine to convert from char* into + // needed string type, and that's more work. +#if !defined(BOOST_NO_STD_WSTRING) + BOOST_PROGRAM_OPTIONS_DECL + void validate(any& v, const vector<wstring>& xs, bool*, int) + { + check_first_occurrence(v); + wstring s(get_single_string(xs, true)); + + for (size_t i = 0; i < s.size(); ++i) + s[i] = wchar_t(tolower(s[i])); + + if (s.empty() || s == L"on" || s == L"yes" || s == L"1" || s == L"true") + v = any(true); + else if (s == L"off" || s == L"no" || s == L"0" || s == L"false") + v = any(false); + else + boost::throw_exception(invalid_bool_value(convert_value(s))); + } +#endif + BOOST_PROGRAM_OPTIONS_DECL + void validate(any& v, const vector<string>& xs, std::string*, int) + { + check_first_occurrence(v); + v = any(get_single_string(xs)); + } + +#if !defined(BOOST_NO_STD_WSTRING) + BOOST_PROGRAM_OPTIONS_DECL + void validate(any& v, const vector<wstring>& xs, std::string*, int) + { + check_first_occurrence(v); + v = any(get_single_string(xs)); + } +#endif + + namespace validators { + + BOOST_PROGRAM_OPTIONS_DECL + void check_first_occurrence(const boost::any& value) + { + if (!value.empty()) + boost::throw_exception( + multiple_occurrences()); + } + } + + + invalid_option_value:: + invalid_option_value(const std::string& bad_value) + : validation_error(validation_error::invalid_option_value) + { + set_substitute("value", bad_value); + } + +#ifndef BOOST_NO_STD_WSTRING + invalid_option_value:: + invalid_option_value(const std::wstring& bad_value) + : validation_error(validation_error::invalid_option_value) + { + set_substitute("value", convert_value(bad_value)); + } +#endif + + + + invalid_bool_value:: + invalid_bool_value(const std::string& bad_value) + : validation_error(validation_error::invalid_bool_value) + { + set_substitute("value", bad_value); + } + + + + + + + error_with_option_name::error_with_option_name( const std::string& template_, + const std::string& option_name, + const std::string& original_token, + int option_style) : + error(template_), + m_option_style(option_style), + m_error_template(template_) + { + // parameter | placeholder | value + // --------- | ----------- | ----- + set_substitute_default("canonical_option", "option '%canonical_option%'", "option"); + set_substitute_default("value", "argument ('%value%')", "argument"); + set_substitute_default("prefix", "%prefix%", ""); + m_substitutions["option"] = option_name; + m_substitutions["original_token"] = original_token; + } + + const char* error_with_option_name::what() const noexcept - { - // will substitute tokens each time what is run() - substitute_placeholders(m_error_template); - - return m_message.c_str(); - } - - void error_with_option_name::replace_token(const string& from, const string& to) const - { - for (;;) - { - std::size_t pos = m_message.find(from.c_str(), 0, from.length()); - // not found: all replaced - if (pos == std::string::npos) - return; - m_message.replace(pos, from.length(), to); - } - } - - string error_with_option_name::get_canonical_option_prefix() const - { - switch (m_option_style) - { - case command_line_style::allow_dash_for_short: - return "-"; - case command_line_style::allow_slash_for_short: - return "/"; - case command_line_style::allow_long_disguise: - return "-"; - case command_line_style::allow_long: - return "--"; - case 0: - return ""; - } - throw std::logic_error("error_with_option_name::m_option_style can only be " - "one of [0, allow_dash_for_short, allow_slash_for_short, " - "allow_long_disguise or allow_long]"); - } - - - string error_with_option_name::get_canonical_option_name() const - { - if (!m_substitutions.find("option")->second.length()) - return m_substitutions.find("original_token")->second; - - string original_token = strip_prefixes(m_substitutions.find("original_token")->second); - string option_name = strip_prefixes(m_substitutions.find("option")->second); - - // For long options, use option name - if (m_option_style == command_line_style::allow_long || - m_option_style == command_line_style::allow_long_disguise) - return get_canonical_option_prefix() + option_name; - - // For short options use first letter of original_token - if (m_option_style && original_token.length()) - return get_canonical_option_prefix() + original_token[0]; - - // no prefix - return option_name; - } - - - void error_with_option_name::substitute_placeholders(const string& error_template) const - { - m_message = error_template; - std::map<std::string, std::string> substitutions(m_substitutions); - substitutions["canonical_option"] = get_canonical_option_name(); - substitutions["prefix"] = get_canonical_option_prefix(); - - - // - // replace placeholder with defaults if values are missing + { + // will substitute tokens each time what is run() + substitute_placeholders(m_error_template); + + return m_message.c_str(); + } + + void error_with_option_name::replace_token(const string& from, const string& to) const + { + for (;;) + { + std::size_t pos = m_message.find(from.c_str(), 0, from.length()); + // not found: all replaced + if (pos == std::string::npos) + return; + m_message.replace(pos, from.length(), to); + } + } + + string error_with_option_name::get_canonical_option_prefix() const + { + switch (m_option_style) + { + case command_line_style::allow_dash_for_short: + return "-"; + case command_line_style::allow_slash_for_short: + return "/"; + case command_line_style::allow_long_disguise: + return "-"; + case command_line_style::allow_long: + return "--"; + case 0: + return ""; + } + throw std::logic_error("error_with_option_name::m_option_style can only be " + "one of [0, allow_dash_for_short, allow_slash_for_short, " + "allow_long_disguise or allow_long]"); + } + + + string error_with_option_name::get_canonical_option_name() const + { + if (!m_substitutions.find("option")->second.length()) + return m_substitutions.find("original_token")->second; + + string original_token = strip_prefixes(m_substitutions.find("original_token")->second); + string option_name = strip_prefixes(m_substitutions.find("option")->second); + + // For long options, use option name + if (m_option_style == command_line_style::allow_long || + m_option_style == command_line_style::allow_long_disguise) + return get_canonical_option_prefix() + option_name; + + // For short options use first letter of original_token + if (m_option_style && original_token.length()) + return get_canonical_option_prefix() + original_token[0]; + + // no prefix + return option_name; + } + + + void error_with_option_name::substitute_placeholders(const string& error_template) const + { + m_message = error_template; + std::map<std::string, std::string> substitutions(m_substitutions); + substitutions["canonical_option"] = get_canonical_option_name(); + substitutions["prefix"] = get_canonical_option_prefix(); + + // - for (map<string, string_pair>::const_iterator iter = m_substitution_defaults.begin(); - iter != m_substitution_defaults.end(); ++iter) - { - // missing parameter: use default - if (substitutions.count(iter->first) == 0 || - substitutions[iter->first].length() == 0) - replace_token(iter->second.first, iter->second.second); - } - - - // - // replace placeholder with values - // placeholder are denoted by surrounding '%' + // replace placeholder with defaults if values are missing + // + for (map<string, string_pair>::const_iterator iter = m_substitution_defaults.begin(); + iter != m_substitution_defaults.end(); ++iter) + { + // missing parameter: use default + if (substitutions.count(iter->first) == 0 || + substitutions[iter->first].length() == 0) + replace_token(iter->second.first, iter->second.second); + } + + // - for (map<string, string>::iterator iter = substitutions.begin(); - iter != substitutions.end(); ++iter) - replace_token('%' + iter->first + '%', iter->second); - } - - - void ambiguous_option::substitute_placeholders(const string& original_error_template) const - { - // For short forms, all alternatives must be identical, by - // definition, to the specified option, so we don't need to - // display alternatives - if (m_option_style == command_line_style::allow_dash_for_short || - m_option_style == command_line_style::allow_slash_for_short) - { - error_with_option_name::substitute_placeholders(original_error_template); - return; - } - - - string error_template = original_error_template; - // remove duplicates using std::set - std::set<std::string> alternatives_set (m_alternatives.begin(), m_alternatives.end()); - std::vector<std::string> alternatives_vec (alternatives_set.begin(), alternatives_set.end()); - - error_template += " and matches "; - // Being very cautious: should be > 1 alternative! - if (alternatives_vec.size() > 1) - { - for (unsigned i = 0; i < alternatives_vec.size() - 1; ++i) - error_template += "'%prefix%" + alternatives_vec[i] + "', "; - error_template += "and "; - } - - // there is a programming error if multiple options have the same name... - if (m_alternatives.size() > 1 && alternatives_vec.size() == 1) - error_template += "different versions of "; - - error_template += "'%prefix%" + alternatives_vec.back() + "'"; - - - // use inherited logic - error_with_option_name::substitute_placeholders(error_template); - } - - - - - - - string - validation_error::get_template(kind_t kind) - { - // Initially, store the message in 'const char*' variable, - // to avoid conversion to std::string in all cases. - const char* msg; - switch(kind) - { - case invalid_bool_value: - msg = "the argument ('%value%') for option '%canonical_option%' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'"; - break; - case invalid_option_value: - msg = "the argument ('%value%') for option '%canonical_option%' is invalid"; - break; - case multiple_values_not_allowed: - msg = "option '%canonical_option%' only takes a single argument"; - break; - case at_least_one_value_required: - msg = "option '%canonical_option%' requires at least one argument"; - break; - // currently unused - case invalid_option: - msg = "option '%canonical_option%' is not valid"; - break; - default: - msg = "unknown error"; - } - return msg; - } - -}} + // replace placeholder with values + // placeholder are denoted by surrounding '%' + // + for (map<string, string>::iterator iter = substitutions.begin(); + iter != substitutions.end(); ++iter) + replace_token('%' + iter->first + '%', iter->second); + } + + + void ambiguous_option::substitute_placeholders(const string& original_error_template) const + { + // For short forms, all alternatives must be identical, by + // definition, to the specified option, so we don't need to + // display alternatives + if (m_option_style == command_line_style::allow_dash_for_short || + m_option_style == command_line_style::allow_slash_for_short) + { + error_with_option_name::substitute_placeholders(original_error_template); + return; + } + + + string error_template = original_error_template; + // remove duplicates using std::set + std::set<std::string> alternatives_set (m_alternatives.begin(), m_alternatives.end()); + std::vector<std::string> alternatives_vec (alternatives_set.begin(), alternatives_set.end()); + + error_template += " and matches "; + // Being very cautious: should be > 1 alternative! + if (alternatives_vec.size() > 1) + { + for (unsigned i = 0; i < alternatives_vec.size() - 1; ++i) + error_template += "'%prefix%" + alternatives_vec[i] + "', "; + error_template += "and "; + } + + // there is a programming error if multiple options have the same name... + if (m_alternatives.size() > 1 && alternatives_vec.size() == 1) + error_template += "different versions of "; + + error_template += "'%prefix%" + alternatives_vec.back() + "'"; + + + // use inherited logic + error_with_option_name::substitute_placeholders(error_template); + } + + + + + + + string + validation_error::get_template(kind_t kind) + { + // Initially, store the message in 'const char*' variable, + // to avoid conversion to std::string in all cases. + const char* msg; + switch(kind) + { + case invalid_bool_value: + msg = "the argument ('%value%') for option '%canonical_option%' is invalid. Valid choices are 'on|off', 'yes|no', '1|0' and 'true|false'"; + break; + case invalid_option_value: + msg = "the argument ('%value%') for option '%canonical_option%' is invalid"; + break; + case multiple_values_not_allowed: + msg = "option '%canonical_option%' only takes a single argument"; + break; + case at_least_one_value_required: + msg = "option '%canonical_option%' requires at least one argument"; + break; + // currently unused + case invalid_option: + msg = "option '%canonical_option%' is not valid"; + break; + default: + msg = "unknown error"; + } + return msg; + } + +}} diff --git a/contrib/restricted/boost/libs/program_options/src/variables_map.cpp b/contrib/restricted/boost/libs/program_options/src/variables_map.cpp index bc85f7e34b..63cb5b3287 100644 --- a/contrib/restricted/boost/libs/program_options/src/variables_map.cpp +++ b/contrib/restricted/boost/libs/program_options/src/variables_map.cpp @@ -1,248 +1,248 @@ -// Copyright Vladimir Prus 2002-2004. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - - -#define BOOST_PROGRAM_OPTIONS_SOURCE -#include <boost/program_options/config.hpp> -#include <boost/program_options/parsers.hpp> -#include <boost/program_options/options_description.hpp> -#include <boost/program_options/value_semantic.hpp> -#include <boost/program_options/variables_map.hpp> - -#include <cassert> - -namespace boost { namespace program_options { - - using namespace std; - - // First, performs semantic actions for 'oa'. - // Then, stores in 'm' all options that are defined in 'desc'. - BOOST_PROGRAM_OPTIONS_DECL - void store(const parsed_options& options, variables_map& xm, - bool utf8) - { - // TODO: what if we have different definition - // for the same option name during different calls - // 'store'. - assert(options.description); - const options_description& desc = *options.description; - - // We need to access map's operator[], not the overriden version - // variables_map. Ehmm.. messy. - std::map<std::string, variable_value>& m = xm; - - std::set<std::string> new_final; - - // Declared once, to please Intel in VC++ mode; - unsigned i; - - // Declared here so can be used to provide context for exceptions - string option_name; - string original_token; - -#ifndef BOOST_NO_EXCEPTIONS - try -#endif - { - - // First, convert/store all given options - for (i = 0; i < options.options.size(); ++i) { - - option_name = options.options[i].string_key; - // Skip positional options without name - if (option_name.empty()) - continue; - - // Ignore unregistered option. The 'unregistered' - // field can be true only if user has explicitly asked - // to allow unregistered options. We can't store them - // to variables map (lacking any information about paring), - // so just ignore them. - if (options.options[i].unregistered) - continue; - - // If option has final value, skip this assignment - if (xm.m_final.count(option_name)) - continue; - - original_token = options.options[i].original_tokens.size() ? - options.options[i].original_tokens[0] : ""; - const option_description& d = desc.find(option_name, false, - false, false); - - variable_value& v = m[option_name]; - if (v.defaulted()) { - // Explicit assignment here erases defaulted value - v = variable_value(); - } - - d.semantic()->parse(v.value(), options.options[i].value, utf8); - - v.m_value_semantic = d.semantic(); - - // The option is not composing, and the value is explicitly - // provided. Ignore values of this option for subsequent - // calls to 'store'. We store this to a temporary set, - // so that several assignment inside *this* 'store' call - // are allowed. - if (!d.semantic()->is_composing()) - new_final.insert(option_name); - } - } -#ifndef BOOST_NO_EXCEPTIONS - catch(error_with_option_name& e) - { - // add context and rethrow - e.add_context(option_name, original_token, options.m_options_prefix); - throw; - } -#endif - xm.m_final.insert(new_final.begin(), new_final.end()); - - - - // Second, apply default values and store required options. - const vector<shared_ptr<option_description> >& all = desc.options(); - for(i = 0; i < all.size(); ++i) - { - const option_description& d = *all[i]; - string key = d.key(""); - // FIXME: this logic relies on knowledge of option_description - // internals. - // The 'key' is empty if options description contains '*'. - // In that - // case, default value makes no sense at all. - if (key.empty()) - { - continue; - } - if (m.count(key) == 0) { - - boost::any def; - if (d.semantic()->apply_default(def)) { - m[key] = variable_value(def, true); - m[key].m_value_semantic = d.semantic(); - } - } - - // add empty value if this is an required option - if (d.semantic()->is_required()) { - - // For option names specified in multiple ways, e.g. on the command line, - // config file etc, the following precedence rules apply: - // "--" > ("-" or "/") > "" - // Precedence is set conveniently by a single call to length() - string canonical_name = d.canonical_display_name(options.m_options_prefix); - if (canonical_name.length() > xm.m_required[key].length()) - xm.m_required[key] = canonical_name; - } - } - } - - BOOST_PROGRAM_OPTIONS_DECL - void store(const wparsed_options& options, variables_map& m) - { - store(options.utf8_encoded_options, m, true); - } - - BOOST_PROGRAM_OPTIONS_DECL - void notify(variables_map& vm) - { - vm.notify(); - } - - abstract_variables_map::abstract_variables_map() - : m_next(0) - {} - - abstract_variables_map:: - abstract_variables_map(const abstract_variables_map* next) - : m_next(next) - {} - - const variable_value& - abstract_variables_map::operator[](const std::string& name) const - { - const variable_value& v = get(name); - if (v.empty() && m_next) - return (*m_next)[name]; - else if (v.defaulted() && m_next) { - const variable_value& v2 = (*m_next)[name]; - if (!v2.empty() && !v2.defaulted()) - return v2; - else return v; - } else { - return v; - } - } - - void - abstract_variables_map::next(abstract_variables_map* next) - { - m_next = next; - } - - variables_map::variables_map() - {} - - variables_map::variables_map(const abstract_variables_map* next) - : abstract_variables_map(next) - {} - - void variables_map::clear() - { - std::map<std::string, variable_value>::clear(); - m_final.clear(); - m_required.clear(); - } - - const variable_value& - variables_map::get(const std::string& name) const - { - static variable_value empty; - const_iterator i = this->find(name); - if (i == this->end()) - return empty; - else - return i->second; - } - - void - variables_map::notify() - { - // This checks if all required options occur - for (map<string, string>::const_iterator r = m_required.begin(); - r != m_required.end(); - ++r) - { - const string& opt = r->first; - const string& display_opt = r->second; - map<string, variable_value>::const_iterator iter = find(opt); - if (iter == end() || iter->second.empty()) - { - boost::throw_exception(required_option(display_opt)); - - } - } - - // Lastly, run notify actions. - for (map<string, variable_value>::iterator k = begin(); - k != end(); - ++k) - { - /* Users might wish to use variables_map to store their own values - that are not parsed, and therefore will not have value_semantics - defined. Do not crash on such values. In multi-module programs, - one module might add custom values, and the 'notify' function - will be called after that, so we check that value_sematics is - not NULL. See: - https://svn.boost.org/trac/boost/ticket/2782 - */ - if (k->second.m_value_semantic) - k->second.m_value_semantic->notify(k->second.value()); - } - } - -}} +// Copyright Vladimir Prus 2002-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/config.hpp> +#include <boost/program_options/parsers.hpp> +#include <boost/program_options/options_description.hpp> +#include <boost/program_options/value_semantic.hpp> +#include <boost/program_options/variables_map.hpp> + +#include <cassert> + +namespace boost { namespace program_options { + + using namespace std; + + // First, performs semantic actions for 'oa'. + // Then, stores in 'm' all options that are defined in 'desc'. + BOOST_PROGRAM_OPTIONS_DECL + void store(const parsed_options& options, variables_map& xm, + bool utf8) + { + // TODO: what if we have different definition + // for the same option name during different calls + // 'store'. + assert(options.description); + const options_description& desc = *options.description; + + // We need to access map's operator[], not the overriden version + // variables_map. Ehmm.. messy. + std::map<std::string, variable_value>& m = xm; + + std::set<std::string> new_final; + + // Declared once, to please Intel in VC++ mode; + unsigned i; + + // Declared here so can be used to provide context for exceptions + string option_name; + string original_token; + +#ifndef BOOST_NO_EXCEPTIONS + try +#endif + { + + // First, convert/store all given options + for (i = 0; i < options.options.size(); ++i) { + + option_name = options.options[i].string_key; + // Skip positional options without name + if (option_name.empty()) + continue; + + // Ignore unregistered option. The 'unregistered' + // field can be true only if user has explicitly asked + // to allow unregistered options. We can't store them + // to variables map (lacking any information about paring), + // so just ignore them. + if (options.options[i].unregistered) + continue; + + // If option has final value, skip this assignment + if (xm.m_final.count(option_name)) + continue; + + original_token = options.options[i].original_tokens.size() ? + options.options[i].original_tokens[0] : ""; + const option_description& d = desc.find(option_name, false, + false, false); + + variable_value& v = m[option_name]; + if (v.defaulted()) { + // Explicit assignment here erases defaulted value + v = variable_value(); + } + + d.semantic()->parse(v.value(), options.options[i].value, utf8); + + v.m_value_semantic = d.semantic(); + + // The option is not composing, and the value is explicitly + // provided. Ignore values of this option for subsequent + // calls to 'store'. We store this to a temporary set, + // so that several assignment inside *this* 'store' call + // are allowed. + if (!d.semantic()->is_composing()) + new_final.insert(option_name); + } + } +#ifndef BOOST_NO_EXCEPTIONS + catch(error_with_option_name& e) + { + // add context and rethrow + e.add_context(option_name, original_token, options.m_options_prefix); + throw; + } +#endif + xm.m_final.insert(new_final.begin(), new_final.end()); + + + + // Second, apply default values and store required options. + const vector<shared_ptr<option_description> >& all = desc.options(); + for(i = 0; i < all.size(); ++i) + { + const option_description& d = *all[i]; + string key = d.key(""); + // FIXME: this logic relies on knowledge of option_description + // internals. + // The 'key' is empty if options description contains '*'. + // In that + // case, default value makes no sense at all. + if (key.empty()) + { + continue; + } + if (m.count(key) == 0) { + + boost::any def; + if (d.semantic()->apply_default(def)) { + m[key] = variable_value(def, true); + m[key].m_value_semantic = d.semantic(); + } + } + + // add empty value if this is an required option + if (d.semantic()->is_required()) { + + // For option names specified in multiple ways, e.g. on the command line, + // config file etc, the following precedence rules apply: + // "--" > ("-" or "/") > "" + // Precedence is set conveniently by a single call to length() + string canonical_name = d.canonical_display_name(options.m_options_prefix); + if (canonical_name.length() > xm.m_required[key].length()) + xm.m_required[key] = canonical_name; + } + } + } + + BOOST_PROGRAM_OPTIONS_DECL + void store(const wparsed_options& options, variables_map& m) + { + store(options.utf8_encoded_options, m, true); + } + + BOOST_PROGRAM_OPTIONS_DECL + void notify(variables_map& vm) + { + vm.notify(); + } + + abstract_variables_map::abstract_variables_map() + : m_next(0) + {} + + abstract_variables_map:: + abstract_variables_map(const abstract_variables_map* next) + : m_next(next) + {} + + const variable_value& + abstract_variables_map::operator[](const std::string& name) const + { + const variable_value& v = get(name); + if (v.empty() && m_next) + return (*m_next)[name]; + else if (v.defaulted() && m_next) { + const variable_value& v2 = (*m_next)[name]; + if (!v2.empty() && !v2.defaulted()) + return v2; + else return v; + } else { + return v; + } + } + + void + abstract_variables_map::next(abstract_variables_map* next) + { + m_next = next; + } + + variables_map::variables_map() + {} + + variables_map::variables_map(const abstract_variables_map* next) + : abstract_variables_map(next) + {} + + void variables_map::clear() + { + std::map<std::string, variable_value>::clear(); + m_final.clear(); + m_required.clear(); + } + + const variable_value& + variables_map::get(const std::string& name) const + { + static variable_value empty; + const_iterator i = this->find(name); + if (i == this->end()) + return empty; + else + return i->second; + } + + void + variables_map::notify() + { + // This checks if all required options occur + for (map<string, string>::const_iterator r = m_required.begin(); + r != m_required.end(); + ++r) + { + const string& opt = r->first; + const string& display_opt = r->second; + map<string, variable_value>::const_iterator iter = find(opt); + if (iter == end() || iter->second.empty()) + { + boost::throw_exception(required_option(display_opt)); + + } + } + + // Lastly, run notify actions. + for (map<string, variable_value>::iterator k = begin(); + k != end(); + ++k) + { + /* Users might wish to use variables_map to store their own values + that are not parsed, and therefore will not have value_semantics + defined. Do not crash on such values. In multi-module programs, + one module might add custom values, and the 'notify' function + will be called after that, so we check that value_sematics is + not NULL. See: + https://svn.boost.org/trac/boost/ticket/2782 + */ + if (k->second.m_value_semantic) + k->second.m_value_semantic->notify(k->second.value()); + } + } + +}} diff --git a/contrib/restricted/boost/libs/program_options/src/winmain.cpp b/contrib/restricted/boost/libs/program_options/src/winmain.cpp index 6220043f6c..7ea4ef0290 100644 --- a/contrib/restricted/boost/libs/program_options/src/winmain.cpp +++ b/contrib/restricted/boost/libs/program_options/src/winmain.cpp @@ -1,102 +1,102 @@ -// Copyright Vladimir Prus 2002-2004. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt -// or copy at http://www.boost.org/LICENSE_1_0.txt) - -#define BOOST_PROGRAM_OPTIONS_SOURCE -#include <boost/program_options/parsers.hpp> -#include <cctype> - -using std::size_t; - -#ifdef _WIN32 -namespace boost { namespace program_options { - - // Take a command line string and splits in into tokens, according - // to the rules windows command line processor uses. - // - // The rules are pretty funny, see - // http://article.gmane.org/gmane.comp.lib.boost.user/3005 - // http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp - BOOST_PROGRAM_OPTIONS_DECL - std::vector<std::string> split_winmain(const std::string& input) - { - std::vector<std::string> result; - - std::string::const_iterator i = input.begin(), e = input.end(); - for(;i != e; ++i) - if (!isspace((unsigned char)*i)) - break; - - if (i != e) { - - std::string current; - bool inside_quoted = false; - bool empty_quote = false; - int backslash_count = 0; - - for(; i != e; ++i) { - if (*i == '"') { - // '"' preceded by even number (n) of backslashes generates - // n/2 backslashes and is a quoted block delimiter - if (backslash_count % 2 == 0) { - current.append(backslash_count / 2, '\\'); - empty_quote = inside_quoted && current.empty(); - inside_quoted = !inside_quoted; - // '"' preceded by odd number (n) of backslashes generates - // (n-1)/2 backslashes and is literal quote. - } else { - current.append(backslash_count / 2, '\\'); - current += '"'; - } - backslash_count = 0; - } else if (*i == '\\') { - ++backslash_count; - } else { - // Not quote or backslash. All accumulated backslashes should be - // added - if (backslash_count) { - current.append(backslash_count, '\\'); - backslash_count = 0; - } - if (isspace((unsigned char)*i) && !inside_quoted) { - // Space outside quoted section terminate the current argument - result.push_back(current); - current.resize(0); - empty_quote = false; - for(;i != e && isspace((unsigned char)*i); ++i) - ; - --i; - } else { - current += *i; - } - } - } - - // If we have trailing backslashes, add them - if (backslash_count) - current.append(backslash_count, '\\'); +// Copyright Vladimir Prus 2002-2004. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_PROGRAM_OPTIONS_SOURCE +#include <boost/program_options/parsers.hpp> +#include <cctype> + +using std::size_t; + +#ifdef _WIN32 +namespace boost { namespace program_options { + + // Take a command line string and splits in into tokens, according + // to the rules windows command line processor uses. + // + // The rules are pretty funny, see + // http://article.gmane.org/gmane.comp.lib.boost.user/3005 + // http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp + BOOST_PROGRAM_OPTIONS_DECL + std::vector<std::string> split_winmain(const std::string& input) + { + std::vector<std::string> result; + + std::string::const_iterator i = input.begin(), e = input.end(); + for(;i != e; ++i) + if (!isspace((unsigned char)*i)) + break; - // If we have non-empty 'current' or we're still in quoted - // section (even if 'current' is empty), add the last token. - if (!current.empty() || inside_quoted || empty_quote) - result.push_back(current); - } - return result; - } - -#ifndef BOOST_NO_STD_WSTRING - BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring> - split_winmain(const std::wstring& cmdline) - { - std::vector<std::wstring> result; - std::vector<std::string> aux = split_winmain(to_internal(cmdline)); - for (size_t i = 0, e = aux.size(); i < e; ++i) - result.push_back(from_utf8(aux[i])); - return result; - } -#endif - -}} -#endif - + if (i != e) { + + std::string current; + bool inside_quoted = false; + bool empty_quote = false; + int backslash_count = 0; + + for(; i != e; ++i) { + if (*i == '"') { + // '"' preceded by even number (n) of backslashes generates + // n/2 backslashes and is a quoted block delimiter + if (backslash_count % 2 == 0) { + current.append(backslash_count / 2, '\\'); + empty_quote = inside_quoted && current.empty(); + inside_quoted = !inside_quoted; + // '"' preceded by odd number (n) of backslashes generates + // (n-1)/2 backslashes and is literal quote. + } else { + current.append(backslash_count / 2, '\\'); + current += '"'; + } + backslash_count = 0; + } else if (*i == '\\') { + ++backslash_count; + } else { + // Not quote or backslash. All accumulated backslashes should be + // added + if (backslash_count) { + current.append(backslash_count, '\\'); + backslash_count = 0; + } + if (isspace((unsigned char)*i) && !inside_quoted) { + // Space outside quoted section terminate the current argument + result.push_back(current); + current.resize(0); + empty_quote = false; + for(;i != e && isspace((unsigned char)*i); ++i) + ; + --i; + } else { + current += *i; + } + } + } + + // If we have trailing backslashes, add them + if (backslash_count) + current.append(backslash_count, '\\'); + + // If we have non-empty 'current' or we're still in quoted + // section (even if 'current' is empty), add the last token. + if (!current.empty() || inside_quoted || empty_quote) + result.push_back(current); + } + return result; + } + +#ifndef BOOST_NO_STD_WSTRING + BOOST_PROGRAM_OPTIONS_DECL std::vector<std::wstring> + split_winmain(const std::wstring& cmdline) + { + std::vector<std::wstring> result; + std::vector<std::string> aux = split_winmain(to_internal(cmdline)); + for (size_t i = 0, e = aux.size(); i < e; ++i) + result.push_back(from_utf8(aux[i])); + return result; + } +#endif + +}} +#endif + |