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:
Vladimir Prus
2005-05-06 06:40:39 +00:00
parent dc9097c3d0
commit 9a149beb76
3 changed files with 67 additions and 18 deletions

View File

@@ -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();