diff options
Diffstat (limited to '3rdParty/Boost/src/libs/program_options')
9 files changed, 510 insertions, 305 deletions
diff --git a/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp b/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp index be31385..cd9a5fe 100644 --- a/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/cmdline.cpp @@ -34,64 +34,43 @@ namespace boost { namespace program_options {      using namespace std;      using namespace boost::program_options::command_line_style; -    invalid_syntax:: -    invalid_syntax(const string& tokens, kind_t kind) -     : error(error_message(kind).append(" in '").append(tokens).append("'")) -     , m_tokens(tokens) -     , m_kind(kind)                        -    {}      string  -    invalid_syntax::error_message(kind_t kind) +    invalid_syntax::get_template(kind_t kind)      {          // Initially, store the message in 'const char*' variable,          // to avoid conversion to string in all cases.          const char* msg;          switch(kind)          { +        case empty_adjacent_parameter: +            msg = "the argument for option '%canonical_option%' should follow immediately after the equal sign"; +            break; +        case missing_parameter: +            msg = "the required argument for option '%canonical_option%' is missing"; +            break; +        case unrecognized_line: +            msg = "the options configuration file contains an invalid line '%invalid_line%'"; +            break; +        // none of the following are currently used:          case long_not_allowed: -            msg = "long options are not allowed"; +            msg = "the unabbreviated option '%canonical_option%' is not valid";              break;          case long_adjacent_not_allowed: -            msg = "parameters adjacent to long options not allowed"; +            msg = "the unabbreviated option '%canonical_option%' does not take any arguments";              break;          case short_adjacent_not_allowed: -            msg = "parameters adjust to short options are not allowed"; -            break; -        case empty_adjacent_parameter: -            msg = "adjacent parameter is empty"; -            break; -        case missing_parameter: -            msg = "required parameter is missing"; +            msg = "the abbreviated option '%canonical_option%' does not take any arguments";              break;          case extra_parameter: -            msg = "extra parameter"; -            break; -        case unrecognized_line: -            msg = "unrecognized line"; +            msg = "option '%canonical_option%' does not take any arguments";              break;          default: -            msg = "unknown error"; +            msg = "unknown command line syntax error for '%s'";          }          return msg;      } -    invalid_syntax::kind_t  -    invalid_syntax::kind() const -    { -        return m_kind; -    } -     -    const string&  -    invalid_syntax::tokens() const -    { -        return m_tokens; -    } - -    invalid_command_line_syntax:: -    invalid_command_line_syntax(const string& tokens, kind_t kind) -    : invalid_syntax(tokens, kind) -    {}  }} @@ -156,15 +135,26 @@ namespace boost { namespace program_options { namespace detail {          const char* error = 0;          if (allow_some_long &&               !(style & long_allow_adjacent) && !(style & long_allow_next)) -            error = "style disallows parameters for long options"; +            error = "boost::program_options misconfiguration: " +                    "choose one or other of 'command_line_style::long_allow_next' " +                    "(whitespace separated arguments) or " +                    "'command_line_style::long_allow_adjacent' ('=' separated arguments) for " +                    "long options.";          if (!error && (style & allow_short) &&              !(style & short_allow_adjacent) && !(style & short_allow_next)) -            error = "style disallows parameters for short options"; +            error = "boost::program_options misconfiguration: " +                    "choose one or other of 'command_line_style::short_allow_next' " +                    "(whitespace separated arguments) or " +                    "'command_line_style::short_allow_adjacent' ('=' separated arguments) for " +                    "short options.";          if (!error && (style & allow_short) &&              !(style & allow_dash_for_short) && !(style & allow_slash_for_short)) -            error = "style disallows all characters for short options"; +            error = "boost::program_options misconfiguration: " +                    "choose one or other of 'command_line_style::allow_slash_for_short' " +                    "(slashes) or 'command_line_style::allow_dash_for_short' (dashes) for " +                    "short options.";          if (error)              boost::throw_exception(invalid_command_line_style(error)); @@ -192,6 +182,23 @@ namespace boost { namespace program_options { namespace detail {          m_positional = &positional;      } +    int +    cmdline::get_canonical_option_prefix() +    { +        if (m_style & allow_long) +            return allow_long; + +        if (m_style & allow_long_disguise) +            return allow_long_disguise; + +        if ((m_style & allow_short) && (m_style & allow_dash_for_short)) +            return allow_dash_for_short; + +        if ((m_style & allow_short) && (m_style & allow_slash_for_short)) +            return allow_slash_for_short; + +        return 0; +    }      vector<option>      cmdline::run() @@ -242,7 +249,7 @@ namespace boost { namespace program_options { namespace detail {              bool ok = false;              for(unsigned i = 0; i < style_parsers.size(); ++i)              { -                unsigned current_size = args.size(); +                unsigned current_size = static_cast<unsigned>(args.size());                  vector<option> next = style_parsers[i](args);                  // Check that option names @@ -277,7 +284,7 @@ namespace boost { namespace program_options { namespace detail {          }          /* If an key option is followed by a positional option, -           can can consume more tokens (e.g. it's multitoke option), +           can can consume more tokens (e.g. it's multitoken option),             give those tokens to it.  */          vector<option> result2;          for (unsigned i = 0; i < result.size(); ++i) @@ -288,11 +295,21 @@ namespace boost { namespace program_options { namespace detail {              if (opt.string_key.empty())                  continue; -            const option_description* xd =  -                m_desc->find_nothrow(opt.string_key,  -                                        is_style_active(allow_guessing), -                                        is_style_active(long_case_insensitive), -                                        is_style_active(short_case_insensitive)); +            const option_description* xd; +            try +            { +                xd = m_desc->find_nothrow(opt.string_key,  +                                            is_style_active(allow_guessing), +                                            is_style_active(long_case_insensitive), +                                            is_style_active(short_case_insensitive)); +            }  +            catch(error_with_option_name& e) +            { +                // add context and rethrow +                e.add_context(opt.string_key, opt.original_tokens[0], get_canonical_option_prefix()); +                throw; +            } +              if (!xd)                  continue; @@ -304,7 +321,7 @@ namespace boost { namespace program_options { namespace detail {                  // We only allow to grab tokens that are not already                  // recognized as key options. -                int can_take_more = max_tokens - opt.value.size(); +                int can_take_more = max_tokens - static_cast<int>(opt.value.size());                  unsigned j = i+1;                  for (; can_take_more && j < result.size(); --can_take_more, ++j)                  { @@ -383,92 +400,112 @@ namespace boost { namespace program_options { namespace detail {          if (opt.string_key.empty())              return; -        // First check that the option is valid, and get its description. -        const option_description* xd = m_desc->find_nothrow(opt.string_key,  -                is_style_active(allow_guessing), -                is_style_active(long_case_insensitive), -                is_style_active(short_case_insensitive)); +        //  +        // Be defensive: +        // will have no original token if option created by handle_additional_parser() +        std::string original_token_for_exceptions = opt.string_key; +        if (opt.original_tokens.size()) +            original_token_for_exceptions = opt.original_tokens[0]; -        if (!xd) +        try          { -            if (m_allow_unregistered) { -                opt.unregistered = true; -                return; -            } else { -                boost::throw_exception(unknown_option(opt.string_key)); -            }                 -        } -        const option_description& d = *xd; +            // First check that the option is valid, and get its description. +            const option_description* xd = m_desc->find_nothrow(opt.string_key,  +                    is_style_active(allow_guessing), +                    is_style_active(long_case_insensitive), +                    is_style_active(short_case_insensitive)); -        // Canonize the name -        opt.string_key = d.key(opt.string_key); +            if (!xd) +            { +                if (m_allow_unregistered) { +                    opt.unregistered = true; +                    return; +                } else { +                    boost::throw_exception(unknown_option()); +                }                 +            } +            const option_description& d = *xd; -        // We check that the min/max number of tokens for the option -        // agrees with the number of tokens we have. The 'adjacent_value' -        // (the value in --foo=1) counts as a separate token, and if present -        // must be consumed. The following tokens on the command line may be -        // left unconsumed. +            // Canonize the name +            opt.string_key = d.key(opt.string_key); -        // We don't check if those tokens look like option, or not! +            // We check that the min/max number of tokens for the option +            // agrees with the number of tokens we have. The 'adjacent_value' +            // (the value in --foo=1) counts as a separate token, and if present +            // must be consumed. The following tokens on the command line may be +            // left unconsumed. -        unsigned min_tokens = d.semantic()->min_tokens(); -        unsigned max_tokens = d.semantic()->max_tokens(); -         -        unsigned present_tokens = opt.value.size() + other_tokens.size(); -         -        if (present_tokens >= min_tokens) -        { -            if (!opt.value.empty() && max_tokens == 0)  -            { -                boost::throw_exception(invalid_command_line_syntax(opt.string_key, -                                             invalid_command_line_syntax::extra_parameter)); -            } -             -            // If an option wants, at minimum, N tokens, we grab them there, -            // when adding these tokens as values to current option we check -            // if they look like options -            if (opt.value.size() <= min_tokens)  -            { -                min_tokens -= opt.value.size(); -            } -            else -            { -                min_tokens = 0; -            } +            // We don't check if those tokens look like option, or not! -            // Everything's OK, move the values to the result.             -            for(;!other_tokens.empty() && min_tokens--; )  +            unsigned min_tokens = d.semantic()->min_tokens(); +            unsigned max_tokens = d.semantic()->max_tokens(); +             +            unsigned present_tokens = static_cast<unsigned>(opt.value.size() + other_tokens.size()); +             +            if (present_tokens >= min_tokens)              { -                // check if extra parameter looks like a known option -                // we use style parsers to check if it is syntactically an option,  -                // additionally we check if an option_description exists -                vector<option> followed_option;   -                vector<string> next_token(1, other_tokens[0]);       -                for (unsigned i = 0; followed_option.empty() && i < style_parsers.size(); ++i) +                if (!opt.value.empty() && max_tokens == 0)  +                { +                    boost::throw_exception( +                        invalid_command_line_syntax(invalid_command_line_syntax::extra_parameter)); +                } +                 +                // If an option wants, at minimum, N tokens, we grab them there, +                // when adding these tokens as values to current option we check +                // if they look like options +                if (opt.value.size() <= min_tokens)                   { -                    followed_option = style_parsers[i](next_token); +		    min_tokens -= static_cast<unsigned>(opt.value.size());                  } -                if (!followed_option.empty())  +                else                  { -                    const option_description* od = m_desc->find_nothrow(other_tokens[0],  -                              is_style_active(allow_guessing), -                              is_style_active(long_case_insensitive), -                              is_style_active(short_case_insensitive)); -                    if (od)  -                        boost::throw_exception(invalid_command_line_syntax(opt.string_key, -                                                    invalid_command_line_syntax::missing_parameter)); +                    min_tokens = 0; +                } + +                // Everything's OK, move the values to the result.             +                for(;!other_tokens.empty() && min_tokens--; )  +                { +                    // check if extra parameter looks like a known option +                    // we use style parsers to check if it is syntactically an option,  +                    // additionally we check if an option_description exists +                    vector<option> followed_option;   +                    vector<string> next_token(1, other_tokens[0]);       +                    for (unsigned i = 0; followed_option.empty() && i < style_parsers.size(); ++i) +                    { +                        followed_option = style_parsers[i](next_token); +                    } +                    if (!followed_option.empty())  +                    { +                        original_token_for_exceptions = other_tokens[0]; +                        const option_description* od = m_desc->find_nothrow(other_tokens[0],  +                                  is_style_active(allow_guessing), +                                  is_style_active(long_case_insensitive), +                                  is_style_active(short_case_insensitive)); +                        if (od)  +                            boost::throw_exception( +                                invalid_command_line_syntax(invalid_command_line_syntax::missing_parameter)); +                    } +                    opt.value.push_back(other_tokens[0]); +                    opt.original_tokens.push_back(other_tokens[0]); +                    other_tokens.erase(other_tokens.begin());                  } -                opt.value.push_back(other_tokens[0]); -                opt.original_tokens.push_back(other_tokens[0]); -                other_tokens.erase(other_tokens.begin());              } -        } -        else -        { -            boost::throw_exception(invalid_command_line_syntax(opt.string_key, -                                            invalid_command_line_syntax::missing_parameter));  +            else +            { +                boost::throw_exception( +                            invalid_command_line_syntax(invalid_command_line_syntax::missing_parameter));  +            } +        }  +        // use only original token for unknown_option / ambiguous_option since by definition +        //    they are unrecognised / unparsable +        catch(error_with_option_name& e) +        { +            // add context and rethrow +            e.add_context(opt.string_key, original_token_for_exceptions, get_canonical_option_prefix()); +            throw;          } +      }      vector<option>  @@ -486,8 +523,11 @@ namespace boost { namespace program_options { namespace detail {                  name = tok.substr(2, p-2);                  adjacent = tok.substr(p+1);                  if (adjacent.empty()) -                    boost::throw_exception( invalid_command_line_syntax(name, -                                                      invalid_command_line_syntax::empty_adjacent_parameter) ); +                    boost::throw_exception( invalid_command_line_syntax( +                                                      invalid_command_line_syntax::empty_adjacent_parameter,  +                                                      name, +                                                      name, +                                                      get_canonical_option_prefix()) );              }              else              { @@ -523,9 +563,20 @@ namespace boost { namespace program_options { namespace detail {              // of token is considered to be value, not further grouped              // option.              for(;;) { -                const option_description* d  -                    = m_desc->find_nothrow(name, false, false, -                            is_style_active(short_case_insensitive)); +                const option_description* d; +                try +                { +                      +                    d = m_desc->find_nothrow(name, false, false, +                                                is_style_active(short_case_insensitive)); +                }  +                catch(error_with_option_name& e) +                { +                    // add context and rethrow +                    e.add_context(name, name, get_canonical_option_prefix()); +                    throw; +                } +                  // FIXME: check for 'allow_sticky'.                  if (d && (m_style & allow_sticky) && @@ -589,15 +640,24 @@ namespace boost { namespace program_options { namespace detail {              ((tok[0] == '-' && tok[1] != '-') ||               ((m_style & allow_slash_for_short) && tok[0] == '/')))                      { -            if (m_desc->find_nothrow(tok.substr(1, tok.find('=')-1),  -                                     is_style_active(allow_guessing), -                                     is_style_active(long_case_insensitive), -                                     is_style_active(short_case_insensitive))) +            try +            { +                if (m_desc->find_nothrow(tok.substr(1, tok.find('=')-1),  +                                         is_style_active(allow_guessing), +                                         is_style_active(long_case_insensitive), +                                         is_style_active(short_case_insensitive))) +                { +                    args[0].insert(0, "-"); +                    if (args[0][1] == '/') +                        args[0][1] = '-'; +                    return parse_long_option(args); +                } +            }  +            catch(error_with_option_name& e)              { -                args[0].insert(0, "-"); -                if (args[0][1] == '/') -                    args[0][1] = '-'; -                return parse_long_option(args); +                // add context and rethrow +                e.add_context(tok, tok, get_canonical_option_prefix()); +                throw;              }          }          return vector<option>(); diff --git a/3rdParty/Boost/src/libs/program_options/src/config_file.cpp b/3rdParty/Boost/src/libs/program_options/src/config_file.cpp index a12844c..f2a57b4 100644 --- a/3rdParty/Boost/src/libs/program_options/src/config_file.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/config_file.cpp @@ -57,7 +57,9 @@ namespace boost { namespace program_options { namespace detail {                      bad_prefixes = true;              }              if (bad_prefixes) -                boost::throw_exception(error("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);          }      } @@ -117,7 +119,7 @@ namespace boost { namespace program_options { namespace detail {                      break;                  } else { -                    boost::throw_exception(invalid_syntax(s, invalid_syntax::unrecognized_line)); +                    boost::throw_exception(invalid_config_file_syntax(s, invalid_syntax::unrecognized_line));                  }              }          } diff --git a/3rdParty/Boost/src/libs/program_options/src/options_description.cpp b/3rdParty/Boost/src/libs/program_options/src/options_description.cpp index 0d8dfd4..343bd30 100644 --- a/3rdParty/Boost/src/libs/program_options/src/options_description.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/options_description.cpp @@ -137,6 +137,31 @@ namespace boost { namespace program_options {              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      { @@ -174,10 +199,13 @@ namespace boost { namespace program_options {      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); +        { +            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  @@ -289,7 +317,7 @@ namespace boost { namespace program_options {          const option_description* d = find_nothrow(name, approx,                                          long_ignore_case, short_ignore_case);          if (!d) -            boost::throw_exception(unknown_option(name)); +            boost::throw_exception(unknown_option());          return *d;      } @@ -337,8 +365,7 @@ namespace boost { namespace program_options {              }          }          if (full_matches.size() > 1)  -            boost::throw_exception( -                ambiguous_option(name, full_matches)); +            boost::throw_exception(ambiguous_option(full_matches));          // If we have a full match, and an approximate match,          // ignore approximate match instead of reporting error. @@ -346,8 +373,7 @@ namespace boost { namespace program_options {          // "--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)); +            boost::throw_exception(ambiguous_option(approximate_matches));          return found.get();      } @@ -396,7 +422,7 @@ namespace boost { namespace program_options {                  if (count(par.begin(), par.end(), '\t') > 1)                  {                      boost::throw_exception(program_options::error( -                        "Only one tab per paragraph is allowed")); +                        "Only one tab per paragraph is allowed in the options description"));                  }                  // erase tab from string @@ -443,7 +469,7 @@ namespace boost { namespace program_options {                      // 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); +                    unsigned remaining = static_cast<unsigned>(std::distance(line_begin, par_end));                      string::const_iterator line_end = line_begin +                           ((remaining < line_length) ? remaining : line_length); @@ -463,7 +489,7 @@ namespace boost { namespace program_options {                          {                                               // is last_space within the second half ot the                               // current line -                            if (static_cast<unsigned>(distance(last_space, line_end)) <  +                            if (static_cast<unsigned>(std::distance(last_space, line_end)) <                                   (line_length / 2))                              {                                  line_end = last_space; @@ -476,8 +502,8 @@ namespace boost { namespace program_options {                      if (first_line)                      { -                        indent += par_indent; -                        line_length -= par_indent; // there's less to work with now +                        indent += static_cast<unsigned>(par_indent); +                        line_length -= static_cast<unsigned>(par_indent); // there's less to work with now                          first_line = false;                      } @@ -566,7 +592,7 @@ namespace boost { namespace program_options {                        os.put(' ');                     }                  } else { -                   for(unsigned pad = first_column_width - ss.str().size(); pad > 0; --pad) +                   for(unsigned pad = first_column_width - static_cast<unsigned>(ss.str().size()); pad > 0; --pad)                     {                        os.put(' ');                     } diff --git a/3rdParty/Boost/src/libs/program_options/src/parsers.cpp b/3rdParty/Boost/src/libs/program_options/src/parsers.cpp index bc3b858..2361a48 100644 --- a/3rdParty/Boost/src/libs/program_options/src/parsers.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/parsers.cpp @@ -45,7 +45,10 @@  // 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> +// 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__) @@ -85,7 +88,8 @@ namespace boost { namespace program_options {      basic_parsed_options<wchar_t>      ::basic_parsed_options(const parsed_options& po)      : description(po.description), -      utf8_encoded_options(po) +      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])); @@ -107,7 +111,7 @@ namespace boost { namespace program_options {              if (d.long_name().empty())                  boost::throw_exception( -                    error("long name required for config file")); +                    error("abbreviated option names are not permitted in options configuration files"));              allowed_options.insert(d.long_name());          } diff --git a/3rdParty/Boost/src/libs/program_options/src/positional_options.cpp b/3rdParty/Boost/src/libs/program_options/src/positional_options.cpp index 55995d7..72dc0d6 100644 --- a/3rdParty/Boost/src/libs/program_options/src/positional_options.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/positional_options.cpp @@ -34,7 +34,7 @@ namespace boost { namespace program_options {      positional_options_description::max_total_count() const      {          return m_trailing.empty() ?  -          m_names.size() : (std::numeric_limits<unsigned>::max)(); +          static_cast<unsigned>(m_names.size()) : (std::numeric_limits<unsigned>::max)();      }      const std::string&  diff --git a/3rdParty/Boost/src/libs/program_options/src/program_options_utf8_codecvt_facet.cpp b/3rdParty/Boost/src/libs/program_options/src/program_options_utf8_codecvt_facet.cpp index c0fd7c0..2e4c532 100644 --- a/3rdParty/Boost/src/libs/program_options/src/program_options_utf8_codecvt_facet.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/program_options_utf8_codecvt_facet.cpp @@ -12,7 +12,7 @@  #define BOOST_UTF8_END_NAMESPACE }}}  #define BOOST_UTF8_DECL BOOST_PROGRAM_OPTIONS_DECL -#include "../../detail/utf8_codecvt_facet.cpp" +#include <boost/detail/utf8_codecvt_facet.ipp>  #undef BOOST_UTF8_BEGIN_NAMESPACE diff --git a/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp b/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp index f5770f1..5314029 100644 --- a/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/value_semantic.cpp @@ -7,6 +7,8 @@  #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> @@ -14,6 +16,22 @@ 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,  @@ -139,7 +157,7 @@ namespace boost { namespace program_options {          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)); +            boost::throw_exception(invalid_bool_value(s));      }      // This is blatant copy-paste. However, templating this will cause a problem, @@ -161,7 +179,7 @@ namespace boost { namespace program_options {          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)); +            boost::throw_exception(invalid_bool_value(convert_value(s)));      }  #endif      BOOST_PROGRAM_OPTIONS_DECL  @@ -194,120 +212,212 @@ namespace boost { namespace program_options {      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 +    : validation_error(validation_error::invalid_option_value)      { -        std::string convert_value(const std::wstring& s) -        { -            try { -                return to_local_8_bit(s); -            } -            catch(const std::exception&) { -                return "<unrepresentable unicode string>"; -            } -        } +        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, convert_value(bad_value)) -    {} -#endif -    const std::string&  -    unknown_option::get_option_name() const throw() -    {  -        return m_option_name;  +    : validation_error(validation_error::invalid_option_value) +    { +        set_substitute("value", convert_value(bad_value));      } +#endif -    const std::string&  -    ambiguous_option::get_option_name() const throw() -    {  -        return m_option_name;  -    } -  -    const std::vector<std::string>&  -    ambiguous_option::alternatives() const throw() + + +    invalid_bool_value:: +    invalid_bool_value(const std::string& bad_value) +    : validation_error(validation_error::invalid_bool_value)      { -        return m_alternatives; +        set_substitute("value", bad_value);      } -    void  -    multiple_values::set_option_name(const std::string& option_name) + + + + + +    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_)      { -        m_option_name = option_name; +        //                     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 std::string&  -    multiple_values::get_option_name() const throw() + +    const char* error_with_option_name::what() const throw()      { -        return m_option_name; +        // will substitute tokens each time what is run() +        substitute_placeholders(m_error_template); + +        return m_message.c_str();      } -     -    void  -    multiple_occurrences::set_option_name(const std::string& option_name) + +    void error_with_option_name::replace_token(const string& from, const string& to) const      { -        m_option_name = option_name; +        while (1) +        { +            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); +        }      } -    const std::string&  -    multiple_occurrences::get_option_name() const throw() +    string error_with_option_name::get_canonical_option_prefix() const      { -        return m_option_name; +        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]");      } -         -    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)) + + +    string error_with_option_name::get_canonical_option_name() const      { -       if (!option_value.empty()) -       { -          m_message.append(std::string("'") + option_value + std::string("'")); -       } +        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  -    validation_error::set_option_name(const std::string& option_name) + +    void error_with_option_name::substitute_placeholders(const string& error_template) const      { -        m_option_name = option_name; +        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  +        //  +        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 '%' +        //  +        for (map<string, string>::iterator iter = substitutions.begin(); +              iter != substitutions.end(); ++iter) +            replace_token('%' + iter->first + '%', iter->second);      } -    const std::string&  -    validation_error::get_option_name() const throw() + +    void ambiguous_option::substitute_placeholders(const string& original_error_template) const      { -        return m_option_name; +        // 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);      } -    std::string  -    validation_error::error_message(kind_t kind) + + + + + +    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 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"; +            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 = "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 = "invalid option"; +            msg = "option '%canonical_option%' is not valid";              break;          default:              msg = "unknown error"; @@ -315,21 +425,4 @@ namespace boost { namespace program_options {          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 index 29b1de9..caf354e 100644 --- a/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/variables_map.cpp @@ -38,65 +38,68 @@ namespace boost { namespace program_options {          // Declared once, to please Intel in VC++ mode;          unsigned i; -        // First, convert/store all given options -        for (i = 0; i < options.options.size(); ++i) { +        // Declared here so can be used to provide context for exceptions +        string option_name; +        string original_token; -            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); +        try +        { -            variable_value& v = m[name];             -            if (v.defaulted()) { -                // Explicit assignment here erases defaulted value -                v = variable_value(); -            } -             -            try { +            // First, convert/store all given options +            for (i = 0; i < options.options.size(); ++i) { + +                option_name = options.options[i].string_key; +                original_token = options.options[i].original_tokens.size() ?  +                                options.options[i].original_tokens[0] : +                                option_name; +                // 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; + +                string 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(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); +        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()); @@ -127,7 +130,14 @@ namespace boost { namespace program_options {              // add empty value if this is an required option              if (d.semantic()->is_required()) { -               xm.m_required.insert(key); + +                // 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;              }          }      } @@ -182,6 +192,13 @@ namespace boost { namespace program_options {      : 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      { @@ -197,15 +214,16 @@ namespace boost { namespace program_options {      variables_map::notify()      {          // This checks if all required options occur -        for (set<string>::const_iterator r = m_required.begin(); +        for (map<string, string>::const_iterator r = m_required.begin();               r != m_required.end();               ++r)          { -            const string& opt = *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(opt)); +                boost::throw_exception(required_option(display_opt));              }          } diff --git a/3rdParty/Boost/src/libs/program_options/src/winmain.cpp b/3rdParty/Boost/src/libs/program_options/src/winmain.cpp index 8a7c43f..6220043 100644 --- a/3rdParty/Boost/src/libs/program_options/src/winmain.cpp +++ b/3rdParty/Boost/src/libs/program_options/src/winmain.cpp @@ -7,6 +7,8 @@  #include <boost/program_options/parsers.hpp>  #include <cctype> +using std::size_t; +  #ifdef _WIN32  namespace boost { namespace program_options { @@ -89,7 +91,7 @@ namespace boost { namespace program_options {      {          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) +        for (size_t i = 0, e = aux.size(); i < e; ++i)              result.push_back(from_utf8(aux[i]));          return result;              }  | 
 Swift