boost::program_options exception reasons.

Good day, guys. I am new to boost and have some qestion concerns boost::program_options library. I've wrote a simple program (see code below), and when I trying to pass multiple '--help' option to the program, it throws exception with reason "multiple_occurrences". This exception reason may confuse the end-user, I wanna get some more pretty error description. So, I have only 2 solutions: 1) Prase exception reason and give a user more informative/pretty description. 2) Refactor boost::program_options to enable it to throw exceptions with informative reason. I need a hint from professional. BTW, how can I contribute to boost::program_options? Where can I read some docs? Thank you very much in advance and sorry for inconvenience. // Code: #include <string> #include <vector> #include <iostream> #include <exception> #include <boost/program_options.hpp> using namespace std; namespace po = boost::program_options; template<class T> ostream & operator << (ostream & os, const vector<T> & v) { copy(v.begin(), v.end(), ostream_iterator<T>(cout, " ")); return os; } int main(int argc, char *argv[]) { try { po::options_description desc("Options:"); desc.add_options() ("help", "produce help message") ("phone", po::value<vector<string> >()->multitoken(), "mobile phone number to send SMS to") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); if (vm.count("phone") > 0) { cout << "Phones: " << vm["phone"].as< vector<string> >() << endl; } } catch(exception & e) { cerr << "Unable to parse command line: " << e.what() << endl; return 1; } return 0; }

Hi Vladislav,
Good day, guys. I am new to boost and have some qestion concerns boost::program_options library. I've wrote a simple program (see code below), and when I trying to pass multiple '--help' option to the program, it throws exception with reason "multiple_occurrences". This exception reason may confuse the end-user, I wanna get some more pretty error description.
So, I have only 2 solutions:
1) Prase exception reason and give a user more informative/pretty description. 2) Refactor boost::program_options to enable it to throw exceptions with informative reason.
The second approach is clearly better. Even adding passing the name of the duplicate option to the message would help. Are you willing to code this change?
I need a hint from professional. BTW, how can I contribute to boost::program_options?
Just by sending patches to this list ;-) Or more speicifcally, the output of "cvs diff -u boost/program_options libs/program_options". Thanks, Volodya

