mirror of
https://github.com/boostorg/program_options.git
synced 2026-01-26 18:52:25 +00:00
Fix 'unknown option' error for two successive calls to 'store'.
The bug triggered if - we store two parsed_option object into variables_map - the options descriptions associated with those parsed_option objects are different - an option present in first parser_option object is not declared in second options_description. The problem was that on the second 'store' call we went over all stored options, trying to get their description from the *second* options description object. Thanks to Hartmut Kaiser for the bug report. [SVN r28685]
This commit is contained in:
@@ -23,6 +23,9 @@ namespace boost { namespace program_options {
|
||||
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;
|
||||
|
||||
@@ -30,23 +33,7 @@ namespace boost { namespace program_options {
|
||||
// variables_map. Ehmm.. messy.
|
||||
std::map<std::string, variable_value>& m = xm;
|
||||
|
||||
// The set of existing values that should not be changed.
|
||||
std::set<std::string> final;
|
||||
for (map<string, variable_value>::iterator k = m.begin();
|
||||
k != m.end();
|
||||
++k)
|
||||
{
|
||||
if (!k->second.defaulted()) {
|
||||
// TODO: what if we have different definition
|
||||
// for the same option name during different calls
|
||||
// 'store'.
|
||||
// FIXME: consider the 'false'.
|
||||
bool composing = desc.find(k->first, false).semantic()->is_composing();
|
||||
|
||||
if (!composing)
|
||||
final.insert(k->first);
|
||||
}
|
||||
}
|
||||
std::set<std::string> new_final;
|
||||
|
||||
// First, convert/store all given options
|
||||
for (size_t i = 0; i < options.options.size(); ++i) {
|
||||
@@ -57,7 +44,7 @@ namespace boost { namespace program_options {
|
||||
continue;
|
||||
|
||||
// If option has final value, skip this assignment
|
||||
if (final.count(name))
|
||||
if (xm.m_final.count(name))
|
||||
continue;
|
||||
|
||||
// Ignore options which are not described
|
||||
@@ -72,6 +59,7 @@ namespace boost { namespace program_options {
|
||||
// Explicit assignment here erases defaulted value
|
||||
v = variable_value();
|
||||
}
|
||||
|
||||
try {
|
||||
d.semantic()->parse(v.value(), options.options[i].value, utf8);
|
||||
}
|
||||
@@ -81,7 +69,18 @@ namespace boost { namespace program_options {
|
||||
throw;
|
||||
}
|
||||
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.
|
||||
const vector<shared_ptr<option_description> >& all = desc.options();
|
||||
|
||||
Reference in New Issue
Block a user