summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-09-14 10:52:55 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-09-14 10:52:55 +0200
commit3e10322425fa0a3cf6e125bc6f9d833b015cc9b5 (patch)
tree3ee842d8bff4ba1d2aaf22ed0936a77d60038509
parent4433307f8c0c6cfbcabe3316e98b9699223c97d3 (diff)
Implement the --cli-namespace option
-rw-r--r--NEWS3
-rw-r--r--cli/context.cxx53
-rw-r--r--cli/context.hxx11
-rw-r--r--cli/header.cxx6
-rw-r--r--cli/options.cli11
-rw-r--r--cli/options.cxx101
-rw-r--r--cli/options.hxx4
-rw-r--r--cli/options.ixx6
-rw-r--r--cli/runtime-header.cxx5
-rw-r--r--cli/runtime-inline.cxx5
-rw-r--r--cli/runtime-source.cxx5
-rw-r--r--cli/source.cxx34
12 files changed, 157 insertions, 87 deletions
diff --git a/NEWS b/NEWS
index dfeb3e2..dc3ce70 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,9 @@ Version 1.2.0
* New option, --generate-specifier, triggers the generation of functions
for determining whether the option was specified on the command line.
+ * New option, --cli-namespace, allows changing of the namespace for the
+ generated CLI support types.
+
* The argv_file_scanner now supports double and single-quoting option
values in option files. This is useful to preserve leading and trailing
whitespaces as well as to specify empty values.
diff --git a/cli/context.cxx b/cli/context.cxx
index a740374..8d5cba3 100644
--- a/cli/context.cxx
+++ b/cli/context.cxx
@@ -105,12 +105,18 @@ context (ostream& os_,
inl (data_->inl_),
opt_prefix (options.option_prefix ()),
opt_sep (options.option_separator ()),
+ cli (data_->cli_),
reserved_name_map (options.reserved_name ()),
keyword_set (data_->keyword_set_)
{
if (!options.suppress_inline ())
data_->inl_ = "inline ";
+ data_->cli_ = options.cli_namespace ();
+
+ if (!cli.empty () && cli[0] != ':')
+ data_->cli_ = "::" + data_->cli_;
+
for (size_t i (0); i < sizeof (keywords) / sizeof (char*); ++i)
data_->keyword_set_.insert (keywords[i]);
}
@@ -127,6 +133,7 @@ context (context& c)
inl (c.inl),
opt_prefix (c.opt_prefix),
opt_sep (c.opt_sep),
+ cli (c.cli),
reserved_name_map (c.reserved_name_map),
keyword_set (c.keyword_set)
{
@@ -614,6 +621,52 @@ fq_name (semantics::nameable& n, bool cxx_name)
return r;
}
+void context::
+cli_open ()
+{
+ string::size_type b (0), e;
+
+ do
+ {
+ e = cli.find ("::", b);
+ string n (cli, b, e == string::npos ? e : e - b);
+
+ if (!n.empty ())
+ os << "namespace " << n << "{";
+
+ b = e;
+
+ if (b == string::npos)
+ break;
+
+ b += 2;
+
+ } while (true);
+}
+
+void context::
+cli_close ()
+{
+ string::size_type b (0), e;
+
+ do
+ {
+ e = cli.find ("::", b);
+ string n (cli, b, e == string::npos ? e : e - b);
+
+ if (!n.empty ())
+ os << "}";
+
+ b = e;
+
+ if (b == string::npos)
+ break;
+
+ b += 2;
+
+ } while (true);
+}
+
// namespace
//
diff --git a/cli/context.hxx b/cli/context.hxx
index 1f2625d..ed0e058 100644
--- a/cli/context.hxx
+++ b/cli/context.hxx
@@ -45,6 +45,7 @@ public:
string const& inl;
string const& opt_prefix;
string const& opt_sep;
+ string const& cli;
typedef std::map<string, string> reserved_name_map_type;
reserved_name_map_type const& reserved_name_map;
@@ -56,6 +57,7 @@ private:
struct data
{
string inl_;
+ string cli_;
keyword_set_type keyword_set_;
};
@@ -116,6 +118,15 @@ public:
string
fq_name (semantics::nameable& n, bool cxx_name = true);
+ // Open/close cli namespace.
+ //
+public:
+ void
+ cli_open ();
+
+ void
+ cli_close ();
+
public:
context (std::ostream&, semantics::cli_unit&, options_type const&);
diff --git a/cli/header.cxx b/cli/header.cxx
index e43c0af..7905b22 100644
--- a/cli/header.cxx
+++ b/cli/header.cxx
@@ -88,7 +88,7 @@ namespace
// c-tors
//
- string um ("::cli::unknown_mode");
+ string um (cli + "::unknown_mode");
os << name << " (int& argc," << endl
<< "char** argv," << endl
@@ -122,7 +122,7 @@ namespace
<< um << " argument = " << um << "::stop);"
<< endl;
- os << name << " (::cli::scanner&," << endl
+ os << name << " (" << cli << "::scanner&," << endl
<< um << " option = " << um << "::fail," << endl
<< um << " argument = " << um << "::stop);"
<< endl;
@@ -150,7 +150,7 @@ namespace
//
os << "private:" << endl
<< "void" << endl
- << "_parse (::cli::scanner&," << endl
+ << "_parse (" << cli << "::scanner&," << endl
<< um << " option," << endl
<< um << " argument);"
<< endl;
diff --git a/cli/options.cli b/cli/options.cli
index 896a1a0..8955e08 100644
--- a/cli/options.cli
+++ b/cli/options.cli
@@ -67,6 +67,15 @@ class options
files, and would like their usage to have the same indentation level."
};
+ std::string --cli-namespace = "::cli"
+ {
+ "<ns>"
+ "Generate the CLI support types in the <ns> namespace (\cb{cli} by
+ default). The namespace can be nested, for example \cb{details::cli}.
+ If the namespace is empty, then the support types are generated in
+ the global namespace."
+ };
+
bool --generate-cxx
{
"Generate C++ code. If neither \cb{--generate-man} nor \cb{--generate-html}
@@ -225,6 +234,6 @@ class options
the same set of options in the same order on the command line at the
point where the \cb{--options-file} option is specified except that
the shell escaping and quoting is not required. Repeat this option
- to specify more than one options files."
+ to specify more than one options file."
};
};
diff --git a/cli/options.cxx b/cli/options.cxx
index 1c46fd4..6a14702 100644
--- a/cli/options.cxx
+++ b/cli/options.cxx
@@ -425,7 +425,8 @@ namespace cli
parse (std::vector<X>& c, scanner& s)
{
X x;
- parser<X>::parse (x, s);
+ bool dummy;
+ parser<X>::parse (x, dummy, s);
c.push_back (x);
}
};
@@ -437,7 +438,8 @@ namespace cli
parse (std::set<X>& c, scanner& s)
{
X x;
- parser<X>::parse (x, s);
+ bool dummy;
+ parser<X>::parse (x, dummy, s);
c.insert (x);
}
};
@@ -530,6 +532,7 @@ options (int& argc,
suppress_usage_ (),
long_usage_ (),
option_length_ (0),
+ cli_namespace_ ("::cli"),
generate_cxx_ (),
generate_man_ (),
generate_html_ (),
@@ -573,6 +576,7 @@ options (int start,
suppress_usage_ (),
long_usage_ (),
option_length_ (0),
+ cli_namespace_ ("::cli"),
generate_cxx_ (),
generate_man_ (),
generate_html_ (),
@@ -616,6 +620,7 @@ options (int& argc,
suppress_usage_ (),
long_usage_ (),
option_length_ (0),
+ cli_namespace_ ("::cli"),
generate_cxx_ (),
generate_man_ (),
generate_html_ (),
@@ -661,6 +666,7 @@ options (int start,
suppress_usage_ (),
long_usage_ (),
option_length_ (0),
+ cli_namespace_ ("::cli"),
generate_cxx_ (),
generate_man_ (),
generate_html_ (),
@@ -702,6 +708,7 @@ options (::cli::scanner& s,
suppress_usage_ (),
long_usage_ (),
option_length_ (0),
+ cli_namespace_ ("::cli"),
generate_cxx_ (),
generate_man_ (),
generate_html_ (),
@@ -730,91 +737,69 @@ options (::cli::scanner& s,
void options::
print_usage (::std::ostream& os)
{
- os << "--help Print usage information and exit." << ::std::endl;
+ os << "--help Print usage information and exit." << ::std::endl;
- os << "--version Print version and exit." << ::std::endl;
+ os << "--version Print version and exit." << ::std::endl;
- os << "--output-dir|-o <dir> Write the generated files to <dir> instead of the" << ::std::endl
- << " current directory." << ::std::endl;
+ os << "--output-dir|-o <dir> Write the generated files to <dir> instead of the current directory." << ::std::endl;
- os << "--generate-modifier Generate option value modifiers in addition to" << ::std::endl
- << " accessors." << ::std::endl;
+ os << "--generate-modifier Generate option value modifiers in addition to accessors." << ::std::endl;
- os << "--generate-specifier Generate functions for determining whether the" << ::std::endl
- << " option was specified on the command line." << ::std::endl;
+ os << "--generate-specifier Generate functions for determining whether the option was specified on the command line." << ::std::endl;
- os << "--generate-file-scanner Generate the 'argv_file_scanner' implementation." << ::std::endl;
+ os << "--generate-file-scanner Generate the 'argv_file_scanner' implementation." << ::std::endl;
- os << "--suppress-inline Generate all functions non-inline." << ::std::endl;
+ os << "--suppress-inline Generate all functions non-inline." << ::std::endl;
- os << "--suppress-usage Suppress the generation of the usage printing code." << ::std::endl;
+ os << "--suppress-usage Suppress the generation of the usage printing code." << ::std::endl;
- os << "--long-usage If no short documentation string is provided, use" << ::std::endl
- << " the complete long documentation string in usage." << ::std::endl;
+ os << "--long-usage If no short documentation string is provided, use the complete long documentation string in usage." << ::std::endl;
- os << "--option-length <len> Indent option descriptions <len> characters when" << ::std::endl
- << " printing usage." << ::std::endl;
+ os << "--option-length <len> Indent option descriptions <len> characters when printing usage." << ::std::endl;
- os << "--generate-cxx Generate C++ code." << ::std::endl;
+ os << "--cli-namespace <ns>Generate the CLI support types in the <ns> namespace ('cli' by default). The namespace can be nested, for example 'details::cli'. If the namespace is empty, then the support types are generated in the global namespace." << std::endl;
- os << "--generate-man Generate documentation in the man page format." << ::std::endl;
+ os << "--generate-cxx Generate C++ code." << ::std::endl;
- os << "--generate-html Generate documentation in the HTML format." << ::std::endl;
+ os << "--generate-man Generate documentation in the man page format." << ::std::endl;
- os << "--man-prologue <file> Insert the content of <file> at the beginning of" << ::std::endl
- << " the man page file." << ::std::endl;
+ os << "--generate-html Generate documentation in the HTML format." << ::std::endl;
- os << "--man-epilogue <file> Insert the content of <file> at the end of the man" << ::std::endl
- << " page file." << ::std::endl;
+ os << "--man-prologue <file> Insert the content of <file> at the beginning of the man page file." << ::std::endl;
- os << "--html-prologue <file> Insert the content of <file> at the beginning of" << ::std::endl
- << " the HTML file." << ::std::endl;
+ os << "--man-epilogue <file> Insert the content of <file> at the end of the man page file." << ::std::endl;
- os << "--html-epilogue <file> Insert the content of <file> at the end of the HTML" << ::std::endl
- << " file." << ::std::endl;
+ os << "--html-prologue <file> Insert the content of <file> at the beginning of the HTML file." << ::std::endl;
- os << "--class <fq-name> Generate the man page or HTML documentation only" << ::std::endl
- << " for the <fq-name> options class." << ::std::endl;
+ os << "--html-epilogue <file> Insert the content of <file> at the end of the HTML file." << ::std::endl;
- os << "--stdout Write output to STDOUT instead of a file." << ::std::endl;
+ os << "--class <fq-name> Generate the man page or HTML documentation only for the <fq-name> options class." << ::std::endl;
- os << "--hxx-suffix <suffix> Use <suffix> instead of the default '.hxx' to" << ::std::endl
- << " construct the name of the generated header file." << ::std::endl;
+ os << "--stdout Write output to STDOUT instead of a file." << ::std::endl;
- os << "--ixx-suffix <suffix> Use <suffix> instead of the default '.ixx' to" << ::std::endl
- << " construct the name of the generated inline file." << ::std::endl;
+ os << "--hxx-suffix <suffix> Use <suffix> instead of the default '.hxx' to construct the name of the generated header file." << ::std::endl;
- os << "--cxx-suffix <suffix> Use <suffix> instead of the default '.cxx' to" << ::std::endl
- << " construct the name of the generated source file." << ::std::endl;
+ os << "--ixx-suffix <suffix> Use <suffix> instead of the default '.ixx' to construct the name of the generated inline file." << ::std::endl;
- os << "--man-suffix <suffix> Use <suffix> instead of the default '.1' to" << ::std::endl
- << " construct the name of the generated man page file." << ::std::endl;
+ os << "--cxx-suffix <suffix> Use <suffix> instead of the default '.cxx' to construct the name of the generated source file." << ::std::endl;
- os << "--html-suffix <suffix> Use <suffix> instead of the default '.html' to" << ::std::endl
- << " construct the name of the generated HTML file." << ::std::endl;
+ os << "--man-suffix <suffix> Use <suffix> instead of the default '.1' to construct the name of the generated man page file." << ::std::endl;
- os << "--option-prefix <prefix> Use <prefix> instead of the default '-' as an" << ::std::endl
- << " option prefix." << ::std::endl;
+ os << "--html-suffix <suffix> Use <suffix> instead of the default '.html' to construct the name of the generated HTML file." << ::std::endl;
- os << "--option-separator <sep> Use <sep> instead of the default '--' as an" << ::std::endl
- << " optional separator between options and arguments." << ::std::endl;
+ os << "--option-prefix <prefix> Use <prefix> instead of the default '-' as an option prefix." << ::std::endl;
- os << "--include-with-brackets Use angle brackets (<>) instead of quotes (\"\") in" << ::std::endl
- << " the generated '#include' directives." << ::std::endl;
+ os << "--option-separator <sep> Use <sep> instead of the default '--' as an optional separator between options and arguments." << ::std::endl;
- os << "--include-prefix <prefix> Add <prefix> to the generated '#include' directive" << ::std::endl
- << " paths." << ::std::endl;
+ os << "--include-with-brackets Use angle brackets (<>) instead of quotes (\"\") in the generated '#include' directives." << ::std::endl;
- os << "--guard-prefix <prefix> Add <prefix> to the generated header inclusion" << ::std::endl
- << " guards." << ::std::endl;
+ os << "--include-prefix <prefix> Add <prefix> to the generated '#include' directive paths." << ::std::endl;
- os << "--reserved-name <name>=<rep> Add <name> with an optional <rep> replacement to" << ::std::endl
- << " the list of names that should not be used as" << ::std::endl
- << " identifiers." << ::std::endl;
+ os << "--guard-prefix <prefix> Add <prefix> to the generated header inclusion guards." << ::std::endl;
- os << "--options-file <file> Read additional options from <file> with each" << ::std::endl
- << " option appearing on a separate line optionally" << ::std::endl
- << " followed by space and an option value." << ::std::endl;
+ os << "--reserved-name <name>=<rep> Add <name> with an optional <rep> replacement to the list of names that should not be used as identifiers." << ::std::endl;
+
+ os << "--options-file <file> Read additional options from <file> with each option appearing on a separate line optionally followed by space and an option value." << ::std::endl;
}
typedef
@@ -849,6 +834,8 @@ struct _cli_options_map_init
&::cli::thunk< options, bool, &options::long_usage_ >;
_cli_options_map_["--option-length"] =
&::cli::thunk< options, std::size_t, &options::option_length_ >;
+ _cli_options_map_["--cli-namespace"] =
+ &::cli::thunk< options, std::string, &options::cli_namespace_ >;
_cli_options_map_["--generate-cxx"] =
&::cli::thunk< options, bool, &options::generate_cxx_ >;
_cli_options_map_["--generate-man"] =
diff --git a/cli/options.hxx b/cli/options.hxx
index 2c60c83..5c5e1bb 100644
--- a/cli/options.hxx
+++ b/cli/options.hxx
@@ -350,6 +350,9 @@ class options
const std::size_t&
option_length () const;
+ const std::string&
+ cli_namespace () const;
+
const bool&
generate_cxx () const;
@@ -435,6 +438,7 @@ class options
bool suppress_usage_;
bool long_usage_;
std::size_t option_length_;
+ std::string cli_namespace_;
bool generate_cxx_;
bool generate_man_;
bool generate_html_;
diff --git a/cli/options.ixx b/cli/options.ixx
index 4a5b17e..f79d75e 100644
--- a/cli/options.ixx
+++ b/cli/options.ixx
@@ -221,6 +221,12 @@ option_length () const
return this->option_length_;
}
+inline const std::string& options::
+cli_namespace () const
+{
+ return this->cli_namespace_;
+}
+
inline const bool& options::
generate_cxx () const
{
diff --git a/cli/runtime-header.cxx b/cli/runtime-header.cxx
index 5a2905c..99da036 100644
--- a/cli/runtime-header.cxx
+++ b/cli/runtime-header.cxx
@@ -20,8 +20,7 @@ generate_runtime_header (context& ctx)
<< "#include <exception>" << endl
<< endl;
- os << "namespace cli"
- << "{";
+ ctx.cli_open ();
// unknown_mode
//
@@ -300,5 +299,5 @@ generate_runtime_header (context& ctx)
os << "};";
}
- os << "}"; // namespace cli
+ ctx.cli_close ();
}
diff --git a/cli/runtime-inline.cxx b/cli/runtime-inline.cxx
index da2decf..753e86b 100644
--- a/cli/runtime-inline.cxx
+++ b/cli/runtime-inline.cxx
@@ -13,8 +13,7 @@ generate_runtime_inline (context& ctx)
ostream& os (ctx.os);
string const& inl (ctx.inl);
- os << "namespace cli"
- << "{";
+ ctx.cli_open ();
// unknown_mode
//
@@ -212,5 +211,5 @@ generate_runtime_inline (context& ctx)
<< "}";
}
- os << "}"; // namespace cli
+ ctx.cli_close ();
}
diff --git a/cli/runtime-source.cxx b/cli/runtime-source.cxx
index 35ee265..c76b745 100644
--- a/cli/runtime-source.cxx
+++ b/cli/runtime-source.cxx
@@ -25,8 +25,7 @@ generate_runtime_source (context& ctx)
os << endl;
- os << "namespace cli"
- << "{";
+ ctx.cli_open ();
// unknown_option
//
@@ -596,5 +595,5 @@ generate_runtime_source (context& ctx)
<< "parser<T>::parse (x.*M, x.*S, s);"
<< "}";
- os << "}"; // namespace cli
+ ctx.cli_close ();
}
diff --git a/cli/source.cxx b/cli/source.cxx
index c9273f4..f68f2d3 100644
--- a/cli/source.cxx
+++ b/cli/source.cxx
@@ -89,7 +89,7 @@ namespace
for (names::name_iterator i (n.name_begin ()); i != n.name_end (); ++i)
{
os << "_cli_" << scope << "_map_[\"" << *i << "\"] = " << endl
- << "&::cli::thunk< " << scope << ", " << type << ", " <<
+ << "&" << cli << "::thunk< " << scope << ", " << type << ", " <<
"&" << scope << "::" << member;
if (specifier && type != "bool")
@@ -368,7 +368,7 @@ namespace
// c-tors
//
- string um ("::cli::unknown_mode");
+ string um (cli + "::unknown_mode");
os << name << "::" << endl
<< name << " (int& argc," << endl
@@ -382,7 +382,7 @@ namespace
names (c, names_init);
}
os << "{"
- << "::cli::argv_scanner s (argc, argv, erase);"
+ << cli << "::argv_scanner s (argc, argv, erase);"
<< "_parse (s, opt, arg);"
<< "}";
@@ -399,7 +399,7 @@ namespace
names (c, names_init);
}
os << "{"
- << "::cli::argv_scanner s (start, argc, argv, erase);"
+ << cli << "::argv_scanner s (start, argc, argv, erase);"
<< "_parse (s, opt, arg);"
<< "}";
@@ -416,7 +416,7 @@ namespace
names (c, names_init);
}
os << "{"
- << "::cli::argv_scanner s (argc, argv, erase);"
+ << cli << "::argv_scanner s (argc, argv, erase);"
<< "_parse (s, opt, arg);"
<< "end = s.end ();"
<< "}";
@@ -435,13 +435,13 @@ namespace
names (c, names_init);
}
os << "{"
- << "::cli::argv_scanner s (start, argc, argv, erase);"
+ << cli << "::argv_scanner s (start, argc, argv, erase);"
<< "_parse (s, opt, arg);"
<< "end = s.end ();"
<< "}";
os << name << "::" << endl
- << name << " (::cli::scanner& s," << endl
+ << name << " (" << cli << "::scanner& s," << endl
<< um << " opt," << endl
<< um << " arg)";
{
@@ -503,7 +503,7 @@ namespace
os << "typedef" << endl
<< "std::map<std::string, void (*) (" <<
- name << "&, ::cli::scanner&)>" << endl
+ name << "&, " << cli << "::scanner&)>" << endl
<< map << ";"
<< endl
<< "static " << map << " " << map << "_;"
@@ -524,7 +524,7 @@ namespace
bool sep (!opt_sep.empty ());
os << "void " << name << "::" << endl
- << "_parse (::cli::scanner& s," << endl
+ << "_parse (" << cli << "::scanner& s," << endl
<< um << " opt_mode," << endl
<< um << " arg_mode)"
<< "{";
@@ -572,18 +572,18 @@ namespace
<< "{"
<< "switch (opt_mode)"
<< "{"
- << "case ::cli::unknown_mode::skip:" << endl
+ << "case " << cli << "::unknown_mode::skip:" << endl
<< "{"
<< "s.skip ();"
<< "continue;"
<< "}"
- << "case ::cli::unknown_mode::stop:" << endl
+ << "case " << cli << "::unknown_mode::stop:" << endl
<< "{"
<< "break;"
<< "}"
- << "case ::cli::unknown_mode::fail:" << endl
+ << "case " << cli << "::unknown_mode::fail:" << endl
<< "{"
- << "throw ::cli::unknown_option (o);"
+ << "throw " << cli << "::unknown_option (o);"
<< "}"
<< "}" // switch
<< "break;" // The stop case.
@@ -596,18 +596,18 @@ namespace
<< "{"
<< "switch (arg_mode)"
<< "{"
- << "case ::cli::unknown_mode::skip:" << endl
+ << "case " << cli << "::unknown_mode::skip:" << endl
<< "{"
<< "s.skip ();"
<< "continue;"
<< "}"
- << "case ::cli::unknown_mode::stop:" << endl
+ << "case " << cli << "::unknown_mode::stop:" << endl
<< "{"
<< "break;"
<< "}"
- << "case ::cli::unknown_mode::fail:" << endl
+ << "case " << cli << "::unknown_mode::fail:" << endl
<< "{"
- << "throw ::cli::unknown_argument (o);"
+ << "throw " << cli << "::unknown_argument (o);"
<< "}"
<< "}" // switch
<< "break;" // The stop case.