Okey-dockey, I will make this change as soon as possible and post a patch here. Vladimir Prus wrote:
Hi Vladislav,
Good day, guys. I am new to boost and have some qestion concerns boost::program_options library. I've wrote a simple program (see code below), and when I trying to pass multiple '--help' option to the program, it throws exception with reason "multiple_occurrences". This exception reason may confuse the end-user, I wanna get some more pretty error description.
So, I have only 2 solutions:
1) Prase exception reason and give a user more informative/pretty description. 2) Refactor boost::program_options to enable it to throw exceptions with informative reason.
The second approach is clearly better. Even adding passing the name of the duplicate option to the message would help. Are you willing to code this change?
I need a hint from professional. BTW, how can I contribute to boost::program_options?
Just by sending patches to this list ;-) Or more speicifcally, the output of "cvs diff -u boost/program_options libs/program_options".
Thanks, Volodya
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Hi there again, I've add the feature we talk about. Unfortunately I have no CVS code with boost sources and can't make "cvs diff -u boost/program_options libs/program_options". So... I've copy file to file.org, change code and make "diff -dru file.org file" etc (see diff files in attachment). As a result I got: # D:\SnaiL\Projects\SMSMan\bin>smsman --help --help # Unable to parse command line: Multiple option 'help' is not allowed. As you can see, exception reason now is: "Multiple option 'help' is not allowed" -- Volodya, I am not sure that I need to change tests, moreone I don't know how to test.... So, let's discuss it. Please make peer-review and let me know about the result. P.S.: Hm... Now I became a contributor? :-)) very interesting. Vladislav Lazarenko wrote:
Okey-dockey, I will make this change as soon as possible and post a patch here.
Vladimir Prus wrote:
Hi Vladislav,
Good day, guys. I am new to boost and have some qestion concerns boost::program_options library. I've wrote a simple program (see code below), and when I trying to pass multiple '--help' option to the program, it throws exception with reason "multiple_occurrences". This exception reason may confuse the end-user, I wanna get some more pretty error description.
So, I have only 2 solutions:
1) Prase exception reason and give a user more informative/pretty description. 2) Refactor boost::program_options to enable it to throw exceptions with informative reason.
The second approach is clearly better. Even adding passing the name of the duplicate option to the message would help. Are you willing to code this change?
I need a hint from professional. BTW, how can I contribute to boost::program_options?
Just by sending patches to this list ;-) Or more speicifcally, the output of "cvs diff -u boost/program_options libs/program_options".
Thanks, Volodya
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
--- variables_map.cpp.org 2004-09-16 11:10:28.000000000 +0300 +++ variables_map.cpp 2005-04-20 18:54:04.999875000 +0300 @@ -72,7 +72,7 @@ v = variable_value(); } try { - d.semantic()->parse(v.value(), options.options[i].value, utf8); + d.semantic()->parse(v.value(), options.options[i].value, utf8, name); } catch(validation_error& e) { --- value_semantic.hpp.org 2004-09-20 10:14:18.000000000 +0300 +++ value_semantic.hpp 2005-04-20 19:39:17.281250000 +0300 @@ -144,7 +144,8 @@ void typed_value<T, charT>:: xparse(boost::any& value_store, - const std::vector<std::basic_string<charT> >& new_tokens) const + const std::vector<std::basic_string<charT> >& new_tokens, + const std::string & opt_name) const { validate(value_store, new_tokens, (T*)0, 0); } --- value_semantic.cpp.org 2004-09-21 10:20:02.000000000 +0300 +++ value_semantic.cpp 2005-04-20 20:01:51.640625000 +0300 @@ -16,7 +16,7 @@ value_semantic_codecvt_helper<char>:: parse(boost::any& value_store, const std::vector<std::string>& new_tokens, - bool utf8) const + bool utf8, const std::string & opt_name) const { if (utf8) { #ifndef BOOST_NO_STD_WSTRING @@ -26,13 +26,13 @@ std::wstring w = from_utf8(new_tokens[i]); local_tokens.push_back(to_local_8_bit(w)); } - xparse(value_store, local_tokens); + xparse(value_store, local_tokens, opt_name); #else throw std::runtime_error("UTF-8 conversion not supported."); #endif } else { // Already in local encoding, pass unmodified - xparse(value_store, new_tokens); + xparse(value_store, new_tokens, opt_name); } } @@ -41,7 +41,7 @@ value_semantic_codecvt_helper<wchar_t>:: parse(boost::any& value_store, const std::vector<std::string>& new_tokens, - bool utf8) const + bool utf8, const std::string & opt_name) const { std::vector<wstring> tokens; if (utf8) { @@ -57,7 +57,7 @@ } } - xparse(value_store, tokens); + xparse(value_store, tokens, opt_name); } #endif @@ -71,12 +71,22 @@ void untyped_value::xparse(boost::any& value_store, - const std::vector<std::string>& new_tokens) const + const std::vector<std::string>& new_tokens, + const std::string & opt_name) const { - if (!value_store.empty()) - throw multiple_occurrences("multiple_occurrences"); + if (!value_store.empty()) + { + std::string reason = "Multiple option '"; + reason.append(opt_name).append("' is not allowed"); + throw multiple_occurrences(reason); + } + if (new_tokens.size() > 1) - throw multiple_values("multiple_values"); + { + std::string reason = "Multiple values for option '"; + reason.append(opt_name).append("' is not allowed"); + throw multiple_values(reason); + } value_store = new_tokens.empty() ? std::string("") : new_tokens.front(); } --- value_semantic.hpp.org 2004-09-15 13:57:32.000000000 +0300 +++ value_semantic.hpp 2005-04-20 19:10:11.890625000 +0300 @@ -56,8 +56,7 @@ */ virtual void parse(boost::any& value_store, const std::vector<std::string>& new_tokens, - bool utf8) const - = 0; + bool utf8, const std::string & opt_name) const = 0; /** Called to assign default value to 'value_store'. Returns true if default value is assigned, and false if no default @@ -85,11 +84,11 @@ private: // base overrides void parse(boost::any& value_store, const std::vector<std::string>& new_tokens, - bool utf8) const; + bool utf8, const std::string & opt_name) const; protected: // interface for derived classes. virtual void xparse(boost::any& value_store, - const std::vector<std::string>& new_tokens) - const = 0; + const std::vector<std::string>& new_tokens, + const std::string & opt_name) const = 0; }; template<> @@ -98,12 +97,12 @@ private: // base overrides void parse(boost::any& value_store, const std::vector<std::string>& new_tokens, - bool utf8) const; + bool utf8, const std::string & opt_name) const; protected: // interface for derived classes. #if !defined(BOOST_NO_STD_WSTRING) virtual void xparse(boost::any& value_store, - const std::vector<std::wstring>& new_tokens) - const = 0; + const std::vector<std::wstring>& new_tokens, + const std::string & opt_name) const = 0; #endif }; /** Class which specifies a simple handling of a value: the value will @@ -128,7 +127,8 @@ any modifications. */ void xparse(boost::any& value_store, - const std::vector<std::string>& new_tokens) const; + const std::vector<std::string>& new_tokens, + const std::string & opt_name) const; /** Does nothing. */ bool apply_default(boost::any&) const { return false; } @@ -225,8 +225,8 @@ /** Creates an instance of the 'validator' class and calls its operator() to perform athe ctual conversion. */ void xparse(boost::any& value_store, - const std::vector< std::basic_string<charT> >& new_tokens) - const; + const std::vector< std::basic_string<charT> >& new_tokens, + const std::string & opt_name) const; /** If default value was specified via previous call to 'default_value', stores that value into 'value_store'.
participants (2)
-
Vladimir Prus
-
Vladislav Lazarenko