From dca38b27afc25d329fd7a7241095b40e2a1ecae2 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sat, 27 Jul 2019 11:38:53 +0200 Subject: Add support for option merging (--generate-merge) --- cli/context.cxx | 21 ++-- cli/context.hxx | 8 +- cli/header.cxx | 34 +++++-- cli/inline.cxx | 6 +- cli/name-processor.cxx | 4 +- cli/options.cli | 23 +++-- cli/options.cxx | 10 ++ cli/options.hxx | 10 ++ cli/options.ixx | 18 ++++ cli/runtime-source.cxx | 263 ++++++++++++++++++++++++++++--------------------- cli/source.cxx | 102 ++++++++++++++++--- 11 files changed, 337 insertions(+), 162 deletions(-) (limited to 'cli') diff --git a/cli/context.cxx b/cli/context.cxx index 3715efa..061129e 100644 --- a/cli/context.cxx +++ b/cli/context.cxx @@ -106,8 +106,11 @@ context (ostream& os_, unit (unit_), options (ops), ot (ot_), - modifier (options.generate_modifier ()), - specifier (options.generate_specifier ()), + gen_modifier (options.generate_modifier ()), + gen_specifier (options.generate_specifier () || + options.generate_merge ()), + gen_parse (options.generate_parse ()), + gen_merge (options.generate_merge ()), inl (data_->inl_), opt_prefix (options.option_prefix ()), opt_sep (options.option_separator ()), @@ -122,13 +125,13 @@ context (ostream& os_, tocs (data_->tocs_) { if (options.suppress_usage ()) - usage = ut_none; + gen_usage = ut_none; else { if (options.long_usage ()) - usage = options.short_usage () ? ut_both : ut_long; + gen_usage = options.short_usage () ? ut_both : ut_long; else - usage = ut_short; + gen_usage = ut_short; } if (!options.suppress_inline ()) @@ -168,9 +171,11 @@ context (context& c) unit (c.unit), options (c.options), ot (c.ot), - modifier (c.modifier), - specifier (c.specifier), - usage (c.usage), + gen_modifier (c.gen_modifier), + gen_specifier (c.gen_specifier), + gen_parse (c.gen_parse), + gen_merge (c.gen_merge), + gen_usage (c.gen_usage), inl (c.inl), opt_prefix (c.opt_prefix), opt_sep (c.opt_sep), diff --git a/cli/context.hxx b/cli/context.hxx index a076c17..14cdb7c 100644 --- a/cli/context.hxx +++ b/cli/context.hxx @@ -83,9 +83,11 @@ public: output_type ot; - bool modifier; - bool specifier; - usage_type usage; + bool gen_modifier; + bool gen_specifier; + bool gen_parse; + bool gen_merge; + usage_type gen_usage; string const& inl; string const& opt_prefix; diff --git a/cli/header.cxx b/cli/header.cxx index dc0ea9e..a1ab963 100644 --- a/cli/header.cxx +++ b/cli/header.cxx @@ -25,7 +25,7 @@ namespace << name << " () const;" << endl; - if (modifier) + if (gen_modifier) { os << type << "&" << endl << name << " ();" @@ -36,7 +36,7 @@ namespace << endl; } - if (specifier && type != "bool") + if (gen_specifier && type != "bool") { string spec (especifier (o)); @@ -44,7 +44,7 @@ namespace << spec << " () const;" << endl; - if (modifier) + if (gen_modifier) os << "void" << endl << spec << " (bool);" << endl; @@ -66,7 +66,7 @@ namespace os << type << " " << member << ";"; - if (specifier && type != "bool") + if (gen_specifier && type != "bool") os << "bool " << especifier_member (o) << ";"; } }; @@ -137,7 +137,7 @@ namespace // Are we generating parsing constructors or parse() functions? // string n; - if (options.generate_parse ()) + if (gen_parse) { os << "// Return true if anything has been parsed." << endl << "//" << endl; @@ -185,16 +185,30 @@ namespace << endl; } + + // Note that we are generating public merge() function even for abstract + // classes; theoretically, one may want to merge options only starting + // form a specific point in the inheritance hierarchy (e.g., only common + // options or some such). + // + if (gen_merge) + os << "// Merge options from the specified instance appending/overriding" << endl + << "// them as if they appeared after options in this instance." << endl + << "//" << endl + << "void" << endl + << "merge (const " << name << "&);" + << endl; + // // - os << "// Option accessors" << (modifier ? " and modifiers." : ".") << endl + os << "// Option accessors" << (gen_modifier ? " and modifiers." : ".") << endl << "//" << endl; names (c, names_option_); // Usage. // - if (usage != ut_none) + if (gen_usage != ut_none) { string up (cli + "::usage_para"); string const& ost (options.ostream_type ()); @@ -207,7 +221,7 @@ namespace << up << " = " << up << "::none);" << endl; - if (usage == ut_both) + if (gen_usage == ut_both) os << "static " << up << endl << "print_long_usage (" << ost << "&," << endl << up << " = " << up << "::none);" @@ -343,7 +357,7 @@ generate_header (context& ctx) // Entire page usage. // - if (ctx.usage != ut_none && ctx.options.page_usage_specified ()) + if (ctx.gen_usage != ut_none && ctx.options.page_usage_specified ()) { os << "// Print page usage information." << endl << "//" << endl; @@ -359,7 +373,7 @@ generate_header (context& ctx) << up << " = " << up << "::none);" << endl; - if (ctx.usage == ut_both) + if (ctx.gen_usage == ut_both) os << up << endl << n << "long_usage (" << ost << "&," << endl << up << " = " << up << "::none);" diff --git a/cli/inline.cxx b/cli/inline.cxx index 9dc5440..4bc0182 100644 --- a/cli/inline.cxx +++ b/cli/inline.cxx @@ -26,7 +26,7 @@ namespace << "return this->" << emember (o) << ";" << "}"; - if (modifier) + if (gen_modifier) { os << inl << type << "& " << scope << "::" << endl << name << " ()" @@ -41,7 +41,7 @@ namespace << "}"; } - if (specifier && type != "bool") + if (gen_specifier && type != "bool") { string spec (especifier (o)); @@ -51,7 +51,7 @@ namespace << "return this->" << especifier_member (o) << ";" << "}"; - if (modifier) + if (gen_modifier) os << inl << "void " << scope << "::" << endl << spec << "(bool x)" << "{" diff --git a/cli/name-processor.cxx b/cli/name-processor.cxx index c0f7179..d533a5b 100644 --- a/cli/name-processor.cxx +++ b/cli/name-processor.cxx @@ -85,7 +85,7 @@ namespace virtual void traverse (type& o) { - if (specifier && o.type ().name () != "bool") + if (gen_specifier && o.type ().name () != "bool") { semantics::context& oc (o.context ()); string const& base (oc.get ("name")); @@ -111,7 +111,7 @@ namespace string const& base (oc.get ("name")); oc.set ("member", find_name (base + "_", set_)); - if (specifier && o.type ().name () != "bool") + if (gen_specifier && o.type ().name () != "bool") { string const& base (oc.get ("specifier")); oc.set ("specifier-member", find_name (base + "_", set_)); diff --git a/cli/options.cli b/cli/options.cli index 631f52f..da9a52a 100644 --- a/cli/options.cli +++ b/cli/options.cli @@ -51,9 +51,18 @@ class options 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." + "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 option + appending/overriding." + }; + + bool --generate-merge + { + "Generate \cb{merge()} functions. This is primarily useful for being able + to merge several already parsed options class instances, for example, to + implement option appending/overriding. Note that this option forces + \cb{--generate-specifier}." }; bool --generate-description @@ -63,20 +72,20 @@ class options bool --generate-file-scanner { - "Generate the \c{argv_file_scanner} implementation. This scanner is - capable of reading command line arguments from the \c{argv} array as + "Generate the \cb{argv_file_scanner} implementation. This scanner is + capable of reading command line arguments from the \cb{argv} array as well as files specified with command line options." }; bool --generate-vector-scanner { - "Generate the \c{vector_scanner} implementation. This scanner is capable + "Generate the \cb{vector_scanner} implementation. This scanner is capable of reading command line arguments from \cb{vector}." }; bool --generate-group-scanner { - "Generate the \c{group_scanner} implementation. This scanner supports + "Generate the \cb{group_scanner} implementation. This scanner supports grouping of arguments (usually options) to apply only to a certain argument. diff --git a/cli/options.cxx b/cli/options.cxx index bb102e0..2e69cc9 100644 --- a/cli/options.cxx +++ b/cli/options.cxx @@ -612,6 +612,7 @@ options () generate_modifier_ (), generate_specifier_ (), generate_parse_ (), + generate_merge_ (), generate_description_ (), generate_file_scanner_ (), generate_vector_scanner_ (), @@ -750,6 +751,7 @@ options (int& argc, generate_modifier_ (), generate_specifier_ (), generate_parse_ (), + generate_merge_ (), generate_description_ (), generate_file_scanner_ (), generate_vector_scanner_ (), @@ -891,6 +893,7 @@ options (int start, generate_modifier_ (), generate_specifier_ (), generate_parse_ (), + generate_merge_ (), generate_description_ (), generate_file_scanner_ (), generate_vector_scanner_ (), @@ -1032,6 +1035,7 @@ options (int& argc, generate_modifier_ (), generate_specifier_ (), generate_parse_ (), + generate_merge_ (), generate_description_ (), generate_file_scanner_ (), generate_vector_scanner_ (), @@ -1175,6 +1179,7 @@ options (int start, generate_modifier_ (), generate_specifier_ (), generate_parse_ (), + generate_merge_ (), generate_description_ (), generate_file_scanner_ (), generate_vector_scanner_ (), @@ -1314,6 +1319,7 @@ options (::cli::scanner& s, generate_modifier_ (), generate_specifier_ (), generate_parse_ (), + generate_merge_ (), generate_description_ (), generate_file_scanner_ (), generate_vector_scanner_ (), @@ -1466,6 +1472,8 @@ print_usage (::std::ostream& os, ::cli::usage_para p) os << "--generate-parse Generate parse() functions instead of parsing" << ::std::endl << " constructors." << ::std::endl; + os << "--generate-merge Generate merge() functions." << ::std::endl; + os << "--generate-description Generate the option description list that can be" << ::std::endl << " examined at runtime." << ::std::endl; @@ -1715,6 +1723,8 @@ struct _cli_options_map_init &::cli::thunk< options, bool, &options::generate_specifier_ >; _cli_options_map_["--generate-parse"] = &::cli::thunk< options, bool, &options::generate_parse_ >; + _cli_options_map_["--generate-merge"] = + &::cli::thunk< options, bool, &options::generate_merge_ >; _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 dce59bd..9f5124f 100644 --- a/cli/options.hxx +++ b/cli/options.hxx @@ -500,6 +500,15 @@ class options generate_parse (const bool&); const bool& + generate_merge () const; + + bool& + generate_merge (); + + void + generate_merge (const bool&); + + const bool& generate_description () const; bool& @@ -1450,6 +1459,7 @@ class options bool generate_modifier_; bool generate_specifier_; bool generate_parse_; + bool generate_merge_; bool generate_description_; bool generate_file_scanner_; bool generate_vector_scanner_; diff --git a/cli/options.ixx b/cli/options.ixx index 4c5cfb7..ba5fff2 100644 --- a/cli/options.ixx +++ b/cli/options.ixx @@ -407,6 +407,24 @@ generate_parse(const bool& x) } inline const bool& options:: +generate_merge () const +{ + return this->generate_merge_; +} + +inline bool& options:: +generate_merge () +{ + return this->generate_merge_; +} + +inline void options:: +generate_merge(const bool& x) +{ + this->generate_merge_ = x; +} + +inline const bool& options:: generate_description () const { return this->generate_description_; diff --git a/cli/runtime-source.cxx b/cli/runtime-source.cxx index 778bed4..54a085f 100644 --- a/cli/runtime-source.cxx +++ b/cli/runtime-source.cxx @@ -802,166 +802,203 @@ generate_runtime_source (context& ctx, bool complete) // generated header file, we always generate the following templates // in the source file. // - bool sp (ctx.specifier); + bool sp (ctx.gen_specifier); + bool gen_merge (ctx.gen_merge); // parser class template & its specializations // os << "template " << endl << "struct parser" - << "{" - << "static void" << endl - << "parse (X& x, " << (sp ? "bool& xs, " : "") << "scanner& s)" - << "{" - << "using namespace std;" - << endl - << "const char* o (s.next ());" - << endl - << "if (s.more ())" - << "{" - << "string v (s.next ());" - << "istringstream is (v);" - << "if (!(is >> x && " << - "is.peek () == istringstream::traits_type::eof ()))" << endl - << "throw invalid_value (o, v);" - << "}" - << "else" << endl - << "throw missing_value (o);"; - + << "{"; + + os << "static void" << endl + << "parse (X& x, " << (sp ? "bool& xs, " : "") << "scanner& s)" + << "{" + << "using namespace std;" + << endl + << "const char* o (s.next ());" + << "if (s.more ())" + << "{" + << "string v (s.next ());" + << "istringstream is (v);" + << "if (!(is >> x && is.peek () == istringstream::traits_type::eof ()))" << endl + << "throw invalid_value (o, v);" + << "}" + << "else" << endl + << "throw missing_value (o);"; if (sp) os << endl - << "xs = true;"; + << "xs = true;"; + os << "}"; - os << "}" - << "};"; + if (gen_merge) + os << "static void" << endl + << "merge (X& b, const X& a)" + << "{" + << "b = a;" + << "}"; + + os << "};"; // parser // os << "template <>" << endl << "struct parser" - << "{" - << "static void" << endl - << "parse (bool& x, scanner& s)" - << "{" - << "s.next ();" - << "x = true;" - << "}" - << "};"; + << "{"; + + os << "static void" << endl + << "parse (bool& x, scanner& s)" + << "{" + << "s.next ();" + << "x = true;" + << "}"; + + if (gen_merge) + os << "static void" << endl + << "merge (bool& b, const bool&)" + << "{" + << "b = true;" // We wouldn't be here if a is false. + << "}"; + + os << "};"; // parser // os << "template <>" << endl << "struct parser" - << "{" - << "static void" << endl - << "parse (std::string& x, " << (sp ? "bool& xs, " : "") << "scanner& s)" - << "{" - << "const char* o (s.next ());" - << endl - << "if (s.more ())" << endl - << "x = s.next ();" - << "else" << endl - << "throw missing_value (o);"; - + << "{"; + + os << "static void" << endl + << "parse (std::string& x, " << (sp ? "bool& xs, " : "") << "scanner& s)" + << "{" + << "const char* o (s.next ());" + << endl + << "if (s.more ())" << endl + << "x = s.next ();" + << "else" << endl + << "throw missing_value (o);"; if (sp) - os << endl + os << endl << "xs = true;"; + os << "}"; - os << "}" - << "};"; + if (gen_merge) + os << "static void" << endl + << "merge (std::string& b, const std::string& a)" + << "{" + << "b = a;" + << "}"; + + os << "};"; // parser> // os << "template " << endl << "struct parser >" - << "{" - << "static void" << endl - << "parse (std::vector& c, " << (sp ? "bool& xs, " : "") << - "scanner& s)" - << "{" - << "X x;"; + << "{"; + os << "static void" << endl + << "parse (std::vector& c, " << (sp ? "bool& xs, " : "") << "scanner& s)" + << "{" + << "X x;"; if (sp) - os << "bool dummy;"; - - os << "parser::parse (x, " << (sp ? "dummy, " : "") << "s);" - << "c.push_back (x);"; - + os << "bool dummy;"; + os << "parser::parse (x, " << (sp ? "dummy, " : "") << "s);" + << "c.push_back (x);"; if (sp) - os << "xs = true;"; + os << "xs = true;"; + os << "}"; + + if (gen_merge) + os << "static void" << endl + << "merge (std::vector& b, const std::vector& a)" + << "{" + << "b.insert (b.end (), a.begin (), a.end ());" + << "}"; - os << "}" - << "};"; + os << "};"; // parser> // os << "template " << endl << "struct parser >" - << "{" - << "static void" << endl - << "parse (std::set& c, " << (sp ? "bool& xs, " : "") << "scanner& s)" - << "{" - << "X x;"; + << "{"; + os << "static void" << endl + << "parse (std::set& c, " << (sp ? "bool& xs, " : "") << "scanner& s)" + << "{" + << "X x;"; if (sp) - os << "bool dummy;"; - - os << "parser::parse (x, " << (sp ? "dummy, " : "") << "s);" - << "c.insert (x);"; - + os << "bool dummy;"; + os << "parser::parse (x, " << (sp ? "dummy, " : "") << "s);" + << "c.insert (x);"; if (sp) - os << "xs = true;"; + os << "xs = true;"; + os << "}"; + + if (gen_merge) + os << "static void" << endl + << "merge (std::set& b, const std::set& a)" + << "{" + << "b.insert (a.begin (), a.end ());" + << "}"; - os << "}" - << "};"; + os << "};"; // parser> // os << "template " << endl << "struct parser >" - << "{" - << "static void" << endl - << "parse (std::map& m, " << (sp ? "bool& xs, " : "") << - "scanner& s)" - << "{" - << "const char* o (s.next ());" - << endl - << "if (s.more ())" - << "{" - << "std::string ov (s.next ());" - << "std::string::size_type p = ov.find ('=');" - << endl - << "K k = K ();" - << "V v = V ();" - << "std::string kstr (ov, 0, p);" - << "std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ()));" - << endl - << "int ac (2);" - << "char* av[] = {const_cast (o), 0};"; + << "{"; + + os << "static void" << endl + << "parse (std::map& m, " << (sp ? "bool& xs, " : "") << "scanner& s)" + << "{" + << "const char* o (s.next ());" + << endl + << "if (s.more ())" + << "{" + << "std::string ov (s.next ());" + << "std::string::size_type p = ov.find ('=');" + << endl + << "K k = K ();" + << "V v = V ();" + << "std::string kstr (ov, 0, p);" + << "std::string vstr (ov, (p != std::string::npos ? p + 1 : ov.size ()));" + << endl + << "int ac (2);" + << "char* av[] = {const_cast (o), 0};"; if (sp) - os << "bool dummy;"; - os << "if (!kstr.empty ())" - << "{" - << "av[1] = const_cast (kstr.c_str ());" - << "argv_scanner s (0, ac, av);" - << "parser::parse (k, " << (sp ? "dummy, " : "") << "s);" - << "}" - << "if (!vstr.empty ())" - << "{" - << "av[1] = const_cast (vstr.c_str ());" - << "argv_scanner s (0, ac, av);" - << "parser::parse (v, " << (sp ? "dummy, " : "") << "s);" - << "}" - << "m[k] = v;" - << "}" - << "else" << endl - << "throw missing_value (o);"; - + os << "bool dummy;"; + os << "if (!kstr.empty ())" + << "{" + << "av[1] = const_cast (kstr.c_str ());" + << "argv_scanner s (0, ac, av);" + << "parser::parse (k, " << (sp ? "dummy, " : "") << "s);" + << "}" + << "if (!vstr.empty ())" + << "{" + << "av[1] = const_cast (vstr.c_str ());" + << "argv_scanner s (0, ac, av);" + << "parser::parse (v, " << (sp ? "dummy, " : "") << "s);" + << "}" + << "m[k] = v;" + << "}" + << "else" << endl + << "throw missing_value (o);"; if (sp) os << endl - << "xs = true;"; + << "xs = true;"; + os << "}"; + + if (gen_merge) + os << "static void" << endl + << "merge (std::map& b, const std::map& a)" + << "{" + << "b.insert (a.begin (), a.end ());" + << "}"; - os << "}" - << "};"; + os << "};"; // Parser thunk. // @@ -972,7 +1009,7 @@ generate_runtime_source (context& ctx, bool complete) << "parser::parse (x.*M, s);" << "}"; - if (ctx.specifier) + if (ctx.gen_specifier) os << "template " << endl << "void" << endl << "thunk (X& x, scanner& s)" diff --git a/cli/source.cxx b/cli/source.cxx index 3d0b7cc..2333faf 100644 --- a/cli/source.cxx +++ b/cli/source.cxx @@ -58,7 +58,7 @@ namespace else os << " ()"; - if (specifier && o.type ().name () != "bool") + if (gen_specifier && o.type ().name () != "bool") os << "," << endl << " " << especifier_member (o) << " (false)"; } @@ -67,6 +67,29 @@ namespace bool comma_; }; + struct option_merge: traversal::option, context + { + option_merge (context& c) : context (c) {} + + virtual void + traverse (type& o) + { + string type (o.type ().name ()); + bool b (type == "bool"); + + string member (emember (o)); + string spec_member (b ? member : especifier_member (o)); + + os << "if (a." << spec_member << ")" + << "{" + << cli << "::parser< " << type << ">::merge (" << endl + << "this->" << member << ", a." << member << ");"; + if (!b) + os << "this->" << spec_member << " = true;"; + os << "}"; + } + }; + // // struct option_map: traversal::option, context @@ -91,7 +114,7 @@ namespace << "&" << cli << "::thunk< " << scope << ", " << type << ", " << "&" << scope << "::" << member; - if (specifier && type != "bool") + if (gen_specifier && type != "bool") os << "," << endl << " &" << scope << "::" << especifier_member (o); @@ -243,7 +266,7 @@ namespace size_t n (ds.size ()); string d; - if (usage == ut_both && usage_ == ut_long) + if (gen_usage == ut_both && usage_ == ut_long) { d = n > 2 // Have both short and long? ? ds[2] // Then use long. @@ -436,7 +459,7 @@ namespace if (doc.size () > i) // Have at least one. { - if (usage == ut_both && usage_ == ut_long) + if (gen_usage == ut_both && usage_ == ut_long) { d = doc.size () > i + 1 // Have both short and long? ? doc[i + 1] // Then use long. @@ -444,10 +467,10 @@ namespace } else // Short or long. { - d = doc.size () > i + 1 // Have both short and long? - ? doc[i] // Then use short, - : (usage == ut_long // Otherwise, if asked for long, - ? doc[i] // Then use long, + d = doc.size () > i + 1 // Have both short and long? + ? doc[i] // Then use short, + : (gen_usage == ut_long // Otherwise, if asked for long, + ? doc[i] // Then use long, : first_sentence (doc[i])); // Else first sentence of long. } } @@ -496,6 +519,22 @@ namespace // // + struct base_merge: traversal::class_, context + { + base_merge (context& c): context (c) {} + + virtual void + traverse (type& c) + { + os << "// " << escape (c.name ()) << " base" << endl + << "//" << endl + << fq_name (c) << "::merge (a);" + << endl; + } + }; + + // + // struct base_desc: traversal::class_, context { base_desc (context& c): context (c) {} @@ -524,7 +563,7 @@ namespace const char* t ( (cd == cd_default - ? usage != ut_both || usage_ == ut_short + ? gen_usage != ut_both || usage_ == ut_short : cd == cd_short) ? "" : "long_"); os << "// " << escape (c.name ()) << " base" << endl @@ -544,12 +583,16 @@ namespace class_ (context& c) : context (c), base_parse_ (c), + base_merge_ (c), base_desc_ (c), + option_merge_ (c), option_map_ (c), option_desc_ (c) { inherits_base_parse_ >> base_parse_; + inherits_base_merge_ >> base_merge_; inherits_base_desc_ >> base_desc_; + names_option_merge_ >> option_merge_; names_option_map_ >> option_map_; names_option_desc_ >> option_desc_; } @@ -583,7 +626,7 @@ namespace if (!abst) { - bool p (options.generate_parse ()); + bool p (gen_parse); string n, res, ret; if (p) @@ -684,9 +727,30 @@ namespace << "}"; } + // merge() + // + if (gen_merge) + { + os << "void " << name << "::" << endl + << "merge (const " << name << "& a)" + << "{" + << "CLI_POTENTIALLY_UNUSED (a);" + << endl; + + // First merge all our bases. + // + inherits (c, inherits_base_merge_); + + // Then our options. + // + names (c, names_option_merge_); + + os << "}"; + } + // Usage. // - if (usage != ut_none) + if (gen_usage != ut_none) { bool b (hb && !options.exclude_base ()); @@ -775,7 +839,7 @@ namespace << "CLI_POTENTIALLY_UNUSED (os);" << endl; { - usage_type u (usage == ut_both ? ut_short : usage); + usage_type u (gen_usage == ut_both ? ut_short : gen_usage); base_usage bu (*this, u); traversal::inherits i (bu); @@ -808,7 +872,7 @@ namespace // Long version. // - if (usage == ut_both) + if (gen_usage == ut_both) { os << up << " " << name << "::" << endl << "print_long_usage (" << ost << "& os, " << up << " p)" @@ -1136,9 +1200,15 @@ namespace base_parse base_parse_; traversal::inherits inherits_base_parse_; + base_merge base_merge_; + traversal::inherits inherits_base_merge_; + base_desc base_desc_; traversal::inherits inherits_base_desc_; + option_merge option_merge_; + traversal::names names_option_merge_; + option_map option_map_; traversal::names names_option_map_; @@ -1163,7 +1233,7 @@ namespace const char* t ( (cd == cd_default || cd == cd_exclude_base - ? usage != ut_both || usage_ == ut_short + ? gen_usage != ut_both || usage_ == ut_short : cd == cd_short) ? "" : "long_"); string p ( @@ -1210,12 +1280,12 @@ generate_source (context& ctx) // Entire page usage. // - if (ctx.usage != ut_none && ctx.options.page_usage_specified ()) + if (ctx.gen_usage != ut_none && ctx.options.page_usage_specified ()) { const string& qn (ctx.options.page_usage ()); string n (ctx.escape (ctx.substitute (ctx.ns_open (qn, false)))); - usage u (ctx.usage); + usage u (ctx.gen_usage); string up (ctx.cli + "::usage_para"); string const& ost (ctx.options.ostream_type ()); -- cgit v1.1