summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-06-02 17:22:12 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-06-02 17:22:12 +0200
commited60746355044dd39acd82b8f42c4d9886914567 (patch)
treea958825cb9bca8960eafb41c373d91e22ca9e4ed /cli
parent62166bfe7031522bd851eb5d7047a19182e24a45 (diff)
Implement generation of specifier functions (--generate-specifier)
These functions determine whether the option was specified on the command line. New test: specifier.
Diffstat (limited to 'cli')
-rw-r--r--cli/cli.cxx3
-rw-r--r--cli/context.cxx2
-rw-r--r--cli/context.hxx13
-rw-r--r--cli/header.cxx17
-rw-r--r--cli/inline.cxx18
-rw-r--r--cli/name-processor.cxx39
-rw-r--r--cli/options.cli6
-rw-r--r--cli/options.cxx10
-rw-r--r--cli/options.hxx4
-rw-r--r--cli/options.ixx6
-rw-r--r--cli/runtime-source.cxx69
-rw-r--r--cli/source.cxx12
12 files changed, 178 insertions, 21 deletions
diff --git a/cli/cli.cxx b/cli/cli.cxx
index 23552b4..15fabb2 100644
--- a/cli/cli.cxx
+++ b/cli/cli.cxx
@@ -45,8 +45,7 @@ main (int argc, char* argv[])
//
if (ops.help ())
{
- e << "Usage: " << argv[0] << " [options] file"
- << endl
+ e << "Usage: " << argv[0] << " [options] file" << endl
<< "Options:" << endl;
options::print_usage (e);
diff --git a/cli/context.cxx b/cli/context.cxx
index 43dfde2..a740374 100644
--- a/cli/context.cxx
+++ b/cli/context.cxx
@@ -100,6 +100,7 @@ context (ostream& os_,
unit (unit_),
options (ops),
modifier (options.generate_modifier ()),
+ specifier (options.generate_specifier ()),
usage (!options.suppress_usage ()),
inl (data_->inl_),
opt_prefix (options.option_prefix ()),
@@ -121,6 +122,7 @@ context (context& c)
unit (c.unit),
options (c.options),
modifier (c.modifier),
+ specifier (c.specifier),
usage (c.usage),
inl (c.inl),
opt_prefix (c.opt_prefix),
diff --git a/cli/context.hxx b/cli/context.hxx
index 00cbcde..1f2625d 100644
--- a/cli/context.hxx
+++ b/cli/context.hxx
@@ -39,6 +39,7 @@ public:
options_type const& options;
bool modifier;
+ bool specifier;
bool usage;
string const& inl;
@@ -92,11 +93,23 @@ public:
}
static string const&
+ especifier (semantics::nameable& n)
+ {
+ return n.context ().get<string> ("specifier");
+ }
+
+ static string const&
emember (semantics::nameable& n)
{
return n.context ().get<string> ("member");
}
+ static string const&
+ especifier_member (semantics::nameable& n)
+ {
+ return n.context ().get<string> ("specifier-member");
+ }
+
public:
// Return fully-qualified C++ or CLI name.
//
diff --git a/cli/header.cxx b/cli/header.cxx
index ad11aa7..e43c0af 100644
--- a/cli/header.cxx
+++ b/cli/header.cxx
@@ -27,6 +27,20 @@ namespace
os << "void" << endl
<< name << " (const " << type << "&);"
<< endl;
+
+ if (specifier && type != "bool")
+ {
+ string spec (especifier (o));
+
+ os << "bool" << endl
+ << spec << " () const;"
+ << endl;
+
+ if (modifier)
+ os << "void" << endl
+ << spec << " (bool);"
+ << endl;
+ }
}
};
@@ -43,6 +57,9 @@ namespace
string type (o.type ().name ());
os << type << " " << member << ";";
+
+ if (specifier && type != "bool")
+ os << "bool " << especifier_member (o) << ";";
}
};
diff --git a/cli/inline.cxx b/cli/inline.cxx
index 0d1393d..702bd6c 100644
--- a/cli/inline.cxx
+++ b/cli/inline.cxx
@@ -32,6 +32,24 @@ namespace
<< "{"
<< "this->" << emember (o) << " = x;"
<< "}";
+
+ if (specifier && type != "bool")
+ {
+ string spec (especifier (o));
+
+ os << inl << "bool " << scope << "::" << endl
+ << spec << " () const"
+ << "{"
+ << "return this->" << especifier_member (o) << ";"
+ << "}";
+
+ if (modifier)
+ os << inl << "void " << scope << "::" << endl
+ << spec << "(bool x)"
+ << "{"
+ << "this->" << especifier_member (o) << " = x;"
+ << "}";
+ }
}
};
diff --git a/cli/name-processor.cxx b/cli/name-processor.cxx
index 20e4b43..d846c7e 100644
--- a/cli/name-processor.cxx
+++ b/cli/name-processor.cxx
@@ -75,6 +75,28 @@ namespace
name_set& set_;
};
+ struct intermediate_option: traversal::option, context
+ {
+ intermediate_option (context& c, name_set& set)
+ : context (c), set_ (set)
+ {
+ }
+
+ virtual void
+ traverse (type& o)
+ {
+ if (specifier && o.type ().name () != "bool")
+ {
+ semantics::context& oc (o.context ());
+ string const& base (oc.get<string> ("name"));
+ oc.set ("specifier", find_name (base + "_specified", set_));
+ }
+ }
+
+ private:
+ name_set& set_;
+ };
+
struct secondary_option: traversal::option, context
{
secondary_option (context& c, name_set& set)
@@ -88,6 +110,12 @@ namespace
semantics::context& oc (o.context ());
string const& base (oc.get<string> ("name"));
oc.set ("member", find_name (base + "_", set_));
+
+ if (specifier && o.type ().name () != "bool")
+ {
+ string const& base (oc.get<string> ("specifier"));
+ oc.set ("specifier-member", find_name (base + "_", set_));
+ }
}
private:
@@ -117,7 +145,16 @@ namespace
class_::names (c, names);
}
- // Then assign secondary names.
+ // Then assign intermediate names.
+ //
+ {
+ intermediate_option option (*this, member_set);
+ traversal::names names (option);
+
+ class_::names (c, names);
+ }
+
+ // Finally assign secondary names.
//
{
secondary_option option (*this, member_set);
diff --git a/cli/options.cli b/cli/options.cli
index de0c1a2..dff5443 100644
--- a/cli/options.cli
+++ b/cli/options.cli
@@ -28,6 +28,12 @@ class options
"Generate option value modifiers in addition to accessors."
};
+ bool --generate-specifier
+ {
+ "Generate functions for determining whether the option was specified
+ on the command line."
+ };
+
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 5acc325..a079f9e 100644
--- a/cli/options.cxx
+++ b/cli/options.cxx
@@ -492,6 +492,7 @@ options (int& argc,
version_ (),
output_dir_ (),
generate_modifier_ (),
+ generate_specifier_ (),
generate_file_scanner_ (),
suppress_inline_ (),
suppress_usage_ (),
@@ -534,6 +535,7 @@ options (int start,
version_ (),
output_dir_ (),
generate_modifier_ (),
+ generate_specifier_ (),
generate_file_scanner_ (),
suppress_inline_ (),
suppress_usage_ (),
@@ -576,6 +578,7 @@ options (int& argc,
version_ (),
output_dir_ (),
generate_modifier_ (),
+ generate_specifier_ (),
generate_file_scanner_ (),
suppress_inline_ (),
suppress_usage_ (),
@@ -620,6 +623,7 @@ options (int start,
version_ (),
output_dir_ (),
generate_modifier_ (),
+ generate_specifier_ (),
generate_file_scanner_ (),
suppress_inline_ (),
suppress_usage_ (),
@@ -660,6 +664,7 @@ options (::cli::scanner& s,
version_ (),
output_dir_ (),
generate_modifier_ (),
+ generate_specifier_ (),
generate_file_scanner_ (),
suppress_inline_ (),
suppress_usage_ (),
@@ -703,6 +708,9 @@ print_usage (::std::ostream& os)
os << "--generate-modifier Generate option value modifiers in addition to" << ::std::endl
<< " 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-file-scanner Generate the 'argv_file_scanner' implementation." << ::std::endl;
os << "--suppress-inline Generate all functions non-inline." << ::std::endl;
@@ -797,6 +805,8 @@ struct _cli_options_map_init
&::cli::thunk< options, std::string, &options::output_dir_ >;
_cli_options_map_["--generate-modifier"] =
&::cli::thunk< options, bool, &options::generate_modifier_ >;
+ _cli_options_map_["--generate-specifier"] =
+ &::cli::thunk< options, bool, &options::generate_specifier_ >;
_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 24af0f2..e17a7d3 100644
--- a/cli/options.hxx
+++ b/cli/options.hxx
@@ -312,6 +312,9 @@ class options
generate_modifier () const;
const bool&
+ generate_specifier () const;
+
+ const bool&
generate_file_scanner () const;
const bool&
@@ -405,6 +408,7 @@ class options
bool version_;
std::string output_dir_;
bool generate_modifier_;
+ bool generate_specifier_;
bool generate_file_scanner_;
bool suppress_inline_;
bool suppress_usage_;
diff --git a/cli/options.ixx b/cli/options.ixx
index b814835..df0e39e 100644
--- a/cli/options.ixx
+++ b/cli/options.ixx
@@ -172,6 +172,12 @@ generate_modifier () const
}
inline const bool& options::
+generate_specifier () const
+{
+ return this->generate_specifier_;
+}
+
+inline const bool& options::
generate_file_scanner () const
{
return this->generate_file_scanner_;
diff --git a/cli/runtime-source.cxx b/cli/runtime-source.cxx
index e605c73..fea0347 100644
--- a/cli/runtime-source.cxx
+++ b/cli/runtime-source.cxx
@@ -380,13 +380,15 @@ generate_runtime_source (context& ctx)
<< "}";
}
+ bool sp (ctx.specifier);
+
// parser class template & its specializations
//
os << "template <typename X>" << endl
<< "struct parser"
<< "{"
<< "static void" << endl
- << "parse (X& x, scanner& s)"
+ << "parse (X& x, " << (sp ? "bool& xs, " : "") << "scanner& s)"
<< "{"
<< "const char* o (s.next ());"
<< endl
@@ -398,8 +400,13 @@ generate_runtime_source (context& ctx)
<< "throw invalid_value (o, v);"
<< "}"
<< "else" << endl
- << "throw missing_value (o);"
- << "}"
+ << "throw missing_value (o);";
+
+ if (sp)
+ os << endl
+ << "xs = true;";
+
+ os << "}"
<< "};";
// parser<bool>
@@ -421,15 +428,20 @@ generate_runtime_source (context& ctx)
<< "struct parser<std::string>"
<< "{"
<< "static void" << endl
- << "parse (std::string& x, scanner& s)"
+ << "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);"
- << "}"
+ << "throw missing_value (o);";
+
+ if (sp)
+ os << endl
+ << "xs = true;";
+
+ os << "}"
<< "};";
// parser<std::vector<X>>
@@ -438,12 +450,17 @@ generate_runtime_source (context& ctx)
<< "struct parser<std::vector<X> >"
<< "{"
<< "static void" << endl
- << "parse (std::vector<X>& c, scanner& s)"
+ << "parse (std::vector<X>& c, " << (sp ? "bool& xs, " : "") <<
+ "scanner& s)"
<< "{"
<< "X x;"
<< "parser<X>::parse (x, s);"
- << "c.push_back (x);"
- << "}"
+ << "c.push_back (x);";
+
+ if (sp)
+ os << "xs = true;";
+
+ os << "}"
<< "};";
// parser<std::set<X>>
@@ -452,12 +469,16 @@ generate_runtime_source (context& ctx)
<< "struct parser<std::set<X> >"
<< "{"
<< "static void" << endl
- << "parse (std::set<X>& c, scanner& s)"
+ << "parse (std::set<X>& c, " << (sp ? "bool& xs, " : "") << "scanner& s)"
<< "{"
<< "X x;"
<< "parser<X>::parse (x, s);"
- << "c.insert (x);"
- << "}"
+ << "c.insert (x);";
+
+ if (sp)
+ os << "xs = true;";
+
+ os << "}"
<< "};";
// parser<std::map<K,V>>
@@ -466,7 +487,8 @@ generate_runtime_source (context& ctx)
<< "struct parser<std::map<K, V> >"
<< "{"
<< "static void" << endl
- << "parse (std::map<K, V>& m, scanner& s)"
+ << "parse (std::map<K, V>& m, " << (sp ? "bool& xs, " : "") <<
+ "scanner& s)"
<< "{"
<< "const char* o (s.next ());"
<< endl
@@ -513,18 +535,31 @@ generate_runtime_source (context& ctx)
<< "}"
<< "}"
<< "else" << endl
- << "throw missing_value (o);"
- << "}"
+ << "throw missing_value (o);";
+
+ if (sp)
+ os << endl
+ << "xs = true;";
+
+ os << "}"
<< "};";
// Parser thunk.
//
- os << "template <typename X, typename T, T X::*P>" << endl
+ os << "template <typename X, typename T, T X::*M>" << endl
<< "void" << endl
<< "thunk (X& x, scanner& s)"
<< "{"
- << "parser<T>::parse (x.*P, s);"
+ << "parser<T>::parse (x.*M, s);"
<< "}";
+ if (ctx.specifier)
+ os << "template <typename X, typename T, T X::*M, bool X::*S>" << endl
+ << "void" << endl
+ << "thunk (X& x, scanner& s)"
+ << "{"
+ << "parser<T>::parse (x.*M, x.*S, s);"
+ << "}";
+
os << "}"; // namespace cli
}
diff --git a/cli/source.cxx b/cli/source.cxx
index 70a7fc9..c9273f4 100644
--- a/cli/source.cxx
+++ b/cli/source.cxx
@@ -58,6 +58,10 @@ namespace
}
else
os << " ()";
+
+ if (specifier && o.type ().name () != "bool")
+ os << "," << endl
+ << " " << especifier_member (o) << " (false)";
}
private:
@@ -86,7 +90,13 @@ namespace
{
os << "_cli_" << scope << "_map_[\"" << *i << "\"] = " << endl
<< "&::cli::thunk< " << scope << ", " << type << ", " <<
- "&" << scope << "::" << member << " >;";
+ "&" << scope << "::" << member;
+
+ if (specifier && type != "bool")
+ os << "," << endl
+ << " &" << scope << "::" << especifier_member (o);
+
+ os << " >;";
}
}
};