Index: boost/program_options/cmdline.hpp =================================================================== --- boost/program_options/cmdline.hpp (revision 57720) +++ boost/program_options/cmdline.hpp (working copy) @@ -26,7 +26,7 @@ enum style_t { /// Allow "--long_name" style allow_long = 1, - /// Alow "- +#include +#include +#include +using namespace boost::program_options; + +#include +#include +#include +#include +using namespace std; + +#include "minitest.hpp" + + + +void test_unknown_option() +{ + options_description desc; + desc.add_options() + ("cfgfile,c", value(), "the configfile") + ; + + const char* cmdline[] = {"program", "-c", "file", "-f", "anotherfile"}; + + variables_map vm; + try { + store(parse_command_line(sizeof(cmdline)/sizeof(const char*), + const_cast(cmdline), desc), vm); + } + catch (unknown_option& e) + { + BOOST_CHECK_EQUAL(e.get_option_name(), "-f"); + BOOST_CHECK_EQUAL(string(e.what()), "unknown option -f"); + } +} + + + +void test_multiple_values() +{ + options_description desc; + desc.add_options() + ("cfgfile,c", value()->multitoken(), "the config file") + ("output,o", value(), "the output file") + ; + + const char* cmdline[] = { "program", "-o", "fritz", "hugo", "--cfgfile", "file", "c", "-o", "text.out" }; + + variables_map vm; + try { + store(parse_command_line(sizeof(cmdline)/sizeof(const char*), + const_cast(cmdline), desc), vm); + notify(vm); + } + catch (validation_error& e) + { + // TODO: this is currently validation_error, shouldn't it be multiple_values ??? + // + // multiple_values is thrown only at one place untyped_value::xparse(), + // but I think this can never be reached + // because: untyped_value always has one value and this is filtered before reach specific + // validation and parsing + // + BOOST_CHECK_EQUAL(e.get_option_name(), "cfgfile"); + BOOST_CHECK_EQUAL(string(e.what()), "in option 'cfgfile': multiple values not allowed"); + } +} + + +void test_multiple_occurrences() +{ + options_description desc; + desc.add_options() + ("cfgfile,c", value(), "the configfile") + ; + + const char* cmdline[] = {"program", "--cfgfile", "file", "-c", "anotherfile"}; + + variables_map vm; + try { + store(parse_command_line(sizeof(cmdline)/sizeof(const char*), + const_cast(cmdline), desc), vm); + notify(vm); + } + catch (multiple_occurrences& e) + { + BOOST_CHECK_EQUAL(e.get_option_name(), "cfgfile"); + BOOST_CHECK_EQUAL(string(e.what()), "multiple_occurrences"); + } +} + + + + +int main(int /*ac*/, char** /*av*/) +{ + test_unknown_option(); + test_multiple_values(); + test_multiple_occurrences(); + + bool helpflag = false; + + options_description desc; + desc.add_options() + ("cfgfile,c", value(), "the configfile") + ("help,h", value(&helpflag)->implicit_value(true), "help") + ; + + const char* cmdline[] = {"program", "--cfgfile", "hugo", "-h", "yes" }; + + variables_map vm; + store(parse_command_line(sizeof(cmdline)/sizeof(const char*), + const_cast(cmdline), desc), vm); + notify(vm); + + cout << " help: " << (helpflag ? "true" : "false") << endl; + + + return 0; +} Index: libs/program_options/src/value_semantic.cpp =================================================================== --- libs/program_options/src/value_semantic.cpp (revision 57720) +++ libs/program_options/src/value_semantic.cpp (working copy) @@ -223,7 +223,20 @@ #endif + void multiple_values::set_option_name(const std::string& option_name) + { + m_option_name = option_name; + } + + + void multiple_occurrences::set_option_name(const std::string& option_name) + { + m_option_name = option_name; + } + + + void validation_error::set_option_name(const std::string& option_name) { m_option_name = option_name; Index: libs/program_options/src/variables_map.cpp =================================================================== --- libs/program_options/src/variables_map.cpp (revision 57720) +++ libs/program_options/src/variables_map.cpp (working copy) @@ -80,6 +80,16 @@ 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();