From 7c83b407648f1ef919218d8965d4c21378910755 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 2 Sep 2015 17:06:10 +0200 Subject: Add --generate-parse option When specified, CLI will generate parse() functions instead of parsing constructors. This is primarily useful for being able to parse into an already initialized options class instance, for example, to implement merging/overriding. --- cli/header.cxx | 22 ++++++++++++++-------- cli/options.cli | 7 +++++++ cli/options.cxx | 11 +++++++++++ cli/options.hxx | 8 ++++++-- cli/options.ixx | 6 ++++++ cli/source.cxx | 26 ++++++++++++++++---------- 6 files changed, 60 insertions(+), 20 deletions(-) (limited to 'cli') diff --git a/cli/header.cxx b/cli/header.cxx index ddf0895..6ff1f6b 100644 --- a/cli/header.cxx +++ b/cli/header.cxx @@ -129,14 +129,23 @@ namespace // if (!abst) { - os << name << " (int& argc," << endl + os << name << " ();" + << endl; + + // Are we generating parsing constructors or parse() functions? + // + string n (options.generate_parse () + ? string ("void\n") + (name != "parse" ? "parse" : "parse_") + : name); + + os << n << " (int& argc," << endl << "char** argv," << endl << "bool erase = false," << endl << um << " option = " << um << "::fail," << endl << um << " argument = " << um << "::stop);" << endl; - os << name << " (int start," << endl + os << n << " (int start," << endl << "int& argc," << endl << "char** argv," << endl << "bool erase = false," << endl @@ -144,7 +153,7 @@ namespace << um << " argument = " << um << "::stop);" << endl; - os << name << " (int& argc," << endl + os << n << " (int& argc," << endl << "char** argv," << endl << "int& end," << endl << "bool erase = false," << endl @@ -152,7 +161,7 @@ namespace << um << " argument = " << um << "::stop);" << endl; - os << name << " (int start," << endl + os << n << " (int start," << endl << "int& argc," << endl << "char** argv," << endl << "int& end," << endl @@ -161,13 +170,10 @@ namespace << um << " argument = " << um << "::stop);" << endl; - os << name << " (" << cli << "::scanner&," << endl + os << n << " (" << cli << "::scanner&," << endl << um << " option = " << um << "::fail," << endl << um << " argument = " << um << "::stop);" << endl; - - os << name << " ();" - << endl; } // diff --git a/cli/options.cli b/cli/options.cli index 28a4ee4..7f8e2dc 100644 --- a/cli/options.cli +++ b/cli/options.cli @@ -40,6 +40,13 @@ class options on the command line." }; + bool --generate-parse + { + "Generate \cb{parse()} functions instead of parsing constructors. This + is primarily useful for being able to parse into an already initialized + options class instance, for example, to implement merging/overriding." + }; + bool --generate-description { "Generate the option description list that can be examined at runtime." diff --git a/cli/options.cxx b/cli/options.cxx index dcb408a..dd9d075 100644 --- a/cli/options.cxx +++ b/cli/options.cxx @@ -562,6 +562,7 @@ options () output_dir_ (), generate_modifier_ (), generate_specifier_ (), + generate_parse_ (), generate_description_ (), generate_file_scanner_ (), suppress_inline_ (), @@ -625,6 +626,7 @@ options (int& argc, output_dir_ (), generate_modifier_ (), generate_specifier_ (), + generate_parse_ (), generate_description_ (), generate_file_scanner_ (), suppress_inline_ (), @@ -691,6 +693,7 @@ options (int start, output_dir_ (), generate_modifier_ (), generate_specifier_ (), + generate_parse_ (), generate_description_ (), generate_file_scanner_ (), suppress_inline_ (), @@ -757,6 +760,7 @@ options (int& argc, output_dir_ (), generate_modifier_ (), generate_specifier_ (), + generate_parse_ (), generate_description_ (), generate_file_scanner_ (), suppress_inline_ (), @@ -825,6 +829,7 @@ options (int start, output_dir_ (), generate_modifier_ (), generate_specifier_ (), + generate_parse_ (), generate_description_ (), generate_file_scanner_ (), suppress_inline_ (), @@ -889,6 +894,7 @@ options (::cli::scanner& s, output_dir_ (), generate_modifier_ (), generate_specifier_ (), + generate_parse_ (), generate_description_ (), generate_file_scanner_ (), suppress_inline_ (), @@ -960,6 +966,9 @@ print_usage (::std::ostream& os) os << "--generate-specifier Generate functions for determining whether the" << ::std::endl << " option was specified on the command line." << ::std::endl; + os << "--generate-parse Generate 'parse()' functions instead of parsing" << ::std::endl + << " constructors." << ::std::endl; + os << "--generate-description Generate the option description list that can be" << ::std::endl << " examined at runtime." << ::std::endl; @@ -1128,6 +1137,8 @@ struct _cli_options_map_init &::cli::thunk< options, bool, &options::generate_modifier_ >; _cli_options_map_["--generate-specifier"] = &::cli::thunk< options, bool, &options::generate_specifier_ >; + _cli_options_map_["--generate-parse"] = + &::cli::thunk< options, bool, &options::generate_parse_ >; _cli_options_map_["--generate-description"] = &::cli::thunk< options, bool, &options::generate_description_ >; _cli_options_map_["--generate-file-scanner"] = diff --git a/cli/options.hxx b/cli/options.hxx index 22495e4..0328661 100644 --- a/cli/options.hxx +++ b/cli/options.hxx @@ -326,6 +326,8 @@ namespace cli class options { public: + options (); + options (int& argc, char** argv, bool erase = false, @@ -358,8 +360,6 @@ class options ::cli::unknown_mode option = ::cli::unknown_mode::fail, ::cli::unknown_mode argument = ::cli::unknown_mode::stop); - options (); - // Option accessors. // const bool& @@ -381,6 +381,9 @@ class options generate_specifier () const; const bool& + generate_parse () const; + + const bool& generate_description () const; const bool& @@ -548,6 +551,7 @@ class options std::string output_dir_; bool generate_modifier_; bool generate_specifier_; + bool generate_parse_; bool generate_description_; bool generate_file_scanner_; bool suppress_inline_; diff --git a/cli/options.ixx b/cli/options.ixx index a66312d..c2b9a80 100644 --- a/cli/options.ixx +++ b/cli/options.ixx @@ -240,6 +240,12 @@ generate_specifier () const } inline const bool& options:: +generate_parse () const +{ + return this->generate_parse_; +} + +inline const bool& options:: generate_description () const { return this->generate_description_; diff --git a/cli/source.cxx b/cli/source.cxx index 6a8ea76..1e0be15 100644 --- a/cli/source.cxx +++ b/cli/source.cxx @@ -535,12 +535,18 @@ namespace if (!abst) { - os << name << "::" << endl - << name << " (int& argc," << endl + bool p (options.generate_parse ()); + string n ( + p + ? "void " + name + "::\n" + (name != "parse" ? "parse" : "parse_") + : name + "::\n" + name); + + os << n << " (int& argc," << endl << "char** argv," << endl << "bool erase," << endl << um << " opt," << endl << um << " arg)"; + if (!p) { option_init init (*this); traversal::names names_init (init); @@ -551,13 +557,13 @@ namespace << "_parse (s, opt, arg);" << "}"; - os << name << "::" << endl - << name << " (int start," << endl + os << n << " (int start," << endl << "int& argc," << endl << "char** argv," << endl << "bool erase," << endl << um << " opt," << endl << um << " arg)"; + if (!p) { option_init init (*this); traversal::names names_init (init); @@ -568,13 +574,13 @@ namespace << "_parse (s, opt, arg);" << "}"; - os << name << "::" << endl - << name << " (int& argc," << endl + os << n << " (int& argc," << endl << "char** argv," << endl << "int& end," << endl << "bool erase," << endl << um << " opt," << endl << um << " arg)"; + if (!p) { option_init init (*this); traversal::names names_init (init); @@ -586,14 +592,14 @@ namespace << "end = s.end ();" << "}"; - os << name << "::" << endl - << name << " (int start," << endl + os << n << " (int start," << endl << "int& argc," << endl << "char** argv," << endl << "int& end," << endl << "bool erase," << endl << um << " opt," << endl << um << " arg)"; + if (!p) { option_init init (*this); traversal::names names_init (init); @@ -605,10 +611,10 @@ namespace << "end = s.end ();" << "}"; - os << name << "::" << endl - << name << " (" << cli << "::scanner& s," << endl + os << n << " (" << cli << "::scanner& s," << endl << um << " opt," << endl << um << " arg)"; + if (!p) { option_init init (*this); traversal::names names_init (init); -- cgit v1.1