diff --git a/doc/howto.xml b/doc/howto.xml index 1173c4d..b573d46 100644 --- a/doc/howto.xml +++ b/doc/howto.xml @@ -21,7 +21,7 @@ options groups/hidden options -->
Non-conventional Syntax - + Sometimes, standard command line syntaxes are not enough. For example, the gcc compiler has "-frtti" and -fno-rtti" options, and this syntax is not directly supported. @@ -57,14 +57,14 @@ store(command_line_parser(ac, av).options(desc).extra_parser(reg_foo) .run(), vm); The complete example can be found in the "example/custom_syntax.cpp" - file. + file.
Response Files - response files + response files Some operating system have very low limits of the command line length. The common way to work around those limitations is using @@ -79,7 +79,7 @@ store(command_line_parser(ac, av).options(desc).extra_parser(reg_foo) First, you need to define an option for the response file: -("response-file", value<string>(), +("response-file", value<string>(), "can be specified with '@name', too") @@ -120,14 +120,14 @@ if (vm.count("response-file")) { vector args; copy(tok.begin(), tok.end(), back_inserter(args)); // Parse the file and store the options - store(command_line_parser(args).options(desc).run(), vm); + store(command_line_parser(args).options(desc).run(), vm); } ]]> The complete example can be found in the "example/response_file.cpp" - file. + file. - +
@@ -146,7 +146,7 @@ if (vm.count("response-file")) { vector<string> args = split_winmain(lpCmdLine); store(command_line_parser(args).options(desc).run(), vm); - + The split_winmain function is overloaded for wchar_t strings, so can also be used in Unicode applications. @@ -223,7 +223,7 @@ visible.add(general).add(gui); variables_map vm; store(parse_command_line(ac, av, all), vm); -if (vm.count("help")) +if (vm.count("help")) { cout << visible; return 0; @@ -235,7 +235,7 @@ if (vm.count("help-module")) { } else if (s == "backend") { cout << backend; } else { - cout << "Unknown module '" + cout << "Unknown module '" << s << "' in the --help-module option\n"; return 1; } @@ -243,8 +243,8 @@ if (vm.count("help-module")) { } if (vm.count("num-threads")) { cout << "The 'num-threads' options was set to " - << vm["num-threads"].as() << "\n"; -} + << vm["num-threads"].as() << "\n"; +} ]]> When parsing the command line, all options are allowed. The "--help" message, however, does not include the "Backend options" group -- the @@ -253,7 +253,7 @@ if (vm.count("num-threads")) { option. The complete example can be found in the "example/option_groups.cpp" file. - +
@@ -276,7 +276,7 @@ public: }; ]]> and then overload the validate function: & values, magic_number* target_type, int) { @@ -290,16 +290,16 @@ void validate(boost::any& v, // one string, it's an error, and exception will be thrown. const string& s = validators::get_single_string(values); - // Do regex match and convert the interesting part to + // Do regex match and convert the interesting part to // int. smatch match; if (regex_match(s, match, r)) { v = any(magic_number(lexical_cast(match[1]))); } else { throw validation_error(validation_error::invalid_option_value); - } + } } -]]> +]]> The function takes four parameters. The first is the storage for the value, and in this case is either empty or contains an instance of the magic_number class. The second is the list of strings @@ -372,7 +372,7 @@ void validate(boost::any& v, locale::global(locale("")); which would set up the conversion facet according to the user's selected - locale. + locale. It's wise to check the status of the C++ locale support on your @@ -402,37 +402,37 @@ $ export LC_CTYPE=ru_RU.KOI8-R
Allowing Unknown Options - Usually, the library throws an exception on unknown option names. This - behaviour can be changed. For example, only some part of your application uses + Usually, the library throws an exception on unknown option names. This + behaviour can be changed. For example, only some part of your application uses Program_options, and you wish to pass unrecognized options to another part of the program, or even to another application. - To allow unregistered options on the command line, you need to use + To allow unregistered options on the command line, you need to use the &basic_command_line_parser; class for parsing (not &parse_command_line;) - and call the allow_unregistered + and call the allow_unregistered method of that class: -parsed_options parsed = - command_line_parser(argc, argv).options(desc).allow_unregistered().run(); +parsed_options parsed = + command_line_parser(argc, argv).options(desc).allow_unregistered().run(); - - For each token that looks like an option, but does not have a known name, - an instance of &basic_option; will be added to the result. - The string_key and value fields of the instance will contain results + + For each token that looks like an option, but does not have a known name, + an instance of &basic_option; will be added to the result. + The string_key and value fields of the instance will contain results of syntactic parsing of the token, the unregistered field will be set to true, and the original_tokens field will contain the token as it appeared on the command line. - If you want to pass the unrecognized options further, the + If you want to pass the unrecognized options further, the collect_unrecognized function can be used. The function will collect original tokens for all unrecognized values, and optionally, all found positional options. Say, if your code handles a few options, but does not handles positional options at all, you can use the function like this: vector<string> to_pass_further = collect_unrecognized(parsed.options, include_positional); - - - + + +
diff --git a/example/options_description.cpp b/example/options_description.cpp index d7ef4ce..e9ad2a6 100644 --- a/example/options_description.cpp +++ b/example/options_description.cpp @@ -18,7 +18,7 @@ using namespace std; template ostream& operator<<(ostream& os, const vector& v) { - copy(v.begin(), v.end(), ostream_iterator(os, " ")); + copy(v.begin(), v.end(), ostream_iterator(os, " ")); return os; } @@ -30,26 +30,26 @@ int main(int ac, char* av[]) po::options_description desc("Allowed options"); desc.add_options() ("help", "produce help message") - ("optimization", po::value(&opt)->default_value(10), + ("optimization", po::value(&opt)->default_value(10), "optimization level") ("verbose,v", po::value()->implicit_value(1), "enable verbosity (optionally specify level)") ("listen,l", po::value(&portnum)->implicit_value(1001) ->default_value(0,"no"), "listen on a port.") - ("include-path,I", po::value< vector >(), + ("include-path,I", po::value< vector >(), "include path") ("input-file", po::value< vector >(), "input file") ; po::positional_options_description p; p.add("input-file", -1); - + po::variables_map vm; po::store(po::command_line_parser(ac, av). options(desc).positional(p).run(), vm); po::notify(vm); - + if (vm.count("help")) { cout << "Usage: options_description [options]\n"; cout << desc; @@ -58,13 +58,13 @@ int main(int ac, char* av[]) if (vm.count("include-path")) { - cout << "Include paths are: " + cout << "Include paths are: " << vm["include-path"].as< vector >() << "\n"; } if (vm.count("input-file")) { - cout << "Input files are: " + cout << "Input files are: " << vm["input-file"].as< vector >() << "\n"; } @@ -73,14 +73,14 @@ int main(int ac, char* av[]) << "\n"; } - cout << "Optimization level is " << opt << "\n"; + cout << "Optimization level is " << opt << "\n"; - cout << "Listen port is " << portnum << "\n"; + cout << "Listen port is " << portnum << "\n"; } catch(std::exception& e) { cout << e.what() << "\n"; return 1; - } + } return 0; } diff --git a/src/variables_map.cpp b/src/variables_map.cpp index caf354e..9a6c506 100644 --- a/src/variables_map.cpp +++ b/src/variables_map.cpp @@ -17,12 +17,12 @@ namespace boost { namespace program_options { using namespace std; - // First, performs semantic actions for 'oa'. - // Then, stores in 'm' all options that are defined in 'desc'. - BOOST_PROGRAM_OPTIONS_DECL + // First, performs semantic actions for 'oa'. + // Then, stores in 'm' all options that are defined in 'desc'. + BOOST_PROGRAM_OPTIONS_DECL 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'. @@ -49,7 +49,7 @@ namespace boost { namespace program_options { for (i = 0; i < options.options.size(); ++i) { option_name = options.options[i].string_key; - original_token = options.options[i].original_tokens.size() ? + original_token = options.options[i].original_tokens.size() ? options.options[i].original_tokens[0] : option_name; // Skip positional options without name @@ -59,7 +59,7 @@ namespace boost { namespace program_options { // 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), + // to variables map (lacking any information about paring), // so just ignore them. if (options.options[i].unregistered) continue; @@ -68,21 +68,21 @@ namespace boost { namespace program_options { if (xm.m_final.count(option_name)) continue; - string original_token = options.options[i].original_tokens.size() ? + string original_token = options.options[i].original_tokens.size() ? options.options[i].original_tokens[0] : ""; - const option_description& d = desc.find(option_name, false, + const option_description& d = desc.find(option_name, false, false, false); - variable_value& v = m[option_name]; + 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, @@ -91,7 +91,7 @@ namespace boost { namespace program_options { if (!d.semantic()->is_composing()) new_final.insert(option_name); } - } + } #ifndef BOOST_NO_EXCEPTIONS catch(error_with_option_name& e) { @@ -102,8 +102,8 @@ namespace boost { namespace program_options { #endif xm.m_final.insert(new_final.begin(), new_final.end()); - - + + // Second, apply default values and store required options. const vector >& all = desc.options(); for(i = 0; i < all.size(); ++i) @@ -112,21 +112,21 @@ namespace boost { namespace program_options { string key = d.key(""); // FIXME: this logic relies on knowledge of option_description // internals. - // The 'key' is empty if options description contains '*'. - // In that + // The 'key' is empty if options description contains '*'. + // In that // case, default value makes no sense at all. if (key.empty()) { continue; } if (m.count(key) == 0) { - + boost::any def; if (d.semantic()->apply_default(def)) { m[key] = variable_value(def, true); m[key].m_value_semantic = d.semantic(); } - } + } // add empty value if this is an required option if (d.semantic()->is_required()) { @@ -142,16 +142,16 @@ namespace boost { namespace program_options { } } - BOOST_PROGRAM_OPTIONS_DECL + BOOST_PROGRAM_OPTIONS_DECL void store(const wparsed_options& options, variables_map& m) { store(options.utf8_encoded_options, m, true); } - BOOST_PROGRAM_OPTIONS_DECL + BOOST_PROGRAM_OPTIONS_DECL void notify(variables_map& vm) - { - vm.notify(); + { + vm.notify(); } abstract_variables_map::abstract_variables_map() @@ -163,7 +163,7 @@ namespace boost { namespace program_options { : m_next(next) {} - const variable_value& + const variable_value& abstract_variables_map::operator[](const std::string& name) const { const variable_value& v = get(name); @@ -179,7 +179,7 @@ namespace boost { namespace program_options { } } - void + void abstract_variables_map::next(abstract_variables_map* next) { m_next = next; @@ -209,7 +209,7 @@ namespace boost { namespace program_options { else return i->second; } - + void variables_map::notify() { @@ -221,29 +221,29 @@ namespace boost { namespace program_options { const string& opt = r->first; const string& display_opt = r->second; map::const_iterator iter = find(opt); - if (iter == end() || iter->second.empty()) + if (iter == end() || iter->second.empty()) { boost::throw_exception(required_option(display_opt)); - + } } // Lastly, run notify actions. - for (map::iterator k = begin(); - k != end(); - ++k) + for (map::iterator k = begin(); + k != end(); + ++k) { /* Users might wish to use variables_map to store their own values that are not parsed, and therefore will not have value_semantics - defined. Do no crash on such values. In multi-module programs, + defined. Do not crash on such values. In multi-module programs, one module might add custom values, and the 'notify' function - will be called after that, so we check that value_sematics is + will be called after that, so we check that value_sematics is not NULL. See: https://svn.boost.org/trac/boost/ticket/2782 */ if (k->second.m_value_semantic) k->second.m_value_semantic->notify(k->second.value()); - } + } } - + }}