diff options
author | Kevin Smith <git@kismith.co.uk> | 2010-04-21 11:45:51 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2010-04-23 10:54:04 (GMT) |
commit | 91686a86876553774452d97f3f74d5f147b19164 (patch) | |
tree | fd0d601497f0cc757f12ec7c336b5b64213bbfd3 /3rdParty/Boost/src/libs/program_options | |
parent | 6bd72c67896a20041556519548650590553f47c9 (diff) | |
download | swift-contrib-91686a86876553774452d97f3f74d5f147b19164.zip swift-contrib-91686a86876553774452d97f3f74d5f147b19164.tar.bz2 |
Make latency stats optional.
Includes boost program_options so we can use commandline parameters.
Netbook mode is now activated with --netbook-mode.
Latency debug is activated with --latency-debug.
Diffstat (limited to '3rdParty/Boost/src/libs/program_options')
11 files changed, 2677 insertions, 0 deletions
diff --git a/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp b/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp new file mode 100644 index 0000000..be31385 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp @@ -0,0 +1,656 @@ +// 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; + + invalid_syntax:: + invalid_syntax(const string& tokens, kind_t kind) + : error(error_message(kind).append(" in '").append(tokens).append("'")) + , m_tokens(tokens) + , m_kind(kind) + {} + + string + invalid_syntax::error_message(kind_t kind) + { + // Initially, store the message in 'const char*' variable, + // to avoid conversion to string in all cases. + const char* msg; + switch(kind) + { + case long_not_allowed: + msg = "long options are not allowed"; + break; + case long_adjacent_not_allowed: + msg = "parameters adjacent to long options not allowed"; + break; + case short_adjacent_not_allowed: + msg = "parameters adjust to short options are not allowed"; + break; + case empty_adjacent_parameter: + msg = "adjacent parameter is empty"; + break; + case missing_parameter: + msg = "required parameter is missing"; + break; + case extra_parameter: + msg = "extra parameter"; + break; + case unrecognized_line: + msg = "unrecognized line"; + break; + default: + msg = "unknown error"; + } + return msg; + } + + invalid_syntax::kind_t + invalid_syntax::kind() const + { + return m_kind; + } + + const string& + invalid_syntax::tokens() const + { + return m_tokens; + } + + invalid_command_line_syntax:: + invalid_command_line_syntax(const string& tokens, kind_t kind) + : invalid_syntax(tokens, kind) + {} + +}} + + +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->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 = "style disallows parameters for long options"; + + if (!error && (style & allow_short) && + !(style & short_allow_adjacent) && !(style & short_allow_next)) + error = "style disallows parameters for short options"; + + if (!error && (style & allow_short) && + !(style & allow_dash_for_short) && !(style & allow_slash_for_short)) + error = "style disallows all characters for short options"; + + 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; + } + + + 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; + while(!args.empty()) + { + bool ok = false; + for(unsigned i = 0; i < style_parsers.size(); ++i) + { + unsigned current_size = 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; + } + } + + 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 multitoke 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 = + 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) + 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 - 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; + + // 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(opt.string_key)); + } + } + 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. + + // We don't check if those tokens look like option, or not! + + unsigned min_tokens = d.semantic()->min_tokens(); + unsigned max_tokens = d.semantic()->max_tokens(); + + unsigned present_tokens = opt.value.size() + other_tokens.size(); + + if (present_tokens >= min_tokens) + { + if (!opt.value.empty() && max_tokens == 0) + { + boost::throw_exception(invalid_command_line_syntax(opt.string_key, + invalid_command_line_syntax::extra_parameter)); + } + + // If an option wants, at minimum, N tokens, we grab them there, + // when adding these tokens as values to current option we check + // if they look like options + if (opt.value.size() <= min_tokens) + { + min_tokens -= opt.value.size(); + } + else + { + min_tokens = 0; + } + + // 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()) + { + const option_description* od = m_desc->find_nothrow(other_tokens[0], + is_style_active(allow_guessing), + is_style_active(long_case_insensitive), + is_style_active(short_case_insensitive)); + if (od) + boost::throw_exception(invalid_command_line_syntax(opt.string_key, + invalid_command_line_syntax::missing_parameter)); + } + opt.value.push_back(other_tokens[0]); + opt.original_tokens.push_back(other_tokens[0]); + other_tokens.erase(other_tokens.begin()); + } + } + else + { + boost::throw_exception(invalid_command_line_syntax(opt.string_key, + invalid_command_line_syntax::missing_parameter)); + + } + } + + 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(name, + invalid_command_line_syntax::empty_adjacent_parameter) ); + } + 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 + = m_desc->find_nothrow(name, false, false, + is_style_active(short_case_insensitive)); + + // 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] == '/'))) + { + 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); + } + } + 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/3rdParty/Boost/src/libs/program_options/src/config_file.cpp b/3rdParty/Boost/src/libs/program_options/src/config_file.cpp new file mode 100644 index 0000000..a12844c --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/config_file.cpp @@ -0,0 +1,196 @@ +// 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("bad prefixes")); + 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_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 + 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/3rdParty/Boost/src/libs/program_options/src/convert.cpp b/3rdParty/Boost/src/libs/program_options/src/convert.cpp new file mode 100644 index 0000000..9be759e --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/convert.cpp @@ -0,0 +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 + 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_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 + } + + +} diff --git a/3rdParty/Boost/src/libs/program_options/src/options_description.cpp b/3rdParty/Boost/src/libs/program_options/src/options_description.cpp new file mode 100644 index 0000000..bfd113d --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/options_description.cpp @@ -0,0 +1,621 @@ +// 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_occurences 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; + } + } + } + + 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; + } + + 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 string(m_short_name).append(" [ --"). + append(m_long_name).append(" ]"); + else + 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(name)); + 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; + 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)); + } + else + { + // FIXME: the use of 'key' here might not + // be the best approach. + approximate_matches.push_back(m_options[i]->key(name)); + } + + found = m_options[i]; + } + if (full_matches.size() > 1) + boost::throw_exception( + ambiguous_option(name, 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(name, 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")); + } + + // 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 = 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>(distance(last_space, line_end)) < + (line_length / 2)) + { + line_end = last_space; + } + } + } // prevent chopped words + + // write line to stream + copy(line_begin, line_end, ostream_iterator<char>(os)); + + if (first_line) + { + indent += par_indent; + line_length -= 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 - ss.str().size(); pad > 0; --pad) + { + os.put(' '); + } + } + + format_description(os, opt.description(), + first_column_width, line_length); + } + } + } + + void + options_description::print(std::ostream& os) const + { + if (!m_caption.empty()) + os << m_caption << ":\n"; + + /* 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())); + } + /* 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; + + /* The options formatting style is stolen from Subversion. */ + for (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]; + } + } + +}} diff --git a/3rdParty/Boost/src/libs/program_options/src/parsers.cpp b/3rdParty/Boost/src/libs/program_options/src/parsers.cpp new file mode 100644 index 0000000..bc3b858 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/parsers.cpp @@ -0,0 +1,245 @@ +// 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__) +#include <crt_externs.h> +#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) + { + 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("long name required for config file")); + + 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)); + } + return parse_config_file(strm, desc, allow_unregistered); + } + + 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 += 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/3rdParty/Boost/src/libs/program_options/src/positional_options.cpp b/3rdParty/Boost/src/libs/program_options/src/positional_options.cpp new file mode 100644 index 0000000..55995d7 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/positional_options.cpp @@ -0,0 +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() ? + 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/3rdParty/Boost/src/libs/program_options/src/split.cpp b/3rdParty/Boost/src/libs/program_options/src/split.cpp new file mode 100644 index 0000000..96da068 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/split.cpp @@ -0,0 +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 + diff --git a/3rdParty/Boost/src/libs/program_options/src/utf8_codecvt_facet.cpp b/3rdParty/Boost/src/libs/program_options/src/utf8_codecvt_facet.cpp new file mode 100644 index 0000000..c0fd7c0 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/utf8_codecvt_facet.cpp @@ -0,0 +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 "../../detail/utf8_codecvt_facet.cpp" + + +#undef BOOST_UTF8_BEGIN_NAMESPACE +#undef BOOST_UTF8_END_NAMESPACE +#undef BOOST_UTF8_DECL + diff --git a/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp b/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp new file mode 100644 index 0000000..f5770f1 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp @@ -0,0 +1,335 @@ +// 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 <cctype> + +namespace boost { namespace program_options { + + using namespace std; + + 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(validation_error(validation_error::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(validation_error(validation_error::invalid_bool_value)); + } +#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, bad_value) + {} + +#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>"; + } + } + } + + invalid_option_value:: + invalid_option_value(const std::wstring& bad_value) + : validation_error(validation_error::invalid_option_value, convert_value(bad_value)) + {} +#endif + const std::string& + unknown_option::get_option_name() const throw() + { + return m_option_name; + } + + const std::string& + ambiguous_option::get_option_name() const throw() + { + return m_option_name; + } + + const std::vector<std::string>& + ambiguous_option::alternatives() const throw() + { + return m_alternatives; + } + + void + multiple_values::set_option_name(const std::string& option_name) + { + m_option_name = option_name; + } + + const std::string& + multiple_values::get_option_name() const throw() + { + return m_option_name; + } + + void + multiple_occurrences::set_option_name(const std::string& option_name) + { + m_option_name = option_name; + } + + const std::string& + multiple_occurrences::get_option_name() const throw() + { + return m_option_name; + } + + validation_error:: + validation_error(kind_t kind, + const std::string& option_value, + const std::string& option_name) + : error("") + , m_kind(kind) + , m_option_name(option_name) + , m_option_value(option_value) + , m_message(error_message(kind)) + { + if (!option_value.empty()) + { + m_message.append(std::string("'") + option_value + std::string("'")); + } + } + + void + validation_error::set_option_name(const std::string& option_name) + { + m_option_name = option_name; + } + + const std::string& + validation_error::get_option_name() const throw() + { + return m_option_name; + } + + std::string + validation_error::error_message(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 multiple_values_not_allowed: + msg = "multiple values not allowed"; + break; + case at_least_one_value_required: + msg = "at least one value required"; + break; + case invalid_bool_value: + msg = "invalid bool value"; + break; + case invalid_option_value: + msg = "invalid option value"; + break; + case invalid_option: + msg = "invalid option"; + break; + default: + msg = "unknown error"; + } + return msg; + } + + const char* + validation_error::what() const throw() + { + if (!m_option_name.empty()) + { + m_message = "in option '" + m_option_name + "': " + + error_message(m_kind); + } + return m_message.c_str(); + } + + const std::string& + required_option::get_option_name() const throw() + { + return m_option_name; + } + +}} diff --git a/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp b/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp new file mode 100644 index 0000000..29b1de9 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp @@ -0,0 +1,231 @@ +// 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; + + // First, convert/store all given options + for (i = 0; i < options.options.size(); ++i) { + + const string& name = options.options[i].string_key; + // Skip positional options without name + if (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(name)) + continue; + + const option_description& d = desc.find(name, false, + false, false); + + variable_value& v = m[name]; + if (v.defaulted()) { + // Explicit assignment here erases defaulted value + v = variable_value(); + } + + try { + d.semantic()->parse(v.value(), options.options[i].value, utf8); + } +#ifndef BOOST_NO_EXCEPTIONS + catch(validation_error& e) + { + e.set_option_name(name); + throw; + } + catch(multiple_occurrences& e) + { + e.set_option_name(name); + throw; + } + catch(multiple_values& e) + { + e.set_option_name(name); + throw; + } +#endif + 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(name); + } + 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()) { + xm.m_required.insert(key); + } + } + } + + 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) + {} + + 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 (set<string>::const_iterator r = m_required.begin(); + r != m_required.end(); + ++r) + { + const string& opt = *r; + map<string, variable_value>::const_iterator iter = find(opt); + if (iter == end() || iter->second.empty()) + { + boost::throw_exception(required_option(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 no 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/3rdParty/Boost/src/libs/program_options/src/winmain.cpp b/3rdParty/Boost/src/libs/program_options/src/winmain.cpp new file mode 100644 index 0000000..64cc790 --- /dev/null +++ b/3rdParty/Boost/src/libs/program_options/src/winmain.cpp @@ -0,0 +1,96 @@ +// 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> + +#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; + 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, '\\'); + 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); + 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) + 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 (unsigned i = 0, e = aux.size(); i < e; ++i) + result.push_back(from_utf8(aux[i])); + return result; + } +#endif + +}} +#endif |