summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/header.cxx13
-rw-r--r--cli/options.cli5
-rw-r--r--cli/options.cxx10
-rw-r--r--cli/options.hxx4
-rw-r--r--cli/options.ixx6
-rw-r--r--cli/runtime-header.cxx57
-rw-r--r--cli/runtime-inline.cxx54
-rw-r--r--cli/runtime-source.cxx19
-rw-r--r--cli/source.cxx109
9 files changed, 273 insertions, 4 deletions
diff --git a/cli/header.cxx b/cli/header.cxx
index 7905b22..d1b078f 100644
--- a/cli/header.cxx
+++ b/cli/header.cxx
@@ -135,7 +135,7 @@ namespace
names (c, names_option_);
- // usage
+ // Usage.
//
if (usage)
{
@@ -146,6 +146,17 @@ namespace
<< endl;
}
+ // Description.
+ //
+ if (options.generate_description ())
+ {
+ os << "// Option description." << endl
+ << "//" << endl
+ << "static const " << cli << "::options&" << endl
+ << "description ();"
+ << endl;
+ }
+
// _parse()
//
os << "private:" << endl
diff --git a/cli/options.cli b/cli/options.cli
index ccafa68..a1cc3b4 100644
--- a/cli/options.cli
+++ b/cli/options.cli
@@ -34,6 +34,11 @@ class options
on the command line."
};
+ bool --generate-description
+ {
+ "Generate the option description list that can be examined at runtime."
+ };
+
bool --generate-file-scanner
{
"Generate the \c{argv_file_scanner} implementation. This scanner is
diff --git a/cli/options.cxx b/cli/options.cxx
index 093fd55..c8a83df 100644
--- a/cli/options.cxx
+++ b/cli/options.cxx
@@ -527,6 +527,7 @@ options (int& argc,
output_dir_ (),
generate_modifier_ (),
generate_specifier_ (),
+ generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
suppress_undocumented_ (),
@@ -572,6 +573,7 @@ options (int start,
output_dir_ (),
generate_modifier_ (),
generate_specifier_ (),
+ generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
suppress_undocumented_ (),
@@ -617,6 +619,7 @@ options (int& argc,
output_dir_ (),
generate_modifier_ (),
generate_specifier_ (),
+ generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
suppress_undocumented_ (),
@@ -664,6 +667,7 @@ options (int start,
output_dir_ (),
generate_modifier_ (),
generate_specifier_ (),
+ generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
suppress_undocumented_ (),
@@ -707,6 +711,7 @@ options (::cli::scanner& s,
output_dir_ (),
generate_modifier_ (),
generate_specifier_ (),
+ generate_description_ (),
generate_file_scanner_ (),
suppress_inline_ (),
suppress_undocumented_ (),
@@ -755,6 +760,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-description Generate the option description list that can be" << ::std::endl
+ << " examined at runtime." << ::std::endl;
+
os << "--generate-file-scanner Generate the 'argv_file_scanner' implementation." << ::std::endl;
os << "--suppress-inline Generate all functions non-inline." << ::std::endl;
@@ -857,6 +865,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-description"] =
+ &::cli::thunk< options, bool, &options::generate_description_ >;
_cli_options_map_["--generate-file-scanner"] =
&::cli::thunk< options, bool, &options::generate_file_scanner_ >;
_cli_options_map_["--suppress-inline"] =
diff --git a/cli/options.hxx b/cli/options.hxx
index d8a880d..a7a7094 100644
--- a/cli/options.hxx
+++ b/cli/options.hxx
@@ -336,6 +336,9 @@ class options
generate_specifier () const;
const bool&
+ generate_description () const;
+
+ const bool&
generate_file_scanner () const;
const bool&
@@ -436,6 +439,7 @@ class options
std::string output_dir_;
bool generate_modifier_;
bool generate_specifier_;
+ bool generate_description_;
bool generate_file_scanner_;
bool suppress_inline_;
bool suppress_undocumented_;
diff --git a/cli/options.ixx b/cli/options.ixx
index 9c9afda..f2072fe 100644
--- a/cli/options.ixx
+++ b/cli/options.ixx
@@ -192,6 +192,12 @@ generate_specifier () const
}
inline const bool& options::
+generate_description () const
+{
+ return this->generate_description_;
+}
+
+inline const bool& options::
generate_file_scanner () const
{
return this->generate_file_scanner_;
diff --git a/cli/runtime-header.cxx b/cli/runtime-header.cxx
index 99da036..de24073 100644
--- a/cli/runtime-header.cxx
+++ b/cli/runtime-header.cxx
@@ -15,6 +15,10 @@ generate_runtime_header (context& ctx)
if (ctx.options.generate_file_scanner ())
os << "#include <deque>" << endl;
+ if (ctx.options.generate_description ())
+ os << "#include <map>" << endl
+ << "#include <vector>" << endl;
+
os << "#include <iosfwd>" << endl
<< "#include <string>" << endl
<< "#include <exception>" << endl
@@ -299,5 +303,58 @@ generate_runtime_header (context& ctx)
os << "};";
}
+ // Option description.
+ //
+ if (ctx.options.generate_description ())
+ {
+ os << "typedef std::vector<std::string> option_names;"
+ << endl;
+
+ os << "class option"
+ << "{"
+ << "public:" << endl
+ << endl
+ << "const std::string&" << endl
+ << "name () const;"
+ << endl
+ << "const option_names&" << endl
+ << "aliases () const;"
+ << endl
+ << "bool" << endl
+ << "flag () const;"
+ << endl
+ << "const std::string&" << endl
+ << "default_value () const;"
+ << endl
+ << "public:"
+ << "option ();"
+ << "option (const std::string& name," << endl
+ << "const option_names& aliases," << endl
+ << "bool flag," << endl
+ << "const std::string& default_value);"
+ << endl
+ << "private:"
+ << "std::string name_;"
+ << "option_names aliases_;"
+ << "bool flag_;"
+ << "std::string default_value_;"
+ << "};";
+
+ os << "class options: public std::vector<option>"
+ << "{"
+ << "public:" << endl
+ << "typedef std::vector<option> container_type;"
+ << endl
+ << "container_type::const_iterator" << endl
+ << "find (const std::string& name) const;"
+ << endl
+ << "void" << endl
+ << "push_back (const option&);"
+ << "private:"
+ << "typedef std::map<std::string, container_type::size_type> map_type;"
+ << "map_type map_;"
+ << "};";
+ }
+
ctx.cli_close ();
}
diff --git a/cli/runtime-inline.cxx b/cli/runtime-inline.cxx
index 753e86b..fecbd02 100644
--- a/cli/runtime-inline.cxx
+++ b/cli/runtime-inline.cxx
@@ -211,5 +211,59 @@ generate_runtime_inline (context& ctx)
<< "}";
}
+ // Option description.
+ //
+ if (ctx.options.generate_description ())
+ {
+ // option
+ //
+ os << inl << "const std::string& option::" << endl
+ << "name () const"
+ << "{"
+ << "return name_;"
+ << "}";
+
+ os << inl << "const option_names& option::" << endl
+ << "aliases () const"
+ << "{"
+ << "return aliases_;"
+ << "}";
+
+ os << inl << "bool option::" << endl
+ << "flag () const"
+ << "{"
+ << "return flag_;"
+ << "}";
+
+ os << inl << "const std::string& option::" << endl
+ << "default_value () const"
+ << "{"
+ << "return default_value_;"
+ << "}";
+
+ os << inl << "option::" << endl
+ << "option ()"
+ << "{"
+ << "}";
+
+ os << inl << "option::" << endl
+ << "option (const std::string& n," << endl
+ << "const option_names& a," << endl
+ << "bool f," << endl
+ << "const std::string& dv)" << endl
+ << ": name_ (n), aliases_ (a), flag_ (f), default_value_ (dv)"
+ << "{"
+ << "}";
+
+ // options
+ //
+ os << inl << "options::container_type::const_iterator options::" << endl
+ << "find (const std::string& name) const"
+ << "{"
+ << "map_type::const_iterator i (map_.find (name));"
+ << "return i != map_.end () ? begin () + i->second : end ();"
+ << "}";
+ }
+
ctx.cli_close ();
}
diff --git a/cli/runtime-source.cxx b/cli/runtime-source.cxx
index c76b745..7ccf404 100644
--- a/cli/runtime-source.cxx
+++ b/cli/runtime-source.cxx
@@ -412,6 +412,25 @@ generate_runtime_source (context& ctx)
<< "}";
}
+ // Option description.
+ //
+ if (ctx.options.generate_description ())
+ {
+ // options
+ //
+ os << "void options::" << endl
+ << "push_back (const option& o)"
+ << "{"
+ << "container_type::size_type n (size ());"
+ << "container_type::push_back (o);"
+ << "map_[o.name ()] = n;"
+ << endl
+ << "for (option_names::const_iterator i (o.aliases ().begin ());" << endl
+ << "i != o.aliases ().end (); ++i)" << endl
+ << "map_[*i] = n;"
+ << "}";
+ }
+
bool sp (ctx.specifier);
// parser class template & its specializations
diff --git a/cli/source.cxx b/cli/source.cxx
index 7d85859..b6f4234 100644
--- a/cli/source.cxx
+++ b/cli/source.cxx
@@ -103,6 +103,75 @@ namespace
//
//
+ struct option_desc: traversal::option, context
+ {
+ option_desc (context& c) : context (c) {}
+
+ virtual void
+ traverse (type& o)
+ {
+ using semantics::names;
+
+ names& n (o.named ());
+
+ os << "// " << o.name () << endl
+ << "//" << endl
+ << "{"
+ << cli << "::option_names a;";
+
+ for (names::name_iterator b (n.name_begin ()), i (b);
+ i != n.name_end (); ++i)
+ {
+ if (i == b) // Skip the primary name.
+ continue;
+
+ os << "a.push_back (\"" << *i << "\");";
+ }
+
+ if (o.initialized_p ())
+ {
+ using semantics::expression;
+ expression const& i (o.initializer ());
+
+ switch (i.type ())
+ {
+ case expression::string_lit:
+ {
+ os << "std::string dv (" << i.value () << ");";
+ break;
+ }
+ case expression::char_lit:
+ {
+ os << "std::string dv (1, " << i.value () << ");";
+ break;
+ }
+ case expression::bool_lit:
+ case expression::int_lit:
+ case expression::float_lit:
+ {
+ os << "std::string dv (\"" << i.value () << "\");";
+ }
+ case expression::identifier:
+ case expression::call_expr:
+ {
+ os << "std::string dv;";
+ break;
+ }
+ }
+ }
+ else
+ os << "std::string dv;";
+
+
+ os << cli << "::option o (\"" << o.name () << "\", a, " <<
+ (o.type ().name () == "bool" ? "true" : "false") << ", dv);"
+ << "os.push_back (o);"
+ << "}";
+ }
+ };
+
+ //
+ //
struct option_length: traversal::option, context
{
option_length (context& c, size_t& l, type*& o)
@@ -358,9 +427,10 @@ namespace
struct class_: traversal::class_, context
{
class_ (context& c)
- : context (c), option_map_ (c)
+ : context (c), option_map_ (c), option_desc_ (c)
{
names_option_map_ >> option_map_;
+ names_option_desc_ >> option_desc_;
}
virtual void
@@ -460,7 +530,7 @@ namespace
<< "_parse (s, opt, arg);"
<< "}";
- // usage
+ // Usage.
//
if (usage)
{
@@ -504,6 +574,35 @@ namespace
os << "}";
}
+ // Description.
+ //
+ if (options.generate_description ())
+ {
+ string desc ("_cli_" + name + "_desc");
+
+ os << "static " << cli << "::options " << desc << "_;"
+ << endl;
+
+ os << "struct " << desc << "_init"
+ << "{"
+ << desc << "_init (" << cli << "::options& os)"
+ << "{";
+
+ names (c, names_option_desc_);
+
+ os << "}"
+ << "};"
+ << "static " << desc << "_init " << desc << "_init_ (" <<
+ desc << "_);"
+ << endl;
+
+ os << "const " << cli << "::options& " << name << "::" << endl
+ << "description ()"
+ << "{"
+ << "return " << desc << "_;"
+ << "};";
+ }
+
// _parse()
//
string map ("_cli_" + name + "_map");
@@ -524,7 +623,8 @@ namespace
names (c, names_option_map_);
os << "}"
- << "} " << map << "_init_;"
+ << "};"
+ << "static " << map << "_init " << map << "_init_;"
<< endl;
bool pfx (!opt_prefix.empty ());
@@ -627,6 +727,9 @@ namespace
private:
option_map option_map_;
traversal::names names_option_map_;
+
+ option_desc option_desc_;
+ traversal::names names_option_desc_;
};
}