summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/context.cxx21
-rw-r--r--cli/context.hxx8
-rw-r--r--cli/header.cxx34
-rw-r--r--cli/inline.cxx6
-rw-r--r--cli/name-processor.cxx4
-rw-r--r--cli/options.cli23
-rw-r--r--cli/options.cxx10
-rw-r--r--cli/options.hxx10
-rw-r--r--cli/options.ixx18
-rw-r--r--cli/runtime-source.cxx263
-rw-r--r--cli/source.cxx102
11 files changed, 337 insertions, 162 deletions
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<string> ("name"));
@@ -111,7 +111,7 @@ namespace
string const& base (oc.get<string> ("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<string> ("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<string>}."
};
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 <typename X>" << 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<bool>
//
os << "template <>" << endl
<< "struct parser<bool>"
- << "{"
- << "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<string>
//
os << "template <>" << endl
<< "struct parser<std::string>"
- << "{"
- << "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<std::vector<X>>
//
os << "template <typename X>" << endl
<< "struct parser<std::vector<X> >"
- << "{"
- << "static void" << endl
- << "parse (std::vector<X>& c, " << (sp ? "bool& xs, " : "") <<
- "scanner& s)"
- << "{"
- << "X x;";
+ << "{";
+ os << "static void" << endl
+ << "parse (std::vector<X>& c, " << (sp ? "bool& xs, " : "") << "scanner& s)"
+ << "{"
+ << "X x;";
if (sp)
- os << "bool dummy;";
-
- os << "parser<X>::parse (x, " << (sp ? "dummy, " : "") << "s);"
- << "c.push_back (x);";
-
+ os << "bool dummy;";
+ os << "parser<X>::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<X>& b, const std::vector<X>& a)"
+ << "{"
+ << "b.insert (b.end (), a.begin (), a.end ());"
+ << "}";
- os << "}"
- << "};";
+ os << "};";
// parser<std::set<X>>
//
os << "template <typename X>" << endl
<< "struct parser<std::set<X> >"
- << "{"
- << "static void" << endl
- << "parse (std::set<X>& c, " << (sp ? "bool& xs, " : "") << "scanner& s)"
- << "{"
- << "X x;";
+ << "{";
+ os << "static void" << endl
+ << "parse (std::set<X>& c, " << (sp ? "bool& xs, " : "") << "scanner& s)"
+ << "{"
+ << "X x;";
if (sp)
- os << "bool dummy;";
-
- os << "parser<X>::parse (x, " << (sp ? "dummy, " : "") << "s);"
- << "c.insert (x);";
-
+ os << "bool dummy;";
+ os << "parser<X>::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<X>& b, const std::set<X>& a)"
+ << "{"
+ << "b.insert (a.begin (), a.end ());"
+ << "}";
- os << "}"
- << "};";
+ os << "};";
// parser<std::map<K,V>>
//
os << "template <typename K, typename V>" << endl
<< "struct parser<std::map<K, V> >"
- << "{"
- << "static void" << endl
- << "parse (std::map<K, V>& 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<char*> (o), 0};";
+ << "{";
+
+ os << "static void" << endl
+ << "parse (std::map<K, V>& 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<char*> (o), 0};";
if (sp)
- os << "bool dummy;";
- os << "if (!kstr.empty ())"
- << "{"
- << "av[1] = const_cast<char*> (kstr.c_str ());"
- << "argv_scanner s (0, ac, av);"
- << "parser<K>::parse (k, " << (sp ? "dummy, " : "") << "s);"
- << "}"
- << "if (!vstr.empty ())"
- << "{"
- << "av[1] = const_cast<char*> (vstr.c_str ());"
- << "argv_scanner s (0, ac, av);"
- << "parser<V>::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<char*> (kstr.c_str ());"
+ << "argv_scanner s (0, ac, av);"
+ << "parser<K>::parse (k, " << (sp ? "dummy, " : "") << "s);"
+ << "}"
+ << "if (!vstr.empty ())"
+ << "{"
+ << "av[1] = const_cast<char*> (vstr.c_str ());"
+ << "argv_scanner s (0, ac, av);"
+ << "parser<V>::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<K, V>& b, const std::map<K, V>& a)"
+ << "{"
+ << "b.insert (a.begin (), a.end ());"
+ << "}";
- os << "}"
- << "};";
+ os << "};";
// Parser thunk.
//
@@ -972,7 +1009,7 @@ generate_runtime_source (context& ctx, bool complete)
<< "parser<T>::parse (x.*M, s);"
<< "}";
- if (ctx.specifier)
+ if (ctx.gen_specifier)
os << "template <typename X, typename T, T X::*M, bool X::*S>" << 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 ());